aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/include
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/include')
-rw-r--r--contrib/llvm/include/llvm-c/Comdat.h75
-rw-r--r--contrib/llvm/include/llvm-c/Core.h369
-rw-r--r--contrib/llvm/include/llvm-c/DataTypes.h90
-rw-r--r--contrib/llvm/include/llvm-c/DebugInfo.h924
-rw-r--r--contrib/llvm/include/llvm-c/Disassembler.h147
-rw-r--r--contrib/llvm/include/llvm-c/DisassemblerTypes.h160
-rw-r--r--contrib/llvm/include/llvm-c/ExecutionEngine.h7
-rw-r--r--contrib/llvm/include/llvm-c/Initialization.h1
-rw-r--r--contrib/llvm/include/llvm-c/OrcBindings.h59
-rw-r--r--contrib/llvm/include/llvm-c/Support.h2
-rw-r--r--contrib/llvm/include/llvm-c/TargetMachine.h12
-rw-r--r--contrib/llvm/include/llvm-c/Transforms/InstCombine.h43
-rw-r--r--contrib/llvm/include/llvm-c/Transforms/Scalar.h12
-rw-r--r--contrib/llvm/include/llvm-c/Transforms/Utils.h50
-rw-r--r--contrib/llvm/include/llvm-c/Transforms/Vectorize.h3
-rw-r--r--contrib/llvm/include/llvm-c/Types.h19
-rw-r--r--contrib/llvm/include/llvm-c/lto.h36
-rw-r--r--contrib/llvm/include/llvm/ADT/APFloat.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/APInt.h352
-rw-r--r--contrib/llvm/include/llvm/ADT/APSInt.h6
-rw-r--r--contrib/llvm/include/llvm/ADT/Any.h150
-rw-r--r--contrib/llvm/include/llvm/ADT/ArrayRef.h30
-rw-r--r--contrib/llvm/include/llvm/ADT/BitVector.h11
-rw-r--r--contrib/llvm/include/llvm/ADT/CachedHashString.h1
-rw-r--r--contrib/llvm/include/llvm/ADT/DenseMapInfo.h7
-rw-r--r--contrib/llvm/include/llvm/ADT/DepthFirstIterator.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/EpochTracker.h13
-rw-r--r--contrib/llvm/include/llvm/ADT/FunctionExtras.h293
-rw-r--r--contrib/llvm/include/llvm/ADT/GraphTraits.h20
-rw-r--r--contrib/llvm/include/llvm/ADT/Hashing.h62
-rw-r--r--contrib/llvm/include/llvm/ADT/ImmutableList.h4
-rw-r--r--contrib/llvm/include/llvm/ADT/ImmutableMap.h5
-rw-r--r--contrib/llvm/include/llvm/ADT/ImmutableSet.h4
-rw-r--r--contrib/llvm/include/llvm/ADT/MapVector.h32
-rw-r--r--contrib/llvm/include/llvm/ADT/None.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/Optional.h176
-rw-r--r--contrib/llvm/include/llvm/ADT/PackedVector.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/PointerUnion.h6
-rw-r--r--contrib/llvm/include/llvm/ADT/SCCIterator.h10
-rw-r--r--contrib/llvm/include/llvm/ADT/STLExtras.h215
-rw-r--r--contrib/llvm/include/llvm/ADT/ScopeExit.h16
-rw-r--r--contrib/llvm/include/llvm/ADT/SetVector.h56
-rw-r--r--contrib/llvm/include/llvm/ADT/SmallPtrSet.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/SmallSet.h118
-rw-r--r--contrib/llvm/include/llvm/ADT/SmallVector.h241
-rw-r--r--contrib/llvm/include/llvm/ADT/SparseMultiSet.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/SparseSet.h3
-rw-r--r--contrib/llvm/include/llvm/ADT/Statistic.h59
-rw-r--r--contrib/llvm/include/llvm/ADT/StringExtras.h55
-rw-r--r--contrib/llvm/include/llvm/ADT/StringMap.h24
-rw-r--r--contrib/llvm/include/llvm/ADT/StringRef.h42
-rw-r--r--contrib/llvm/include/llvm/ADT/StringSwitch.h188
-rw-r--r--contrib/llvm/include/llvm/ADT/TinyPtrVector.h6
-rw-r--r--contrib/llvm/include/llvm/ADT/Triple.h30
-rw-r--r--contrib/llvm/include/llvm/ADT/UniqueVector.h8
-rw-r--r--contrib/llvm/include/llvm/ADT/VariadicFunction.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/edit_distance.h2
-rw-r--r--contrib/llvm/include/llvm/ADT/ilist.h25
-rw-r--r--contrib/llvm/include/llvm/ADT/ilist_node.h8
-rw-r--r--contrib/llvm/include/llvm/ADT/ilist_node_options.h1
-rw-r--r--contrib/llvm/include/llvm/ADT/iterator.h10
-rw-r--r--contrib/llvm/include/llvm/ADT/iterator_range.h11
-rw-r--r--contrib/llvm/include/llvm/Analysis/AliasAnalysis.h51
-rw-r--r--contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h2
-rw-r--r--contrib/llvm/include/llvm/Analysis/AliasSetTracker.h35
-rw-r--r--contrib/llvm/include/llvm/Analysis/AssumptionCache.h36
-rw-r--r--contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h47
-rw-r--r--contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h16
-rw-r--r--contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h139
-rw-r--r--contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h30
-rw-r--r--contrib/llvm/include/llvm/Analysis/CFG.h73
-rw-r--r--contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h10
-rw-r--r--contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h8
-rw-r--r--contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h72
-rw-r--r--contrib/llvm/include/llvm/Analysis/CallGraph.h89
-rw-r--r--contrib/llvm/include/llvm/Analysis/CaptureTracking.h2
-rw-r--r--contrib/llvm/include/llvm/Analysis/CodeMetrics.h34
-rw-r--r--contrib/llvm/include/llvm/Analysis/ConstantFolding.h22
-rw-r--r--contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h6
-rw-r--r--contrib/llvm/include/llvm/Analysis/DemandedBits.h6
-rw-r--r--contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h15
-rw-r--r--contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h15
-rw-r--r--contrib/llvm/include/llvm/Analysis/DominanceFrontier.h9
-rw-r--r--contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h1
-rw-r--r--contrib/llvm/include/llvm/Analysis/EHPersonalities.h29
-rw-r--r--contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h2
-rw-r--r--contrib/llvm/include/llvm/Analysis/InlineCost.h22
-rw-r--r--contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h12
-rw-r--r--contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h8
-rw-r--r--contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h10
-rw-r--r--contrib/llvm/include/llvm/Analysis/LazyValueInfo.h9
-rw-r--r--contrib/llvm/include/llvm/Analysis/Lint.h4
-rw-r--r--contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h186
-rw-r--r--contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h2
-rw-r--r--contrib/llvm/include/llvm/Analysis/LoopInfo.h50
-rw-r--r--contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h84
-rw-r--r--contrib/llvm/include/llvm/Analysis/LoopIterator.h19
-rw-r--r--contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h6
-rw-r--r--contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h20
-rw-r--r--contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h8
-rw-r--r--contrib/llvm/include/llvm/Analysis/MemoryLocation.h20
-rw-r--r--contrib/llvm/include/llvm/Analysis/MemorySSA.h185
-rw-r--r--contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h89
-rw-r--r--contrib/llvm/include/llvm/Analysis/MustExecute.h64
-rw-r--r--contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h2
-rw-r--r--contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h27
-rw-r--r--contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h22
-rw-r--r--contrib/llvm/include/llvm/Analysis/ObjectUtils.h42
-rw-r--r--contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h16
-rw-r--r--contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h12
-rw-r--r--contrib/llvm/include/llvm/Analysis/PHITransAddr.h2
-rw-r--r--contrib/llvm/include/llvm/Analysis/Passes.h8
-rw-r--r--contrib/llvm/include/llvm/Analysis/PhiValues.h143
-rw-r--r--contrib/llvm/include/llvm/Analysis/PostDominators.h15
-rw-r--r--contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h36
-rw-r--r--contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h44
-rw-r--r--contrib/llvm/include/llvm/Analysis/RegionInfo.h127
-rw-r--r--contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h3
-rw-r--r--contrib/llvm/include/llvm/Analysis/RegionIterator.h12
-rw-r--r--contrib/llvm/include/llvm/Analysis/RegionPass.h14
-rw-r--r--contrib/llvm/include/llvm/Analysis/RegionPrinter.h8
-rw-r--r--contrib/llvm/include/llvm/Analysis/ScalarEvolution.h133
-rw-r--r--contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h3
-rw-r--r--contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h4
-rw-r--r--contrib/llvm/include/llvm/Analysis/SparsePropagation.h21
-rw-r--r--contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h52
-rw-r--r--contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def63
-rw-r--r--contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h238
-rw-r--r--contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h27
-rw-r--r--contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h4
-rw-r--r--contrib/llvm/include/llvm/Analysis/Utils/Local.h91
-rw-r--r--contrib/llvm/include/llvm/Analysis/ValueLattice.h125
-rw-r--r--contrib/llvm/include/llvm/Analysis/ValueTracking.h70
-rw-r--r--contrib/llvm/include/llvm/Analysis/VectorUtils.h28
-rw-r--r--contrib/llvm/include/llvm/AsmParser/Parser.h106
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/COFF.h19
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/Dwarf.def54
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/Dwarf.h115
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/DynamicTags.def216
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/ELF.h355
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def14
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/WebAssembly.def8
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/MachO.h4
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/Magic.h7
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/Wasm.h154
-rw-r--r--contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def2
-rw-r--r--contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h10
-rw-r--r--contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h12
-rw-r--r--contrib/llvm/include/llvm/Bitcode/BitstreamReader.h2
-rw-r--r--contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h4
-rw-r--r--contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h18
-rw-r--r--contrib/llvm/include/llvm/CodeGen/AccelTable.h434
-rw-r--r--contrib/llvm/include/llvm/CodeGen/Analysis.h4
-rw-r--r--contrib/llvm/include/llvm/CodeGen/AsmPrinter.h70
-rw-r--r--contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h4
-rw-r--r--contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h107
-rw-r--r--contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h12
-rw-r--r--contrib/llvm/include/llvm/CodeGen/CallingConvLower.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/CommandFlags.inc (renamed from contrib/llvm/include/llvm/CodeGen/CommandFlags.def)34
-rw-r--r--contrib/llvm/include/llvm/CodeGen/CostTable.h4
-rw-r--r--contrib/llvm/include/llvm/CodeGen/DIE.h8
-rw-r--r--contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ExecutionDepsFix.h230
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ExecutionDomainFix.h213
-rw-r--r--contrib/llvm/include/llvm/CodeGen/FastISel.h156
-rw-r--r--contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h13
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GCStrategy.h6
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h6
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h43
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h44
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h48
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h134
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h133
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h122
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h280
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h45
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h14
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h803
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h338
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h545
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h25
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h18
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h9
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h8
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LiveInterval.h12
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LiveIntervals.h6
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h17
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h16
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h7
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h33
-rw-r--r--contrib/llvm/include/llvm/CodeGen/LoopTraversal.h116
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MIRPrinter.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h24
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h50
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h6
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h4
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineDominators.h16
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h38
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineFunction.h44
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineInstr.h99
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h25
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h4
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h5
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineOperand.h98
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h8
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineOutliner.h226
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h81
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MachineScheduler.h37
-rw-r--r--contrib/llvm/include/llvm/CodeGen/MacroFusion.h6
-rw-r--r--contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h62
-rw-r--r--contrib/llvm/include/llvm/CodeGen/PBQP/Math.h58
-rw-r--r--contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h4
-rw-r--r--contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h8
-rw-r--r--contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h4
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ParallelCG.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/Passes.h33
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h118
-rw-r--r--contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h18
-rw-r--r--contrib/llvm/include/llvm/CodeGen/RegisterPressure.h8
-rw-r--r--contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h6
-rw-r--r--contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h22
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h4
-rw-r--r--contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h50
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h8
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h34
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/SelectionDAG.h169
-rw-r--r--contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h24
-rw-r--r--contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h163
-rw-r--r--contrib/llvm/include/llvm/CodeGen/SlotIndexes.h8
-rw-r--r--contrib/llvm/include/llvm/CodeGen/StackMaps.h24
-rw-r--r--contrib/llvm/include/llvm/CodeGen/StackProtector.h30
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h12
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h141
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetLowering.h241
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h29
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h23
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h33
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetSchedule.h58
-rw-r--r--contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h33
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ValueTypes.h2
-rw-r--r--contrib/llvm/include/llvm/CodeGen/ValueTypes.td7
-rw-r--r--contrib/llvm/include/llvm/CodeGen/VirtRegMap.h28
-rw-r--r--contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h80
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h24
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h6
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def448
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def4
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h16
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h17
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h11
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h31
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h6
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DIContext.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h524
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h68
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h8
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h44
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h7
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h1
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h278
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h118
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h3
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h45
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h60
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h38
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h14
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h63
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h278
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h4
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h20
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h241
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h58
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h9
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h50
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h40
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h40
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h38
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h22
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h55
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h26
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h10
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h31
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h42
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h23
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h50
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h27
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h1
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h13
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h5
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h308
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h28
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h6
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h37
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h22
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h25
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h34
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h13
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h44
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h4
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h1
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h7
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h6
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h2
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h4
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h3
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h48
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h10
-rw-r--r--contrib/llvm/include/llvm/Demangle/Demangle.h74
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h31
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h13
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h131
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h346
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h84
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/Core.h779
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h160
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h20
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h90
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h71
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h164
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h143
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h2
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/Layer.h129
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h97
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h211
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h11
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h71
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h36
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h16
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h125
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h83
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h12
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h339
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h55
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h63
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h8
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h13
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h14
-rw-r--r--contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h10
-rw-r--r--contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h6
-rw-r--r--contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h6
-rw-r--r--contrib/llvm/include/llvm/IR/Attributes.h240
-rw-r--r--contrib/llvm/include/llvm/IR/Attributes.td11
-rw-r--r--contrib/llvm/include/llvm/IR/AutoUpgrade.h8
-rw-r--r--contrib/llvm/include/llvm/IR/BasicBlock.h119
-rw-r--r--contrib/llvm/include/llvm/IR/CFG.h6
-rw-r--r--contrib/llvm/include/llvm/IR/CallSite.h3
-rw-r--r--contrib/llvm/include/llvm/IR/CallingConv.h12
-rw-r--r--contrib/llvm/include/llvm/IR/Comdat.h6
-rw-r--r--contrib/llvm/include/llvm/IR/Constant.h24
-rw-r--r--contrib/llvm/include/llvm/IR/ConstantRange.h2
-rw-r--r--contrib/llvm/include/llvm/IR/Constants.h108
-rw-r--r--contrib/llvm/include/llvm/IR/DIBuilder.h113
-rw-r--r--contrib/llvm/include/llvm/IR/DataLayout.h92
-rw-r--r--contrib/llvm/include/llvm/IR/DebugInfo.h27
-rw-r--r--contrib/llvm/include/llvm/IR/DebugInfoFlags.def7
-rw-r--r--contrib/llvm/include/llvm/IR/DebugInfoMetadata.h430
-rw-r--r--contrib/llvm/include/llvm/IR/DebugLoc.h22
-rw-r--r--contrib/llvm/include/llvm/IR/DerivedTypes.h12
-rw-r--r--contrib/llvm/include/llvm/IR/DiagnosticHandler.h2
-rw-r--r--contrib/llvm/include/llvm/IR/DiagnosticInfo.h29
-rw-r--r--contrib/llvm/include/llvm/IR/DiagnosticPrinter.h4
-rw-r--r--contrib/llvm/include/llvm/IR/DomTreeUpdater.h259
-rw-r--r--contrib/llvm/include/llvm/IR/Dominators.h126
-rw-r--r--contrib/llvm/include/llvm/IR/Function.h190
-rw-r--r--contrib/llvm/include/llvm/IR/GlobalObject.h12
-rw-r--r--contrib/llvm/include/llvm/IR/GlobalValue.h34
-rw-r--r--contrib/llvm/include/llvm/IR/GlobalVariable.h13
-rw-r--r--contrib/llvm/include/llvm/IR/IRBuilder.h805
-rw-r--r--contrib/llvm/include/llvm/IR/IRPrintingPasses.h14
-rw-r--r--contrib/llvm/include/llvm/IR/InstVisitor.h4
-rw-r--r--contrib/llvm/include/llvm/IR/InstrTypes.h270
-rw-r--r--contrib/llvm/include/llvm/IR/Instruction.h25
-rw-r--r--contrib/llvm/include/llvm/IR/Instructions.h1290
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicInst.h244
-rw-r--r--contrib/llvm/include/llvm/IR/Intrinsics.h4
-rw-r--r--contrib/llvm/include/llvm/IR/Intrinsics.td57
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td26
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td749
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicsARM.td58
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td129
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td183
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td23
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td51
-rw-r--r--contrib/llvm/include/llvm/IR/IntrinsicsX86.td2283
-rw-r--r--contrib/llvm/include/llvm/IR/LLVMContext.h40
-rw-r--r--contrib/llvm/include/llvm/IR/LegacyPassManagers.h9
-rw-r--r--contrib/llvm/include/llvm/IR/MDBuilder.h55
-rw-r--r--contrib/llvm/include/llvm/IR/Mangler.h3
-rw-r--r--contrib/llvm/include/llvm/IR/Metadata.def1
-rw-r--r--contrib/llvm/include/llvm/IR/Metadata.h146
-rw-r--r--contrib/llvm/include/llvm/IR/Module.h49
-rw-r--r--contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h453
-rw-r--r--contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h27
-rw-r--r--contrib/llvm/include/llvm/IR/Operator.h31
-rw-r--r--contrib/llvm/include/llvm/IR/OptBisect.h48
-rw-r--r--contrib/llvm/include/llvm/IR/PassManager.h106
-rw-r--r--contrib/llvm/include/llvm/IR/PassManagerInternal.h38
-rw-r--r--contrib/llvm/include/llvm/IR/PatternMatch.h758
-rw-r--r--contrib/llvm/include/llvm/IR/ProfileSummary.h6
-rw-r--r--contrib/llvm/include/llvm/IR/RuntimeLibcalls.def (renamed from contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.def)32
-rw-r--r--contrib/llvm/include/llvm/IR/Statepoint.h4
-rw-r--r--contrib/llvm/include/llvm/IR/TrackingMDRef.h8
-rw-r--r--contrib/llvm/include/llvm/IR/Type.h19
-rw-r--r--contrib/llvm/include/llvm/IR/Use.h14
-rw-r--r--contrib/llvm/include/llvm/IR/UseListOrder.h2
-rw-r--r--contrib/llvm/include/llvm/IR/User.h40
-rw-r--r--contrib/llvm/include/llvm/IR/Value.h101
-rw-r--r--contrib/llvm/include/llvm/IR/ValueHandle.h28
-rw-r--r--contrib/llvm/include/llvm/IR/ValueMap.h4
-rw-r--r--contrib/llvm/include/llvm/IR/ValueSymbolTable.h24
-rw-r--r--contrib/llvm/include/llvm/IR/Verifier.h6
-rw-r--r--contrib/llvm/include/llvm/IRReader/IRReader.h9
-rw-r--r--contrib/llvm/include/llvm/InitializePasses.h43
-rw-r--r--contrib/llvm/include/llvm/LTO/Caching.h7
-rw-r--r--contrib/llvm/include/llvm/LTO/Config.h11
-rw-r--r--contrib/llvm/include/llvm/LTO/LTO.h17
-rw-r--r--contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h27
-rw-r--r--contrib/llvm/include/llvm/LinkAllPasses.h10
-rw-r--r--contrib/llvm/include/llvm/Linker/Linker.h2
-rw-r--r--contrib/llvm/include/llvm/MC/MCAsmBackend.h43
-rw-r--r--contrib/llvm/include/llvm/MC/MCAsmInfo.h20
-rw-r--r--contrib/llvm/include/llvm/MC/MCAsmLayout.h20
-rw-r--r--contrib/llvm/include/llvm/MC/MCAsmMacro.h122
-rw-r--r--contrib/llvm/include/llvm/MC/MCAssembler.h57
-rw-r--r--contrib/llvm/include/llvm/MC/MCCodePadder.h3
-rw-r--r--contrib/llvm/include/llvm/MC/MCCodeView.h18
-rw-r--r--contrib/llvm/include/llvm/MC/MCContext.h60
-rw-r--r--contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h2
-rw-r--r--contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h4
-rw-r--r--contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h8
-rw-r--r--contrib/llvm/include/llvm/MC/MCDwarf.h180
-rw-r--r--contrib/llvm/include/llvm/MC/MCELFObjectWriter.h15
-rw-r--r--contrib/llvm/include/llvm/MC/MCELFStreamer.h15
-rw-r--r--contrib/llvm/include/llvm/MC/MCExpr.h41
-rw-r--r--contrib/llvm/include/llvm/MC/MCFixup.h60
-rw-r--r--contrib/llvm/include/llvm/MC/MCFixupKindInfo.h2
-rw-r--r--contrib/llvm/include/llvm/MC/MCFragment.h122
-rw-r--r--contrib/llvm/include/llvm/MC/MCInst.h12
-rw-r--r--contrib/llvm/include/llvm/MC/MCInstBuilder.h14
-rw-r--r--contrib/llvm/include/llvm/MC/MCInstPrinter.h15
-rw-r--r--contrib/llvm/include/llvm/MC/MCInstrAnalysis.h29
-rw-r--r--contrib/llvm/include/llvm/MC/MCInstrDesc.h145
-rw-r--r--contrib/llvm/include/llvm/MC/MCInstrInfo.h8
-rw-r--r--contrib/llvm/include/llvm/MC/MCInstrItineraries.h38
-rw-r--r--contrib/llvm/include/llvm/MC/MCLabel.h12
-rw-r--r--contrib/llvm/include/llvm/MC/MCMachObjectWriter.h17
-rw-r--r--contrib/llvm/include/llvm/MC/MCObjectFileInfo.h36
-rw-r--r--contrib/llvm/include/llvm/MC/MCObjectStreamer.h27
-rw-r--r--contrib/llvm/include/llvm/MC/MCObjectWriter.h116
-rw-r--r--contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h111
-rw-r--r--contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h50
-rw-r--r--contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h4
-rw-r--r--contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h2
-rw-r--r--contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h63
-rw-r--r--contrib/llvm/include/llvm/MC/MCRegisterInfo.h60
-rw-r--r--contrib/llvm/include/llvm/MC/MCSchedule.h188
-rw-r--r--contrib/llvm/include/llvm/MC/MCSection.h8
-rw-r--r--contrib/llvm/include/llvm/MC/MCSectionWasm.h14
-rw-r--r--contrib/llvm/include/llvm/MC/MCStreamer.h231
-rw-r--r--contrib/llvm/include/llvm/MC/MCSubtargetInfo.h52
-rw-r--r--contrib/llvm/include/llvm/MC/MCSymbol.h45
-rw-r--r--contrib/llvm/include/llvm/MC/MCSymbolMachO.h4
-rw-r--r--contrib/llvm/include/llvm/MC/MCSymbolWasm.h28
-rw-r--r--contrib/llvm/include/llvm/MC/MCTargetOptions.h1
-rw-r--r--contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.inc (renamed from contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.def)0
-rw-r--r--contrib/llvm/include/llvm/MC/MCValue.h8
-rw-r--r--contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h15
-rw-r--r--contrib/llvm/include/llvm/MC/MCWasmStreamer.h12
-rw-r--r--contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h11
-rw-r--r--contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h7
-rw-r--r--contrib/llvm/include/llvm/MC/StringTableBuilder.h10
-rw-r--r--contrib/llvm/include/llvm/Object/Archive.h4
-rw-r--r--contrib/llvm/include/llvm/Object/Binary.h2
-rw-r--r--contrib/llvm/include/llvm/Object/COFF.h21
-rw-r--r--contrib/llvm/include/llvm/Object/COFFImportFile.h7
-rw-r--r--contrib/llvm/include/llvm/Object/CVDebugRecord.h (renamed from contrib/llvm/include/llvm/DebugInfo/CodeView/CVDebugRecord.h)4
-rw-r--r--contrib/llvm/include/llvm/Object/Decompressor.h16
-rw-r--r--contrib/llvm/include/llvm/Object/ELF.h121
-rw-r--r--contrib/llvm/include/llvm/Object/ELFObjectFile.h109
-rw-r--r--contrib/llvm/include/llvm/Object/ELFTypes.h185
-rw-r--r--contrib/llvm/include/llvm/Object/IRObjectFile.h15
-rw-r--r--contrib/llvm/include/llvm/Object/MachO.h4
-rw-r--r--contrib/llvm/include/llvm/Object/MachOUniversal.h4
-rw-r--r--contrib/llvm/include/llvm/Object/ModuleSymbolTable.h9
-rw-r--r--contrib/llvm/include/llvm/Object/ObjectFile.h27
-rw-r--r--contrib/llvm/include/llvm/Object/RelocVisitor.h26
-rw-r--r--contrib/llvm/include/llvm/Object/Wasm.h137
-rw-r--r--contrib/llvm/include/llvm/Object/WasmTraits.h63
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h1
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h6
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h6
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h7
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h2
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h2
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h2
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h53
-rw-r--r--contrib/llvm/include/llvm/ObjectYAML/YAML.h12
-rw-r--r--contrib/llvm/include/llvm/Option/Arg.h28
-rw-r--r--contrib/llvm/include/llvm/Option/ArgList.h7
-rw-r--r--contrib/llvm/include/llvm/Option/OptTable.h46
-rw-r--r--contrib/llvm/include/llvm/Option/Option.h8
-rw-r--r--contrib/llvm/include/llvm/Pass.h6
-rw-r--r--contrib/llvm/include/llvm/PassAnalysisSupport.h2
-rw-r--r--contrib/llvm/include/llvm/Passes/PassBuilder.h58
-rw-r--r--contrib/llvm/include/llvm/Passes/PassPlugin.h114
-rw-r--r--contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h3
-rw-r--r--contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h14
-rw-r--r--contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h8
-rw-r--r--contrib/llvm/include/llvm/ProfileData/GCOV.h5
-rw-r--r--contrib/llvm/include/llvm/ProfileData/InstrProf.h62
-rw-r--r--contrib/llvm/include/llvm/ProfileData/InstrProfData.inc22
-rw-r--r--contrib/llvm/include/llvm/ProfileData/InstrProfReader.h4
-rw-r--r--contrib/llvm/include/llvm/ProfileData/ProfileCommon.h2
-rw-r--r--contrib/llvm/include/llvm/ProfileData/SampleProf.h44
-rw-r--r--contrib/llvm/include/llvm/ProfileData/SampleProfReader.h140
-rw-r--r--contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h46
-rw-r--r--contrib/llvm/include/llvm/Support/AArch64TargetParser.def11
-rw-r--r--contrib/llvm/include/llvm/Support/AMDGPUKernelDescriptor.h139
-rw-r--r--contrib/llvm/include/llvm/Support/AMDGPUMetadata.h238
-rw-r--r--contrib/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h185
-rw-r--r--contrib/llvm/include/llvm/Support/ARMTargetParser.def8
-rw-r--r--contrib/llvm/include/llvm/Support/AlignOf.h8
-rw-r--r--contrib/llvm/include/llvm/Support/Allocator.h46
-rw-r--r--contrib/llvm/include/llvm/Support/AtomicOrdering.h2
-rw-r--r--contrib/llvm/include/llvm/Support/BinaryByteStream.h24
-rw-r--r--contrib/llvm/include/llvm/Support/BinaryStream.h18
-rw-r--r--contrib/llvm/include/llvm/Support/BinaryStreamArray.h2
-rw-r--r--contrib/llvm/include/llvm/Support/BinaryStreamReader.h2
-rw-r--r--contrib/llvm/include/llvm/Support/BinaryStreamRef.h4
-rw-r--r--contrib/llvm/include/llvm/Support/BinaryStreamWriter.h8
-rw-r--r--contrib/llvm/include/llvm/Support/BlockFrequency.h14
-rw-r--r--contrib/llvm/include/llvm/Support/BranchProbability.h4
-rw-r--r--contrib/llvm/include/llvm/Support/CachePruning.h12
-rw-r--r--contrib/llvm/include/llvm/Support/Casting.h2
-rw-r--r--contrib/llvm/include/llvm/Support/CheckedArithmetic.h104
-rw-r--r--contrib/llvm/include/llvm/Support/CodeGenCoverage.h7
-rw-r--r--contrib/llvm/include/llvm/Support/CommandLine.h28
-rw-r--r--contrib/llvm/include/llvm/Support/Compiler.h79
-rw-r--r--contrib/llvm/include/llvm/Support/ConvertUTF.h16
-rw-r--r--contrib/llvm/include/llvm/Support/CrashRecoveryContext.h92
-rw-r--r--contrib/llvm/include/llvm/Support/DJB.h33
-rw-r--r--contrib/llvm/include/llvm/Support/DataExtractor.h8
-rw-r--r--contrib/llvm/include/llvm/Support/DataTypes.h17
-rw-r--r--contrib/llvm/include/llvm/Support/Debug.h23
-rw-r--r--contrib/llvm/include/llvm/Support/DebugCounter.h56
-rw-r--r--contrib/llvm/include/llvm/Support/DynamicLibrary.h8
-rw-r--r--contrib/llvm/include/llvm/Support/Endian.h2
-rw-r--r--contrib/llvm/include/llvm/Support/EndianStream.h54
-rw-r--r--contrib/llvm/include/llvm/Support/Errc.h1
-rw-r--r--contrib/llvm/include/llvm/Support/Errno.h5
-rw-r--r--contrib/llvm/include/llvm/Support/Error.h61
-rw-r--r--contrib/llvm/include/llvm/Support/ErrorHandling.h4
-rw-r--r--contrib/llvm/include/llvm/Support/ErrorOr.h18
-rw-r--r--contrib/llvm/include/llvm/Support/FileOutputBuffer.h16
-rw-r--r--contrib/llvm/include/llvm/Support/FileSystem.h422
-rw-r--r--contrib/llvm/include/llvm/Support/FormatAdapters.h18
-rw-r--r--contrib/llvm/include/llvm/Support/FormatVariadic.h13
-rw-r--r--contrib/llvm/include/llvm/Support/FormatVariadicDetails.h57
-rw-r--r--contrib/llvm/include/llvm/Support/GenericDomTree.h47
-rw-r--r--contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h346
-rw-r--r--contrib/llvm/include/llvm/Support/GraphWriter.h2
-rw-r--r--contrib/llvm/include/llvm/Support/Host.h8
-rw-r--r--contrib/llvm/include/llvm/Support/InitLLVM.h46
-rw-r--r--contrib/llvm/include/llvm/Support/JSON.h704
-rw-r--r--contrib/llvm/include/llvm/Support/JamCRC.h2
-rw-r--r--contrib/llvm/include/llvm/Support/KnownBits.h2
-rw-r--r--contrib/llvm/include/llvm/Support/LEB128.h17
-rw-r--r--contrib/llvm/include/llvm/Support/LineIterator.h18
-rw-r--r--contrib/llvm/include/llvm/Support/LockFileManager.h31
-rw-r--r--contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h2
-rw-r--r--contrib/llvm/include/llvm/Support/MD5.h10
-rw-r--r--contrib/llvm/include/llvm/Support/MachineValueType.h (renamed from contrib/llvm/include/llvm/CodeGen/MachineValueType.h)13
-rw-r--r--contrib/llvm/include/llvm/Support/MathExtras.h58
-rw-r--r--contrib/llvm/include/llvm/Support/MemAlloc.h49
-rw-r--r--contrib/llvm/include/llvm/Support/Memory.h10
-rw-r--r--contrib/llvm/include/llvm/Support/MemoryBuffer.h79
-rw-r--r--contrib/llvm/include/llvm/Support/MipsABIFlags.h4
-rw-r--r--contrib/llvm/include/llvm/Support/Mutex.h13
-rw-r--r--contrib/llvm/include/llvm/Support/MutexGuard.h2
-rw-r--r--contrib/llvm/include/llvm/Support/OnDiskHashTable.h47
-rw-r--r--contrib/llvm/include/llvm/Support/Options.h10
-rw-r--r--contrib/llvm/include/llvm/Support/Parallel.h10
-rw-r--r--contrib/llvm/include/llvm/Support/Path.h83
-rw-r--r--contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h34
-rw-r--r--contrib/llvm/include/llvm/Support/Process.h17
-rw-r--r--contrib/llvm/include/llvm/Support/Program.h64
-rw-r--r--contrib/llvm/include/llvm/Support/RWMutex.h14
-rw-r--r--contrib/llvm/include/llvm/Support/Regex.h4
-rw-r--r--contrib/llvm/include/llvm/Support/SMLoc.h6
-rw-r--r--contrib/llvm/include/llvm/Support/SaveAndRestore.h12
-rw-r--r--contrib/llvm/include/llvm/Support/ScaledNumber.h82
-rw-r--r--contrib/llvm/include/llvm/Support/ScopedPrinter.h10
-rw-r--r--contrib/llvm/include/llvm/Support/Signals.h20
-rw-r--r--contrib/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h (renamed from contrib/llvm/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h)23
-rw-r--r--contrib/llvm/include/llvm/Support/SourceMgr.h37
-rw-r--r--contrib/llvm/include/llvm/Support/StringSaver.h28
-rw-r--r--contrib/llvm/include/llvm/Support/SystemUtils.h2
-rw-r--r--contrib/llvm/include/llvm/Support/TargetOpcodes.def (renamed from contrib/llvm/include/llvm/CodeGen/TargetOpcodes.def)31
-rw-r--r--contrib/llvm/include/llvm/Support/TargetParser.h15
-rw-r--r--contrib/llvm/include/llvm/Support/TargetRegistry.h93
-rw-r--r--contrib/llvm/include/llvm/Support/TaskQueue.h139
-rw-r--r--contrib/llvm/include/llvm/Support/ThreadLocal.h2
-rw-r--r--contrib/llvm/include/llvm/Support/ThreadPool.h1
-rw-r--r--contrib/llvm/include/llvm/Support/Threading.h12
-rw-r--r--contrib/llvm/include/llvm/Support/Timer.h8
-rw-r--r--contrib/llvm/include/llvm/Support/ToolOutputFile.h4
-rw-r--r--contrib/llvm/include/llvm/Support/TrailingObjects.h16
-rw-r--r--contrib/llvm/include/llvm/Support/Unicode.h4
-rw-r--r--contrib/llvm/include/llvm/Support/UnicodeCharRanges.h26
-rw-r--r--contrib/llvm/include/llvm/Support/UniqueLock.h2
-rw-r--r--contrib/llvm/include/llvm/Support/VersionTuple.h154
-rw-r--r--contrib/llvm/include/llvm/Support/Win64EH.h14
-rw-r--r--contrib/llvm/include/llvm/Support/WithColor.h67
-rw-r--r--contrib/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h475
-rw-r--r--contrib/llvm/include/llvm/Support/X86TargetParser.def2
-rw-r--r--contrib/llvm/include/llvm/Support/YAMLParser.h80
-rw-r--r--contrib/llvm/include/llvm/Support/YAMLTraits.h18
-rw-r--r--contrib/llvm/include/llvm/Support/raw_ostream.h23
-rw-r--r--contrib/llvm/include/llvm/Support/type_traits.h47
-rw-r--r--contrib/llvm/include/llvm/TableGen/Record.h632
-rw-r--r--contrib/llvm/include/llvm/TableGen/SearchableTable.td131
-rw-r--r--contrib/llvm/include/llvm/Target/CodeGenCWrappers.h (renamed from contrib/llvm/include/llvm/Support/CodeGenCWrappers.h)9
-rw-r--r--contrib/llvm/include/llvm/Target/GenericOpcodes.td27
-rw-r--r--contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td21
-rw-r--r--contrib/llvm/include/llvm/Target/GlobalISel/Target.td13
-rw-r--r--contrib/llvm/include/llvm/Target/Target.td51
-rw-r--r--contrib/llvm/include/llvm/Target/TargetInstrPredicate.td197
-rw-r--r--contrib/llvm/include/llvm/Target/TargetItinerary.td6
-rw-r--r--contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h (renamed from contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFile.h)16
-rw-r--r--contrib/llvm/include/llvm/Target/TargetMachine.h50
-rw-r--r--contrib/llvm/include/llvm/Target/TargetOptions.h28
-rw-r--r--contrib/llvm/include/llvm/Target/TargetSchedule.td138
-rw-r--r--contrib/llvm/include/llvm/Target/TargetSelectionDAG.td42
-rw-r--r--contrib/llvm/include/llvm/Testing/Support/Error.h64
-rw-r--r--contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h20
-rw-r--r--contrib/llvm/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h41
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO.h23
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h8
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h4
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h38
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO/Inliner.h5
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h6
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO/SampleProfile.h (renamed from contrib/llvm/include/llvm/Transforms/SampleProfile.h)6
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO/SyntheticCountsPropagation.h19
-rw-r--r--contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h8
-rw-r--r--contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h19
-rw-r--r--contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h5
-rw-r--r--contrib/llvm/include/llvm/Transforms/Instrumentation.h7
-rw-r--r--contrib/llvm/include/llvm/Transforms/Instrumentation/CGProfile.h31
-rw-r--r--contrib/llvm/include/llvm/Transforms/Instrumentation/GCOVProfiler.h (renamed from contrib/llvm/include/llvm/Transforms/GCOVProfiler.h)2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h (renamed from contrib/llvm/include/llvm/Transforms/InstrProfiling.h)5
-rw-r--r--contrib/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h (renamed from contrib/llvm/include/llvm/Transforms/PGOInstrumentation.h)2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar.h141
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h6
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h10
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h4
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/GVN.h10
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h31
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/InstSimplifyPass.h46
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h6
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h10
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h35
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h13
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h5
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/SROA.h16
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h31
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h4
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils.h118
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h6
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h48
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/Cloning.h13
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h26
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h13
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h12
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/Local.h134
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/LoopRotationUtils.h40
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h2
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h65
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h44
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h8
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h11
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h14
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h4
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h30
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h92
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h10
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/SimplifyInstructions.h31
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h19
-rw-r--r--contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h45
-rw-r--r--contrib/llvm/include/llvm/Transforms/Vectorize.h54
-rw-r--r--contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h482
-rw-r--r--contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h8
-rw-r--r--contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h18
-rw-r--r--contrib/llvm/include/llvm/XRay/XRayRecord.h3
-rw-r--r--contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h2
-rw-r--r--contrib/llvm/include/llvm/module.modulemap24
723 files changed, 31562 insertions, 12665 deletions
diff --git a/contrib/llvm/include/llvm-c/Comdat.h b/contrib/llvm/include/llvm-c/Comdat.h
new file mode 100644
index 000000000000..499996d68a53
--- /dev/null
+++ b/contrib/llvm/include/llvm-c/Comdat.h
@@ -0,0 +1,75 @@
+/*===-- llvm-c/Comdat.h - Module Comdat C Interface -------------*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This file defines the C interface to COMDAT. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_COMDAT_H
+#define LLVM_C_COMDAT_H
+
+#include "llvm-c/Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ LLVMAnyComdatSelectionKind, ///< The linker may choose any COMDAT.
+ LLVMExactMatchComdatSelectionKind, ///< The data referenced by the COMDAT must
+ ///< be the same.
+ LLVMLargestComdatSelectionKind, ///< The linker will choose the largest
+ ///< COMDAT.
+ LLVMNoDuplicatesComdatSelectionKind, ///< No other Module may specify this
+ ///< COMDAT.
+ LLVMSameSizeComdatSelectionKind ///< The data referenced by the COMDAT must be
+ ///< the same size.
+} LLVMComdatSelectionKind;
+
+/**
+ * Return the Comdat in the module with the specified name. It is created
+ * if it didn't already exist.
+ *
+ * @see llvm::Module::getOrInsertComdat()
+ */
+LLVMComdatRef LLVMGetOrInsertComdat(LLVMModuleRef M, const char *Name);
+
+/**
+ * Get the Comdat assigned to the given global object.
+ *
+ * @see llvm::GlobalObject::getComdat()
+ */
+LLVMComdatRef LLVMGetComdat(LLVMValueRef V);
+
+/**
+ * Assign the Comdat to the given global object.
+ *
+ * @see llvm::GlobalObject::setComdat()
+ */
+void LLVMSetComdat(LLVMValueRef V, LLVMComdatRef C);
+
+/*
+ * Get the conflict resolution selection kind for the Comdat.
+ *
+ * @see llvm::Comdat::getSelectionKind()
+ */
+LLVMComdatSelectionKind LLVMGetComdatSelectionKind(LLVMComdatRef C);
+
+/*
+ * Set the conflict resolution selection kind for the Comdat.
+ *
+ * @see llvm::Comdat::setSelectionKind()
+ */
+void LLVMSetComdatSelectionKind(LLVMComdatRef C, LLVMComdatSelectionKind Kind);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/llvm/include/llvm-c/Core.h b/contrib/llvm/include/llvm-c/Core.h
index 8238c09f9dd0..6792219f8730 100644
--- a/contrib/llvm/include/llvm-c/Core.h
+++ b/contrib/llvm/include/llvm-c/Core.h
@@ -187,19 +187,60 @@ typedef enum {
} LLVMVisibility;
typedef enum {
+ LLVMNoUnnamedAddr, /**< Address of the GV is significant. */
+ LLVMLocalUnnamedAddr, /**< Address of the GV is locally insignificant. */
+ LLVMGlobalUnnamedAddr /**< Address of the GV is globally insignificant. */
+} LLVMUnnamedAddr;
+
+typedef enum {
LLVMDefaultStorageClass = 0,
LLVMDLLImportStorageClass = 1, /**< Function to be imported from DLL. */
LLVMDLLExportStorageClass = 2 /**< Function to be accessible from DLL. */
} LLVMDLLStorageClass;
typedef enum {
- LLVMCCallConv = 0,
- LLVMFastCallConv = 8,
- LLVMColdCallConv = 9,
- LLVMWebKitJSCallConv = 12,
- LLVMAnyRegCallConv = 13,
- LLVMX86StdcallCallConv = 64,
- LLVMX86FastcallCallConv = 65
+ LLVMCCallConv = 0,
+ LLVMFastCallConv = 8,
+ LLVMColdCallConv = 9,
+ LLVMGHCCallConv = 10,
+ LLVMHiPECallConv = 11,
+ LLVMWebKitJSCallConv = 12,
+ LLVMAnyRegCallConv = 13,
+ LLVMPreserveMostCallConv = 14,
+ LLVMPreserveAllCallConv = 15,
+ LLVMSwiftCallConv = 16,
+ LLVMCXXFASTTLSCallConv = 17,
+ LLVMX86StdcallCallConv = 64,
+ LLVMX86FastcallCallConv = 65,
+ LLVMARMAPCSCallConv = 66,
+ LLVMARMAAPCSCallConv = 67,
+ LLVMARMAAPCSVFPCallConv = 68,
+ LLVMMSP430INTRCallConv = 69,
+ LLVMX86ThisCallCallConv = 70,
+ LLVMPTXKernelCallConv = 71,
+ LLVMPTXDeviceCallConv = 72,
+ LLVMSPIRFUNCCallConv = 75,
+ LLVMSPIRKERNELCallConv = 76,
+ LLVMIntelOCLBICallConv = 77,
+ LLVMX8664SysVCallConv = 78,
+ LLVMWin64CallConv = 79,
+ LLVMX86VectorCallCallConv = 80,
+ LLVMHHVMCallConv = 81,
+ LLVMHHVMCCallConv = 82,
+ LLVMX86INTRCallConv = 83,
+ LLVMAVRINTRCallConv = 84,
+ LLVMAVRSIGNALCallConv = 85,
+ LLVMAVRBUILTINCallConv = 86,
+ LLVMAMDGPUVSCallConv = 87,
+ LLVMAMDGPUGSCallConv = 88,
+ LLVMAMDGPUPSCallConv = 89,
+ LLVMAMDGPUCSCallConv = 90,
+ LLVMAMDGPUKERNELCallConv = 91,
+ LLVMX86RegCallCallConv = 92,
+ LLVMAMDGPUHSCallConv = 93,
+ LLVMMSP430BUILTINCallConv = 94,
+ LLVMAMDGPULSCallConv = 95,
+ LLVMAMDGPUESCallConv = 96
} LLVMCallConv;
typedef enum {
@@ -335,6 +376,62 @@ typedef enum {
LLVMDSNote
} LLVMDiagnosticSeverity;
+typedef enum {
+ LLVMInlineAsmDialectATT,
+ LLVMInlineAsmDialectIntel
+} LLVMInlineAsmDialect;
+
+typedef enum {
+ /**
+ * Emits an error if two values disagree, otherwise the resulting value is
+ * that of the operands.
+ *
+ * @see Module::ModFlagBehavior::Error
+ */
+ LLVMModuleFlagBehaviorError,
+ /**
+ * Emits a warning if two values disagree. The result value will be the
+ * operand for the flag from the first module being linked.
+ *
+ * @see Module::ModFlagBehavior::Warning
+ */
+ LLVMModuleFlagBehaviorWarning,
+ /**
+ * Adds a requirement that another module flag be present and have a
+ * specified value after linking is performed. The value must be a metadata
+ * pair, where the first element of the pair is the ID of the module flag
+ * to be restricted, and the second element of the pair is the value the
+ * module flag should be restricted to. This behavior can be used to
+ * restrict the allowable results (via triggering of an error) of linking
+ * IDs with the **Override** behavior.
+ *
+ * @see Module::ModFlagBehavior::Require
+ */
+ LLVMModuleFlagBehaviorRequire,
+ /**
+ * Uses the specified value, regardless of the behavior or value of the
+ * other module. If both modules specify **Override**, but the values
+ * differ, an error will be emitted.
+ *
+ * @see Module::ModFlagBehavior::Override
+ */
+ LLVMModuleFlagBehaviorOverride,
+ /**
+ * Appends the two values, which are required to be metadata nodes.
+ *
+ * @see Module::ModFlagBehavior::Append
+ */
+ LLVMModuleFlagBehaviorAppend,
+ /**
+ * Appends the two values, which are required to be metadata
+ * nodes. However, duplicate entries in the second list are dropped
+ * during the append operation.
+ *
+ * @see Module::ModFlagBehavior::AppendUnique
+ */
+ LLVMModuleFlagBehaviorAppendUnique,
+} LLVMModuleFlagBehavior;
+
/**
* Attribute index are either LLVMAttributeReturnIndex,
* LLVMAttributeFunctionIndex or a parameter number from 1 to N.
@@ -566,6 +663,27 @@ const char *LLVMGetModuleIdentifier(LLVMModuleRef M, size_t *Len);
void LLVMSetModuleIdentifier(LLVMModuleRef M, const char *Ident, size_t Len);
/**
+ * Obtain the module's original source file name.
+ *
+ * @param M Module to obtain the name of
+ * @param Len Out parameter which holds the length of the returned string
+ * @return The original source file name of M
+ * @see Module::getSourceFileName()
+ */
+const char *LLVMGetSourceFileName(LLVMModuleRef M, size_t *Len);
+
+/**
+ * Set the original source file name of a module to a string Name with length
+ * Len.
+ *
+ * @param M The module to set the source file name of
+ * @param Name The string to set M's source file name to
+ * @param Len Length of Name
+ * @see Module::setSourceFileName()
+ */
+void LLVMSetSourceFileName(LLVMModuleRef M, const char *Name, size_t Len);
+
+/**
* Obtain the data layout for a module.
*
* @see Module::getDataLayoutStr()
@@ -599,6 +717,64 @@ const char *LLVMGetTarget(LLVMModuleRef M);
void LLVMSetTarget(LLVMModuleRef M, const char *Triple);
/**
+ * Returns the module flags as an array of flag-key-value triples. The caller
+ * is responsible for freeing this array by calling
+ * \c LLVMDisposeModuleFlagsMetadata.
+ *
+ * @see Module::getModuleFlagsMetadata()
+ */
+LLVMModuleFlagEntry *LLVMCopyModuleFlagsMetadata(LLVMModuleRef M, size_t *Len);
+
+/**
+ * Destroys module flags metadata entries.
+ */
+void LLVMDisposeModuleFlagsMetadata(LLVMModuleFlagEntry *Entries);
+
+/**
+ * Returns the flag behavior for a module flag entry at a specific index.
+ *
+ * @see Module::ModuleFlagEntry::Behavior
+ */
+LLVMModuleFlagBehavior
+LLVMModuleFlagEntriesGetFlagBehavior(LLVMModuleFlagEntry *Entries,
+ unsigned Index);
+
+/**
+ * Returns the key for a module flag entry at a specific index.
+ *
+ * @see Module::ModuleFlagEntry::Key
+ */
+const char *LLVMModuleFlagEntriesGetKey(LLVMModuleFlagEntry *Entries,
+ unsigned Index, size_t *Len);
+
+/**
+ * Returns the metadata for a module flag entry at a specific index.
+ *
+ * @see Module::ModuleFlagEntry::Val
+ */
+LLVMMetadataRef LLVMModuleFlagEntriesGetMetadata(LLVMModuleFlagEntry *Entries,
+ unsigned Index);
+
+/**
+ * Add a module-level flag to the module-level flags metadata if it doesn't
+ * already exist.
+ *
+ * @see Module::getModuleFlag()
+ */
+LLVMMetadataRef LLVMGetModuleFlag(LLVMModuleRef M,
+ const char *Key, size_t KeyLen);
+
+/**
+ * Add a module-level flag to the module-level flags metadata if it doesn't
+ * already exist.
+ *
+ * @see Module::addModuleFlag()
+ */
+void LLVMAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior,
+ const char *Key, size_t KeyLen,
+ LLVMMetadataRef Val);
+
+/**
* Dump a representation of a module to stderr.
*
* @see Module::dump()
@@ -623,11 +799,36 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,
char *LLVMPrintModuleToString(LLVMModuleRef M);
/**
+ * Get inline assembly for a module.
+ *
+ * @see Module::getModuleInlineAsm()
+ */
+const char *LLVMGetModuleInlineAsm(LLVMModuleRef M, size_t *Len);
+
+/**
* Set inline assembly for a module.
*
* @see Module::setModuleInlineAsm()
*/
-void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm);
+void LLVMSetModuleInlineAsm2(LLVMModuleRef M, const char *Asm, size_t Len);
+
+/**
+ * Append inline assembly to a module.
+ *
+ * @see Module::appendModuleInlineAsm()
+ */
+void LLVMAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, size_t Len);
+
+/**
+ * Create the specified uniqued inline asm string.
+ *
+ * @see InlineAsm::get()
+ */
+LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty,
+ char *AsmString, size_t AsmStringSize,
+ char *Constraints, size_t ConstraintsSize,
+ LLVMBool HasSideEffects, LLVMBool IsAlignStack,
+ LLVMInlineAsmDialect Dialect);
/**
* Obtain the context to which this module is associated.
@@ -718,6 +919,9 @@ LLVMValueRef LLVMGetNextFunction(LLVMValueRef Fn);
*/
LLVMValueRef LLVMGetPreviousFunction(LLVMValueRef Fn);
+/** Deprecated: Use LLVMSetModuleInlineAsm2 instead. */
+void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm);
+
/**
* @}
*/
@@ -1292,14 +1496,14 @@ LLVMValueKind LLVMGetValueKind(LLVMValueRef Val);
*
* @see llvm::Value::getName()
*/
-const char *LLVMGetValueName(LLVMValueRef Val);
+const char *LLVMGetValueName2(LLVMValueRef Val, size_t *Length);
/**
* Set the string name of a value.
*
* @see llvm::Value::setName()
*/
-void LLVMSetValueName(LLVMValueRef Val, const char *Name);
+void LLVMSetValueName2(LLVMValueRef Val, const char *Name, size_t NameLen);
/**
* Dump a representation of a value to stderr.
@@ -1351,6 +1555,11 @@ LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST)
LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val);
LLVMValueRef LLVMIsAMDString(LLVMValueRef Val);
+/** Deprecated: Use LLVMGetValueName2 instead. */
+const char *LLVMGetValueName(LLVMValueRef Val);
+/** Deprecated: Use LLVMSetValueName2 instead. */
+void LLVMSetValueName(LLVMValueRef Val, const char *Name);
+
/**
* @}
*/
@@ -1793,10 +2002,12 @@ LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList,
LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant,
LLVMValueRef ElementValueConstant,
unsigned *IdxList, unsigned NumIdx);
+LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB);
+
+/** Deprecated: Use LLVMGetInlineAsm instead. */
LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty,
const char *AsmString, const char *Constraints,
LLVMBool HasSideEffects, LLVMBool IsAlignStack);
-LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB);
/**
* @}
@@ -1823,7 +2034,12 @@ LLVMVisibility LLVMGetVisibility(LLVMValueRef Global);
void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz);
LLVMDLLStorageClass LLVMGetDLLStorageClass(LLVMValueRef Global);
void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class);
+LLVMUnnamedAddr LLVMGetUnnamedAddress(LLVMValueRef Global);
+void LLVMSetUnnamedAddress(LLVMValueRef Global, LLVMUnnamedAddr UnnamedAddr);
+
+/** Deprecated: Use LLVMGetUnnamedAddress instead. */
LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global);
+/** Deprecated: Use LLVMSetUnnamedAddress instead. */
void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr);
/**
@@ -1902,6 +2118,56 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee,
const char *Name);
/**
+ * Obtain a GlobalAlias value from a Module by its name.
+ *
+ * The returned value corresponds to a llvm::GlobalAlias value.
+ *
+ * @see llvm::Module::getNamedAlias()
+ */
+LLVMValueRef LLVMGetNamedGlobalAlias(LLVMModuleRef M,
+ const char *Name, size_t NameLen);
+
+/**
+ * Obtain an iterator to the first GlobalAlias in a Module.
+ *
+ * @see llvm::Module::alias_begin()
+ */
+LLVMValueRef LLVMGetFirstGlobalAlias(LLVMModuleRef M);
+
+/**
+ * Obtain an iterator to the last GlobalAlias in a Module.
+ *
+ * @see llvm::Module::alias_end()
+ */
+LLVMValueRef LLVMGetLastGlobalAlias(LLVMModuleRef M);
+
+/**
+ * Advance a GlobalAlias iterator to the next GlobalAlias.
+ *
+ * Returns NULL if the iterator was already at the end and there are no more
+ * global aliases.
+ */
+LLVMValueRef LLVMGetNextGlobalAlias(LLVMValueRef GA);
+
+/**
+ * Decrement a GlobalAlias iterator to the previous GlobalAlias.
+ *
+ * Returns NULL if the iterator was already at the beginning and there are
+ * no previous global aliases.
+ */
+LLVMValueRef LLVMGetPreviousGlobalAlias(LLVMValueRef GA);
+
+/**
+ * Retrieve the target value of an alias.
+ */
+LLVMValueRef LLVMAliasGetAliasee(LLVMValueRef Alias);
+
+/**
+ * Set the target value of an alias.
+ */
+void LLVMAliasSetAliasee(LLVMValueRef Alias, LLVMValueRef Aliasee);
+
+/**
* @}
*/
@@ -2523,11 +2789,12 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
/**
* Obtain the argument count for a call instruction.
*
- * This expects an LLVMValueRef that corresponds to a llvm::CallInst or
- * llvm::InvokeInst.
+ * This expects an LLVMValueRef that corresponds to a llvm::CallInst,
+ * llvm::InvokeInst, or llvm:FuncletPadInst.
*
* @see llvm::CallInst::getNumArgOperands()
* @see llvm::InvokeInst::getNumArgOperands()
+ * @see llvm::FuncletPadInst::getNumArgOperands()
*/
unsigned LLVMGetNumArgOperands(LLVMValueRef Instr);
@@ -2612,9 +2879,12 @@ LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef InvokeInst);
/**
* Return the unwind destination basic block.
*
- * This only works on llvm::InvokeInst instructions.
+ * Works on llvm::InvokeInst, llvm::CleanupReturnInst, and
+ * llvm::CatchSwitchInst instructions.
*
* @see llvm::InvokeInst::getUnwindDest()
+ * @see llvm::CleanupReturnInst::getUnwindDest()
+ * @see llvm::CatchSwitchInst::getUnwindDest()
*/
LLVMBasicBlockRef LLVMGetUnwindDest(LLVMValueRef InvokeInst);
@@ -2630,9 +2900,12 @@ void LLVMSetNormalDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
/**
* Set the unwind destination basic block.
*
- * This only works on llvm::InvokeInst instructions.
+ * Works on llvm::InvokeInst, llvm::CleanupReturnInst, and
+ * llvm::CatchSwitchInst instructions.
*
* @see llvm::InvokeInst::setUnwindDest()
+ * @see llvm::CleanupReturnInst::setUnwindDest()
+ * @see llvm::CatchSwitchInst::setUnwindDest()
*/
void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
@@ -2861,11 +3134,26 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name);
+LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
+
+/* Exception Handling */
+LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn);
LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef PersFn, unsigned NumClauses,
const char *Name);
-LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn);
-LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
+LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
+ LLVMBasicBlockRef BB);
+LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
+ LLVMBasicBlockRef BB);
+LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
+ LLVMValueRef *Args, unsigned NumArgs,
+ const char *Name);
+LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
+ LLVMValueRef *Args, unsigned NumArgs,
+ const char *Name);
+LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad,
+ LLVMBasicBlockRef UnwindBB,
+ unsigned NumHandlers, const char *Name);
/* Add a case to the switch instruction */
void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal,
@@ -2889,6 +3177,51 @@ LLVMBool LLVMIsCleanup(LLVMValueRef LandingPad);
/* Set the 'cleanup' flag in the landingpad instruction */
void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val);
+/* Add a destination to the catchswitch instruction */
+void LLVMAddHandler(LLVMValueRef CatchSwitch, LLVMBasicBlockRef Dest);
+
+/* Get the number of handlers on the catchswitch instruction */
+unsigned LLVMGetNumHandlers(LLVMValueRef CatchSwitch);
+
+/**
+ * Obtain the basic blocks acting as handlers for a catchswitch instruction.
+ *
+ * The Handlers parameter should point to a pre-allocated array of
+ * LLVMBasicBlockRefs at least LLVMGetNumHandlers() large. On return, the
+ * first LLVMGetNumHandlers() entries in the array will be populated
+ * with LLVMBasicBlockRef instances.
+ *
+ * @param CatchSwitch The catchswitch instruction to operate on.
+ * @param Handlers Memory address of an array to be filled with basic blocks.
+ */
+void LLVMGetHandlers(LLVMValueRef CatchSwitch, LLVMBasicBlockRef *Handlers);
+
+/* Funclets */
+
+/* Get the number of funcletpad arguments. */
+LLVMValueRef LLVMGetArgOperand(LLVMValueRef Funclet, unsigned i);
+
+/* Set a funcletpad argument at the given index. */
+void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value);
+
+/**
+ * Get the parent catchswitch instruction of a catchpad instruction.
+ *
+ * This only works on llvm::CatchPadInst instructions.
+ *
+ * @see llvm::CatchPadInst::getCatchSwitch()
+ */
+LLVMValueRef LLVMGetParentCatchSwitch(LLVMValueRef CatchPad);
+
+/**
+ * Set the parent catchswitch instruction of a catchpad instruction.
+ *
+ * This only works on llvm::CatchPadInst instructions.
+ *
+ * @see llvm::CatchPadInst::setCatchSwitch()
+ */
+void LLVMSetParentCatchSwitch(LLVMValueRef CatchPad, LLVMValueRef CatchSwitch);
+
/* Arithmetic */
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS,
const char *Name);
@@ -3186,7 +3519,7 @@ LLVMBool LLVMInitializeFunctionPassManager(LLVMPassManagerRef FPM);
@see llvm::FunctionPassManager::run(Function&) */
LLVMBool LLVMRunFunctionPassManager(LLVMPassManagerRef FPM, LLVMValueRef F);
-/** Finalizes all of the function passes scheduled in in the function pass
+/** Finalizes all of the function passes scheduled in the function pass
manager. Returns 1 if any of the passes modified the module, 0 otherwise.
@see llvm::FunctionPassManager::doFinalization */
LLVMBool LLVMFinalizeFunctionPassManager(LLVMPassManagerRef FPM);
diff --git a/contrib/llvm/include/llvm-c/DataTypes.h b/contrib/llvm/include/llvm-c/DataTypes.h
new file mode 100644
index 000000000000..7081c83ffc2b
--- /dev/null
+++ b/contrib/llvm/include/llvm-c/DataTypes.h
@@ -0,0 +1,90 @@
+/*===-- include/llvm-c/DataTypes.h - Define fixed size types ------*- C -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This file contains definitions to figure out the size of _HOST_ data types.*|
+|* This file is important because different host OS's define different macros,*|
+|* which makes portability tough. This file exports the following *|
+|* definitions: *|
+|* *|
+|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*|
+|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *|
+|* *|
+|* No library is required when using these functions. *|
+|* *|
+|*===----------------------------------------------------------------------===*/
+
+/* Please leave this file C-compatible. */
+
+#ifndef LLVM_C_DATATYPES_H
+#define LLVM_C_DATATYPES_H
+
+#ifdef __cplusplus
+#include <cmath>
+#else
+#include <math.h>
+#endif
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#ifndef _MSC_VER
+
+#if !defined(UINT32_MAX)
+# error "The standard header <cstdint> is not C++11 compliant. Must #define "\
+ "__STDC_LIMIT_MACROS before #including llvm-c/DataTypes.h"
+#endif
+
+#if !defined(UINT32_C)
+# error "The standard header <cstdint> is not C++11 compliant. Must #define "\
+ "__STDC_CONSTANT_MACROS before #including llvm-c/DataTypes.h"
+#endif
+
+/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */
+#include <sys/types.h>
+
+#ifdef _AIX
+// GCC is strict about defining large constants: they must have LL modifier.
+#undef INT64_MAX
+#undef INT64_MIN
+#endif
+
+#else /* _MSC_VER */
+#ifdef __cplusplus
+#include <cstddef>
+#include <cstdlib>
+#else
+#include <stddef.h>
+#include <stdlib.h>
+#endif
+#include <sys/types.h>
+
+#if defined(_WIN64)
+typedef signed __int64 ssize_t;
+#else
+typedef signed int ssize_t;
+#endif /* _WIN64 */
+
+#endif /* _MSC_VER */
+
+/* Set defaults for constants which we cannot find. */
+#if !defined(INT64_MAX)
+# define INT64_MAX 9223372036854775807LL
+#endif
+#if !defined(INT64_MIN)
+# define INT64_MIN ((-INT64_MAX)-1)
+#endif
+#if !defined(UINT64_MAX)
+# define UINT64_MAX 0xffffffffffffffffULL
+#endif
+
+#ifndef HUGE_VALF
+#define HUGE_VALF (float)HUGE_VAL
+#endif
+
+#endif /* LLVM_C_DATATYPES_H */
diff --git a/contrib/llvm/include/llvm-c/DebugInfo.h b/contrib/llvm/include/llvm-c/DebugInfo.h
index d17c690be4da..cee6755f1874 100644
--- a/contrib/llvm/include/llvm-c/DebugInfo.h
+++ b/contrib/llvm/include/llvm-c/DebugInfo.h
@@ -52,6 +52,11 @@ typedef enum {
LLVMDIFlagBitField = 1 << 19,
LLVMDIFlagNoReturn = 1 << 20,
LLVMDIFlagMainSubprogram = 1 << 21,
+ LLVMDIFlagTypePassByValue = 1 << 22,
+ LLVMDIFlagTypePassByReference = 1 << 23,
+ LLVMDIFlagFixedEnum = 1 << 24,
+ LLVMDIFlagThunk = 1 << 25,
+ LLVMDIFlagTrivial = 1 << 26,
LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5),
LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected |
LLVMDIFlagPublic,
@@ -120,6 +125,11 @@ typedef enum {
} LLVMDWARFEmissionKind;
/**
+ * An LLVM DWARF type encoding.
+ */
+typedef unsigned LLVMDWARFTypeEncoding;
+
+/**
* The current debug metadata version number.
*/
unsigned LLVMDebugMetadataVersion(void);
@@ -211,6 +221,158 @@ LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename,
size_t DirectoryLen);
/**
+ * Creates a new descriptor for a module with the specified parent scope.
+ * \param Builder The \c DIBuilder.
+ * \param ParentScope The parent scope containing this module declaration.
+ * \param Name Module name.
+ * \param NameLen The length of the C string passed to \c Name.
+ * \param ConfigMacros A space-separated shell-quoted list of -D macro
+ definitions as they would appear on a command line.
+ * \param ConfigMacrosLen The length of the C string passed to \c ConfigMacros.
+ * \param IncludePath The path to the module map file.
+ * \param IncludePathLen The length of the C string passed to \c IncludePath.
+ * \param ISysRoot The Clang system root (value of -isysroot).
+ * \param ISysRootLen The length of the C string passed to \c ISysRoot.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateModule(LLVMDIBuilderRef Builder, LLVMMetadataRef ParentScope,
+ const char *Name, size_t NameLen,
+ const char *ConfigMacros, size_t ConfigMacrosLen,
+ const char *IncludePath, size_t IncludePathLen,
+ const char *ISysRoot, size_t ISysRootLen);
+
+/**
+ * Creates a new descriptor for a namespace with the specified parent scope.
+ * \param Builder The \c DIBuilder.
+ * \param ParentScope The parent scope containing this module declaration.
+ * \param Name NameSpace name.
+ * \param NameLen The length of the C string passed to \c Name.
+ * \param ExportSymbols Whether or not the namespace exports symbols, e.g.
+ * this is true of C++ inline namespaces.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateNameSpace(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef ParentScope,
+ const char *Name, size_t NameLen,
+ LLVMBool ExportSymbols);
+
+/**
+ * Create a new descriptor for the specified subprogram.
+ * \param Builder The \c DIBuilder.
+ * \param Scope Function scope.
+ * \param Name Function name.
+ * \param NameLen Length of enumeration name.
+ * \param LinkageName Mangled function name.
+ * \param LinkageNameLen Length of linkage name.
+ * \param File File where this variable is defined.
+ * \param LineNo Line number.
+ * \param Ty Function type.
+ * \param IsLocalToUnit True if this function is not externally visible.
+ * \param IsDefinition True if this is a function definition.
+ * \param ScopeLine Set to the beginning of the scope this starts
+ * \param Flags E.g.: \c LLVMDIFlagLValueReference. These flags are
+ * used to emit dwarf attributes.
+ * \param IsOptimized True if optimization is ON.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateFunction(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
+ LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
+ LLVMBool IsLocalToUnit, LLVMBool IsDefinition,
+ unsigned ScopeLine, LLVMDIFlags Flags, LLVMBool IsOptimized);
+
+/**
+ * Create a descriptor for a lexical block with the specified parent context.
+ * \param Builder The \c DIBuilder.
+ * \param Scope Parent lexical block.
+ * \param File Source file.
+ * \param Line The line in the source file.
+ * \param Column The column in the source file.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope,
+ LLVMMetadataRef File, unsigned Line, unsigned Column);
+
+/**
+ * Create a descriptor for a lexical block with a new file attached.
+ * \param Builder The \c DIBuilder.
+ * \param Scope Lexical block.
+ * \param File Source file.
+ * \param Discriminator DWARF path discriminator value.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef File,
+ unsigned Discriminator);
+
+/**
+ * Create a descriptor for an imported namespace. Suitable for e.g. C++
+ * using declarations.
+ * \param Builder The \c DIBuilder.
+ * \param Scope The scope this module is imported into
+ * \param File File where the declaration is located.
+ * \param Line Line number of the declaration.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateImportedModuleFromNamespace(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef NS,
+ LLVMMetadataRef File,
+ unsigned Line);
+
+/**
+ * Create a descriptor for an imported module that aliases another
+ * imported entity descriptor.
+ * \param Builder The \c DIBuilder.
+ * \param Scope The scope this module is imported into
+ * \param ImportedEntity Previous imported entity to alias.
+ * \param File File where the declaration is located.
+ * \param Line Line number of the declaration.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateImportedModuleFromAlias(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef ImportedEntity,
+ LLVMMetadataRef File,
+ unsigned Line);
+
+/**
+ * Create a descriptor for an imported module.
+ * \param Builder The \c DIBuilder.
+ * \param Scope The scope this module is imported into
+ * \param M The module being imported here
+ * \param File File where the declaration is located.
+ * \param Line Line number of the declaration.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateImportedModuleFromModule(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef M,
+ LLVMMetadataRef File,
+ unsigned Line);
+
+/**
+ * Create a descriptor for an imported function, type, or variable. Suitable
+ * for e.g. FORTRAN-style USE declarations.
+ * \param Builder The DIBuilder.
+ * \param Scope The scope this module is imported into.
+ * \param Decl The declaration (or definition) of a function, type,
+ or variable.
+ * \param File File where the declaration is located.
+ * \param Line Line number of the declaration.
+ * \param Name A name that uniquely identifies this imported declaration.
+ * \param NameLen The length of the C string passed to \c Name.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateImportedDeclaration(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef Decl,
+ LLVMMetadataRef File,
+ unsigned Line,
+ const char *Name, size_t NameLen);
+
+/**
* Creates a new DebugLocation that describes a source location.
* \param Line The line in the source file.
* \param Column The column in the source file.
@@ -225,6 +387,768 @@ LLVMDIBuilderCreateDebugLocation(LLVMContextRef Ctx, unsigned Line,
unsigned Column, LLVMMetadataRef Scope,
LLVMMetadataRef InlinedAt);
+/**
+ * Get the line number of this debug location.
+ * \param Location The debug location.
+ *
+ * @see DILocation::getLine()
+ */
+unsigned LLVMDILocationGetLine(LLVMMetadataRef Location);
+
+/**
+ * Get the column number of this debug location.
+ * \param Location The debug location.
+ *
+ * @see DILocation::getColumn()
+ */
+unsigned LLVMDILocationGetColumn(LLVMMetadataRef Location);
+
+/**
+ * Get the local scope associated with this debug location.
+ * \param Location The debug location.
+ *
+ * @see DILocation::getScope()
+ */
+LLVMMetadataRef LLVMDILocationGetScope(LLVMMetadataRef Location);
+
+/**
+ * Create a type array.
+ * \param Builder The DIBuilder.
+ * \param Data The type elements.
+ * \param NumElements Number of type elements.
+ */
+LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef *Data,
+ size_t NumElements);
+
+/**
+ * Create subroutine type.
+ * \param Builder The DIBuilder.
+ * \param File The file in which the subroutine resides.
+ * \param ParameterTypes An array of subroutine parameter types. This
+ * includes return type at 0th index.
+ * \param NumParameterTypes The number of parameter types in \c ParameterTypes
+ * \param Flags E.g.: \c LLVMDIFlagLValueReference.
+ * These flags are used to emit dwarf attributes.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef File,
+ LLVMMetadataRef *ParameterTypes,
+ unsigned NumParameterTypes,
+ LLVMDIFlags Flags);
+
+/**
+ * Create debugging information entry for an enumeration.
+ * \param Builder The DIBuilder.
+ * \param Scope Scope in which this enumeration is defined.
+ * \param Name Enumeration name.
+ * \param NameLen Length of enumeration name.
+ * \param File File where this member is defined.
+ * \param LineNumber Line number.
+ * \param SizeInBits Member size.
+ * \param AlignInBits Member alignment.
+ * \param Elements Enumeration elements.
+ * \param NumElements Number of enumeration elements.
+ * \param ClassTy Underlying type of a C++11/ObjC fixed enum.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef *Elements,
+ unsigned NumElements, LLVMMetadataRef ClassTy);
+
+/**
+ * Create debugging information entry for a union.
+ * \param Builder The DIBuilder.
+ * \param Scope Scope in which this union is defined.
+ * \param Name Union name.
+ * \param NameLen Length of union name.
+ * \param File File where this member is defined.
+ * \param LineNumber Line number.
+ * \param SizeInBits Member size.
+ * \param AlignInBits Member alignment.
+ * \param Flags Flags to encode member attribute, e.g. private
+ * \param Elements Union elements.
+ * \param NumElements Number of union elements.
+ * \param RunTimeLang Optional parameter, Objective-C runtime version.
+ * \param UniqueId A unique identifier for the union.
+ * \param UniqueIdLen Length of unique identifier.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateUnionType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef *Elements, unsigned NumElements, unsigned RunTimeLang,
+ const char *UniqueId, size_t UniqueIdLen);
+
+
+/**
+ * Create debugging information entry for an array.
+ * \param Builder The DIBuilder.
+ * \param Size Array size.
+ * \param AlignInBits Alignment.
+ * \param Ty Element type.
+ * \param Subscripts Subscripts.
+ * \param NumSubscripts Number of subscripts.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Builder, uint64_t Size,
+ uint32_t AlignInBits, LLVMMetadataRef Ty,
+ LLVMMetadataRef *Subscripts,
+ unsigned NumSubscripts);
+
+/**
+ * Create debugging information entry for a vector type.
+ * \param Builder The DIBuilder.
+ * \param Size Vector size.
+ * \param AlignInBits Alignment.
+ * \param Ty Element type.
+ * \param Subscripts Subscripts.
+ * \param NumSubscripts Number of subscripts.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size,
+ uint32_t AlignInBits, LLVMMetadataRef Ty,
+ LLVMMetadataRef *Subscripts,
+ unsigned NumSubscripts);
+
+/**
+ * Create a DWARF unspecified type.
+ * \param Builder The DIBuilder.
+ * \param Name The unspecified type's name.
+ * \param NameLen Length of type name.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateUnspecifiedType(LLVMDIBuilderRef Builder, const char *Name,
+ size_t NameLen);
+
+/**
+ * Create debugging information entry for a basic
+ * type.
+ * \param Builder The DIBuilder.
+ * \param Name Type name.
+ * \param NameLen Length of type name.
+ * \param SizeInBits Size of the type.
+ * \param Encoding DWARF encoding code, e.g. \c LLVMDWARFTypeEncoding_float.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name,
+ size_t NameLen, uint64_t SizeInBits,
+ LLVMDWARFTypeEncoding Encoding);
+
+/**
+ * Create debugging information entry for a pointer.
+ * \param Builder The DIBuilder.
+ * \param PointeeTy Type pointed by this pointer.
+ * \param SizeInBits Size.
+ * \param AlignInBits Alignment. (optional, pass 0 to ignore)
+ * \param AddressSpace DWARF address space. (optional, pass 0 to ignore)
+ * \param Name Pointer type name. (optional)
+ * \param NameLen Length of pointer type name. (optional)
+ */
+LLVMMetadataRef LLVMDIBuilderCreatePointerType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
+ uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
+ const char *Name, size_t NameLen);
+
+/**
+ * Create debugging information entry for a struct.
+ * \param Builder The DIBuilder.
+ * \param Scope Scope in which this struct is defined.
+ * \param Name Struct name.
+ * \param NameLen Struct name length.
+ * \param File File where this member is defined.
+ * \param LineNumber Line number.
+ * \param SizeInBits Member size.
+ * \param AlignInBits Member alignment.
+ * \param Flags Flags to encode member attribute, e.g. private
+ * \param Elements Struct elements.
+ * \param NumElements Number of struct elements.
+ * \param RunTimeLang Optional parameter, Objective-C runtime version.
+ * \param VTableHolder The object containing the vtable for the struct.
+ * \param UniqueId A unique identifier for the struct.
+ * \param UniqueIdLen Length of the unique identifier for the struct.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateStructType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef DerivedFrom, LLVMMetadataRef *Elements,
+ unsigned NumElements, unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
+ const char *UniqueId, size_t UniqueIdLen);
+
+/**
+ * Create debugging information entry for a member.
+ * \param Builder The DIBuilder.
+ * \param Scope Member scope.
+ * \param Name Member name.
+ * \param NameLen Length of member name.
+ * \param File File where this member is defined.
+ * \param LineNo Line number.
+ * \param SizeInBits Member size.
+ * \param AlignInBits Member alignment.
+ * \param OffsetInBits Member offset.
+ * \param Flags Flags to encode member attribute, e.g. private
+ * \param Ty Parent type.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateMemberType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
+ uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
+ LLVMDIFlags Flags, LLVMMetadataRef Ty);
+
+/**
+ * Create debugging information entry for a
+ * C++ static data member.
+ * \param Builder The DIBuilder.
+ * \param Scope Member scope.
+ * \param Name Member name.
+ * \param NameLen Length of member name.
+ * \param File File where this member is declared.
+ * \param LineNumber Line number.
+ * \param Type Type of the static member.
+ * \param Flags Flags to encode member attribute, e.g. private.
+ * \param ConstantVal Const initializer of the member.
+ * \param AlignInBits Member alignment.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateStaticMemberType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
+ LLVMMetadataRef Type, LLVMDIFlags Flags, LLVMValueRef ConstantVal,
+ uint32_t AlignInBits);
+
+/**
+ * Create debugging information entry for a pointer to member.
+ * \param Builder The DIBuilder.
+ * \param PointeeType Type pointed to by this pointer.
+ * \param ClassType Type for which this pointer points to members of.
+ * \param SizeInBits Size.
+ * \param AlignInBits Alignment.
+ * \param Flags Flags.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateMemberPointerType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef PointeeType,
+ LLVMMetadataRef ClassType,
+ uint64_t SizeInBits,
+ uint32_t AlignInBits,
+ LLVMDIFlags Flags);
+/**
+ * Create debugging information entry for Objective-C instance variable.
+ * \param Builder The DIBuilder.
+ * \param Name Member name.
+ * \param NameLen The length of the C string passed to \c Name.
+ * \param File File where this member is defined.
+ * \param LineNo Line number.
+ * \param SizeInBits Member size.
+ * \param AlignInBits Member alignment.
+ * \param OffsetInBits Member offset.
+ * \param Flags Flags to encode member attribute, e.g. private
+ * \param Ty Parent type.
+ * \param PropertyNode Property associated with this ivar.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateObjCIVar(LLVMDIBuilderRef Builder,
+ const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNo,
+ uint64_t SizeInBits, uint32_t AlignInBits,
+ uint64_t OffsetInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef Ty, LLVMMetadataRef PropertyNode);
+
+/**
+ * Create debugging information entry for Objective-C property.
+ * \param Builder The DIBuilder.
+ * \param Name Property name.
+ * \param NameLen The length of the C string passed to \c Name.
+ * \param File File where this property is defined.
+ * \param LineNo Line number.
+ * \param GetterName Name of the Objective C property getter selector.
+ * \param GetterNameLen The length of the C string passed to \c GetterName.
+ * \param SetterName Name of the Objective C property setter selector.
+ * \param SetterNameLen The length of the C string passed to \c SetterName.
+ * \param PropertyAttributes Objective C property attributes.
+ * \param Ty Type.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateObjCProperty(LLVMDIBuilderRef Builder,
+ const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNo,
+ const char *GetterName, size_t GetterNameLen,
+ const char *SetterName, size_t SetterNameLen,
+ unsigned PropertyAttributes,
+ LLVMMetadataRef Ty);
+
+/**
+ * Create a uniqued DIType* clone with FlagObjectPointer and FlagArtificial set.
+ * \param Builder The DIBuilder.
+ * \param Type The underlying type to which this pointer points.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateObjectPointerType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Type);
+
+/**
+ * Create debugging information entry for a qualified
+ * type, e.g. 'const int'.
+ * \param Builder The DIBuilder.
+ * \param Tag Tag identifying type,
+ * e.g. LLVMDWARFTypeQualifier_volatile_type
+ * \param Type Base Type.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateQualifiedType(LLVMDIBuilderRef Builder, unsigned Tag,
+ LLVMMetadataRef Type);
+
+/**
+ * Create debugging information entry for a c++
+ * style reference or rvalue reference type.
+ * \param Builder The DIBuilder.
+ * \param Tag Tag identifying type,
+ * \param Type Base Type.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateReferenceType(LLVMDIBuilderRef Builder, unsigned Tag,
+ LLVMMetadataRef Type);
+
+/**
+ * Create C++11 nullptr type.
+ * \param Builder The DIBuilder.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateNullPtrType(LLVMDIBuilderRef Builder);
+
+/**
+ * Create debugging information entry for a typedef.
+ * \param Builder The DIBuilder.
+ * \param Type Original type.
+ * \param Name Typedef name.
+ * \param File File where this type is defined.
+ * \param LineNo Line number.
+ * \param Scope The surrounding context for the typedef.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type,
+ const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNo,
+ LLVMMetadataRef Scope);
+
+/**
+ * Create debugging information entry to establish inheritance relationship
+ * between two types.
+ * \param Builder The DIBuilder.
+ * \param Ty Original type.
+ * \param BaseTy Base type. Ty is inherits from base.
+ * \param BaseOffset Base offset.
+ * \param VBPtrOffset Virtual base pointer offset.
+ * \param Flags Flags to describe inheritance attribute, e.g. private
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateInheritance(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Ty, LLVMMetadataRef BaseTy,
+ uint64_t BaseOffset, uint32_t VBPtrOffset,
+ LLVMDIFlags Flags);
+
+/**
+ * Create a permanent forward-declared type.
+ * \param Builder The DIBuilder.
+ * \param Tag A unique tag for this type.
+ * \param Name Type name.
+ * \param NameLen Length of type name.
+ * \param Scope Type scope.
+ * \param File File where this type is defined.
+ * \param Line Line number where this type is defined.
+ * \param RuntimeLang Indicates runtime version for languages like
+ * Objective-C.
+ * \param SizeInBits Member size.
+ * \param AlignInBits Member alignment.
+ * \param UniqueIdentifier A unique identifier for the type.
+ * \param UniqueIdentifierLen Length of the unique identifier.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateForwardDecl(
+ LLVMDIBuilderRef Builder, unsigned Tag, const char *Name,
+ size_t NameLen, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line,
+ unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits,
+ const char *UniqueIdentifier, size_t UniqueIdentifierLen);
+
+/**
+ * Create a temporary forward-declared type.
+ * \param Builder The DIBuilder.
+ * \param Tag A unique tag for this type.
+ * \param Name Type name.
+ * \param NameLen Length of type name.
+ * \param Scope Type scope.
+ * \param File File where this type is defined.
+ * \param Line Line number where this type is defined.
+ * \param RuntimeLang Indicates runtime version for languages like
+ * Objective-C.
+ * \param SizeInBits Member size.
+ * \param AlignInBits Member alignment.
+ * \param Flags Flags.
+ * \param UniqueIdentifier A unique identifier for the type.
+ * \param UniqueIdentifierLen Length of the unique identifier.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateReplaceableCompositeType(
+ LLVMDIBuilderRef Builder, unsigned Tag, const char *Name,
+ size_t NameLen, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line,
+ unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits,
+ LLVMDIFlags Flags, const char *UniqueIdentifier,
+ size_t UniqueIdentifierLen);
+
+/**
+ * Create debugging information entry for a bit field member.
+ * \param Builder The DIBuilder.
+ * \param Scope Member scope.
+ * \param Name Member name.
+ * \param NameLen Length of member name.
+ * \param File File where this member is defined.
+ * \param LineNumber Line number.
+ * \param SizeInBits Member size.
+ * \param OffsetInBits Member offset.
+ * \param StorageOffsetInBits Member storage offset.
+ * \param Flags Flags to encode member attribute.
+ * \param Type Parent type.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateBitFieldMemberType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t OffsetInBits,
+ uint64_t StorageOffsetInBits,
+ LLVMDIFlags Flags, LLVMMetadataRef Type);
+
+/**
+ * Create debugging information entry for a class.
+ * \param Scope Scope in which this class is defined.
+ * \param Name Class name.
+ * \param NameLen The length of the C string passed to \c Name.
+ * \param File File where this member is defined.
+ * \param LineNumber Line number.
+ * \param SizeInBits Member size.
+ * \param AlignInBits Member alignment.
+ * \param OffsetInBits Member offset.
+ * \param Flags Flags to encode member attribute, e.g. private.
+ * \param DerivedFrom Debug info of the base class of this type.
+ * \param Elements Class members.
+ * \param NumElements Number of class elements.
+ * \param VTableHolder Debug info of the base class that contains vtable
+ * for this type. This is used in
+ * DW_AT_containing_type. See DWARF documentation
+ * for more info.
+ * \param TemplateParamsNode Template type parameters.
+ * \param UniqueIdentifier A unique identifier for the type.
+ * \param UniqueIdentifierLen Length of the unique identifier.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateClassType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope, const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
+ uint32_t AlignInBits, uint64_t OffsetInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef DerivedFrom,
+ LLVMMetadataRef *Elements, unsigned NumElements,
+ LLVMMetadataRef VTableHolder, LLVMMetadataRef TemplateParamsNode,
+ const char *UniqueIdentifier, size_t UniqueIdentifierLen);
+
+/**
+ * Create a uniqued DIType* clone with FlagArtificial set.
+ * \param Builder The DIBuilder.
+ * \param Type The underlying type.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateArtificialType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Type);
+
+/**
+ * Get the name of this DIType.
+ * \param DType The DIType.
+ * \param Length The length of the returned string.
+ *
+ * @see DIType::getName()
+ */
+const char *LLVMDITypeGetName(LLVMMetadataRef DType, size_t *Length);
+
+/**
+ * Get the size of this DIType in bits.
+ * \param DType The DIType.
+ *
+ * @see DIType::getSizeInBits()
+ */
+uint64_t LLVMDITypeGetSizeInBits(LLVMMetadataRef DType);
+
+/**
+ * Get the offset of this DIType in bits.
+ * \param DType The DIType.
+ *
+ * @see DIType::getOffsetInBits()
+ */
+uint64_t LLVMDITypeGetOffsetInBits(LLVMMetadataRef DType);
+
+/**
+ * Get the alignment of this DIType in bits.
+ * \param DType The DIType.
+ *
+ * @see DIType::getAlignInBits()
+ */
+uint32_t LLVMDITypeGetAlignInBits(LLVMMetadataRef DType);
+
+/**
+ * Get the source line where this DIType is declared.
+ * \param DType The DIType.
+ *
+ * @see DIType::getLine()
+ */
+unsigned LLVMDITypeGetLine(LLVMMetadataRef DType);
+
+/**
+ * Get the flags associated with this DIType.
+ * \param DType The DIType.
+ *
+ * @see DIType::getFlags()
+ */
+LLVMDIFlags LLVMDITypeGetFlags(LLVMMetadataRef DType);
+
+/**
+ * Create a descriptor for a value range.
+ * \param Builder The DIBuilder.
+ * \param LowerBound Lower bound of the subrange, e.g. 0 for C, 1 for Fortran.
+ * \param Count Count of elements in the subrange.
+ */
+LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Builder,
+ int64_t LowerBound,
+ int64_t Count);
+
+/**
+ * Create an array of DI Nodes.
+ * \param Builder The DIBuilder.
+ * \param Data The DI Node elements.
+ * \param NumElements Number of DI Node elements.
+ */
+LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef *Data,
+ size_t NumElements);
+
+/**
+ * Create a new descriptor for the specified variable which has a complex
+ * address expression for its address.
+ * \param Builder The DIBuilder.
+ * \param Addr An array of complex address operations.
+ * \param Length Length of the address operation array.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Builder,
+ int64_t *Addr, size_t Length);
+
+/**
+ * Create a new descriptor for the specified variable that does not have an
+ * address, but does have a constant value.
+ * \param Builder The DIBuilder.
+ * \param Value The constant value.
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateConstantValueExpression(LLVMDIBuilderRef Builder,
+ int64_t Value);
+
+/**
+ * Create a new descriptor for the specified variable.
+ * \param Scope Variable scope.
+ * \param Name Name of the variable.
+ * \param NameLen The length of the C string passed to \c Name.
+ * \param Linkage Mangled name of the variable.
+ * \param LinkLen The length of the C string passed to \c Linkage.
+ * \param File File where this variable is defined.
+ * \param LineNo Line number.
+ * \param Ty Variable Type.
+ * \param LocalToUnit Boolean flag indicate whether this variable is
+ * externally visible or not.
+ * \param Expr The location of the global relative to the attached
+ * GlobalVariable.
+ * \param Decl Reference to the corresponding declaration.
+ * \param AlignInBits Variable alignment(or 0 if no alignment attr was
+ * specified)
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateGlobalVariableExpression(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ const char *Name, size_t NameLen,
+ const char *Linkage, size_t LinkLen,
+ LLVMMetadataRef File,
+ unsigned LineNo,
+ LLVMMetadataRef Ty,
+ LLVMBool LocalToUnit,
+ LLVMMetadataRef Expr,
+ LLVMMetadataRef Decl,
+ uint32_t AlignInBits);
+/**
+ * Create a new temporary \c MDNode. Suitable for use in constructing cyclic
+ * \c MDNode structures. A temporary \c MDNode is not uniqued, may be RAUW'd,
+ * and must be manually deleted with \c LLVMDisposeTemporaryMDNode.
+ * \param Ctx The context in which to construct the temporary node.
+ * \param Data The metadata elements.
+ * \param NumElements Number of metadata elements.
+ */
+LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef Ctx, LLVMMetadataRef *Data,
+ size_t NumElements);
+
+/**
+ * Deallocate a temporary node.
+ *
+ * Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining
+ * references will be reset.
+ * \param TempNode The temporary metadata node.
+ */
+void LLVMDisposeTemporaryMDNode(LLVMMetadataRef TempNode);
+
+/**
+ * Replace all uses of temporary metadata.
+ * \param TempTargetMetadata The temporary metadata node.
+ * \param Replacement The replacement metadata node.
+ */
+void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef TempTargetMetadata,
+ LLVMMetadataRef Replacement);
+
+/**
+ * Create a new descriptor for the specified global variable that is temporary
+ * and meant to be RAUWed.
+ * \param Scope Variable scope.
+ * \param Name Name of the variable.
+ * \param NameLen The length of the C string passed to \c Name.
+ * \param Linkage Mangled name of the variable.
+ * \param LnkLen The length of the C string passed to \c Linkage.
+ * \param File File where this variable is defined.
+ * \param LineNo Line number.
+ * \param Ty Variable Type.
+ * \param LocalToUnit Boolean flag indicate whether this variable is
+ * externally visible or not.
+ * \param Decl Reference to the corresponding declaration.
+ * \param AlignInBits Variable alignment(or 0 if no alignment attr was
+ * specified)
+ */
+LLVMMetadataRef
+LLVMDIBuilderCreateTempGlobalVariableFwdDecl(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ const char *Name, size_t NameLen,
+ const char *Linkage, size_t LnkLen,
+ LLVMMetadataRef File,
+ unsigned LineNo,
+ LLVMMetadataRef Ty,
+ LLVMBool LocalToUnit,
+ LLVMMetadataRef Decl,
+ uint32_t AlignInBits);
+
+/**
+ * Insert a new llvm.dbg.declare intrinsic call before the given instruction.
+ * \param Builder The DIBuilder.
+ * \param Storage The storage of the variable to declare.
+ * \param VarInfo The variable's debug info descriptor.
+ * \param Expr A complex location expression for the variable.
+ * \param DebugLoc Debug info location.
+ * \param Instr Instruction acting as a location for the new intrinsic.
+ */
+LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
+ LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo,
+ LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr);
+
+/**
+ * Insert a new llvm.dbg.declare intrinsic call at the end of the given basic
+ * block. If the basic block has a terminator instruction, the intrinsic is
+ * inserted before that terminator instruction.
+ * \param Builder The DIBuilder.
+ * \param Storage The storage of the variable to declare.
+ * \param VarInfo The variable's debug info descriptor.
+ * \param Expr A complex location expression for the variable.
+ * \param DebugLoc Debug info location.
+ * \param Block Basic block acting as a location for the new intrinsic.
+ */
+LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
+ LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo,
+ LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block);
+
+/**
+ * Insert a new llvm.dbg.value intrinsic call before the given instruction.
+ * \param Builder The DIBuilder.
+ * \param Val The value of the variable.
+ * \param VarInfo The variable's debug info descriptor.
+ * \param Expr A complex location expression for the variable.
+ * \param DebugLoc Debug info location.
+ * \param Instr Instruction acting as a location for the new intrinsic.
+ */
+LLVMValueRef LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder,
+ LLVMValueRef Val,
+ LLVMMetadataRef VarInfo,
+ LLVMMetadataRef Expr,
+ LLVMMetadataRef DebugLoc,
+ LLVMValueRef Instr);
+
+/**
+ * Insert a new llvm.dbg.value intrinsic call at the end of the given basic
+ * block. If the basic block has a terminator instruction, the intrinsic is
+ * inserted before that terminator instruction.
+ * \param Builder The DIBuilder.
+ * \param Val The value of the variable.
+ * \param VarInfo The variable's debug info descriptor.
+ * \param Expr A complex location expression for the variable.
+ * \param DebugLoc Debug info location.
+ * \param Block Basic block acting as a location for the new intrinsic.
+ */
+LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd(LLVMDIBuilderRef Builder,
+ LLVMValueRef Val,
+ LLVMMetadataRef VarInfo,
+ LLVMMetadataRef Expr,
+ LLVMMetadataRef DebugLoc,
+ LLVMBasicBlockRef Block);
+
+/**
+ * Create a new descriptor for a local auto variable.
+ * \param Builder The DIBuilder.
+ * \param Scope The local scope the variable is declared in.
+ * \param Name Variable name.
+ * \param NameLen Length of variable name.
+ * \param File File where this variable is defined.
+ * \param LineNo Line number.
+ * \param Ty Metadata describing the type of the variable.
+ * \param AlwaysPreserve If true, this descriptor will survive optimizations.
+ * \param Flags Flags.
+ * \param AlignInBits Variable alignment.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateAutoVariable(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
+ LLVMBool AlwaysPreserve, LLVMDIFlags Flags, uint32_t AlignInBits);
+
+/**
+ * Create a new descriptor for a function parameter variable.
+ * \param Builder The DIBuilder.
+ * \param Scope The local scope the variable is declared in.
+ * \param Name Variable name.
+ * \param NameLen Length of variable name.
+ * \param ArgNo Unique argument number for this variable; starts at 1.
+ * \param File File where this variable is defined.
+ * \param LineNo Line number.
+ * \param Ty Metadata describing the type of the variable.
+ * \param AlwaysPreserve If true, this descriptor will survive optimizations.
+ * \param Flags Flags.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateParameterVariable(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, unsigned ArgNo, LLVMMetadataRef File, unsigned LineNo,
+ LLVMMetadataRef Ty, LLVMBool AlwaysPreserve, LLVMDIFlags Flags);
+
+/**
+ * Get the metadata of the subprogram attached to a function.
+ *
+ * @see llvm::Function::getSubprogram()
+ */
+LLVMMetadataRef LLVMGetSubprogram(LLVMValueRef Func);
+
+/**
+ * Set the subprogram attached to a function.
+ *
+ * @see llvm::Function::setSubprogram()
+ */
+void LLVMSetSubprogram(LLVMValueRef Func, LLVMMetadataRef SP);
+
#ifdef __cplusplus
} /* end extern "C" */
#endif
diff --git a/contrib/llvm/include/llvm-c/Disassembler.h b/contrib/llvm/include/llvm-c/Disassembler.h
index d6f92e505d3c..5e80b95848cf 100644
--- a/contrib/llvm/include/llvm-c/Disassembler.h
+++ b/contrib/llvm/include/llvm-c/Disassembler.h
@@ -15,12 +15,7 @@
#ifndef LLVM_C_DISASSEMBLER_H
#define LLVM_C_DISASSEMBLER_H
-#include "llvm/Support/DataTypes.h"
-#ifdef __cplusplus
-#include <cstddef>
-#else
-#include <stddef.h>
-#endif
+#include "llvm-c/DisassemblerTypes.h"
/**
* @defgroup LLVMCDisassembler Disassembler
@@ -29,146 +24,6 @@
* @{
*/
-/**
- * An opaque reference to a disassembler context.
- */
-typedef void *LLVMDisasmContextRef;
-
-/**
- * The type for the operand information call back function. This is called to
- * get the symbolic information for an operand of an instruction. Typically
- * this is from the relocation information, symbol table, etc. That block of
- * information is saved when the disassembler context is created and passed to
- * the call back in the DisInfo parameter. The instruction containing operand
- * is at the PC parameter. For some instruction sets, there can be more than
- * one operand with symbolic information. To determine the symbolic operand
- * information for each operand, the bytes for the specific operand in the
- * instruction are specified by the Offset parameter and its byte widith is the
- * size parameter. For instructions sets with fixed widths and one symbolic
- * operand per instruction, the Offset parameter will be zero and Size parameter
- * will be the instruction width. The information is returned in TagBuf and is
- * Triple specific with its specific information defined by the value of
- * TagType for that Triple. If symbolic information is returned the function
- * returns 1, otherwise it returns 0.
- */
-typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC,
- uint64_t Offset, uint64_t Size,
- int TagType, void *TagBuf);
-
-/**
- * The initial support in LLVM MC for the most general form of a relocatable
- * expression is "AddSymbol - SubtractSymbol + Offset". For some Darwin targets
- * this full form is encoded in the relocation information so that AddSymbol and
- * SubtractSymbol can be link edited independent of each other. Many other
- * platforms only allow a relocatable expression of the form AddSymbol + Offset
- * to be encoded.
- *
- * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct
- * LLVMOpInfo1. The value of the relocatable expression for the operand,
- * including any PC adjustment, is passed in to the call back in the Value
- * field. The symbolic information about the operand is returned using all
- * the fields of the structure with the Offset of the relocatable expression
- * returned in the Value field. It is possible that some symbols in the
- * relocatable expression were assembly temporary symbols, for example
- * "Ldata - LpicBase + constant", and only the Values of the symbols without
- * symbol names are present in the relocation information. The VariantKind
- * type is one of the Target specific #defines below and is used to print
- * operands like "_foo@GOT", ":lower16:_foo", etc.
- */
-struct LLVMOpInfoSymbol1 {
- uint64_t Present; /* 1 if this symbol is present */
- const char *Name; /* symbol name if not NULL */
- uint64_t Value; /* symbol value if name is NULL */
-};
-
-struct LLVMOpInfo1 {
- struct LLVMOpInfoSymbol1 AddSymbol;
- struct LLVMOpInfoSymbol1 SubtractSymbol;
- uint64_t Value;
- uint64_t VariantKind;
-};
-
-/**
- * The operand VariantKinds for symbolic disassembly.
- */
-#define LLVMDisassembler_VariantKind_None 0 /* all targets */
-
-/**
- * The ARM target VariantKinds.
- */
-#define LLVMDisassembler_VariantKind_ARM_HI16 1 /* :upper16: */
-#define LLVMDisassembler_VariantKind_ARM_LO16 2 /* :lower16: */
-
-/**
- * The ARM64 target VariantKinds.
- */
-#define LLVMDisassembler_VariantKind_ARM64_PAGE 1 /* @page */
-#define LLVMDisassembler_VariantKind_ARM64_PAGEOFF 2 /* @pageoff */
-#define LLVMDisassembler_VariantKind_ARM64_GOTPAGE 3 /* @gotpage */
-#define LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF 4 /* @gotpageoff */
-#define LLVMDisassembler_VariantKind_ARM64_TLVP 5 /* @tvlppage */
-#define LLVMDisassembler_VariantKind_ARM64_TLVOFF 6 /* @tvlppageoff */
-
-/**
- * The type for the symbol lookup function. This may be called by the
- * disassembler for things like adding a comment for a PC plus a constant
- * offset load instruction to use a symbol name instead of a load address value.
- * It is passed the block information is saved when the disassembler context is
- * created and the ReferenceValue to look up as a symbol. If no symbol is found
- * for the ReferenceValue NULL is returned. The ReferenceType of the
- * instruction is passed indirectly as is the PC of the instruction in
- * ReferencePC. If the output reference can be determined its type is returned
- * indirectly in ReferenceType along with ReferenceName if any, or that is set
- * to NULL.
- */
-typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo,
- uint64_t ReferenceValue,
- uint64_t *ReferenceType,
- uint64_t ReferencePC,
- const char **ReferenceName);
-/**
- * The reference types on input and output.
- */
-/* No input reference type or no output reference type. */
-#define LLVMDisassembler_ReferenceType_InOut_None 0
-
-/* The input reference is from a branch instruction. */
-#define LLVMDisassembler_ReferenceType_In_Branch 1
-/* The input reference is from a PC relative load instruction. */
-#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2
-
-/* The input reference is from an ARM64::ADRP instruction. */
-#define LLVMDisassembler_ReferenceType_In_ARM64_ADRP 0x100000001
-/* The input reference is from an ARM64::ADDXri instruction. */
-#define LLVMDisassembler_ReferenceType_In_ARM64_ADDXri 0x100000002
-/* The input reference is from an ARM64::LDRXui instruction. */
-#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXui 0x100000003
-/* The input reference is from an ARM64::LDRXl instruction. */
-#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXl 0x100000004
-/* The input reference is from an ARM64::ADR instruction. */
-#define LLVMDisassembler_ReferenceType_In_ARM64_ADR 0x100000005
-
-/* The output reference is to as symbol stub. */
-#define LLVMDisassembler_ReferenceType_Out_SymbolStub 1
-/* The output reference is to a symbol address in a literal pool. */
-#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2
-/* The output reference is to a cstring address in a literal pool. */
-#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3
-
-/* The output reference is to a Objective-C CoreFoundation string. */
-#define LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref 4
-/* The output reference is to a Objective-C message. */
-#define LLVMDisassembler_ReferenceType_Out_Objc_Message 5
-/* The output reference is to a Objective-C message ref. */
-#define LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref 6
-/* The output reference is to a Objective-C selector ref. */
-#define LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref 7
-/* The output reference is to a Objective-C class ref. */
-#define LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref 8
-
-/* The output reference is to a C++ symbol name. */
-#define LLVMDisassembler_ReferenceType_DeMangled_Name 9
-
#ifdef __cplusplus
extern "C" {
#endif /* !defined(__cplusplus) */
diff --git a/contrib/llvm/include/llvm-c/DisassemblerTypes.h b/contrib/llvm/include/llvm-c/DisassemblerTypes.h
new file mode 100644
index 000000000000..e8754ac77055
--- /dev/null
+++ b/contrib/llvm/include/llvm-c/DisassemblerTypes.h
@@ -0,0 +1,160 @@
+/*===-- llvm-c/DisassemblerTypedefs.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_DISASSEMBLER_TYPES_H
+#define LLVM_DISASSEMBLER_TYPES_H
+
+#include "llvm-c/DataTypes.h"
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+/**
+ * An opaque reference to a disassembler context.
+ */
+typedef void *LLVMDisasmContextRef;
+
+/**
+ * The type for the operand information call back function. This is called to
+ * get the symbolic information for an operand of an instruction. Typically
+ * this is from the relocation information, symbol table, etc. That block of
+ * information is saved when the disassembler context is created and passed to
+ * the call back in the DisInfo parameter. The instruction containing operand
+ * is at the PC parameter. For some instruction sets, there can be more than
+ * one operand with symbolic information. To determine the symbolic operand
+ * information for each operand, the bytes for the specific operand in the
+ * instruction are specified by the Offset parameter and its byte widith is the
+ * size parameter. For instructions sets with fixed widths and one symbolic
+ * operand per instruction, the Offset parameter will be zero and Size parameter
+ * will be the instruction width. The information is returned in TagBuf and is
+ * Triple specific with its specific information defined by the value of
+ * TagType for that Triple. If symbolic information is returned the function
+ * returns 1, otherwise it returns 0.
+ */
+typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC,
+ uint64_t Offset, uint64_t Size,
+ int TagType, void *TagBuf);
+
+/**
+ * The initial support in LLVM MC for the most general form of a relocatable
+ * expression is "AddSymbol - SubtractSymbol + Offset". For some Darwin targets
+ * this full form is encoded in the relocation information so that AddSymbol and
+ * SubtractSymbol can be link edited independent of each other. Many other
+ * platforms only allow a relocatable expression of the form AddSymbol + Offset
+ * to be encoded.
+ *
+ * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct
+ * LLVMOpInfo1. The value of the relocatable expression for the operand,
+ * including any PC adjustment, is passed in to the call back in the Value
+ * field. The symbolic information about the operand is returned using all
+ * the fields of the structure with the Offset of the relocatable expression
+ * returned in the Value field. It is possible that some symbols in the
+ * relocatable expression were assembly temporary symbols, for example
+ * "Ldata - LpicBase + constant", and only the Values of the symbols without
+ * symbol names are present in the relocation information. The VariantKind
+ * type is one of the Target specific #defines below and is used to print
+ * operands like "_foo@GOT", ":lower16:_foo", etc.
+ */
+struct LLVMOpInfoSymbol1 {
+ uint64_t Present; /* 1 if this symbol is present */
+ const char *Name; /* symbol name if not NULL */
+ uint64_t Value; /* symbol value if name is NULL */
+};
+
+struct LLVMOpInfo1 {
+ struct LLVMOpInfoSymbol1 AddSymbol;
+ struct LLVMOpInfoSymbol1 SubtractSymbol;
+ uint64_t Value;
+ uint64_t VariantKind;
+};
+
+/**
+ * The operand VariantKinds for symbolic disassembly.
+ */
+#define LLVMDisassembler_VariantKind_None 0 /* all targets */
+
+/**
+ * The ARM target VariantKinds.
+ */
+#define LLVMDisassembler_VariantKind_ARM_HI16 1 /* :upper16: */
+#define LLVMDisassembler_VariantKind_ARM_LO16 2 /* :lower16: */
+
+/**
+ * The ARM64 target VariantKinds.
+ */
+#define LLVMDisassembler_VariantKind_ARM64_PAGE 1 /* @page */
+#define LLVMDisassembler_VariantKind_ARM64_PAGEOFF 2 /* @pageoff */
+#define LLVMDisassembler_VariantKind_ARM64_GOTPAGE 3 /* @gotpage */
+#define LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF 4 /* @gotpageoff */
+#define LLVMDisassembler_VariantKind_ARM64_TLVP 5 /* @tvlppage */
+#define LLVMDisassembler_VariantKind_ARM64_TLVOFF 6 /* @tvlppageoff */
+
+/**
+ * The type for the symbol lookup function. This may be called by the
+ * disassembler for things like adding a comment for a PC plus a constant
+ * offset load instruction to use a symbol name instead of a load address value.
+ * It is passed the block information is saved when the disassembler context is
+ * created and the ReferenceValue to look up as a symbol. If no symbol is found
+ * for the ReferenceValue NULL is returned. The ReferenceType of the
+ * instruction is passed indirectly as is the PC of the instruction in
+ * ReferencePC. If the output reference can be determined its type is returned
+ * indirectly in ReferenceType along with ReferenceName if any, or that is set
+ * to NULL.
+ */
+typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo,
+ uint64_t ReferenceValue,
+ uint64_t *ReferenceType,
+ uint64_t ReferencePC,
+ const char **ReferenceName);
+/**
+ * The reference types on input and output.
+ */
+/* No input reference type or no output reference type. */
+#define LLVMDisassembler_ReferenceType_InOut_None 0
+
+/* The input reference is from a branch instruction. */
+#define LLVMDisassembler_ReferenceType_In_Branch 1
+/* The input reference is from a PC relative load instruction. */
+#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2
+
+/* The input reference is from an ARM64::ADRP instruction. */
+#define LLVMDisassembler_ReferenceType_In_ARM64_ADRP 0x100000001
+/* The input reference is from an ARM64::ADDXri instruction. */
+#define LLVMDisassembler_ReferenceType_In_ARM64_ADDXri 0x100000002
+/* The input reference is from an ARM64::LDRXui instruction. */
+#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXui 0x100000003
+/* The input reference is from an ARM64::LDRXl instruction. */
+#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXl 0x100000004
+/* The input reference is from an ARM64::ADR instruction. */
+#define LLVMDisassembler_ReferenceType_In_ARM64_ADR 0x100000005
+
+/* The output reference is to as symbol stub. */
+#define LLVMDisassembler_ReferenceType_Out_SymbolStub 1
+/* The output reference is to a symbol address in a literal pool. */
+#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2
+/* The output reference is to a cstring address in a literal pool. */
+#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3
+
+/* The output reference is to a Objective-C CoreFoundation string. */
+#define LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref 4
+/* The output reference is to a Objective-C message. */
+#define LLVMDisassembler_ReferenceType_Out_Objc_Message 5
+/* The output reference is to a Objective-C message ref. */
+#define LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref 6
+/* The output reference is to a Objective-C selector ref. */
+#define LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref 7
+/* The output reference is to a Objective-C class ref. */
+#define LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref 8
+
+/* The output reference is to a C++ symbol name. */
+#define LLVMDisassembler_ReferenceType_DeMangled_Name 9
+
+#endif
diff --git a/contrib/llvm/include/llvm-c/ExecutionEngine.h b/contrib/llvm/include/llvm-c/ExecutionEngine.h
index 51830fe139c6..49ae6fee45f0 100644
--- a/contrib/llvm/include/llvm-c/ExecutionEngine.h
+++ b/contrib/llvm/include/llvm-c/ExecutionEngine.h
@@ -182,6 +182,13 @@ LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager(
void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM);
+/*===-- JIT Event Listener functions -------------------------------------===*/
+
+LLVMJITEventListenerRef LLVMCreateGDBRegistrationListener(void);
+LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void);
+LLVMJITEventListenerRef LLVMCreateOprofileJITEventListener(void);
+LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void);
+
/**
* @}
*/
diff --git a/contrib/llvm/include/llvm-c/Initialization.h b/contrib/llvm/include/llvm-c/Initialization.h
index 90c8396f7ad3..e45eafb139f2 100644
--- a/contrib/llvm/include/llvm-c/Initialization.h
+++ b/contrib/llvm/include/llvm-c/Initialization.h
@@ -37,6 +37,7 @@ void LLVMInitializeScalarOpts(LLVMPassRegistryRef R);
void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R);
void LLVMInitializeVectorization(LLVMPassRegistryRef R);
void LLVMInitializeInstCombine(LLVMPassRegistryRef R);
+void LLVMInitializeAggressiveInstCombiner(LLVMPassRegistryRef R);
void LLVMInitializeIPO(LLVMPassRegistryRef R);
void LLVMInitializeInstrumentation(LLVMPassRegistryRef R);
void LLVMInitializeAnalysis(LLVMPassRegistryRef R);
diff --git a/contrib/llvm/include/llvm-c/OrcBindings.h b/contrib/llvm/include/llvm-c/OrcBindings.h
index abb3ac6a7f03..9497f0d40776 100644
--- a/contrib/llvm/include/llvm-c/OrcBindings.h
+++ b/contrib/llvm/include/llvm-c/OrcBindings.h
@@ -29,9 +29,8 @@
extern "C" {
#endif
-typedef struct LLVMOpaqueSharedModule *LLVMSharedModuleRef;
typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef;
-typedef uint32_t LLVMOrcModuleHandle;
+typedef uint64_t LLVMOrcModuleHandle;
typedef uint64_t LLVMOrcTargetAddress;
typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx);
typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
@@ -40,33 +39,6 @@ typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
typedef enum { LLVMOrcErrSuccess = 0, LLVMOrcErrGeneric } LLVMOrcErrorCode;
/**
- * Turn an LLVMModuleRef into an LLVMSharedModuleRef.
- *
- * The JIT uses shared ownership for LLVM modules, since it is generally
- * difficult to know when the JIT will be finished with a module (and the JIT
- * has no way of knowing when a user may be finished with one).
- *
- * Calling this method with an LLVMModuleRef creates a shared-pointer to the
- * module, and returns a reference to this shared pointer.
- *
- * The shared module should be disposed when finished with by calling
- * LLVMOrcDisposeSharedModule (not LLVMDisposeModule). The Module will be
- * deleted when the last shared pointer owner relinquishes it.
- */
-
-LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod);
-
-/**
- * Dispose of a shared module.
- *
- * The module should not be accessed after this call. The module will be
- * deleted once all clients (including the JIT itself) have released their
- * shared pointers.
- */
-
-void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod);
-
-/**
* Create an ORC JIT stack.
*
* The client owns the resulting stack, and must call OrcDisposeInstance(...)
@@ -125,8 +97,7 @@ LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
*/
LLVMOrcErrorCode
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
- LLVMOrcModuleHandle *RetHandle,
- LLVMSharedModuleRef Mod,
+ LLVMOrcModuleHandle *RetHandle, LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
@@ -135,8 +106,7 @@ LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
*/
LLVMOrcErrorCode
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
- LLVMOrcModuleHandle *RetHandle,
- LLVMSharedModuleRef Mod,
+ LLVMOrcModuleHandle *RetHandle, LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
@@ -171,10 +141,33 @@ LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
const char *SymbolName);
/**
+ * Get symbol address from JIT instance, searching only the specified
+ * handle.
+ */
+LLVMOrcErrorCode LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack,
+ LLVMOrcTargetAddress *RetAddr,
+ LLVMOrcModuleHandle H,
+ const char *SymbolName);
+
+/**
* Dispose of an ORC JIT stack.
*/
LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
+/**
+ * Register a JIT Event Listener.
+ *
+ * A NULL listener is ignored.
+ */
+void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L);
+
+/**
+ * Unegister a JIT Event Listener.
+ *
+ * A NULL listener is ignored.
+ */
+void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L);
+
#ifdef __cplusplus
}
#endif /* extern "C" */
diff --git a/contrib/llvm/include/llvm-c/Support.h b/contrib/llvm/include/llvm-c/Support.h
index 6de184ccab49..37d5d72ff5dc 100644
--- a/contrib/llvm/include/llvm-c/Support.h
+++ b/contrib/llvm/include/llvm-c/Support.h
@@ -14,8 +14,8 @@
#ifndef LLVM_C_SUPPORT_H
#define LLVM_C_SUPPORT_H
+#include "llvm-c/DataTypes.h"
#include "llvm-c/Types.h"
-#include "llvm/Support/DataTypes.h"
#ifdef __cplusplus
extern "C" {
diff --git a/contrib/llvm/include/llvm-c/TargetMachine.h b/contrib/llvm/include/llvm-c/TargetMachine.h
index f4f7f7698c45..7f672b5d10d6 100644
--- a/contrib/llvm/include/llvm-c/TargetMachine.h
+++ b/contrib/llvm/include/llvm-c/TargetMachine.h
@@ -137,6 +137,18 @@ LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleR
disposed with LLVMDisposeMessage. */
char* LLVMGetDefaultTargetTriple(void);
+/** Normalize a target triple. The result needs to be disposed with
+ LLVMDisposeMessage. */
+char* LLVMNormalizeTargetTriple(const char* triple);
+
+/** Get the host CPU as a string. The result needs to be disposed with
+ LLVMDisposeMessage. */
+char* LLVMGetHostCPUName(void);
+
+/** Get the host CPU's features as a string. The result needs to be disposed
+ with LLVMDisposeMessage. */
+char* LLVMGetHostCPUFeatures(void);
+
/** Adds the target-specific analysis passes to the pass manager. */
void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM);
diff --git a/contrib/llvm/include/llvm-c/Transforms/InstCombine.h b/contrib/llvm/include/llvm-c/Transforms/InstCombine.h
new file mode 100644
index 000000000000..e1c1572d53dc
--- /dev/null
+++ b/contrib/llvm/include/llvm-c/Transforms/InstCombine.h
@@ -0,0 +1,43 @@
+/*===-- Scalar.h - Scalar Transformation Library C Interface ----*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header declares the C interface to libLLVMInstCombine.a, which *|
+|* combines instructions to form fewer, simple IR instructions. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_TRANSFORMS_INSTCOMBINE_H
+#define LLVM_C_TRANSFORMS_INSTCOMBINE_H
+
+#include "llvm-c/Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup LLVMCTransformsInstCombine Instruction Combining transformations
+ * @ingroup LLVMCTransforms
+ *
+ * @{
+ */
+
+/** See llvm::createInstructionCombiningPass function. */
+void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* defined(__cplusplus) */
+
+#endif
+
diff --git a/contrib/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm/include/llvm-c/Transforms/Scalar.h
index 8991e0904849..f55cdce86be9 100644
--- a/contrib/llvm/include/llvm-c/Transforms/Scalar.h
+++ b/contrib/llvm/include/llvm-c/Transforms/Scalar.h
@@ -35,6 +35,9 @@ extern "C" {
/** See llvm::createAggressiveDCEPass function. */
void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM);
+/** See llvm::createAggressiveInstCombinerPass function. */
+void LLVMAddAggressiveInstCombinerPass(LLVMPassManagerRef PM);
+
/** See llvm::createBitTrackingDCEPass function. */
void LLVMAddBitTrackingDCEPass(LLVMPassManagerRef PM);
@@ -86,6 +89,9 @@ void LLVMAddLoopRerollPass(LLVMPassManagerRef PM);
/** See llvm::createLoopUnrollPass function. */
void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM);
+/** See llvm::createLoopUnrollAndJamPass function. */
+void LLVMAddLoopUnrollAndJamPass(LLVMPassManagerRef PM);
+
/** See llvm::createLoopUnswitchPass function. */
void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM);
@@ -95,12 +101,6 @@ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM);
/** See llvm::createPartiallyInlineLibCallsPass function. */
void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM);
-/** See llvm::createLowerSwitchPass function. */
-void LLVMAddLowerSwitchPass(LLVMPassManagerRef PM);
-
-/** See llvm::createPromoteMemoryToRegisterPass function. */
-void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);
-
/** See llvm::createReassociatePass function. */
void LLVMAddReassociatePass(LLVMPassManagerRef PM);
diff --git a/contrib/llvm/include/llvm-c/Transforms/Utils.h b/contrib/llvm/include/llvm-c/Transforms/Utils.h
new file mode 100644
index 000000000000..f171f7fbbe3e
--- /dev/null
+++ b/contrib/llvm/include/llvm-c/Transforms/Utils.h
@@ -0,0 +1,50 @@
+/*===-- Utils.h - Transformation Utils Library C Interface ------*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header declares the C interface to libLLVMTransformUtils.a, which *|
+|* implements various transformation utilities of the LLVM IR. *|
+|* *|
+|* Many exotic languages can interoperate with C code but have a harder time *|
+|* with C++ due to name mangling. So in addition to C, this interface enables *|
+|* tools written in such languages. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_TRANSFORMS_UTILS_H
+#define LLVM_C_TRANSFORMS_UTILS_H
+
+#include "llvm-c/Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup LLVMCTransformsUtils Transformation Utilities
+ * @ingroup LLVMCTransforms
+ *
+ * @{
+ */
+
+/** See llvm::createLowerSwitchPass function. */
+void LLVMAddLowerSwitchPass(LLVMPassManagerRef PM);
+
+/** See llvm::createPromoteMemoryToRegisterPass function. */
+void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* defined(__cplusplus) */
+
+#endif
+
diff --git a/contrib/llvm/include/llvm-c/Transforms/Vectorize.h b/contrib/llvm/include/llvm-c/Transforms/Vectorize.h
index cf8306aee762..e3f9961acfb1 100644
--- a/contrib/llvm/include/llvm-c/Transforms/Vectorize.h
+++ b/contrib/llvm/include/llvm-c/Transforms/Vectorize.h
@@ -33,9 +33,6 @@ extern "C" {
* @{
*/
-/** DEPRECATED - Use LLVMAddSLPVectorizePass */
-void LLVMAddBBVectorizePass(LLVMPassManagerRef PM);
-
/** See llvm::createLoopVectorizePass function. */
void LLVMAddLoopVectorizePass(LLVMPassManagerRef PM);
diff --git a/contrib/llvm/include/llvm-c/Types.h b/contrib/llvm/include/llvm-c/Types.h
index d63ea4de933d..4a33542e86cc 100644
--- a/contrib/llvm/include/llvm-c/Types.h
+++ b/contrib/llvm/include/llvm-c/Types.h
@@ -7,14 +7,14 @@
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
-|* This file defines types used by the the C interface to LLVM. *|
+|* This file defines types used by the C interface to LLVM. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_TYPES_H
#define LLVM_C_TYPES_H
-#include "llvm/Support/DataTypes.h"
+#include "llvm-c/DataTypes.h"
#ifdef __cplusplus
extern "C" {
@@ -135,6 +135,21 @@ typedef struct LLVMOpaqueAttributeRef *LLVMAttributeRef;
typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef;
/**
+ * @see llvm::Comdat
+ */
+typedef struct LLVMComdat *LLVMComdatRef;
+
+/**
+ * @see llvm::Module::ModuleFlagEntry
+ */
+typedef struct LLVMOpaqueModuleFlagEntry LLVMModuleFlagEntry;
+
+/**
+ * @see llvm::JITEventListener
+ */
+typedef struct LLVMOpaqueJITEventListener *LLVMJITEventListenerRef;
+
+/**
* @}
*/
diff --git a/contrib/llvm/include/llvm-c/lto.h b/contrib/llvm/include/llvm-c/lto.h
index 55f3e46c45ed..1acd610f70ac 100644
--- a/contrib/llvm/include/llvm-c/lto.h
+++ b/contrib/llvm/include/llvm-c/lto.h
@@ -44,7 +44,7 @@ typedef bool lto_bool_t;
* @{
*/
-#define LTO_API_VERSION 21
+#define LTO_API_VERSION 22
/**
* \since prior to LTO_API_VERSION=3
@@ -190,7 +190,7 @@ lto_module_create_from_memory_with_path(const void* mem, size_t length,
const char *path);
/**
- * \brief Loads an object file in its own context.
+ * Loads an object file in its own context.
*
* Loads an object file in its own LLVMContext. This function call is
* thread-safe. However, modules created this way should not be merged into an
@@ -205,7 +205,7 @@ lto_module_create_in_local_context(const void *mem, size_t length,
const char *path);
/**
- * \brief Loads an object file in the codegen context.
+ * Loads an object file in the codegen context.
*
* Loads an object file into the same context as \c cg. The module is safe to
* add using \a lto_codegen_add_module().
@@ -345,7 +345,7 @@ extern lto_code_gen_t
lto_codegen_create(void);
/**
- * \brief Instantiate a code generator in its own context.
+ * Instantiate a code generator in its own context.
*
* Instantiates a code generator in its own context. Modules added via \a
* lto_codegen_add_module() must have all been created in the same context,
@@ -539,7 +539,7 @@ lto_codegen_set_should_internalize(lto_code_gen_t cg,
lto_bool_t ShouldInternalize);
/**
- * \brief Set whether to embed uselists in bitcode.
+ * Set whether to embed uselists in bitcode.
*
* Sets whether \a lto_codegen_write_merged_modules() should embed uselists in
* output bitcode. This should be turned on for all -save-temps output.
@@ -784,7 +784,7 @@ extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
/**
* Sets the cache pruning interval (in seconds). A negative value disables the
* pruning. An unspecified default value will be applied, and a value of 0 will
- * be ignored.
+ * force prunning to occur.
*
* \since LTO_API_VERSION=18
*/
@@ -793,7 +793,7 @@ extern void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
/**
* Sets the maximum cache size that can be persistent across build, in terms of
- * percentage of the available space on the the disk. Set to 100 to indicate
+ * percentage of the available space on the disk. Set to 100 to indicate
* no limit, 50 to indicate that the cache size will not be left over half the
* available space. A value over 100 will be reduced to 100, a value of 0 will
* be ignored. An unspecified default value will be applied.
@@ -817,6 +817,28 @@ extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
unsigned expiration);
/**
+ * Sets the maximum size of the cache directory (in bytes). A value over the
+ * amount of available space on the disk will be reduced to the amount of
+ * available space. An unspecified default value will be applied. A value of 0
+ * will be ignored.
+ *
+ * \since LTO_API_VERSION=22
+ */
+extern void thinlto_codegen_set_cache_size_bytes(thinlto_code_gen_t cg,
+ unsigned max_size_bytes);
+
+/**
+ * Sets the maximum number of files in the cache directory. An unspecified
+ * default value will be applied. A value of 0 will be ignored.
+ *
+ * \since LTO_API_VERSION=22
+ */
+extern void thinlto_codegen_set_cache_size_files(thinlto_code_gen_t cg,
+ unsigned max_size_files);
+
+
+
+/**
* @} // endgroup LLVMCTLTO_CACHING
*/
diff --git a/contrib/llvm/include/llvm/ADT/APFloat.h b/contrib/llvm/include/llvm/ADT/APFloat.h
index 6c0b6ae78ae3..5c59af4c04ba 100644
--- a/contrib/llvm/include/llvm/ADT/APFloat.h
+++ b/contrib/llvm/include/llvm/ADT/APFloat.h
@@ -1215,7 +1215,7 @@ inline APFloat abs(APFloat X) {
return X;
}
-/// \brief Returns the negated value of the argument.
+/// Returns the negated value of the argument.
inline APFloat neg(APFloat X) {
X.changeSign();
return X;
diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h
index c81363cc16b7..6bf6b22fb010 100644
--- a/contrib/llvm/include/llvm/ADT/APInt.h
+++ b/contrib/llvm/include/llvm/ADT/APInt.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements a class to represent arbitrary precision
+/// This file implements a class to represent arbitrary precision
/// integral constant values and operations on them.
///
//===----------------------------------------------------------------------===//
@@ -40,7 +40,7 @@ inline APInt operator-(APInt);
// APInt Class
//===----------------------------------------------------------------------===//
-/// \brief Class for arbitrary precision integers.
+/// Class for arbitrary precision integers.
///
/// APInt is a functional replacement for common case unsigned integer type like
/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width
@@ -78,6 +78,12 @@ public:
APINT_BITS_PER_WORD = APINT_WORD_SIZE * CHAR_BIT
};
+ enum class Rounding {
+ DOWN,
+ TOWARD_ZERO,
+ UP,
+ };
+
static const WordType WORD_MAX = ~WordType(0);
private:
@@ -94,7 +100,7 @@ private:
friend class APSInt;
- /// \brief Fast internal constructor
+ /// Fast internal constructor
///
/// This constructor is used only internally for speed of construction of
/// temporaries. It is unsafe for general use so it is not public.
@@ -102,19 +108,19 @@ private:
U.pVal = val;
}
- /// \brief Determine if this APInt just has one word to store value.
+ /// Determine if this APInt just has one word to store value.
///
/// \returns true if the number of bits <= 64, false otherwise.
bool isSingleWord() const { return BitWidth <= APINT_BITS_PER_WORD; }
- /// \brief Determine which word a bit is in.
+ /// Determine which word a bit is in.
///
/// \returns the word position for the specified bit position.
static unsigned whichWord(unsigned bitPosition) {
return bitPosition / APINT_BITS_PER_WORD;
}
- /// \brief Determine which bit in a word a bit is in.
+ /// Determine which bit in a word a bit is in.
///
/// \returns the bit position in a word for the specified bit position
/// in the APInt.
@@ -122,7 +128,7 @@ private:
return bitPosition % APINT_BITS_PER_WORD;
}
- /// \brief Get a single bit mask.
+ /// Get a single bit mask.
///
/// \returns a uint64_t with only bit at "whichBit(bitPosition)" set
/// This method generates and returns a uint64_t (word) mask for a single
@@ -132,7 +138,7 @@ private:
return 1ULL << whichBit(bitPosition);
}
- /// \brief Clear unused high order bits
+ /// Clear unused high order bits
///
/// This method is used internally to clear the top "N" bits in the high order
/// word that are not used by the APInt. This is needed after the most
@@ -151,7 +157,7 @@ private:
return *this;
}
- /// \brief Get the word corresponding to a bit position
+ /// Get the word corresponding to a bit position
/// \returns the corresponding word for the specified bit position.
uint64_t getWord(unsigned bitPosition) const {
return isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)];
@@ -162,7 +168,7 @@ private:
/// value of any bits upon return. Caller should populate the bits after.
void reallocate(unsigned NewBitWidth);
- /// \brief Convert a char array into an APInt
+ /// Convert a char array into an APInt
///
/// \param radix 2, 8, 10, 16, or 36
/// Converts a string into a number. The string must be non-empty
@@ -176,7 +182,7 @@ private:
/// result to hold the input.
void fromString(unsigned numBits, StringRef str, uint8_t radix);
- /// \brief An internal division function for dividing APInts.
+ /// An internal division function for dividing APInts.
///
/// This is used by the toString method to divide by the radix. It simply
/// provides a more convenient form of divide for internal use since KnuthDiv
@@ -258,7 +264,7 @@ public:
/// \name Constructors
/// @{
- /// \brief Create a new APInt of numBits width, initialized as val.
+ /// Create a new APInt of numBits width, initialized as val.
///
/// If isSigned is true then val is treated as if it were a signed value
/// (i.e. as an int64_t) and the appropriate sign extension to the bit width
@@ -279,7 +285,7 @@ public:
}
}
- /// \brief Construct an APInt of numBits width, initialized as bigVal[].
+ /// Construct an APInt of numBits width, initialized as bigVal[].
///
/// Note that bigVal.size() can be smaller or larger than the corresponding
/// bit width but any extraneous bits will be dropped.
@@ -297,7 +303,7 @@ public:
/// constructor.
APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]);
- /// \brief Construct an APInt from a string representation.
+ /// Construct an APInt from a string representation.
///
/// This constructor interprets the string \p str in the given radix. The
/// interpretation stops when the first character that is not suitable for the
@@ -311,7 +317,7 @@ public:
APInt(unsigned numBits, StringRef str, uint8_t radix);
/// Simply makes *this a copy of that.
- /// @brief Copy Constructor.
+ /// Copy Constructor.
APInt(const APInt &that) : BitWidth(that.BitWidth) {
if (isSingleWord())
U.VAL = that.U.VAL;
@@ -319,26 +325,26 @@ public:
initSlowCase(that);
}
- /// \brief Move Constructor.
+ /// Move Constructor.
APInt(APInt &&that) : BitWidth(that.BitWidth) {
memcpy(&U, &that.U, sizeof(U));
that.BitWidth = 0;
}
- /// \brief Destructor.
+ /// Destructor.
~APInt() {
if (needsCleanup())
delete[] U.pVal;
}
- /// \brief Default constructor that creates an uninteresting APInt
+ /// Default constructor that creates an uninteresting APInt
/// representing a 1-bit zero value.
///
/// This is useful for object deserialization (pair this with the static
/// method Read).
explicit APInt() : BitWidth(1) { U.VAL = 0; }
- /// \brief Returns whether this instance allocated memory.
+ /// Returns whether this instance allocated memory.
bool needsCleanup() const { return !isSingleWord(); }
/// Used to insert APInt objects, or objects that contain APInt objects, into
@@ -349,33 +355,33 @@ public:
/// \name Value Tests
/// @{
- /// \brief Determine sign of this APInt.
+ /// Determine sign of this APInt.
///
/// This tests the high bit of this APInt to determine if it is set.
///
/// \returns true if this APInt is negative, false otherwise
bool isNegative() const { return (*this)[BitWidth - 1]; }
- /// \brief Determine if this APInt Value is non-negative (>= 0)
+ /// Determine if this APInt Value is non-negative (>= 0)
///
/// This tests the high bit of the APInt to determine if it is unset.
bool isNonNegative() const { return !isNegative(); }
- /// \brief Determine if sign bit of this APInt is set.
+ /// Determine if sign bit of this APInt is set.
///
/// This tests the high bit of this APInt to determine if it is set.
///
/// \returns true if this APInt has its sign bit set, false otherwise.
bool isSignBitSet() const { return (*this)[BitWidth-1]; }
- /// \brief Determine if sign bit of this APInt is clear.
+ /// Determine if sign bit of this APInt is clear.
///
/// This tests the high bit of this APInt to determine if it is clear.
///
/// \returns true if this APInt has its sign bit clear, false otherwise.
bool isSignBitClear() const { return !isSignBitSet(); }
- /// \brief Determine if this APInt Value is positive.
+ /// Determine if this APInt Value is positive.
///
/// This tests if the value of this APInt is positive (> 0). Note
/// that 0 is not a positive value.
@@ -383,7 +389,7 @@ public:
/// \returns true if this APInt is positive.
bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); }
- /// \brief Determine if all bits are set
+ /// Determine if all bits are set
///
/// This checks to see if the value has all bits of the APInt are set or not.
bool isAllOnesValue() const {
@@ -392,13 +398,13 @@ public:
return countTrailingOnesSlowCase() == BitWidth;
}
- /// \brief Determine if all bits are clear
+ /// Determine if all bits are clear
///
/// This checks to see if the value has all bits of the APInt are clear or
/// not.
bool isNullValue() const { return !*this; }
- /// \brief Determine if this is a value of 1.
+ /// Determine if this is a value of 1.
///
/// This checks to see if the value of this APInt is one.
bool isOneValue() const {
@@ -407,13 +413,13 @@ public:
return countLeadingZerosSlowCase() == BitWidth - 1;
}
- /// \brief Determine if this is the largest unsigned value.
+ /// Determine if this is the largest unsigned value.
///
/// This checks to see if the value of this APInt is the maximum unsigned
/// value for the APInt's bit width.
bool isMaxValue() const { return isAllOnesValue(); }
- /// \brief Determine if this is the largest signed value.
+ /// Determine if this is the largest signed value.
///
/// This checks to see if the value of this APInt is the maximum signed
/// value for the APInt's bit width.
@@ -423,13 +429,13 @@ public:
return !isNegative() && countTrailingOnesSlowCase() == BitWidth - 1;
}
- /// \brief Determine if this is the smallest unsigned value.
+ /// Determine if this is the smallest unsigned value.
///
/// This checks to see if the value of this APInt is the minimum unsigned
/// value for the APInt's bit width.
bool isMinValue() const { return isNullValue(); }
- /// \brief Determine if this is the smallest signed value.
+ /// Determine if this is the smallest signed value.
///
/// This checks to see if the value of this APInt is the minimum signed
/// value for the APInt's bit width.
@@ -439,19 +445,19 @@ public:
return isNegative() && countTrailingZerosSlowCase() == BitWidth - 1;
}
- /// \brief Check if this APInt has an N-bits unsigned integer value.
+ /// Check if this APInt has an N-bits unsigned integer value.
bool isIntN(unsigned N) const {
assert(N && "N == 0 ???");
return getActiveBits() <= N;
}
- /// \brief Check if this APInt has an N-bits signed integer value.
+ /// Check if this APInt has an N-bits signed integer value.
bool isSignedIntN(unsigned N) const {
assert(N && "N == 0 ???");
return getMinSignedBits() <= N;
}
- /// \brief Check if this APInt's value is a power of two greater than zero.
+ /// Check if this APInt's value is a power of two greater than zero.
///
/// \returns true if the argument APInt value is a power of two > 0.
bool isPowerOf2() const {
@@ -460,12 +466,12 @@ public:
return countPopulationSlowCase() == 1;
}
- /// \brief Check if the APInt's value is returned by getSignMask.
+ /// Check if the APInt's value is returned by getSignMask.
///
/// \returns true if this is the value returned by getSignMask.
bool isSignMask() const { return isMinSignedValue(); }
- /// \brief Convert APInt to a boolean value.
+ /// Convert APInt to a boolean value.
///
/// This converts the APInt to a boolean value as a test against zero.
bool getBoolValue() const { return !!*this; }
@@ -476,7 +482,7 @@ public:
return ugt(Limit) ? Limit : getZExtValue();
}
- /// \brief Check if the APInt consists of a repeated bit pattern.
+ /// Check if the APInt consists of a repeated bit pattern.
///
/// e.g. 0x01010101 satisfies isSplat(8).
/// \param SplatSizeInBits The size of the pattern in bits. Must divide bit
@@ -505,7 +511,7 @@ public:
return (Ones > 0) && ((Ones + countLeadingZerosSlowCase()) == BitWidth);
}
- /// \brief Return true if this APInt value contains a sequence of ones with
+ /// Return true if this APInt value contains a sequence of ones with
/// the remainder zero.
bool isShiftedMask() const {
if (isSingleWord())
@@ -519,29 +525,29 @@ public:
/// \name Value Generators
/// @{
- /// \brief Gets maximum unsigned value of APInt for specific bit width.
+ /// Gets maximum unsigned value of APInt for specific bit width.
static APInt getMaxValue(unsigned numBits) {
return getAllOnesValue(numBits);
}
- /// \brief Gets maximum signed value of APInt for a specific bit width.
+ /// Gets maximum signed value of APInt for a specific bit width.
static APInt getSignedMaxValue(unsigned numBits) {
APInt API = getAllOnesValue(numBits);
API.clearBit(numBits - 1);
return API;
}
- /// \brief Gets minimum unsigned value of APInt for a specific bit width.
+ /// Gets minimum unsigned value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0); }
- /// \brief Gets minimum signed value of APInt for a specific bit width.
+ /// Gets minimum signed value of APInt for a specific bit width.
static APInt getSignedMinValue(unsigned numBits) {
APInt API(numBits, 0);
API.setBit(numBits - 1);
return API;
}
- /// \brief Get the SignMask for a specific bit width.
+ /// Get the SignMask for a specific bit width.
///
/// This is just a wrapper function of getSignedMinValue(), and it helps code
/// readability when we want to get a SignMask.
@@ -549,19 +555,19 @@ public:
return getSignedMinValue(BitWidth);
}
- /// \brief Get the all-ones value.
+ /// Get the all-ones value.
///
/// \returns the all-ones value for an APInt of the specified bit-width.
static APInt getAllOnesValue(unsigned numBits) {
return APInt(numBits, WORD_MAX, true);
}
- /// \brief Get the '0' value.
+ /// Get the '0' value.
///
/// \returns the '0' value for an APInt of the specified bit-width.
static APInt getNullValue(unsigned numBits) { return APInt(numBits, 0); }
- /// \brief Compute an APInt containing numBits highbits from this APInt.
+ /// Compute an APInt containing numBits highbits from this APInt.
///
/// Get an APInt with the same BitWidth as this APInt, just zero mask
/// the low bits and right shift to the least significant bit.
@@ -569,7 +575,7 @@ public:
/// \returns the high "numBits" bits of this APInt.
APInt getHiBits(unsigned numBits) const;
- /// \brief Compute an APInt containing numBits lowbits from this APInt.
+ /// Compute an APInt containing numBits lowbits from this APInt.
///
/// Get an APInt with the same BitWidth as this APInt, just zero mask
/// the high bits.
@@ -577,14 +583,14 @@ public:
/// \returns the low "numBits" bits of this APInt.
APInt getLoBits(unsigned numBits) const;
- /// \brief Return an APInt with exactly one bit set in the result.
+ /// Return an APInt with exactly one bit set in the result.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo) {
APInt Res(numBits, 0);
Res.setBit(BitNo);
return Res;
}
- /// \brief Get a value with a block of bits set.
+ /// Get a value with a block of bits set.
///
/// Constructs an APInt value that has a contiguous range of bits set. The
/// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other
@@ -603,7 +609,7 @@ public:
return Res;
}
- /// \brief Get a value with upper bits starting at loBit set.
+ /// Get a value with upper bits starting at loBit set.
///
/// Constructs an APInt value that has a contiguous range of bits set. The
/// bits from loBit (inclusive) to numBits (exclusive) will be set. All other
@@ -620,7 +626,7 @@ public:
return Res;
}
- /// \brief Get a value with high bits set
+ /// Get a value with high bits set
///
/// Constructs an APInt value that has the top hiBitsSet bits set.
///
@@ -632,7 +638,7 @@ public:
return Res;
}
- /// \brief Get a value with low bits set
+ /// Get a value with low bits set
///
/// Constructs an APInt value that has the bottom loBitsSet bits set.
///
@@ -644,10 +650,10 @@ public:
return Res;
}
- /// \brief Return a value containing V broadcasted over NewLen bits.
+ /// Return a value containing V broadcasted over NewLen bits.
static APInt getSplat(unsigned NewLen, const APInt &V);
- /// \brief Determine if two APInts have the same value, after zero-extending
+ /// Determine if two APInts have the same value, after zero-extending
/// one of them (if needed!) to ensure that the bit-widths match.
static bool isSameValue(const APInt &I1, const APInt &I2) {
if (I1.getBitWidth() == I2.getBitWidth())
@@ -659,7 +665,7 @@ public:
return I1.zext(I2.getBitWidth()) == I2;
}
- /// \brief Overload to compute a hash_code for an APInt value.
+ /// Overload to compute a hash_code for an APInt value.
friend hash_code hash_value(const APInt &Arg);
/// This function returns a pointer to the internal storage of the APInt.
@@ -675,7 +681,7 @@ public:
/// \name Unary Operators
/// @{
- /// \brief Postfix increment operator.
+ /// Postfix increment operator.
///
/// Increments *this by 1.
///
@@ -686,12 +692,12 @@ public:
return API;
}
- /// \brief Prefix increment operator.
+ /// Prefix increment operator.
///
/// \returns *this incremented by one
APInt &operator++();
- /// \brief Postfix decrement operator.
+ /// Postfix decrement operator.
///
/// Decrements *this by 1.
///
@@ -702,12 +708,12 @@ public:
return API;
}
- /// \brief Prefix decrement operator.
+ /// Prefix decrement operator.
///
/// \returns *this decremented by one.
APInt &operator--();
- /// \brief Logical negation operator.
+ /// Logical negation operator.
///
/// Performs logical negation operation on this APInt.
///
@@ -722,7 +728,7 @@ public:
/// \name Assignment Operators
/// @{
- /// \brief Copy assignment operator.
+ /// Copy assignment operator.
///
/// \returns *this after assignment of RHS.
APInt &operator=(const APInt &RHS) {
@@ -737,8 +743,13 @@ public:
return *this;
}
- /// @brief Move assignment operator.
+ /// Move assignment operator.
APInt &operator=(APInt &&that) {
+#ifdef _MSC_VER
+ // The MSVC std::shuffle implementation still does self-assignment.
+ if (this == &that)
+ return *this;
+#endif
assert(this != &that && "Self-move not supported");
if (!isSingleWord())
delete[] U.pVal;
@@ -753,7 +764,7 @@ public:
return *this;
}
- /// \brief Assignment operator.
+ /// Assignment operator.
///
/// The RHS value is assigned to *this. If the significant bits in RHS exceed
/// the bit width, the excess bits are truncated. If the bit width is larger
@@ -771,7 +782,7 @@ public:
return *this;
}
- /// \brief Bitwise AND assignment operator.
+ /// Bitwise AND assignment operator.
///
/// Performs a bitwise AND operation on this APInt and RHS. The result is
/// assigned to *this.
@@ -786,7 +797,7 @@ public:
return *this;
}
- /// \brief Bitwise AND assignment operator.
+ /// Bitwise AND assignment operator.
///
/// Performs a bitwise AND operation on this APInt and RHS. RHS is
/// logically zero-extended or truncated to match the bit-width of
@@ -801,7 +812,7 @@ public:
return *this;
}
- /// \brief Bitwise OR assignment operator.
+ /// Bitwise OR assignment operator.
///
/// Performs a bitwise OR operation on this APInt and RHS. The result is
/// assigned *this;
@@ -816,7 +827,7 @@ public:
return *this;
}
- /// \brief Bitwise OR assignment operator.
+ /// Bitwise OR assignment operator.
///
/// Performs a bitwise OR operation on this APInt and RHS. RHS is
/// logically zero-extended or truncated to match the bit-width of
@@ -831,7 +842,7 @@ public:
return *this;
}
- /// \brief Bitwise XOR assignment operator.
+ /// Bitwise XOR assignment operator.
///
/// Performs a bitwise XOR operation on this APInt and RHS. The result is
/// assigned to *this.
@@ -846,7 +857,7 @@ public:
return *this;
}
- /// \brief Bitwise XOR assignment operator.
+ /// Bitwise XOR assignment operator.
///
/// Performs a bitwise XOR operation on this APInt and RHS. RHS is
/// logically zero-extended or truncated to match the bit-width of
@@ -861,7 +872,7 @@ public:
return *this;
}
- /// \brief Multiplication assignment operator.
+ /// Multiplication assignment operator.
///
/// Multiplies this APInt by RHS and assigns the result to *this.
///
@@ -869,7 +880,7 @@ public:
APInt &operator*=(const APInt &RHS);
APInt &operator*=(uint64_t RHS);
- /// \brief Addition assignment operator.
+ /// Addition assignment operator.
///
/// Adds RHS to *this and assigns the result to *this.
///
@@ -877,7 +888,7 @@ public:
APInt &operator+=(const APInt &RHS);
APInt &operator+=(uint64_t RHS);
- /// \brief Subtraction assignment operator.
+ /// Subtraction assignment operator.
///
/// Subtracts RHS from *this and assigns the result to *this.
///
@@ -885,7 +896,7 @@ public:
APInt &operator-=(const APInt &RHS);
APInt &operator-=(uint64_t RHS);
- /// \brief Left-shift assignment function.
+ /// Left-shift assignment function.
///
/// Shifts *this left by shiftAmt and assigns the result to *this.
///
@@ -903,7 +914,7 @@ public:
return *this;
}
- /// \brief Left-shift assignment function.
+ /// Left-shift assignment function.
///
/// Shifts *this left by shiftAmt and assigns the result to *this.
///
@@ -914,22 +925,22 @@ public:
/// \name Binary Operators
/// @{
- /// \brief Multiplication operator.
+ /// Multiplication operator.
///
/// Multiplies this APInt by RHS and returns the result.
APInt operator*(const APInt &RHS) const;
- /// \brief Left logical shift operator.
+ /// Left logical shift operator.
///
/// Shifts this APInt left by \p Bits and returns the result.
APInt operator<<(unsigned Bits) const { return shl(Bits); }
- /// \brief Left logical shift operator.
+ /// Left logical shift operator.
///
/// Shifts this APInt left by \p Bits and returns the result.
APInt operator<<(const APInt &Bits) const { return shl(Bits); }
- /// \brief Arithmetic right-shift function.
+ /// Arithmetic right-shift function.
///
/// Arithmetic right-shift this APInt by shiftAmt.
APInt ashr(unsigned ShiftAmt) const {
@@ -953,7 +964,7 @@ public:
ashrSlowCase(ShiftAmt);
}
- /// \brief Logical right-shift function.
+ /// Logical right-shift function.
///
/// Logical right-shift this APInt by shiftAmt.
APInt lshr(unsigned shiftAmt) const {
@@ -975,7 +986,7 @@ public:
lshrSlowCase(ShiftAmt);
}
- /// \brief Left-shift function.
+ /// Left-shift function.
///
/// Left-shift this APInt by shiftAmt.
APInt shl(unsigned shiftAmt) const {
@@ -984,13 +995,13 @@ public:
return R;
}
- /// \brief Rotate left by rotateAmt.
+ /// Rotate left by rotateAmt.
APInt rotl(unsigned rotateAmt) const;
- /// \brief Rotate right by rotateAmt.
+ /// Rotate right by rotateAmt.
APInt rotr(unsigned rotateAmt) const;
- /// \brief Arithmetic right-shift function.
+ /// Arithmetic right-shift function.
///
/// Arithmetic right-shift this APInt by shiftAmt.
APInt ashr(const APInt &ShiftAmt) const {
@@ -1002,7 +1013,7 @@ public:
/// Arithmetic right-shift this APInt by shiftAmt in place.
void ashrInPlace(const APInt &shiftAmt);
- /// \brief Logical right-shift function.
+ /// Logical right-shift function.
///
/// Logical right-shift this APInt by shiftAmt.
APInt lshr(const APInt &ShiftAmt) const {
@@ -1014,7 +1025,7 @@ public:
/// Logical right-shift this APInt by ShiftAmt in place.
void lshrInPlace(const APInt &ShiftAmt);
- /// \brief Left-shift function.
+ /// Left-shift function.
///
/// Left-shift this APInt by shiftAmt.
APInt shl(const APInt &ShiftAmt) const {
@@ -1023,28 +1034,31 @@ public:
return R;
}
- /// \brief Rotate left by rotateAmt.
+ /// Rotate left by rotateAmt.
APInt rotl(const APInt &rotateAmt) const;
- /// \brief Rotate right by rotateAmt.
+ /// Rotate right by rotateAmt.
APInt rotr(const APInt &rotateAmt) const;
- /// \brief Unsigned division operation.
+ /// Unsigned division operation.
///
/// Perform an unsigned divide operation on this APInt by RHS. Both this and
/// RHS are treated as unsigned quantities for purposes of this division.
///
- /// \returns a new APInt value containing the division result
+ /// \returns a new APInt value containing the division result, rounded towards
+ /// zero.
APInt udiv(const APInt &RHS) const;
APInt udiv(uint64_t RHS) const;
- /// \brief Signed division function for APInt.
+ /// Signed division function for APInt.
///
/// Signed divide this APInt by APInt RHS.
+ ///
+ /// The result is rounded towards zero.
APInt sdiv(const APInt &RHS) const;
APInt sdiv(int64_t RHS) const;
- /// \brief Unsigned remainder operation.
+ /// Unsigned remainder operation.
///
/// Perform an unsigned remainder operation on this APInt with RHS being the
/// divisor. Both this and RHS are treated as unsigned quantities for purposes
@@ -1056,13 +1070,13 @@ public:
APInt urem(const APInt &RHS) const;
uint64_t urem(uint64_t RHS) const;
- /// \brief Function for signed remainder operation.
+ /// Function for signed remainder operation.
///
/// Signed remainder operation on APInt.
APInt srem(const APInt &RHS) const;
int64_t srem(int64_t RHS) const;
- /// \brief Dual division/remainder interface.
+ /// Dual division/remainder interface.
///
/// Sometimes it is convenient to divide two APInt values and obtain both the
/// quotient and remainder. This function does both operations in the same
@@ -1090,7 +1104,7 @@ public:
APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
- /// \brief Array-indexing support.
+ /// Array-indexing support.
///
/// \returns the bit value at bitPosition
bool operator[](unsigned bitPosition) const {
@@ -1102,7 +1116,7 @@ public:
/// \name Comparison Operators
/// @{
- /// \brief Equality operator.
+ /// Equality operator.
///
/// Compares this APInt with RHS for the validity of the equality
/// relationship.
@@ -1113,7 +1127,7 @@ public:
return EqualSlowCase(RHS);
}
- /// \brief Equality operator.
+ /// Equality operator.
///
/// Compares this APInt with a uint64_t for the validity of the equality
/// relationship.
@@ -1123,7 +1137,7 @@ public:
return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() == Val;
}
- /// \brief Equality comparison.
+ /// Equality comparison.
///
/// Compares this APInt with RHS for the validity of the equality
/// relationship.
@@ -1131,7 +1145,7 @@ public:
/// \returns true if *this == Val
bool eq(const APInt &RHS) const { return (*this) == RHS; }
- /// \brief Inequality operator.
+ /// Inequality operator.
///
/// Compares this APInt with RHS for the validity of the inequality
/// relationship.
@@ -1139,7 +1153,7 @@ public:
/// \returns true if *this != Val
bool operator!=(const APInt &RHS) const { return !((*this) == RHS); }
- /// \brief Inequality operator.
+ /// Inequality operator.
///
/// Compares this APInt with a uint64_t for the validity of the inequality
/// relationship.
@@ -1147,7 +1161,7 @@ public:
/// \returns true if *this != Val
bool operator!=(uint64_t Val) const { return !((*this) == Val); }
- /// \brief Inequality comparison
+ /// Inequality comparison
///
/// Compares this APInt with RHS for the validity of the inequality
/// relationship.
@@ -1155,7 +1169,7 @@ public:
/// \returns true if *this != Val
bool ne(const APInt &RHS) const { return !((*this) == RHS); }
- /// \brief Unsigned less than comparison
+ /// Unsigned less than comparison
///
/// Regards both *this and RHS as unsigned quantities and compares them for
/// the validity of the less-than relationship.
@@ -1163,7 +1177,7 @@ public:
/// \returns true if *this < RHS when both are considered unsigned.
bool ult(const APInt &RHS) const { return compare(RHS) < 0; }
- /// \brief Unsigned less than comparison
+ /// Unsigned less than comparison
///
/// Regards both *this as an unsigned quantity and compares it with RHS for
/// the validity of the less-than relationship.
@@ -1174,7 +1188,7 @@ public:
return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() < RHS;
}
- /// \brief Signed less than comparison
+ /// Signed less than comparison
///
/// Regards both *this and RHS as signed quantities and compares them for
/// validity of the less-than relationship.
@@ -1182,7 +1196,7 @@ public:
/// \returns true if *this < RHS when both are considered signed.
bool slt(const APInt &RHS) const { return compareSigned(RHS) < 0; }
- /// \brief Signed less than comparison
+ /// Signed less than comparison
///
/// Regards both *this as a signed quantity and compares it with RHS for
/// the validity of the less-than relationship.
@@ -1193,7 +1207,7 @@ public:
: getSExtValue() < RHS;
}
- /// \brief Unsigned less or equal comparison
+ /// Unsigned less or equal comparison
///
/// Regards both *this and RHS as unsigned quantities and compares them for
/// validity of the less-or-equal relationship.
@@ -1201,7 +1215,7 @@ public:
/// \returns true if *this <= RHS when both are considered unsigned.
bool ule(const APInt &RHS) const { return compare(RHS) <= 0; }
- /// \brief Unsigned less or equal comparison
+ /// Unsigned less or equal comparison
///
/// Regards both *this as an unsigned quantity and compares it with RHS for
/// the validity of the less-or-equal relationship.
@@ -1209,7 +1223,7 @@ public:
/// \returns true if *this <= RHS when considered unsigned.
bool ule(uint64_t RHS) const { return !ugt(RHS); }
- /// \brief Signed less or equal comparison
+ /// Signed less or equal comparison
///
/// Regards both *this and RHS as signed quantities and compares them for
/// validity of the less-or-equal relationship.
@@ -1217,7 +1231,7 @@ public:
/// \returns true if *this <= RHS when both are considered signed.
bool sle(const APInt &RHS) const { return compareSigned(RHS) <= 0; }
- /// \brief Signed less or equal comparison
+ /// Signed less or equal comparison
///
/// Regards both *this as a signed quantity and compares it with RHS for the
/// validity of the less-or-equal relationship.
@@ -1225,7 +1239,7 @@ public:
/// \returns true if *this <= RHS when considered signed.
bool sle(uint64_t RHS) const { return !sgt(RHS); }
- /// \brief Unsigned greather than comparison
+ /// Unsigned greather than comparison
///
/// Regards both *this and RHS as unsigned quantities and compares them for
/// the validity of the greater-than relationship.
@@ -1233,7 +1247,7 @@ public:
/// \returns true if *this > RHS when both are considered unsigned.
bool ugt(const APInt &RHS) const { return !ule(RHS); }
- /// \brief Unsigned greater than comparison
+ /// Unsigned greater than comparison
///
/// Regards both *this as an unsigned quantity and compares it with RHS for
/// the validity of the greater-than relationship.
@@ -1244,7 +1258,7 @@ public:
return (!isSingleWord() && getActiveBits() > 64) || getZExtValue() > RHS;
}
- /// \brief Signed greather than comparison
+ /// Signed greather than comparison
///
/// Regards both *this and RHS as signed quantities and compares them for the
/// validity of the greater-than relationship.
@@ -1252,7 +1266,7 @@ public:
/// \returns true if *this > RHS when both are considered signed.
bool sgt(const APInt &RHS) const { return !sle(RHS); }
- /// \brief Signed greater than comparison
+ /// Signed greater than comparison
///
/// Regards both *this as a signed quantity and compares it with RHS for
/// the validity of the greater-than relationship.
@@ -1263,7 +1277,7 @@ public:
: getSExtValue() > RHS;
}
- /// \brief Unsigned greater or equal comparison
+ /// Unsigned greater or equal comparison
///
/// Regards both *this and RHS as unsigned quantities and compares them for
/// validity of the greater-or-equal relationship.
@@ -1271,7 +1285,7 @@ public:
/// \returns true if *this >= RHS when both are considered unsigned.
bool uge(const APInt &RHS) const { return !ult(RHS); }
- /// \brief Unsigned greater or equal comparison
+ /// Unsigned greater or equal comparison
///
/// Regards both *this as an unsigned quantity and compares it with RHS for
/// the validity of the greater-or-equal relationship.
@@ -1279,7 +1293,7 @@ public:
/// \returns true if *this >= RHS when considered unsigned.
bool uge(uint64_t RHS) const { return !ult(RHS); }
- /// \brief Signed greather or equal comparison
+ /// Signed greater or equal comparison
///
/// Regards both *this and RHS as signed quantities and compares them for
/// validity of the greater-or-equal relationship.
@@ -1287,7 +1301,7 @@ public:
/// \returns true if *this >= RHS when both are considered signed.
bool sge(const APInt &RHS) const { return !slt(RHS); }
- /// \brief Signed greater or equal comparison
+ /// Signed greater or equal comparison
///
/// Regards both *this as a signed quantity and compares it with RHS for
/// the validity of the greater-or-equal relationship.
@@ -1316,13 +1330,13 @@ public:
/// \name Resizing Operators
/// @{
- /// \brief Truncate to new width.
+ /// Truncate to new width.
///
/// Truncate the APInt to a specified width. It is an error to specify a width
/// that is greater than or equal to the current width.
APInt trunc(unsigned width) const;
- /// \brief Sign extend to a new width.
+ /// Sign extend to a new width.
///
/// This operation sign extends the APInt to a new width. If the high order
/// bit is set, the fill on the left will be done with 1 bits, otherwise zero.
@@ -1330,32 +1344,32 @@ public:
/// current width.
APInt sext(unsigned width) const;
- /// \brief Zero extend to a new width.
+ /// Zero extend to a new width.
///
/// This operation zero extends the APInt to a new width. The high order bits
/// are filled with 0 bits. It is an error to specify a width that is less
/// than or equal to the current width.
APInt zext(unsigned width) const;
- /// \brief Sign extend or truncate to width
+ /// Sign extend or truncate to width
///
/// Make this APInt have the bit width given by \p width. The value is sign
/// extended, truncated, or left alone to make it that width.
APInt sextOrTrunc(unsigned width) const;
- /// \brief Zero extend or truncate to width
+ /// Zero extend or truncate to width
///
/// Make this APInt have the bit width given by \p width. The value is zero
/// extended, truncated, or left alone to make it that width.
APInt zextOrTrunc(unsigned width) const;
- /// \brief Sign extend or truncate to width
+ /// Sign extend or truncate to width
///
/// Make this APInt have the bit width given by \p width. The value is sign
/// extended, or left alone to make it that width.
APInt sextOrSelf(unsigned width) const;
- /// \brief Zero extend or truncate to width
+ /// Zero extend or truncate to width
///
/// Make this APInt have the bit width given by \p width. The value is zero
/// extended, or left alone to make it that width.
@@ -1365,7 +1379,7 @@ public:
/// \name Bit Manipulation Operators
/// @{
- /// \brief Set every bit to 1.
+ /// Set every bit to 1.
void setAllBits() {
if (isSingleWord())
U.VAL = WORD_MAX;
@@ -1376,7 +1390,7 @@ public:
clearUnusedBits();
}
- /// \brief Set a given bit to 1.
+ /// Set a given bit to 1.
///
/// Set the given bit to 1 whose position is given as "bitPosition".
void setBit(unsigned BitPosition) {
@@ -1427,7 +1441,7 @@ public:
return setBits(BitWidth - hiBits, BitWidth);
}
- /// \brief Set every bit to 0.
+ /// Set every bit to 0.
void clearAllBits() {
if (isSingleWord())
U.VAL = 0;
@@ -1435,7 +1449,7 @@ public:
memset(U.pVal, 0, getNumWords() * APINT_WORD_SIZE);
}
- /// \brief Set a given bit to 0.
+ /// Set a given bit to 0.
///
/// Set the given bit to 0 whose position is given as "bitPosition".
void clearBit(unsigned BitPosition) {
@@ -1452,7 +1466,7 @@ public:
clearBit(BitWidth - 1);
}
- /// \brief Toggle every bit to its opposite value.
+ /// Toggle every bit to its opposite value.
void flipAllBits() {
if (isSingleWord()) {
U.VAL ^= WORD_MAX;
@@ -1462,7 +1476,7 @@ public:
}
}
- /// \brief Toggles a given bit to its opposite value.
+ /// Toggles a given bit to its opposite value.
///
/// Toggle a given bit to its opposite value whose position is given
/// as "bitPosition".
@@ -1484,17 +1498,17 @@ public:
/// \name Value Characterization Functions
/// @{
- /// \brief Return the number of bits in the APInt.
+ /// Return the number of bits in the APInt.
unsigned getBitWidth() const { return BitWidth; }
- /// \brief Get the number of words.
+ /// Get the number of words.
///
/// Here one word's bitwidth equals to that of uint64_t.
///
/// \returns the number of words to hold the integer value of this APInt.
unsigned getNumWords() const { return getNumWords(BitWidth); }
- /// \brief Get the number of words.
+ /// Get the number of words.
///
/// *NOTE* Here one word's bitwidth equals to that of uint64_t.
///
@@ -1504,14 +1518,14 @@ public:
return ((uint64_t)BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
}
- /// \brief Compute the number of active bits in the value
+ /// Compute the number of active bits in the value
///
/// This function returns the number of active bits which is defined as the
/// bit width minus the number of leading zeros. This is used in several
/// computations to see how "wide" the value is.
unsigned getActiveBits() const { return BitWidth - countLeadingZeros(); }
- /// \brief Compute the number of active words in the value of this APInt.
+ /// Compute the number of active words in the value of this APInt.
///
/// This is used in conjunction with getActiveData to extract the raw value of
/// the APInt.
@@ -1520,7 +1534,7 @@ public:
return numActiveBits ? whichWord(numActiveBits - 1) + 1 : 1;
}
- /// \brief Get the minimum bit size for this signed APInt
+ /// Get the minimum bit size for this signed APInt
///
/// Computes the minimum bit width for this APInt while considering it to be a
/// signed (and probably negative) value. If the value is not negative, this
@@ -1534,7 +1548,7 @@ public:
return getActiveBits() + 1;
}
- /// \brief Get zero extended value
+ /// Get zero extended value
///
/// This method attempts to return the value of this APInt as a zero extended
/// uint64_t. The bitwidth must be <= 64 or the value must fit within a
@@ -1546,7 +1560,7 @@ public:
return U.pVal[0];
}
- /// \brief Get sign extended value
+ /// Get sign extended value
///
/// This method attempts to return the value of this APInt as a sign extended
/// int64_t. The bit width must be <= 64 or the value must fit within an
@@ -1558,13 +1572,13 @@ public:
return int64_t(U.pVal[0]);
}
- /// \brief Get bits required for string value.
+ /// Get bits required for string value.
///
/// This method determines how many bits are required to hold the APInt
/// equivalent of the string given by \p str.
static unsigned getBitsNeeded(StringRef str, uint8_t radix);
- /// \brief The APInt version of the countLeadingZeros functions in
+ /// The APInt version of the countLeadingZeros functions in
/// MathExtras.h.
///
/// It counts the number of zeros from the most significant bit to the first
@@ -1580,7 +1594,7 @@ public:
return countLeadingZerosSlowCase();
}
- /// \brief Count the number of leading one bits.
+ /// Count the number of leading one bits.
///
/// This function is an APInt version of the countLeadingOnes
/// functions in MathExtras.h. It counts the number of ones from the most
@@ -1600,7 +1614,7 @@ public:
return isNegative() ? countLeadingOnes() : countLeadingZeros();
}
- /// \brief Count the number of trailing zero bits.
+ /// Count the number of trailing zero bits.
///
/// This function is an APInt version of the countTrailingZeros
/// functions in MathExtras.h. It counts the number of zeros from the least
@@ -1614,7 +1628,7 @@ public:
return countTrailingZerosSlowCase();
}
- /// \brief Count the number of trailing one bits.
+ /// Count the number of trailing one bits.
///
/// This function is an APInt version of the countTrailingOnes
/// functions in MathExtras.h. It counts the number of ones from the least
@@ -1628,7 +1642,7 @@ public:
return countTrailingOnesSlowCase();
}
- /// \brief Count the number of bits set.
+ /// Count the number of bits set.
///
/// This function is an APInt version of the countPopulation functions
/// in MathExtras.h. It counts the number of 1 bits in the APInt value.
@@ -1662,7 +1676,7 @@ public:
toString(Str, Radix, true, false);
}
- /// \brief Return the APInt as a std::string.
+ /// Return the APInt as a std::string.
///
/// Note that this is an inefficient method. It is better to pass in a
/// SmallVector/SmallString to the methods above to avoid thrashing the heap
@@ -1676,16 +1690,16 @@ public:
/// Value.
APInt reverseBits() const;
- /// \brief Converts this APInt to a double value.
+ /// Converts this APInt to a double value.
double roundToDouble(bool isSigned) const;
- /// \brief Converts this unsigned APInt to a double value.
+ /// Converts this unsigned APInt to a double value.
double roundToDouble() const { return roundToDouble(false); }
- /// \brief Converts this signed APInt to a double value.
+ /// Converts this signed APInt to a double value.
double signedRoundToDouble() const { return roundToDouble(true); }
- /// \brief Converts APInt bits to a double
+ /// Converts APInt bits to a double
///
/// The conversion does not do a translation from integer to double, it just
/// re-interprets the bits as a double. Note that it is valid to do this on
@@ -1694,7 +1708,7 @@ public:
return BitsToDouble(getWord(0));
}
- /// \brief Converts APInt bits to a double
+ /// Converts APInt bits to a double
///
/// The conversion does not do a translation from integer to float, it just
/// re-interprets the bits as a float. Note that it is valid to do this on
@@ -1703,7 +1717,7 @@ public:
return BitsToFloat(getWord(0));
}
- /// \brief Converts a double to APInt bits.
+ /// Converts a double to APInt bits.
///
/// The conversion does not do a translation from double to integer, it just
/// re-interprets the bits of the double.
@@ -1711,7 +1725,7 @@ public:
return APInt(sizeof(double) * CHAR_BIT, DoubleToBits(V));
}
- /// \brief Converts a float to APInt bits.
+ /// Converts a float to APInt bits.
///
/// The conversion does not do a translation from float to integer, it just
/// re-interprets the bits of the float.
@@ -1770,10 +1784,10 @@ public:
return logBase2();
}
- /// \brief Compute the square root
+ /// Compute the square root
APInt sqrt() const;
- /// \brief Get the absolute value;
+ /// Get the absolute value;
///
/// If *this is < 0 then return -(*this), otherwise *this;
APInt abs() const {
@@ -1924,7 +1938,7 @@ public:
/// Set the least significant BITS and clear the rest.
static void tcSetLeastSignificantBits(WordType *, unsigned, unsigned bits);
- /// \brief debug method
+ /// debug method
void dump() const;
/// @}
@@ -1947,7 +1961,7 @@ inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; }
inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; }
-/// \brief Unary bitwise complement operator.
+/// Unary bitwise complement operator.
///
/// \returns an APInt that is the bitwise complement of \p v.
inline APInt operator~(APInt v) {
@@ -2080,27 +2094,27 @@ inline APInt operator*(uint64_t LHS, APInt b) {
namespace APIntOps {
-/// \brief Determine the smaller of two APInts considered to be signed.
+/// Determine the smaller of two APInts considered to be signed.
inline const APInt &smin(const APInt &A, const APInt &B) {
return A.slt(B) ? A : B;
}
-/// \brief Determine the larger of two APInts considered to be signed.
+/// Determine the larger of two APInts considered to be signed.
inline const APInt &smax(const APInt &A, const APInt &B) {
return A.sgt(B) ? A : B;
}
-/// \brief Determine the smaller of two APInts considered to be signed.
+/// Determine the smaller of two APInts considered to be signed.
inline const APInt &umin(const APInt &A, const APInt &B) {
return A.ult(B) ? A : B;
}
-/// \brief Determine the larger of two APInts considered to be unsigned.
+/// Determine the larger of two APInts considered to be unsigned.
inline const APInt &umax(const APInt &A, const APInt &B) {
return A.ugt(B) ? A : B;
}
-/// \brief Compute GCD of two unsigned APInt values.
+/// Compute GCD of two unsigned APInt values.
///
/// This function returns the greatest common divisor of the two APInt values
/// using Stein's algorithm.
@@ -2108,44 +2122,50 @@ inline const APInt &umax(const APInt &A, const APInt &B) {
/// \returns the greatest common divisor of A and B.
APInt GreatestCommonDivisor(APInt A, APInt B);
-/// \brief Converts the given APInt to a double value.
+/// Converts the given APInt to a double value.
///
/// Treats the APInt as an unsigned value for conversion purposes.
inline double RoundAPIntToDouble(const APInt &APIVal) {
return APIVal.roundToDouble();
}
-/// \brief Converts the given APInt to a double value.
+/// Converts the given APInt to a double value.
///
/// Treats the APInt as a signed value for conversion purposes.
inline double RoundSignedAPIntToDouble(const APInt &APIVal) {
return APIVal.signedRoundToDouble();
}
-/// \brief Converts the given APInt to a float vlalue.
+/// Converts the given APInt to a float vlalue.
inline float RoundAPIntToFloat(const APInt &APIVal) {
return float(RoundAPIntToDouble(APIVal));
}
-/// \brief Converts the given APInt to a float value.
+/// Converts the given APInt to a float value.
///
/// Treast the APInt as a signed value for conversion purposes.
inline float RoundSignedAPIntToFloat(const APInt &APIVal) {
return float(APIVal.signedRoundToDouble());
}
-/// \brief Converts the given double value into a APInt.
+/// Converts the given double value into a APInt.
///
/// This function convert a double value to an APInt value.
APInt RoundDoubleToAPInt(double Double, unsigned width);
-/// \brief Converts a float value into a APInt.
+/// Converts a float value into a APInt.
///
/// Converts a float value into an APInt value.
inline APInt RoundFloatToAPInt(float Float, unsigned width) {
return RoundDoubleToAPInt(double(Float), width);
}
+/// Return A unsign-divided by B, rounded by the given rounding mode.
+APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
+
+/// Return A sign-divided by B, rounded by the given rounding mode.
+APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
+
} // End of APIntOps namespace
// See friend declaration above. This additional declaration is required in
diff --git a/contrib/llvm/include/llvm/ADT/APSInt.h b/contrib/llvm/include/llvm/ADT/APSInt.h
index dabbf3314bd0..7ee2c4c62fce 100644
--- a/contrib/llvm/include/llvm/ADT/APSInt.h
+++ b/contrib/llvm/include/llvm/ADT/APSInt.h
@@ -72,7 +72,7 @@ public:
}
using APInt::toString;
- /// \brief Get the correctly-extended \c int64_t value.
+ /// 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();
@@ -279,13 +279,13 @@ public:
: APInt::getSignedMinValue(numBits), Unsigned);
}
- /// \brief Determine if two APSInts have the same value, zero- or
+ /// 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.
+ /// 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.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
diff --git a/contrib/llvm/include/llvm/ADT/Any.h b/contrib/llvm/include/llvm/ADT/Any.h
new file mode 100644
index 000000000000..c64c39987542
--- /dev/null
+++ b/contrib/llvm/include/llvm/ADT/Any.h
@@ -0,0 +1,150 @@
+//===- Any.h - Generic type erased holder of any type -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Any, a non-template class modeled in the spirit of
+// std::any. The idea is to provide a type-safe replacement for C's void*.
+// It can hold a value of any copy-constructible copy-assignable type
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ANY_H
+#define LLVM_ADT_ANY_H
+
+#include "llvm/ADT/STLExtras.h"
+
+#include <cassert>
+#include <memory>
+#include <type_traits>
+
+namespace llvm {
+
+class Any {
+ template <typename T> struct TypeId { static const char Id; };
+
+ struct StorageBase {
+ virtual ~StorageBase() = default;
+ virtual std::unique_ptr<StorageBase> clone() const = 0;
+ virtual const void *id() const = 0;
+ };
+
+ template <typename T> struct StorageImpl : public StorageBase {
+ explicit StorageImpl(const T &Value) : Value(Value) {}
+
+ explicit StorageImpl(T &&Value) : Value(std::move(Value)) {}
+
+ std::unique_ptr<StorageBase> clone() const override {
+ return llvm::make_unique<StorageImpl<T>>(Value);
+ }
+
+ const void *id() const override { return &TypeId<T>::Id; }
+
+ T Value;
+
+ private:
+ StorageImpl &operator=(const StorageImpl &Other) = delete;
+ StorageImpl(const StorageImpl &Other) = delete;
+ };
+
+public:
+ Any() = default;
+
+ Any(const Any &Other)
+ : Storage(Other.Storage ? Other.Storage->clone() : nullptr) {}
+
+ // When T is Any or T is not copy-constructible we need to explicitly disable
+ // the forwarding constructor so that the copy constructor gets selected
+ // instead.
+ template <
+ typename T,
+ typename std::enable_if<
+ llvm::conjunction<
+ llvm::negation<std::is_same<typename std::decay<T>::type, Any>>,
+ std::is_copy_constructible<typename std::decay<T>::type>>::value,
+ int>::type = 0>
+ Any(T &&Value) {
+ using U = typename std::decay<T>::type;
+ Storage = llvm::make_unique<StorageImpl<U>>(std::forward<T>(Value));
+ }
+
+ Any(Any &&Other) : Storage(std::move(Other.Storage)) {}
+
+ Any &swap(Any &Other) {
+ std::swap(Storage, Other.Storage);
+ return *this;
+ }
+
+ Any &operator=(Any Other) {
+ Storage = std::move(Other.Storage);
+ return *this;
+ }
+
+ bool hasValue() const { return !!Storage; }
+
+ void reset() { Storage.reset(); }
+
+private:
+ template <class T> friend T any_cast(const Any &Value);
+ template <class T> friend T any_cast(Any &Value);
+ template <class T> friend T any_cast(Any &&Value);
+ template <class T> friend const T *any_cast(const Any *Value);
+ template <class T> friend T *any_cast(Any *Value);
+ template <typename T> friend bool any_isa(const Any &Value);
+
+ std::unique_ptr<StorageBase> Storage;
+};
+
+template <typename T> const char Any::TypeId<T>::Id = 0;
+
+
+template <typename T> bool any_isa(const Any &Value) {
+ if (!Value.Storage)
+ return false;
+ using U =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+ return Value.Storage->id() == &Any::TypeId<U>::Id;
+}
+
+template <class T> T any_cast(const Any &Value) {
+ using U =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+ return static_cast<T>(*any_cast<U>(&Value));
+}
+
+template <class T> T any_cast(Any &Value) {
+ using U =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+ return static_cast<T>(*any_cast<U>(&Value));
+}
+
+template <class T> T any_cast(Any &&Value) {
+ using U =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+ return static_cast<T>(std::move(*any_cast<U>(&Value)));
+}
+
+template <class T> const T *any_cast(const Any *Value) {
+ using U =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+ assert(Value && any_isa<T>(*Value) && "Bad any cast!");
+ if (!Value || !any_isa<U>(*Value))
+ return nullptr;
+ return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value;
+}
+
+template <class T> T *any_cast(Any *Value) {
+ using U = typename std::decay<T>::type;
+ assert(Value && any_isa<U>(*Value) && "Bad any cast!");
+ if (!Value || !any_isa<U>(*Value))
+ return nullptr;
+ return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ANY_H
diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h
index 5f7a769ddac4..9cb25b09c6cb 100644
--- a/contrib/llvm/include/llvm/ADT/ArrayRef.h
+++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h
@@ -184,51 +184,51 @@ namespace llvm {
/// slice(n) - Chop off the first N elements of the array.
ArrayRef<T> slice(size_t N) const { return slice(N, size() - N); }
- /// \brief Drop the first \p N elements of the array.
+ /// Drop the first \p N elements of the array.
ArrayRef<T> drop_front(size_t N = 1) const {
assert(size() >= N && "Dropping more elements than exist");
return slice(N, size() - N);
}
- /// \brief Drop the last \p N elements of the array.
+ /// Drop the last \p N elements of the array.
ArrayRef<T> drop_back(size_t N = 1) const {
assert(size() >= N && "Dropping more elements than exist");
return slice(0, size() - N);
}
- /// \brief Return a copy of *this with the first N elements satisfying the
+ /// Return a copy of *this with the first N elements satisfying the
/// given predicate removed.
template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred) const {
return ArrayRef<T>(find_if_not(*this, Pred), end());
}
- /// \brief Return a copy of *this with the first N elements not satisfying
+ /// Return a copy of *this with the first N elements not satisfying
/// the given predicate removed.
template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred) const {
return ArrayRef<T>(find_if(*this, Pred), end());
}
- /// \brief Return a copy of *this with only the first \p N elements.
+ /// Return a copy of *this with only the first \p N elements.
ArrayRef<T> take_front(size_t N = 1) const {
if (N >= size())
return *this;
return drop_back(size() - N);
}
- /// \brief Return a copy of *this with only the last \p N elements.
+ /// Return a copy of *this with only the last \p N elements.
ArrayRef<T> take_back(size_t N = 1) const {
if (N >= size())
return *this;
return drop_front(size() - N);
}
- /// \brief Return the first N elements of this Array that satisfy the given
+ /// Return the first N elements of this Array that satisfy the given
/// predicate.
template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred) const {
return ArrayRef<T>(begin(), find_if_not(*this, Pred));
}
- /// \brief Return the first N elements of this Array that don't satisfy the
+ /// Return the first N elements of this Array that don't satisfy the
/// given predicate.
template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred) const {
return ArrayRef<T>(begin(), find_if(*this, Pred));
@@ -358,7 +358,7 @@ namespace llvm {
return slice(N, this->size() - N);
}
- /// \brief Drop the first \p N elements of the array.
+ /// Drop the first \p N elements of the array.
MutableArrayRef<T> drop_front(size_t N = 1) const {
assert(this->size() >= N && "Dropping more elements than exist");
return slice(N, this->size() - N);
@@ -369,42 +369,42 @@ namespace llvm {
return slice(0, this->size() - N);
}
- /// \brief Return a copy of *this with the first N elements satisfying the
+ /// Return a copy of *this with the first N elements satisfying the
/// given predicate removed.
template <class PredicateT>
MutableArrayRef<T> drop_while(PredicateT Pred) const {
return MutableArrayRef<T>(find_if_not(*this, Pred), end());
}
- /// \brief Return a copy of *this with the first N elements not satisfying
+ /// Return a copy of *this with the first N elements not satisfying
/// the given predicate removed.
template <class PredicateT>
MutableArrayRef<T> drop_until(PredicateT Pred) const {
return MutableArrayRef<T>(find_if(*this, Pred), end());
}
- /// \brief Return a copy of *this with only the first \p N elements.
+ /// Return a copy of *this with only the first \p N elements.
MutableArrayRef<T> take_front(size_t N = 1) const {
if (N >= this->size())
return *this;
return drop_back(this->size() - N);
}
- /// \brief Return a copy of *this with only the last \p N elements.
+ /// Return a copy of *this with only the last \p N elements.
MutableArrayRef<T> take_back(size_t N = 1) const {
if (N >= this->size())
return *this;
return drop_front(this->size() - N);
}
- /// \brief Return the first N elements of this Array that satisfy the given
+ /// Return the first N elements of this Array that satisfy the given
/// predicate.
template <class PredicateT>
MutableArrayRef<T> take_while(PredicateT Pred) const {
return MutableArrayRef<T>(begin(), find_if_not(*this, Pred));
}
- /// \brief Return the first N elements of this Array that don't satisfy the
+ /// Return the first N elements of this Array that don't satisfy the
/// given predicate.
template <class PredicateT>
MutableArrayRef<T> take_until(PredicateT Pred) const {
diff --git a/contrib/llvm/include/llvm/ADT/BitVector.h b/contrib/llvm/include/llvm/ADT/BitVector.h
index 99147fec4d4c..438c7d84c581 100644
--- a/contrib/llvm/include/llvm/ADT/BitVector.h
+++ b/contrib/llvm/include/llvm/ADT/BitVector.h
@@ -779,7 +779,7 @@ public:
}
private:
- /// \brief Perform a logical left shift of \p Count words by moving everything
+ /// Perform a logical left shift of \p Count words by moving everything
/// \p Count words to the right in memory.
///
/// While confusing, words are stored from least significant at Bits[0] to
@@ -810,7 +810,7 @@ private:
clear_unused_bits();
}
- /// \brief Perform a logical right shift of \p Count words by moving those
+ /// Perform a logical right shift of \p Count words by moving those
/// words to the left in memory. See wordShl for more information.
///
void wordShr(uint32_t Count) {
@@ -828,7 +828,8 @@ private:
}
MutableArrayRef<BitWord> allocate(size_t NumWords) {
- BitWord *RawBits = (BitWord *)std::malloc(NumWords * sizeof(BitWord));
+ BitWord *RawBits = static_cast<BitWord *>(
+ safe_malloc(NumWords * sizeof(BitWord)));
return MutableArrayRef<BitWord>(RawBits, NumWords);
}
@@ -867,8 +868,8 @@ private:
void grow(unsigned NewSize) {
size_t NewCapacity = std::max<size_t>(NumBitWords(NewSize), Bits.size() * 2);
assert(NewCapacity > 0 && "realloc-ing zero space");
- BitWord *NewBits =
- (BitWord *)std::realloc(Bits.data(), NewCapacity * sizeof(BitWord));
+ BitWord *NewBits = static_cast<BitWord *>(
+ safe_realloc(Bits.data(), NewCapacity * sizeof(BitWord)));
Bits = MutableArrayRef<BitWord>(NewBits, NewCapacity);
clear_unused_bits();
}
diff --git a/contrib/llvm/include/llvm/ADT/CachedHashString.h b/contrib/llvm/include/llvm/ADT/CachedHashString.h
index a56a6213a073..d8f0e7afdd49 100644
--- a/contrib/llvm/include/llvm/ADT/CachedHashString.h
+++ b/contrib/llvm/include/llvm/ADT/CachedHashString.h
@@ -43,6 +43,7 @@ public:
}
StringRef val() const { return StringRef(P, Size); }
+ const char *data() const { return P; }
uint32_t size() const { return Size; }
uint32_t hash() const { return Hash; }
};
diff --git a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h
index a96904c7dbbf..5d12b424fb37 100644
--- a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -262,6 +262,13 @@ template <typename T> struct DenseMapInfo<ArrayRef<T>> {
}
};
+template <> struct DenseMapInfo<hash_code> {
+ static inline hash_code getEmptyKey() { return hash_code(-1); }
+ static inline hash_code getTombstoneKey() { return hash_code(-2); }
+ static unsigned getHashValue(hash_code val) { return val; }
+ static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
+};
+
} // end namespace llvm
#endif // LLVM_ADT_DENSEMAPINFO_H
diff --git a/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h b/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h
index e964d7fa2391..1f3766d3c9de 100644
--- a/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h
+++ b/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h
@@ -177,7 +177,7 @@ public:
return *this;
}
- /// \brief Skips all children of the current node and traverses to next node
+ /// Skips all children of the current node and traverses to next node
///
/// Note: This function takes care of incrementing the iterator. If you
/// always increment and call this function, you risk walking off the end.
diff --git a/contrib/llvm/include/llvm/ADT/EpochTracker.h b/contrib/llvm/include/llvm/ADT/EpochTracker.h
index db39ba4e0c50..49ef192364e8 100644
--- a/contrib/llvm/include/llvm/ADT/EpochTracker.h
+++ b/contrib/llvm/include/llvm/ADT/EpochTracker.h
@@ -17,7 +17,6 @@
#define LLVM_ADT_EPOCH_TRACKER_H
#include "llvm/Config/abi-breaking.h"
-#include "llvm/Config/llvm-config.h"
#include <cstdint>
@@ -25,7 +24,7 @@ namespace llvm {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
-/// \brief A base class for data structure classes wishing to make iterators
+/// A base class for data structure classes wishing to make iterators
/// ("handles") pointing into themselves fail-fast. When building without
/// asserts, this class is empty and does nothing.
///
@@ -40,15 +39,15 @@ class DebugEpochBase {
public:
DebugEpochBase() : Epoch(0) {}
- /// \brief Calling incrementEpoch invalidates all handles pointing into the
+ /// Calling incrementEpoch invalidates all handles pointing into the
/// calling instance.
void incrementEpoch() { ++Epoch; }
- /// \brief The destructor calls incrementEpoch to make use-after-free bugs
+ /// The destructor calls incrementEpoch to make use-after-free bugs
/// more likely to crash deterministically.
~DebugEpochBase() { incrementEpoch(); }
- /// \brief A base class for iterator classes ("handles") that wish to poll for
+ /// A base class for iterator classes ("handles") that wish to poll for
/// iterator invalidating modifications in the underlying data structure.
/// When LLVM is built without asserts, this class is empty and does nothing.
///
@@ -66,12 +65,12 @@ public:
explicit HandleBase(const DebugEpochBase *Parent)
: EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
- /// \brief Returns true if the DebugEpochBase this Handle is linked to has
+ /// Returns true if the DebugEpochBase this Handle is linked to has
/// not called incrementEpoch on itself since the creation of this
/// HandleBase instance.
bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
- /// \brief Returns a pointer to the epoch word stored in the data structure
+ /// Returns a pointer to the epoch word stored in the data structure
/// this handle points into. Can be used to check if two iterators point
/// into the same data structure.
const void *getEpochAddress() const { return EpochAddress; }
diff --git a/contrib/llvm/include/llvm/ADT/FunctionExtras.h b/contrib/llvm/include/llvm/ADT/FunctionExtras.h
new file mode 100644
index 000000000000..2b75dc6ac219
--- /dev/null
+++ b/contrib/llvm/include/llvm/ADT/FunctionExtras.h
@@ -0,0 +1,293 @@
+//===- FunctionExtras.h - Function type erasure utilities -------*- 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 collection of function (or more generally, callable)
+/// type erasure utilities supplementing those provided by the standard library
+/// in `<function>`.
+///
+/// It provides `unique_function`, which works like `std::function` but supports
+/// move-only callable objects.
+///
+/// Future plans:
+/// - Add a `function` that provides const, volatile, and ref-qualified support,
+/// which doesn't work with `std::function`.
+/// - Provide support for specifying multiple signatures to type erase callable
+/// objects with an overload set, such as those produced by generic lambdas.
+/// - Expand to include a copyable utility that directly replaces std::function
+/// but brings the above improvements.
+///
+/// Note that LLVM's utilities are greatly simplified by not supporting
+/// allocators.
+///
+/// If the standard library ever begins to provide comparable facilities we can
+/// consider switching to those.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_FUNCTION_EXTRAS_H
+#define LLVM_ADT_FUNCTION_EXTRAS_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/type_traits.h"
+#include <memory>
+
+namespace llvm {
+
+template <typename FunctionT> class unique_function;
+
+template <typename ReturnT, typename... ParamTs>
+class unique_function<ReturnT(ParamTs...)> {
+ static constexpr size_t InlineStorageSize = sizeof(void *) * 3;
+
+ // MSVC has a bug and ICEs if we give it a particular dependent value
+ // expression as part of the `std::conditional` below. To work around this,
+ // we build that into a template struct's constexpr bool.
+ template <typename T> struct IsSizeLessThanThresholdT {
+ static constexpr bool value = sizeof(T) <= (2 * sizeof(void *));
+ };
+
+ // Provide a type function to map parameters that won't observe extra copies
+ // or moves and which are small enough to likely pass in register to values
+ // and all other types to l-value reference types. We use this to compute the
+ // types used in our erased call utility to minimize copies and moves unless
+ // doing so would force things unnecessarily into memory.
+ //
+ // The heuristic used is related to common ABI register passing conventions.
+ // It doesn't have to be exact though, and in one way it is more strict
+ // because we want to still be able to observe either moves *or* copies.
+ template <typename T>
+ using AdjustedParamT = typename std::conditional<
+ !std::is_reference<T>::value &&
+ llvm::is_trivially_copy_constructible<T>::value &&
+ llvm::is_trivially_move_constructible<T>::value &&
+ IsSizeLessThanThresholdT<T>::value,
+ T, T &>::type;
+
+ // The type of the erased function pointer we use as a callback to dispatch to
+ // the stored callable when it is trivial to move and destroy.
+ using CallPtrT = ReturnT (*)(void *CallableAddr,
+ AdjustedParamT<ParamTs>... Params);
+ using MovePtrT = void (*)(void *LHSCallableAddr, void *RHSCallableAddr);
+ using DestroyPtrT = void (*)(void *CallableAddr);
+
+ /// A struct to hold a single trivial callback with sufficient alignment for
+ /// our bitpacking.
+ struct alignas(8) TrivialCallback {
+ CallPtrT CallPtr;
+ };
+
+ /// A struct we use to aggregate three callbacks when we need full set of
+ /// operations.
+ struct alignas(8) NonTrivialCallbacks {
+ CallPtrT CallPtr;
+ MovePtrT MovePtr;
+ DestroyPtrT DestroyPtr;
+ };
+
+ // Create a pointer union between either a pointer to a static trivial call
+ // pointer in a struct or a pointer to a static struct of the call, move, and
+ // destroy pointers.
+ using CallbackPointerUnionT =
+ PointerUnion<TrivialCallback *, NonTrivialCallbacks *>;
+
+ // The main storage buffer. This will either have a pointer to out-of-line
+ // storage or an inline buffer storing the callable.
+ union StorageUnionT {
+ // For out-of-line storage we keep a pointer to the underlying storage and
+ // the size. This is enough to deallocate the memory.
+ struct OutOfLineStorageT {
+ void *StoragePtr;
+ size_t Size;
+ size_t Alignment;
+ } OutOfLineStorage;
+ static_assert(
+ sizeof(OutOfLineStorageT) <= InlineStorageSize,
+ "Should always use all of the out-of-line storage for inline storage!");
+
+ // For in-line storage, we just provide an aligned character buffer. We
+ // provide three pointers worth of storage here.
+ typename std::aligned_storage<InlineStorageSize, alignof(void *)>::type
+ InlineStorage;
+ } StorageUnion;
+
+ // A compressed pointer to either our dispatching callback or our table of
+ // dispatching callbacks and the flag for whether the callable itself is
+ // stored inline or not.
+ PointerIntPair<CallbackPointerUnionT, 1, bool> CallbackAndInlineFlag;
+
+ bool isInlineStorage() const { return CallbackAndInlineFlag.getInt(); }
+
+ bool isTrivialCallback() const {
+ return CallbackAndInlineFlag.getPointer().template is<TrivialCallback *>();
+ }
+
+ CallPtrT getTrivialCallback() const {
+ return CallbackAndInlineFlag.getPointer().template get<TrivialCallback *>()->CallPtr;
+ }
+
+ NonTrivialCallbacks *getNonTrivialCallbacks() const {
+ return CallbackAndInlineFlag.getPointer()
+ .template get<NonTrivialCallbacks *>();
+ }
+
+ void *getInlineStorage() { return &StorageUnion.InlineStorage; }
+
+ void *getOutOfLineStorage() {
+ return StorageUnion.OutOfLineStorage.StoragePtr;
+ }
+ size_t getOutOfLineStorageSize() const {
+ return StorageUnion.OutOfLineStorage.Size;
+ }
+ size_t getOutOfLineStorageAlignment() const {
+ return StorageUnion.OutOfLineStorage.Alignment;
+ }
+
+ void setOutOfLineStorage(void *Ptr, size_t Size, size_t Alignment) {
+ StorageUnion.OutOfLineStorage = {Ptr, Size, Alignment};
+ }
+
+ template <typename CallableT>
+ static ReturnT CallImpl(void *CallableAddr, AdjustedParamT<ParamTs>... Params) {
+ return (*reinterpret_cast<CallableT *>(CallableAddr))(
+ std::forward<ParamTs>(Params)...);
+ }
+
+ template <typename CallableT>
+ static void MoveImpl(void *LHSCallableAddr, void *RHSCallableAddr) noexcept {
+ new (LHSCallableAddr)
+ CallableT(std::move(*reinterpret_cast<CallableT *>(RHSCallableAddr)));
+ }
+
+ template <typename CallableT>
+ static void DestroyImpl(void *CallableAddr) noexcept {
+ reinterpret_cast<CallableT *>(CallableAddr)->~CallableT();
+ }
+
+public:
+ unique_function() = default;
+ unique_function(std::nullptr_t /*null_callable*/) {}
+
+ ~unique_function() {
+ if (!CallbackAndInlineFlag.getPointer())
+ return;
+
+ // Cache this value so we don't re-check it after type-erased operations.
+ bool IsInlineStorage = isInlineStorage();
+
+ if (!isTrivialCallback())
+ getNonTrivialCallbacks()->DestroyPtr(
+ IsInlineStorage ? getInlineStorage() : getOutOfLineStorage());
+
+ if (!IsInlineStorage)
+ deallocate_buffer(getOutOfLineStorage(), getOutOfLineStorageSize(),
+ getOutOfLineStorageAlignment());
+ }
+
+ unique_function(unique_function &&RHS) noexcept {
+ // Copy the callback and inline flag.
+ CallbackAndInlineFlag = RHS.CallbackAndInlineFlag;
+
+ // If the RHS is empty, just copying the above is sufficient.
+ if (!RHS)
+ return;
+
+ if (!isInlineStorage()) {
+ // The out-of-line case is easiest to move.
+ StorageUnion.OutOfLineStorage = RHS.StorageUnion.OutOfLineStorage;
+ } else if (isTrivialCallback()) {
+ // Move is trivial, just memcpy the bytes across.
+ memcpy(getInlineStorage(), RHS.getInlineStorage(), InlineStorageSize);
+ } else {
+ // Non-trivial move, so dispatch to a type-erased implementation.
+ getNonTrivialCallbacks()->MovePtr(getInlineStorage(),
+ RHS.getInlineStorage());
+ }
+
+ // Clear the old callback and inline flag to get back to as-if-null.
+ RHS.CallbackAndInlineFlag = {};
+
+#ifndef NDEBUG
+ // In debug builds, we also scribble across the rest of the storage.
+ memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize);
+#endif
+ }
+
+ unique_function &operator=(unique_function &&RHS) noexcept {
+ if (this == &RHS)
+ return *this;
+
+ // Because we don't try to provide any exception safety guarantees we can
+ // implement move assignment very simply by first destroying the current
+ // object and then move-constructing over top of it.
+ this->~unique_function();
+ new (this) unique_function(std::move(RHS));
+ return *this;
+ }
+
+ template <typename CallableT> unique_function(CallableT Callable) {
+ bool IsInlineStorage = true;
+ void *CallableAddr = getInlineStorage();
+ if (sizeof(CallableT) > InlineStorageSize ||
+ alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) {
+ IsInlineStorage = false;
+ // Allocate out-of-line storage. FIXME: Use an explicit alignment
+ // parameter in C++17 mode.
+ auto Size = sizeof(CallableT);
+ auto Alignment = alignof(CallableT);
+ CallableAddr = allocate_buffer(Size, Alignment);
+ setOutOfLineStorage(CallableAddr, Size, Alignment);
+ }
+
+ // Now move into the storage.
+ new (CallableAddr) CallableT(std::move(Callable));
+
+ // See if we can create a trivial callback. We need the callable to be
+ // trivially moved and trivially destroyed so that we don't have to store
+ // type erased callbacks for those operations.
+ //
+ // FIXME: We should use constexpr if here and below to avoid instantiating
+ // the non-trivial static objects when unnecessary. While the linker should
+ // remove them, it is still wasteful.
+ if (llvm::is_trivially_move_constructible<CallableT>::value &&
+ std::is_trivially_destructible<CallableT>::value) {
+ // We need to create a nicely aligned object. We use a static variable
+ // for this because it is a trivial struct.
+ static TrivialCallback Callback = { &CallImpl<CallableT> };
+
+ CallbackAndInlineFlag = {&Callback, IsInlineStorage};
+ return;
+ }
+
+ // Otherwise, we need to point at an object that contains all the different
+ // type erased behaviors needed. Create a static instance of the struct type
+ // here and then use a pointer to that.
+ static NonTrivialCallbacks Callbacks = {
+ &CallImpl<CallableT>, &MoveImpl<CallableT>, &DestroyImpl<CallableT>};
+
+ CallbackAndInlineFlag = {&Callbacks, IsInlineStorage};
+ }
+
+ ReturnT operator()(ParamTs... Params) {
+ void *CallableAddr =
+ isInlineStorage() ? getInlineStorage() : getOutOfLineStorage();
+
+ return (isTrivialCallback()
+ ? getTrivialCallback()
+ : getNonTrivialCallbacks()->CallPtr)(CallableAddr, Params...);
+ }
+
+ explicit operator bool() const {
+ return (bool)CallbackAndInlineFlag.getPointer();
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_FUNCTION_H
diff --git a/contrib/llvm/include/llvm/ADT/GraphTraits.h b/contrib/llvm/include/llvm/ADT/GraphTraits.h
index 225d9eb847f0..27c647f4bbbd 100644
--- a/contrib/llvm/include/llvm/ADT/GraphTraits.h
+++ b/contrib/llvm/include/llvm/ADT/GraphTraits.h
@@ -47,6 +47,19 @@ struct GraphTraits {
// static nodes_iterator nodes_end (GraphType *G)
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
+ // typedef EdgeRef - Type of Edge token in the graph, which should
+ // be cheap to copy.
+ // typedef ChildEdgeIteratorType - Type used to iterate over children edges in
+ // graph, dereference to a EdgeRef.
+
+ // static ChildEdgeIteratorType child_edge_begin(NodeRef)
+ // static ChildEdgeIteratorType child_edge_end(NodeRef)
+ // Return iterators that point to the beginning and ending of the
+ // edge list for the given callgraph node.
+ //
+ // static NodeRef edge_dest(EdgeRef)
+ // Return the destination node of an edge.
+
// static unsigned size (GraphType *G)
// Return total number of nodes in the graph
@@ -111,6 +124,13 @@ inverse_children(const typename GraphTraits<GraphType>::NodeRef &G) {
GraphTraits<Inverse<GraphType>>::child_end(G));
}
+template <class GraphType>
+iterator_range<typename GraphTraits<GraphType>::ChildEdgeIteratorType>
+children_edges(const typename GraphTraits<GraphType>::NodeRef &G) {
+ return make_range(GraphTraits<GraphType>::child_edge_begin(G),
+ GraphTraits<GraphType>::child_edge_end(G));
+}
+
} // end namespace llvm
#endif // LLVM_ADT_GRAPHTRAITS_H
diff --git a/contrib/llvm/include/llvm/ADT/Hashing.h b/contrib/llvm/include/llvm/ADT/Hashing.h
index c3b574102f69..9f830baa4243 100644
--- a/contrib/llvm/include/llvm/ADT/Hashing.h
+++ b/contrib/llvm/include/llvm/ADT/Hashing.h
@@ -57,7 +57,7 @@
namespace llvm {
-/// \brief An opaque object representing a hash code.
+/// An opaque object representing a hash code.
///
/// This object represents the result of hashing some entity. It is intended to
/// be used to implement hashtables or other hashing-based data structures.
@@ -73,14 +73,14 @@ class hash_code {
size_t value;
public:
- /// \brief Default construct a hash_code.
+ /// Default construct a hash_code.
/// Note that this leaves the value uninitialized.
hash_code() = default;
- /// \brief Form a hash code directly from a numerical value.
+ /// Form a hash code directly from a numerical value.
hash_code(size_t value) : value(value) {}
- /// \brief Convert the hash code to its numerical value for use.
+ /// Convert the hash code to its numerical value for use.
/*explicit*/ operator size_t() const { return value; }
friend bool operator==(const hash_code &lhs, const hash_code &rhs) {
@@ -90,11 +90,11 @@ public:
return lhs.value != rhs.value;
}
- /// \brief Allow a hash_code to be directly run through hash_value.
+ /// Allow a hash_code to be directly run through hash_value.
friend size_t hash_value(const hash_code &code) { return code.value; }
};
-/// \brief Compute a hash_code for any integer value.
+/// Compute a hash_code for any integer value.
///
/// Note that this function is intended to compute the same hash_code for
/// a particular value without regard to the pre-promotion type. This is in
@@ -105,21 +105,21 @@ template <typename T>
typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
hash_value(T value);
-/// \brief Compute a hash_code for a pointer's address.
+/// Compute a hash_code for a pointer's address.
///
/// N.B.: This hashes the *address*. Not the value and not the type.
template <typename T> hash_code hash_value(const T *ptr);
-/// \brief Compute a hash_code for a pair of objects.
+/// Compute a hash_code for a pair of objects.
template <typename T, typename U>
hash_code hash_value(const std::pair<T, U> &arg);
-/// \brief Compute a hash_code for a standard string.
+/// Compute a hash_code for a standard string.
template <typename T>
hash_code hash_value(const std::basic_string<T> &arg);
-/// \brief Override the execution seed with a fixed value.
+/// Override the execution seed with a fixed value.
///
/// This hashing library uses a per-execution seed designed to change on each
/// run with high probability in order to ensure that the hash codes are not
@@ -164,7 +164,7 @@ static const uint64_t k1 = 0xb492b66fbe98f273ULL;
static const uint64_t k2 = 0x9ae16a3b2f90404fULL;
static const uint64_t k3 = 0xc949d7c7509e6557ULL;
-/// \brief Bitwise right rotate.
+/// Bitwise right rotate.
/// Normally this will compile to a single instruction, especially if the
/// shift is a manifest constant.
inline uint64_t rotate(uint64_t val, size_t shift) {
@@ -254,13 +254,13 @@ inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) {
return k2 ^ seed;
}
-/// \brief The intermediate state used during hashing.
+/// The intermediate state used during hashing.
/// Currently, the algorithm for computing hash codes is based on CityHash and
/// keeps 56 bytes of arbitrary state.
struct hash_state {
uint64_t h0, h1, h2, h3, h4, h5, h6;
- /// \brief Create a new hash_state structure and initialize it based on the
+ /// Create a new hash_state structure and initialize it based on the
/// seed and the first 64-byte chunk.
/// This effectively performs the initial mix.
static hash_state create(const char *s, uint64_t seed) {
@@ -272,7 +272,7 @@ struct hash_state {
return state;
}
- /// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a'
+ /// Mix 32-bytes from the input sequence into the 16-bytes of 'a'
/// and 'b', including whatever is already in 'a' and 'b'.
static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) {
a += fetch64(s);
@@ -284,7 +284,7 @@ struct hash_state {
a += c;
}
- /// \brief Mix in a 64-byte buffer of data.
+ /// Mix in a 64-byte buffer of data.
/// We mix all 64 bytes even when the chunk length is smaller, but we
/// record the actual length.
void mix(const char *s) {
@@ -302,7 +302,7 @@ struct hash_state {
std::swap(h2, h0);
}
- /// \brief Compute the final 64-bit hash code value based on the current
+ /// Compute the final 64-bit hash code value based on the current
/// state and the length of bytes hashed.
uint64_t finalize(size_t length) {
return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2,
@@ -311,7 +311,7 @@ struct hash_state {
};
-/// \brief A global, fixed seed-override variable.
+/// A global, fixed seed-override variable.
///
/// This variable can be set using the \see llvm::set_fixed_execution_seed
/// function. See that function for details. Do not, under any circumstances,
@@ -332,7 +332,7 @@ inline size_t get_execution_seed() {
}
-/// \brief Trait to indicate whether a type's bits can be hashed directly.
+/// Trait to indicate whether a type's bits can be hashed directly.
///
/// A type trait which is true if we want to combine values for hashing by
/// reading the underlying data. It is false if values of this type must
@@ -359,14 +359,14 @@ template <typename T, typename U> struct is_hashable_data<std::pair<T, U> >
(sizeof(T) + sizeof(U)) ==
sizeof(std::pair<T, U>))> {};
-/// \brief Helper to get the hashable data representation for a type.
+/// Helper to get the hashable data representation for a type.
/// This variant is enabled when the type itself can be used.
template <typename T>
typename std::enable_if<is_hashable_data<T>::value, T>::type
get_hashable_data(const T &value) {
return value;
}
-/// \brief Helper to get the hashable data representation for a type.
+/// Helper to get the hashable data representation for a type.
/// This variant is enabled when we must first call hash_value and use the
/// result as our data.
template <typename T>
@@ -376,7 +376,7 @@ get_hashable_data(const T &value) {
return hash_value(value);
}
-/// \brief Helper to store data from a value into a buffer and advance the
+/// Helper to store data from a value into a buffer and advance the
/// pointer into that buffer.
///
/// This routine first checks whether there is enough space in the provided
@@ -395,7 +395,7 @@ bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value,
return true;
}
-/// \brief Implement the combining of integral values into a hash_code.
+/// Implement the combining of integral values into a hash_code.
///
/// This overload is selected when the value type of the iterator is
/// integral. Rather than computing a hash_code for each object and then
@@ -435,7 +435,7 @@ hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
return state.finalize(length);
}
-/// \brief Implement the combining of integral values into a hash_code.
+/// Implement the combining of integral values into a hash_code.
///
/// This overload is selected when the value type of the iterator is integral
/// and when the input iterator is actually a pointer. Rather than computing
@@ -470,7 +470,7 @@ hash_combine_range_impl(ValueT *first, ValueT *last) {
} // namespace hashing
-/// \brief Compute a hash_code for a sequence of values.
+/// Compute a hash_code for a sequence of values.
///
/// This hashes a sequence of values. It produces the same hash_code as
/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences
@@ -486,7 +486,7 @@ hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) {
namespace hashing {
namespace detail {
-/// \brief Helper class to manage the recursive combining of hash_combine
+/// Helper class to manage the recursive combining of hash_combine
/// arguments.
///
/// This class exists to manage the state and various calls involved in the
@@ -499,14 +499,14 @@ struct hash_combine_recursive_helper {
const size_t seed;
public:
- /// \brief Construct a recursive hash combining helper.
+ /// Construct a recursive hash combining helper.
///
/// This sets up the state for a recursive hash combine, including getting
/// the seed and buffer setup.
hash_combine_recursive_helper()
: seed(get_execution_seed()) {}
- /// \brief Combine one chunk of data into the current in-flight hash.
+ /// Combine one chunk of data into the current in-flight hash.
///
/// This merges one chunk of data into the hash. First it tries to buffer
/// the data. If the buffer is full, it hashes the buffer into its
@@ -547,7 +547,7 @@ public:
return buffer_ptr;
}
- /// \brief Recursive, variadic combining method.
+ /// Recursive, variadic combining method.
///
/// This function recurses through each argument, combining that argument
/// into a single hash.
@@ -560,7 +560,7 @@ public:
return combine(length, buffer_ptr, buffer_end, args...);
}
- /// \brief Base case for recursive, variadic combining.
+ /// Base case for recursive, variadic combining.
///
/// The base case when combining arguments recursively is reached when all
/// arguments have been handled. It flushes the remaining buffer and
@@ -588,7 +588,7 @@ public:
} // namespace detail
} // namespace hashing
-/// \brief Combine values into a single hash_code.
+/// Combine values into a single hash_code.
///
/// This routine accepts a varying number of arguments of any type. It will
/// attempt to combine them into a single hash_code. For user-defined types it
@@ -610,7 +610,7 @@ template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
namespace hashing {
namespace detail {
-/// \brief Helper to hash the value of a single integer.
+/// Helper to hash the value of a single integer.
///
/// Overloads for smaller integer types are not provided to ensure consistent
/// behavior in the presence of integral promotions. Essentially,
diff --git a/contrib/llvm/include/llvm/ADT/ImmutableList.h b/contrib/llvm/include/llvm/ADT/ImmutableList.h
index 60d63e09d426..1f5e9813798d 100644
--- a/contrib/llvm/include/llvm/ADT/ImmutableList.h
+++ b/contrib/llvm/include/llvm/ADT/ImmutableList.h
@@ -166,7 +166,7 @@ public:
if (ownsAllocator()) delete &getAllocator();
}
- ImmutableList<T> concat(const T& Head, ImmutableList<T> Tail) {
+ LLVM_NODISCARD ImmutableList<T> concat(const T &Head, ImmutableList<T> Tail) {
// Profile the new list to see if it already exists in our cache.
FoldingSetNodeID ID;
void* InsertPos;
@@ -188,7 +188,7 @@ public:
return L;
}
- ImmutableList<T> add(const T& D, ImmutableList<T> L) {
+ LLVM_NODISCARD ImmutableList<T> add(const T& D, ImmutableList<T> L) {
return concat(D, L);
}
diff --git a/contrib/llvm/include/llvm/ADT/ImmutableMap.h b/contrib/llvm/include/llvm/ADT/ImmutableMap.h
index 10d1e1f0139b..cbc27ff17ccf 100644
--- a/contrib/llvm/include/llvm/ADT/ImmutableMap.h
+++ b/contrib/llvm/include/llvm/ADT/ImmutableMap.h
@@ -114,12 +114,13 @@ public:
ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
- ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) {
+ LLVM_NODISCARD ImmutableMap add(ImmutableMap Old, key_type_ref K,
+ data_type_ref D) {
TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D));
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
}
- ImmutableMap remove(ImmutableMap Old, key_type_ref K) {
+ LLVM_NODISCARD ImmutableMap remove(ImmutableMap Old, key_type_ref K) {
TreeTy *T = F.remove(Old.Root,K);
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
}
diff --git a/contrib/llvm/include/llvm/ADT/ImmutableSet.h b/contrib/llvm/include/llvm/ADT/ImmutableSet.h
index 9d580c5a3d41..b1d5f4ac42e4 100644
--- a/contrib/llvm/include/llvm/ADT/ImmutableSet.h
+++ b/contrib/llvm/include/llvm/ADT/ImmutableSet.h
@@ -1017,7 +1017,7 @@ public:
/// of this operation is logarithmic in the size of the original set.
/// The memory allocated to represent the set is released when the
/// factory object that created the set is destroyed.
- ImmutableSet add(ImmutableSet Old, value_type_ref V) {
+ LLVM_NODISCARD ImmutableSet add(ImmutableSet Old, value_type_ref V) {
TreeTy *NewT = F.add(Old.Root, V);
return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
}
@@ -1029,7 +1029,7 @@ public:
/// of this operation is logarithmic in the size of the original set.
/// The memory allocated to represent the set is released when the
/// factory object that created the set is destroyed.
- ImmutableSet remove(ImmutableSet Old, value_type_ref V) {
+ LLVM_NODISCARD ImmutableSet remove(ImmutableSet Old, value_type_ref V) {
TreeTy *NewT = F.remove(Old.Root, V);
return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
}
diff --git a/contrib/llvm/include/llvm/ADT/MapVector.h b/contrib/llvm/include/llvm/ADT/MapVector.h
index 3d78f4b203c8..47b4987f210a 100644
--- a/contrib/llvm/include/llvm/ADT/MapVector.h
+++ b/contrib/llvm/include/llvm/ADT/MapVector.h
@@ -36,13 +36,17 @@ template<typename KeyT, typename ValueT,
typename MapType = DenseMap<KeyT, unsigned>,
typename VectorType = std::vector<std::pair<KeyT, ValueT>>>
class MapVector {
- using value_type = typename VectorType::value_type;
- using size_type = typename VectorType::size_type;
-
MapType Map;
VectorType Vector;
+ static_assert(
+ std::is_integral<typename MapType::mapped_type>::value,
+ "The mapped_type of the specified Map must be an integral type");
+
public:
+ using value_type = typename VectorType::value_type;
+ using size_type = typename VectorType::size_type;
+
using iterator = typename VectorType::iterator;
using const_iterator = typename VectorType::const_iterator;
using reverse_iterator = typename VectorType::reverse_iterator;
@@ -93,9 +97,9 @@ public:
}
ValueT &operator[](const KeyT &Key) {
- std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0);
+ std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(Key, 0);
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
- unsigned &I = Result.first->second;
+ auto &I = Result.first->second;
if (Result.second) {
Vector.push_back(std::make_pair(Key, ValueT()));
I = Vector.size() - 1;
@@ -112,9 +116,9 @@ public:
}
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
- std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0);
+ std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
- unsigned &I = Result.first->second;
+ auto &I = Result.first->second;
if (Result.second) {
Vector.push_back(std::make_pair(KV.first, KV.second));
I = Vector.size() - 1;
@@ -125,9 +129,9 @@ public:
std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
// Copy KV.first into the map, then move it into the vector.
- std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0);
+ std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
- unsigned &I = Result.first->second;
+ auto &I = Result.first->second;
if (Result.second) {
Vector.push_back(std::move(KV));
I = Vector.size() - 1;
@@ -153,14 +157,14 @@ public:
(Vector.begin() + Pos->second);
}
- /// \brief Remove the last element from the vector.
+ /// Remove the last element from the vector.
void pop_back() {
typename MapType::iterator Pos = Map.find(Vector.back().first);
Map.erase(Pos);
Vector.pop_back();
}
- /// \brief Remove the element given by Iterator.
+ /// Remove the element given by Iterator.
///
/// Returns an iterator to the element following the one which was removed,
/// which may be end().
@@ -183,7 +187,7 @@ public:
return Next;
}
- /// \brief Remove all elements with the key value Key.
+ /// Remove all elements with the key value Key.
///
/// Returns the number of elements removed.
size_type erase(const KeyT &Key) {
@@ -194,7 +198,7 @@ public:
return 1;
}
- /// \brief Remove the elements that match the predicate.
+ /// Remove the elements that match the predicate.
///
/// Erase all elements that match \c Pred in a single pass. Takes linear
/// time.
@@ -223,7 +227,7 @@ 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
+/// A MapVector that performs no allocations if smaller than a certain
/// size.
template <typename KeyT, typename ValueT, unsigned N>
struct SmallMapVector
diff --git a/contrib/llvm/include/llvm/ADT/None.h b/contrib/llvm/include/llvm/ADT/None.h
index c7a99c61994e..4b6bc1e005b5 100644
--- a/contrib/llvm/include/llvm/ADT/None.h
+++ b/contrib/llvm/include/llvm/ADT/None.h
@@ -17,7 +17,7 @@
#define LLVM_ADT_NONE_H
namespace llvm {
-/// \brief A simple null object to allow implicit construction of Optional<T>
+/// A simple null object to allow implicit construction of Optional<T>
/// and similar types without having to spell out the specialization's name.
// (constant value 1 in an attempt to workaround MSVC build issue... )
enum class NoneType { None = 1 };
diff --git a/contrib/llvm/include/llvm/ADT/Optional.h b/contrib/llvm/include/llvm/ADT/Optional.h
index 2811d5c1e21b..353e5d0ec9df 100644
--- a/contrib/llvm/include/llvm/ADT/Optional.h
+++ b/contrib/llvm/include/llvm/ADT/Optional.h
@@ -27,124 +27,164 @@
namespace llvm {
-template <typename T> class Optional {
+namespace optional_detail {
+/// Storage for any type.
+template <typename T, bool IsPodLike> struct OptionalStorage {
AlignedCharArrayUnion<T> storage;
bool hasVal = false;
-public:
- using value_type = T;
-
- Optional(NoneType) {}
- explicit Optional() {}
-
- Optional(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
+ OptionalStorage() = default;
- Optional(const Optional &O) : hasVal(O.hasVal) {
+ OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
+ OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) {
if (hasVal)
- new (storage.buffer) T(*O);
+ new (storage.buffer) T(*O.getPointer());
}
-
- Optional(T &&y) : hasVal(true) { new (storage.buffer) T(std::forward<T>(y)); }
-
- Optional(Optional<T> &&O) : hasVal(O) {
- if (O) {
- new (storage.buffer) T(std::move(*O));
- O.reset();
+ OptionalStorage(T &&y) : hasVal(true) {
+ new (storage.buffer) T(std::forward<T>(y));
+ }
+ OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) {
+ if (O.hasVal) {
+ new (storage.buffer) T(std::move(*O.getPointer()));
}
}
- ~Optional() { reset(); }
-
- Optional &operator=(T &&y) {
+ OptionalStorage &operator=(T &&y) {
if (hasVal)
- **this = std::move(y);
+ *getPointer() = std::move(y);
else {
new (storage.buffer) T(std::move(y));
hasVal = true;
}
return *this;
}
-
- Optional &operator=(Optional &&O) {
- if (!O)
+ OptionalStorage &operator=(OptionalStorage &&O) {
+ if (!O.hasVal)
reset();
else {
- *this = std::move(*O);
- O.reset();
+ *this = std::move(*O.getPointer());
}
return *this;
}
- /// Create a new object by constructing it in place with the given arguments.
- template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
- }
-
- static inline Optional create(const T *y) {
- return y ? Optional(*y) : Optional();
- }
-
// FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
// could be made more efficient by passing by value, possibly unifying them
// with the rvalue versions above - but this could place a different set of
// requirements (notably: the existence of a default ctor) when implemented
// in that way. Careful SFINAE to avoid such pitfalls would be required.
- Optional &operator=(const T &y) {
+ OptionalStorage &operator=(const T &y) {
if (hasVal)
- **this = y;
+ *getPointer() = y;
else {
new (storage.buffer) T(y);
hasVal = true;
}
return *this;
}
-
- Optional &operator=(const Optional &O) {
- if (!O)
+ OptionalStorage &operator=(const OptionalStorage &O) {
+ if (!O.hasVal)
reset();
else
- *this = *O;
+ *this = *O.getPointer();
return *this;
}
+ ~OptionalStorage() { reset(); }
+
void reset() {
if (hasVal) {
- (**this).~T();
+ (*getPointer()).~T();
hasVal = false;
}
}
- const T *getPointer() const {
- assert(hasVal);
- return reinterpret_cast<const T *>(storage.buffer);
- }
T *getPointer() {
assert(hasVal);
return reinterpret_cast<T *>(storage.buffer);
}
- const T &getValue() const LLVM_LVALUE_FUNCTION {
+ const T *getPointer() const {
assert(hasVal);
- return *getPointer();
+ return reinterpret_cast<const T *>(storage.buffer);
}
- T &getValue() LLVM_LVALUE_FUNCTION {
- assert(hasVal);
- return *getPointer();
+};
+
+#if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this.
+/// Storage for trivially copyable types only.
+template <typename T> struct OptionalStorage<T, true> {
+ AlignedCharArrayUnion<T> storage;
+ bool hasVal = false;
+
+ OptionalStorage() = default;
+
+ OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
+ OptionalStorage &operator=(const T &y) {
+ *reinterpret_cast<T *>(storage.buffer) = y;
+ hasVal = true;
+ return *this;
}
- explicit operator bool() const { return hasVal; }
- bool hasValue() const { return hasVal; }
- const T *operator->() const { return getPointer(); }
- T *operator->() { return getPointer(); }
- const T &operator*() const LLVM_LVALUE_FUNCTION {
- assert(hasVal);
- return *getPointer();
+ void reset() { hasVal = false; }
+};
+#endif
+} // namespace optional_detail
+
+template <typename T> class Optional {
+ optional_detail::OptionalStorage<T, isPodLike<T>::value> Storage;
+
+public:
+ using value_type = T;
+
+ constexpr Optional() {}
+ constexpr Optional(NoneType) {}
+
+ Optional(const T &y) : Storage(y) {}
+ Optional(const Optional &O) = default;
+
+ Optional(T &&y) : Storage(std::forward<T>(y)) {}
+ Optional(Optional &&O) = default;
+
+ Optional &operator=(T &&y) {
+ Storage = std::move(y);
+ return *this;
}
- T &operator*() LLVM_LVALUE_FUNCTION {
- assert(hasVal);
- return *getPointer();
+ Optional &operator=(Optional &&O) = default;
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
+ reset();
+ Storage.hasVal = true;
+ new (getPointer()) T(std::forward<ArgTypes>(Args)...);
+ }
+
+ static inline Optional create(const T *y) {
+ return y ? Optional(*y) : Optional();
+ }
+
+ Optional &operator=(const T &y) {
+ Storage = y;
+ return *this;
+ }
+ Optional &operator=(const Optional &O) = default;
+
+ void reset() { Storage.reset(); }
+
+ const T *getPointer() const {
+ assert(Storage.hasVal);
+ return reinterpret_cast<const T *>(Storage.storage.buffer);
+ }
+ T *getPointer() {
+ assert(Storage.hasVal);
+ return reinterpret_cast<T *>(Storage.storage.buffer);
}
+ const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
+ T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); }
+
+ explicit operator bool() const { return Storage.hasVal; }
+ bool hasValue() const { return Storage.hasVal; }
+ const T *operator->() const { return getPointer(); }
+ T *operator->() { return getPointer(); }
+ const T &operator*() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
+ T &operator*() LLVM_LVALUE_FUNCTION { return *getPointer(); }
template <typename U>
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
@@ -152,14 +192,8 @@ public:
}
#if LLVM_HAS_RVALUE_REFERENCE_THIS
- T &&getValue() && {
- assert(hasVal);
- return std::move(*getPointer());
- }
- T &&operator*() && {
- assert(hasVal);
- return std::move(*getPointer());
- }
+ T &&getValue() && { return std::move(*getPointer()); }
+ T &&operator*() && { return std::move(*getPointer()); }
template <typename U>
T getValueOr(U &&value) && {
diff --git a/contrib/llvm/include/llvm/ADT/PackedVector.h b/contrib/llvm/include/llvm/ADT/PackedVector.h
index 95adc2926813..3d53c49536d0 100644
--- a/contrib/llvm/include/llvm/ADT/PackedVector.h
+++ b/contrib/llvm/include/llvm/ADT/PackedVector.h
@@ -65,7 +65,7 @@ protected:
}
};
-/// \brief Store a vector of values using a specific number of bits for each
+/// Store a vector of values using a specific number of bits for each
/// value. Both signed and unsigned types can be used, e.g
/// @code
/// PackedVector<signed, 2> vec;
diff --git a/contrib/llvm/include/llvm/ADT/PointerUnion.h b/contrib/llvm/include/llvm/ADT/PointerUnion.h
index 4276859e9254..315e58336cba 100644
--- a/contrib/llvm/include/llvm/ADT/PointerUnion.h
+++ b/contrib/llvm/include/llvm/ADT/PointerUnion.h
@@ -346,6 +346,12 @@ struct PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3>> {
};
};
+template <typename PT1, typename PT2, typename PT3>
+bool operator<(PointerUnion3<PT1, PT2, PT3> lhs,
+ PointerUnion3<PT1, PT2, PT3> rhs) {
+ return lhs.getOpaqueValue() < rhs.getOpaqueValue();
+}
+
/// A pointer union of four pointer types. See documentation for PointerUnion
/// for usage.
template <typename PT1, typename PT2, typename PT3, typename PT4>
diff --git a/contrib/llvm/include/llvm/ADT/SCCIterator.h b/contrib/llvm/include/llvm/ADT/SCCIterator.h
index 784a58dc002f..ab1dc4613be0 100644
--- a/contrib/llvm/include/llvm/ADT/SCCIterator.h
+++ b/contrib/llvm/include/llvm/ADT/SCCIterator.h
@@ -33,7 +33,7 @@
namespace llvm {
-/// \brief Enumerate the SCCs of a directed graph in reverse topological order
+/// Enumerate the SCCs of a directed graph in reverse topological order
/// of the SCC DAG.
///
/// This is implemented using Tarjan's DFS algorithm using an internal stack to
@@ -104,7 +104,7 @@ public:
}
static scc_iterator end(const GraphT &) { return scc_iterator(); }
- /// \brief Direct loop termination test which is more efficient than
+ /// Direct loop termination test which is more efficient than
/// comparison with \c end().
bool isAtEnd() const {
assert(!CurrentSCC.empty() || VisitStack.empty());
@@ -125,7 +125,7 @@ public:
return CurrentSCC;
}
- /// \brief Test if the current SCC has a loop.
+ /// Test if the current SCC has a loop.
///
/// If the SCC has more than one node, this is trivially true. If not, it may
/// still contain a loop if the node has an edge back to itself.
@@ -222,12 +222,12 @@ bool scc_iterator<GraphT, GT>::hasLoop() const {
return false;
}
-/// \brief Construct the begin iterator for a deduced graph type T.
+/// Construct the begin iterator for a deduced graph type T.
template <class T> scc_iterator<T> scc_begin(const T &G) {
return scc_iterator<T>::begin(G);
}
-/// \brief Construct the end iterator for a deduced graph type T.
+/// Construct the end iterator for a deduced graph type T.
template <class T> scc_iterator<T> scc_end(const T &G) {
return scc_iterator<T>::end(G);
}
diff --git a/contrib/llvm/include/llvm/ADT/STLExtras.h b/contrib/llvm/include/llvm/ADT/STLExtras.h
index bcd992b4a716..94365dd9ced1 100644
--- a/contrib/llvm/include/llvm/ADT/STLExtras.h
+++ b/contrib/llvm/include/llvm/ADT/STLExtras.h
@@ -36,6 +36,10 @@
#include <type_traits>
#include <utility>
+#ifdef EXPENSIVE_CHECKS
+#include <random> // for std::mt19937
+#endif
+
namespace llvm {
// Only used by compiler if both template types are the same. Useful when
@@ -54,6 +58,19 @@ using ValueOfRange = typename std::remove_reference<decltype(
} // end namespace detail
//===----------------------------------------------------------------------===//
+// Extra additions to <type_traits>
+//===----------------------------------------------------------------------===//
+
+template <typename T>
+struct negation : std::integral_constant<bool, !bool(T::value)> {};
+
+template <typename...> struct conjunction : std::true_type {};
+template <typename B1> struct conjunction<B1> : B1 {};
+template <typename B1, typename... Bn>
+struct conjunction<B1, Bn...>
+ : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+
+//===----------------------------------------------------------------------===//
// Extra additions to <functional>
//===----------------------------------------------------------------------===//
@@ -101,6 +118,7 @@ class function_ref<Ret(Params...)> {
public:
function_ref() = default;
+ function_ref(std::nullptr_t) {}
template <typename Callable>
function_ref(Callable &&callable,
@@ -266,60 +284,121 @@ auto reverse(
/// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; });
/// // R contains { 1, 3 }.
/// \endcode
-template <typename WrappedIteratorT, typename PredicateT>
-class filter_iterator
+///
+/// Note: filter_iterator_base implements support for forward iteration.
+/// filter_iterator_impl exists to provide support for bidirectional iteration,
+/// conditional on whether the wrapped iterator supports it.
+template <typename WrappedIteratorT, typename PredicateT, typename IterTag>
+class filter_iterator_base
: public iterator_adaptor_base<
- filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT,
+ filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
+ WrappedIteratorT,
typename std::common_type<
- std::forward_iterator_tag,
- typename std::iterator_traits<
- WrappedIteratorT>::iterator_category>::type> {
+ IterTag, typename std::iterator_traits<
+ WrappedIteratorT>::iterator_category>::type> {
using BaseT = iterator_adaptor_base<
- filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT,
+ filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
+ WrappedIteratorT,
typename std::common_type<
- std::forward_iterator_tag,
- typename std::iterator_traits<WrappedIteratorT>::iterator_category>::
- type>;
+ IterTag, typename std::iterator_traits<
+ WrappedIteratorT>::iterator_category>::type>;
- struct PayloadType {
- WrappedIteratorT End;
- PredicateT Pred;
- };
-
- Optional<PayloadType> Payload;
+protected:
+ WrappedIteratorT End;
+ PredicateT Pred;
void findNextValid() {
- assert(Payload && "Payload should be engaged when findNextValid is called");
- while (this->I != Payload->End && !Payload->Pred(*this->I))
+ while (this->I != End && !Pred(*this->I))
BaseT::operator++();
}
- // Construct the begin iterator. The begin iterator requires to know where end
- // is, so that it can properly stop when it hits end.
- filter_iterator(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
- : BaseT(std::move(Begin)),
- Payload(PayloadType{std::move(End), std::move(Pred)}) {
+ // Construct the iterator. The begin iterator needs to know where the end
+ // is, so that it can properly stop when it gets there. The end iterator only
+ // needs the predicate to support bidirectional iteration.
+ filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End,
+ PredicateT Pred)
+ : BaseT(Begin), End(End), Pred(Pred) {
findNextValid();
}
- // Construct the end iterator. It's not incrementable, so Payload doesn't
- // have to be engaged.
- filter_iterator(WrappedIteratorT End) : BaseT(End) {}
-
public:
using BaseT::operator++;
- filter_iterator &operator++() {
+ filter_iterator_base &operator++() {
BaseT::operator++();
findNextValid();
return *this;
}
+};
+
+/// Specialization of filter_iterator_base for forward iteration only.
+template <typename WrappedIteratorT, typename PredicateT,
+ typename IterTag = std::forward_iterator_tag>
+class filter_iterator_impl
+ : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> {
+ using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>;
+
+public:
+ filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
+ PredicateT Pred)
+ : BaseT(Begin, End, Pred) {}
+};
+
+/// Specialization of filter_iterator_base for bidirectional iteration.
+template <typename WrappedIteratorT, typename PredicateT>
+class filter_iterator_impl<WrappedIteratorT, PredicateT,
+ std::bidirectional_iterator_tag>
+ : public filter_iterator_base<WrappedIteratorT, PredicateT,
+ std::bidirectional_iterator_tag> {
+ using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT,
+ std::bidirectional_iterator_tag>;
+ void findPrevValid() {
+ while (!this->Pred(*this->I))
+ BaseT::operator--();
+ }
+
+public:
+ using BaseT::operator--;
+
+ filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
+ PredicateT Pred)
+ : BaseT(Begin, End, Pred) {}
+
+ filter_iterator_impl &operator--() {
+ BaseT::operator--();
+ findPrevValid();
+ return *this;
+ }
+};
+
+namespace detail {
- template <typename RT, typename PT>
- friend iterator_range<filter_iterator<detail::IterOfRange<RT>, PT>>
- make_filter_range(RT &&, PT);
+template <bool is_bidirectional> struct fwd_or_bidi_tag_impl {
+ using type = std::forward_iterator_tag;
};
+template <> struct fwd_or_bidi_tag_impl<true> {
+ using type = std::bidirectional_iterator_tag;
+};
+
+/// Helper which sets its type member to forward_iterator_tag if the category
+/// of \p IterT does not derive from bidirectional_iterator_tag, and to
+/// bidirectional_iterator_tag otherwise.
+template <typename IterT> struct fwd_or_bidi_tag {
+ using type = typename fwd_or_bidi_tag_impl<std::is_base_of<
+ std::bidirectional_iterator_tag,
+ typename std::iterator_traits<IterT>::iterator_category>::value>::type;
+};
+
+} // namespace detail
+
+/// Defines filter_iterator to a suitable specialization of
+/// filter_iterator_impl, based on the underlying iterator's category.
+template <typename WrappedIteratorT, typename PredicateT>
+using filter_iterator = filter_iterator_impl<
+ WrappedIteratorT, PredicateT,
+ typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>;
+
/// Convenience function that takes a range of elements and a predicate,
/// and return a new filter_iterator range.
///
@@ -332,10 +411,11 @@ iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
make_filter_range(RangeT &&Range, PredicateT Pred) {
using FilterIteratorT =
filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
- return make_range(FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
- std::end(std::forward<RangeT>(Range)),
- std::move(Pred)),
- FilterIteratorT(std::end(std::forward<RangeT>(Range))));
+ return make_range(
+ FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
+ std::end(std::forward<RangeT>(Range)), Pred),
+ FilterIteratorT(std::end(std::forward<RangeT>(Range)),
+ std::end(std::forward<RangeT>(Range)), Pred));
}
// forward declarations required by zip_shortest/zip_first
@@ -644,7 +724,7 @@ detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
// Extra additions to <utility>
//===----------------------------------------------------------------------===//
-/// \brief Function object to check whether the first component of a std::pair
+/// Function object to check whether the first component of a std::pair
/// compares less than the first component of another std::pair.
struct less_first {
template <typename T> bool operator()(const T &lhs, const T &rhs) const {
@@ -652,7 +732,7 @@ struct less_first {
}
};
-/// \brief Function object to check whether the second component of a std::pair
+/// Function object to check whether the second component of a std::pair
/// compares less than the second component of another std::pair.
struct less_second {
template <typename T> bool operator()(const T &lhs, const T &rhs) const {
@@ -662,14 +742,14 @@ struct less_second {
// A subset of N3658. More stuff can be added as-needed.
-/// \brief Represents a compile-time sequence of integers.
+/// Represents a compile-time sequence of integers.
template <class T, T... I> struct integer_sequence {
using value_type = T;
static constexpr size_t size() { return sizeof...(I); }
};
-/// \brief Alias for the common case of a sequence of size_ts.
+/// Alias for the common case of a sequence of size_ts.
template <size_t... I>
struct index_sequence : integer_sequence<std::size_t, I...> {};
@@ -678,7 +758,7 @@ 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.
+/// Creates a compile-time integer sequence for a parameter pack.
template <class... Ts>
struct index_sequence_for : build_index_impl<sizeof...(Ts)> {};
@@ -687,7 +767,7 @@ struct index_sequence_for : build_index_impl<sizeof...(Ts)> {};
template <int N> struct rank : rank<N - 1> {};
template <> struct rank<0> {};
-/// \brief traits class for checking whether type T is one of any of the given
+/// traits class for checking whether type T is one of any of the given
/// types in the variadic list.
template <typename T, typename... Ts> struct is_one_of {
static const bool value = false;
@@ -699,7 +779,7 @@ struct is_one_of<T, U, Ts...> {
std::is_same<T, U>::value || is_one_of<T, Ts...>::value;
};
-/// \brief traits class for checking whether type T is a base class for all
+/// traits class for checking whether type T is a base class for all
/// the given types in the variadic list.
template <typename T, typename... Ts> struct are_base_of {
static const bool value = true;
@@ -761,6 +841,10 @@ inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
// behavior with an empty sequence.
auto NElts = End - Start;
if (NElts <= 1) return;
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
}
@@ -774,10 +858,34 @@ inline void array_pod_sort(
// behavior with an empty sequence.
auto NElts = End - Start;
if (NElts <= 1) return;
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
qsort(&*Start, NElts, sizeof(*Start),
reinterpret_cast<int (*)(const void *, const void *)>(Compare));
}
+// Provide wrappers to std::sort which shuffle the elements before sorting
+// to help uncover non-deterministic behavior (PR35135).
+template <typename IteratorTy>
+inline void sort(IteratorTy Start, IteratorTy End) {
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
+ std::sort(Start, End);
+}
+
+template <typename IteratorTy, typename Compare>
+inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
+ std::sort(Start, End, Comp);
+}
+
//===----------------------------------------------------------------------===//
// Extra additions to <algorithm>
//===----------------------------------------------------------------------===//
@@ -861,6 +969,11 @@ OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
}
+template <typename R, typename OutputIt>
+OutputIt copy(R &&Range, OutputIt Out) {
+ return std::copy(adl_begin(Range), adl_end(Range), Out);
+}
+
/// Wrapper function around std::find to detect if an element exists
/// in a container.
template <typename R, typename E>
@@ -905,7 +1018,7 @@ auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) {
return std::lower_bound(adl_begin(Range), adl_end(Range), I);
}
-/// \brief Given a range of type R, iterate the entire range and return a
+/// Given a range of type R, iterate the entire range and return a
/// SmallVector with elements of the vector. This is useful, for example,
/// when you want to iterate a range and then sort the results.
template <unsigned Size, typename R>
@@ -926,13 +1039,25 @@ void erase_if(Container &C, UnaryPredicate P) {
C.erase(remove_if(C, P), C.end());
}
+/// Get the size of a range. This is a wrapper function around std::distance
+/// which is only enabled when the operation is O(1).
+template <typename R>
+auto size(R &&Range, typename std::enable_if<
+ std::is_same<typename std::iterator_traits<decltype(
+ Range.begin())>::iterator_category,
+ std::random_access_iterator_tag>::value,
+ void>::type * = nullptr)
+ -> decltype(std::distance(Range.begin(), Range.end())) {
+ return std::distance(Range.begin(), Range.end());
+}
+
//===----------------------------------------------------------------------===//
// Extra additions to <memory>
//===----------------------------------------------------------------------===//
// Implement make_unique according to N3656.
-/// \brief Constructs a `new T()` with the given args and returns a
+/// Constructs a `new T()` with the given args and returns a
/// `unique_ptr<T>` which owns the object.
///
/// Example:
@@ -945,7 +1070,7 @@ make_unique(Args &&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
-/// \brief Constructs a `new T[n]` with the given args and returns a
+/// Constructs a `new T[n]` with the given args and returns a
/// `unique_ptr<T[]>` which owns the object.
///
/// \param n size of the new array.
diff --git a/contrib/llvm/include/llvm/ADT/ScopeExit.h b/contrib/llvm/include/llvm/ADT/ScopeExit.h
index 4e64352c77df..bd13755fa999 100644
--- a/contrib/llvm/include/llvm/ADT/ScopeExit.h
+++ b/contrib/llvm/include/llvm/ADT/ScopeExit.h
@@ -25,14 +25,26 @@ namespace detail {
template <typename Callable> class scope_exit {
Callable ExitFunction;
+ bool Engaged = true; // False once moved-from or release()d.
public:
template <typename Fp>
explicit scope_exit(Fp &&F) : ExitFunction(std::forward<Fp>(F)) {}
- scope_exit(scope_exit &&Rhs) : ExitFunction(std::move(Rhs.ExitFunction)) {}
+ scope_exit(scope_exit &&Rhs)
+ : ExitFunction(std::move(Rhs.ExitFunction)), Engaged(Rhs.Engaged) {
+ Rhs.release();
+ }
+ scope_exit(const scope_exit &) = delete;
+ scope_exit &operator=(scope_exit &&) = delete;
+ scope_exit &operator=(const scope_exit &) = delete;
- ~scope_exit() { ExitFunction(); }
+ void release() { Engaged = false; }
+
+ ~scope_exit() {
+ if (Engaged)
+ ExitFunction();
+ }
};
} // end namespace detail
diff --git a/contrib/llvm/include/llvm/ADT/SetVector.h b/contrib/llvm/include/llvm/ADT/SetVector.h
index 04ed52fc543f..3d6781041320 100644
--- a/contrib/llvm/include/llvm/ADT/SetVector.h
+++ b/contrib/llvm/include/llvm/ADT/SetVector.h
@@ -31,7 +31,7 @@
namespace llvm {
-/// \brief A vector that has set insertion semantics.
+/// A vector that has set insertion semantics.
///
/// This adapter class provides a way to keep a set of things that also has the
/// property of a deterministic iteration order. The order of iteration is the
@@ -52,10 +52,10 @@ public:
using const_reverse_iterator = typename vector_type::const_reverse_iterator;
using size_type = typename vector_type::size_type;
- /// \brief Construct an empty SetVector
+ /// Construct an empty SetVector
SetVector() = default;
- /// \brief Initialize a SetVector with a range of elements
+ /// Initialize a SetVector with a range of elements
template<typename It>
SetVector(It Start, It End) {
insert(Start, End);
@@ -69,75 +69,75 @@ public:
return std::move(vector_);
}
- /// \brief Determine if the SetVector is empty or not.
+ /// Determine if the SetVector is empty or not.
bool empty() const {
return vector_.empty();
}
- /// \brief Determine the number of elements in the SetVector.
+ /// Determine the number of elements in the SetVector.
size_type size() const {
return vector_.size();
}
- /// \brief Get an iterator to the beginning of the SetVector.
+ /// Get an iterator to the beginning of the SetVector.
iterator begin() {
return vector_.begin();
}
- /// \brief Get a const_iterator to the beginning of the SetVector.
+ /// Get a const_iterator to the beginning of the SetVector.
const_iterator begin() const {
return vector_.begin();
}
- /// \brief Get an iterator to the end of the SetVector.
+ /// Get an iterator to the end of the SetVector.
iterator end() {
return vector_.end();
}
- /// \brief Get a const_iterator to the end of the SetVector.
+ /// Get a const_iterator to the end of the SetVector.
const_iterator end() const {
return vector_.end();
}
- /// \brief Get an reverse_iterator to the end of the SetVector.
+ /// Get an reverse_iterator to the end of the SetVector.
reverse_iterator rbegin() {
return vector_.rbegin();
}
- /// \brief Get a const_reverse_iterator to the end of the SetVector.
+ /// Get a const_reverse_iterator to the end of the SetVector.
const_reverse_iterator rbegin() const {
return vector_.rbegin();
}
- /// \brief Get a reverse_iterator to the beginning of the SetVector.
+ /// Get a reverse_iterator to the beginning of the SetVector.
reverse_iterator rend() {
return vector_.rend();
}
- /// \brief Get a const_reverse_iterator to the beginning of the SetVector.
+ /// Get a const_reverse_iterator to the beginning of the SetVector.
const_reverse_iterator rend() const {
return vector_.rend();
}
- /// \brief Return the first element of the SetVector.
+ /// Return the first element of the SetVector.
const T &front() const {
assert(!empty() && "Cannot call front() on empty SetVector!");
return vector_.front();
}
- /// \brief Return the last element of the SetVector.
+ /// Return the last element of the SetVector.
const T &back() const {
assert(!empty() && "Cannot call back() on empty SetVector!");
return vector_.back();
}
- /// \brief Index into the SetVector.
+ /// Index into the SetVector.
const_reference operator[](size_type n) const {
assert(n < vector_.size() && "SetVector access out of range!");
return vector_[n];
}
- /// \brief Insert a new element into the SetVector.
+ /// Insert a new element into the SetVector.
/// \returns true if the element was inserted into the SetVector.
bool insert(const value_type &X) {
bool result = set_.insert(X).second;
@@ -146,7 +146,7 @@ public:
return result;
}
- /// \brief Insert a range of elements into the SetVector.
+ /// Insert a range of elements into the SetVector.
template<typename It>
void insert(It Start, It End) {
for (; Start != End; ++Start)
@@ -154,7 +154,7 @@ public:
vector_.push_back(*Start);
}
- /// \brief Remove an item from the set vector.
+ /// Remove an item from the set vector.
bool remove(const value_type& X) {
if (set_.erase(X)) {
typename vector_type::iterator I = find(vector_, X);
@@ -183,7 +183,7 @@ public:
return vector_.erase(NI);
}
- /// \brief Remove items from the set vector based on a predicate function.
+ /// Remove items from the set vector based on a predicate function.
///
/// This is intended to be equivalent to the following code, if we could
/// write it:
@@ -206,19 +206,19 @@ public:
return true;
}
- /// \brief Count the number of elements of a given key in the SetVector.
+ /// Count the number of elements of a given key in the SetVector.
/// \returns 0 if the element is not in the SetVector, 1 if it is.
size_type count(const key_type &key) const {
return set_.count(key);
}
- /// \brief Completely clear the SetVector
+ /// Completely clear the SetVector
void clear() {
set_.clear();
vector_.clear();
}
- /// \brief Remove the last element of the SetVector.
+ /// Remove the last element of the SetVector.
void pop_back() {
assert(!empty() && "Cannot remove an element from an empty SetVector!");
set_.erase(back());
@@ -239,7 +239,7 @@ public:
return vector_ != that.vector_;
}
- /// \brief Compute This := This u S, return whether 'This' changed.
+ /// Compute This := This u S, return whether 'This' changed.
/// TODO: We should be able to use set_union from SetOperations.h, but
/// SetVector interface is inconsistent with DenseSet.
template <class STy>
@@ -254,7 +254,7 @@ public:
return Changed;
}
- /// \brief Compute This := This - B
+ /// Compute This := This - B
/// TODO: We should be able to use set_subtract from SetOperations.h, but
/// SetVector interface is inconsistent with DenseSet.
template <class STy>
@@ -265,7 +265,7 @@ public:
}
private:
- /// \brief A wrapper predicate designed for use with std::remove_if.
+ /// A wrapper predicate designed for use with std::remove_if.
///
/// This predicate wraps a predicate suitable for use with std::remove_if to
/// call set_.erase(x) on each element which is slated for removal.
@@ -292,7 +292,7 @@ private:
vector_type vector_; ///< The vector.
};
-/// \brief A SetVector that performs no allocations if smaller than
+/// A SetVector that performs no allocations if smaller than
/// a certain size.
template <typename T, unsigned N>
class SmallSetVector
@@ -300,7 +300,7 @@ class SmallSetVector
public:
SmallSetVector() = default;
- /// \brief Initialize a SmallSetVector with a range of elements
+ /// Initialize a SmallSetVector with a range of elements
template<typename It>
SmallSetVector(It Start, It End) {
this->insert(Start, End);
diff --git a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h
index 78ea613af693..db08e40257ba 100644
--- a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h
+++ b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h
@@ -335,7 +335,7 @@ struct RoundUpToPowerOfTwo {
enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
};
-/// \brief A templated base class for \c SmallPtrSet which provides the
+/// A templated base class for \c SmallPtrSet which provides the
/// typesafe interface that is common across all small sizes.
///
/// This is particularly useful for passing around between interface boundaries
diff --git a/contrib/llvm/include/llvm/ADT/SmallSet.h b/contrib/llvm/include/llvm/ADT/SmallSet.h
index d52d0f07f9a6..5d84627714bc 100644
--- a/contrib/llvm/include/llvm/ADT/SmallSet.h
+++ b/contrib/llvm/include/llvm/ADT/SmallSet.h
@@ -17,21 +17,120 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/type_traits.h"
#include <cstddef>
#include <functional>
#include <set>
+#include <type_traits>
#include <utility>
namespace llvm {
+/// SmallSetIterator - This class implements a const_iterator for SmallSet by
+/// delegating to the underlying SmallVector or Set iterators.
+template <typename T, unsigned N, typename C>
+class SmallSetIterator
+ : public iterator_facade_base<SmallSetIterator<T, N, C>,
+ std::forward_iterator_tag, T> {
+private:
+ using SetIterTy = typename std::set<T, C>::const_iterator;
+ using VecIterTy = typename SmallVector<T, N>::const_iterator;
+ using SelfTy = SmallSetIterator<T, N, C>;
+
+ /// Iterators to the parts of the SmallSet containing the data. They are set
+ /// depending on isSmall.
+ union {
+ SetIterTy SetIter;
+ VecIterTy VecIter;
+ };
+
+ bool isSmall;
+
+public:
+ SmallSetIterator(SetIterTy SetIter) : SetIter(SetIter), isSmall(false) {}
+
+ SmallSetIterator(VecIterTy VecIter) : VecIter(VecIter), isSmall(true) {}
+
+ // Spell out destructor, copy/move constructor and assignment operators for
+ // MSVC STL, where set<T>::const_iterator is not trivially copy constructible.
+ ~SmallSetIterator() {
+ if (isSmall)
+ VecIter.~VecIterTy();
+ else
+ SetIter.~SetIterTy();
+ }
+
+ SmallSetIterator(const SmallSetIterator &Other) : isSmall(Other.isSmall) {
+ if (isSmall)
+ VecIter = Other.VecIter;
+ else
+ // Use placement new, to make sure SetIter is properly constructed, even
+ // if it is not trivially copy-able (e.g. in MSVC).
+ new (&SetIter) SetIterTy(Other.SetIter);
+ }
+
+ SmallSetIterator(SmallSetIterator &&Other) : isSmall(Other.isSmall) {
+ if (isSmall)
+ VecIter = std::move(Other.VecIter);
+ else
+ // Use placement new, to make sure SetIter is properly constructed, even
+ // if it is not trivially copy-able (e.g. in MSVC).
+ new (&SetIter) SetIterTy(std::move(Other.SetIter));
+ }
+
+ SmallSetIterator& operator=(const SmallSetIterator& Other) {
+ // Call destructor for SetIter, so it gets properly destroyed if it is
+ // not trivially destructible in case we are setting VecIter.
+ if (!isSmall)
+ SetIter.~SetIterTy();
+
+ isSmall = Other.isSmall;
+ if (isSmall)
+ VecIter = Other.VecIter;
+ else
+ new (&SetIter) SetIterTy(Other.SetIter);
+ return *this;
+ }
+
+ SmallSetIterator& operator=(SmallSetIterator&& Other) {
+ // Call destructor for SetIter, so it gets properly destroyed if it is
+ // not trivially destructible in case we are setting VecIter.
+ if (!isSmall)
+ SetIter.~SetIterTy();
+
+ isSmall = Other.isSmall;
+ if (isSmall)
+ VecIter = std::move(Other.VecIter);
+ else
+ new (&SetIter) SetIterTy(std::move(Other.SetIter));
+ return *this;
+ }
+
+ bool operator==(const SmallSetIterator &RHS) const {
+ if (isSmall != RHS.isSmall)
+ return false;
+ if (isSmall)
+ return VecIter == RHS.VecIter;
+ return SetIter == RHS.SetIter;
+ }
+
+ SmallSetIterator &operator++() { // Preincrement
+ if (isSmall)
+ VecIter++;
+ else
+ SetIter++;
+ return *this;
+ }
+
+ const T &operator*() const { return isSmall ? *VecIter : *SetIter; }
+};
+
/// SmallSet - This maintains a set of unique values, optimizing for the case
/// when the set is small (less than N). In this case, the set can be
/// maintained with no mallocs. If the set gets large, we expand to using an
/// std::set to maintain reasonable lookup times.
-///
-/// Note that this set does not provide a way to iterate over members in the
-/// set.
template <typename T, unsigned N, typename C = std::less<T>>
class SmallSet {
/// Use a SmallVector to hold the elements here (even though it will never
@@ -50,6 +149,7 @@ class SmallSet {
public:
using size_type = size_t;
+ using const_iterator = SmallSetIterator<T, N, C>;
SmallSet() = default;
@@ -121,6 +221,18 @@ public:
Set.clear();
}
+ const_iterator begin() const {
+ if (isSmall())
+ return {Vector.begin()};
+ return {Set.begin()};
+ }
+
+ const_iterator end() const {
+ if (isSmall())
+ return {Vector.end()};
+ return {Set.end()};
+ }
+
private:
bool isSmall() const { return Set.empty(); }
diff --git a/contrib/llvm/include/llvm/ADT/SmallVector.h b/contrib/llvm/include/llvm/ADT/SmallVector.h
index a9ac98d1ad4c..acb4426b4f45 100644
--- a/contrib/llvm/include/llvm/ADT/SmallVector.h
+++ b/contrib/llvm/include/llvm/ADT/SmallVector.h
@@ -18,6 +18,7 @@
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemAlloc.h"
#include "llvm/Support/type_traits.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -37,28 +38,42 @@ namespace llvm {
/// This is all the non-templated stuff common to all SmallVectors.
class SmallVectorBase {
protected:
- void *BeginX, *EndX, *CapacityX;
+ void *BeginX;
+ unsigned Size = 0, Capacity;
-protected:
- SmallVectorBase(void *FirstEl, size_t Size)
- : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {}
+ SmallVectorBase() = delete;
+ SmallVectorBase(void *FirstEl, size_t Capacity)
+ : BeginX(FirstEl), Capacity(Capacity) {}
/// This is an implementation of the grow() method which only works
/// on POD-like data types and is out of line to reduce code duplication.
- void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize);
+ void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize);
public:
- /// This returns size()*sizeof(T).
- size_t size_in_bytes() const {
- return size_t((char*)EndX - (char*)BeginX);
- }
+ size_t size() const { return Size; }
+ size_t capacity() const { return Capacity; }
+
+ LLVM_NODISCARD bool empty() const { return !Size; }
- /// capacity_in_bytes - This returns capacity()*sizeof(T).
- size_t capacity_in_bytes() const {
- return size_t((char*)CapacityX - (char*)BeginX);
+ /// Set the array size to \p N, which the current array must have enough
+ /// capacity for.
+ ///
+ /// This does not construct or destroy any elements in the vector.
+ ///
+ /// Clients can use this in conjunction with capacity() to write past the end
+ /// of the buffer when they know that more elements are available, and only
+ /// update the size later. This avoids the cost of value initializing elements
+ /// which will only be overwritten.
+ void set_size(size_t Size) {
+ assert(Size <= capacity());
+ this->Size = Size;
}
+};
- LLVM_NODISCARD bool empty() const { return BeginX == EndX; }
+/// Figure out the offset of the first element.
+template <class T, typename = void> struct SmallVectorAlignmentAndSize {
+ AlignedCharArrayUnion<SmallVectorBase> Base;
+ AlignedCharArrayUnion<T> FirstEl;
};
/// This is the part of SmallVectorTemplateBase which does not depend on whether
@@ -66,36 +81,34 @@ public:
/// to avoid unnecessarily requiring T to be complete.
template <typename T, typename = void>
class SmallVectorTemplateCommon : public SmallVectorBase {
-private:
- template <typename, unsigned> friend struct SmallVectorStorage;
-
- // Allocate raw space for N elements of type T. If T has a ctor or dtor, we
- // don't want it to be automatically run, so we need to represent the space as
- // something else. Use an array of char of sufficient alignment.
- using U = AlignedCharArrayUnion<T>;
- U FirstEl;
+ /// Find the address of the first element. For this pointer math to be valid
+ /// with small-size of 0 for T with lots of alignment, it's important that
+ /// SmallVectorStorage is properly-aligned even for small-size of 0.
+ void *getFirstEl() const {
+ return const_cast<void *>(reinterpret_cast<const void *>(
+ reinterpret_cast<const char *>(this) +
+ offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)));
+ }
// Space after 'FirstEl' is clobbered, do not add any instance vars after it.
protected:
- SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {}
+ SmallVectorTemplateCommon(size_t Size)
+ : SmallVectorBase(getFirstEl(), Size) {}
- void grow_pod(size_t MinSizeInBytes, size_t TSize) {
- SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize);
+ void grow_pod(size_t MinCapacity, size_t TSize) {
+ SmallVectorBase::grow_pod(getFirstEl(), MinCapacity, TSize);
}
/// Return true if this is a smallvector which has not had dynamic
/// memory allocated for it.
- bool isSmall() const {
- return BeginX == static_cast<const void*>(&FirstEl);
- }
+ bool isSmall() const { return BeginX == getFirstEl(); }
/// Put this vector in a state of being small.
void resetToSmall() {
- BeginX = EndX = CapacityX = &FirstEl;
+ BeginX = getFirstEl();
+ Size = Capacity = 0; // FIXME: Setting Capacity to 0 is suspect.
}
- void setEnd(T *P) { this->EndX = P; }
-
public:
using size_type = size_t;
using difference_type = ptrdiff_t;
@@ -117,27 +130,20 @@ public:
LLVM_ATTRIBUTE_ALWAYS_INLINE
const_iterator begin() const { return (const_iterator)this->BeginX; }
LLVM_ATTRIBUTE_ALWAYS_INLINE
- iterator end() { return (iterator)this->EndX; }
+ iterator end() { return begin() + size(); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
- const_iterator end() const { return (const_iterator)this->EndX; }
-
-protected:
- iterator capacity_ptr() { return (iterator)this->CapacityX; }
- const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;}
+ const_iterator end() const { return begin() + size(); }
-public:
// reverse iterator creation methods.
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
- LLVM_ATTRIBUTE_ALWAYS_INLINE
- size_type size() const { return end()-begin(); }
+ size_type size_in_bytes() const { return size() * sizeof(T); }
size_type max_size() const { return size_type(-1) / sizeof(T); }
- /// Return the total number of elements in the currently allocated buffer.
- size_t capacity() const { return capacity_ptr() - begin(); }
+ size_t capacity_in_bytes() const { return capacity() * sizeof(T); }
/// Return a pointer to the vector's buffer, even if empty().
pointer data() { return pointer(begin()); }
@@ -210,21 +216,21 @@ protected:
public:
void push_back(const T &Elt) {
- if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+ if (LLVM_UNLIKELY(this->size() >= this->capacity()))
this->grow();
::new ((void*) this->end()) T(Elt);
- this->setEnd(this->end()+1);
+ this->set_size(this->size() + 1);
}
void push_back(T &&Elt) {
- if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+ if (LLVM_UNLIKELY(this->size() >= this->capacity()))
this->grow();
::new ((void*) this->end()) T(::std::move(Elt));
- this->setEnd(this->end()+1);
+ this->set_size(this->size() + 1);
}
void pop_back() {
- this->setEnd(this->end()-1);
+ this->set_size(this->size() - 1);
this->end()->~T();
}
};
@@ -232,15 +238,13 @@ public:
// Define this out-of-line to dissuade the C++ compiler from inlining it.
template <typename T, bool isPodLike>
void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
- size_t CurCapacity = this->capacity();
- size_t CurSize = this->size();
+ if (MinSize > UINT32_MAX)
+ report_bad_alloc_error("SmallVector capacity overflow during allocation");
+
// Always grow, even from zero.
- size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2));
- if (NewCapacity < MinSize)
- NewCapacity = MinSize;
- T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T)));
- if (NewElts == nullptr)
- report_bad_alloc_error("Allocation of SmallVector element failed.");
+ size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2));
+ NewCapacity = std::min(std::max(NewCapacity, MinSize), size_t(UINT32_MAX));
+ T *NewElts = static_cast<T*>(llvm::safe_malloc(NewCapacity*sizeof(T)));
// Move the elements over.
this->uninitialized_move(this->begin(), this->end(), NewElts);
@@ -252,9 +256,8 @@ void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
if (!this->isSmall())
free(this->begin());
- this->setEnd(NewElts+CurSize);
this->BeginX = NewElts;
- this->CapacityX = this->begin()+NewCapacity;
+ this->Capacity = NewCapacity;
}
@@ -301,21 +304,17 @@ protected:
/// Double the size of the allocated memory, guaranteeing space for at
/// least one more element or MinSize if specified.
- void grow(size_t MinSize = 0) {
- this->grow_pod(MinSize*sizeof(T), sizeof(T));
- }
+ void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); }
public:
void push_back(const T &Elt) {
- if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+ if (LLVM_UNLIKELY(this->size() >= this->capacity()))
this->grow();
memcpy(this->end(), &Elt, sizeof(T));
- this->setEnd(this->end()+1);
+ this->set_size(this->size() + 1);
}
- void pop_back() {
- this->setEnd(this->end()-1);
- }
+ void pop_back() { this->set_size(this->size() - 1); }
};
/// This class consists of common code factored out of the SmallVector class to
@@ -332,16 +331,13 @@ public:
protected:
// Default ctor - Initialize to empty.
explicit SmallVectorImpl(unsigned N)
- : SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) {
- }
+ : SmallVectorTemplateBase<T, isPodLike<T>::value>(N) {}
public:
SmallVectorImpl(const SmallVectorImpl &) = delete;
~SmallVectorImpl() {
- // Destroy the constructed elements in the vector.
- this->destroy_range(this->begin(), this->end());
-
+ // Subclass has already destructed this vector's elements.
// If this wasn't grown from the inline copy, deallocate the old space.
if (!this->isSmall())
free(this->begin());
@@ -349,31 +345,31 @@ public:
void clear() {
this->destroy_range(this->begin(), this->end());
- this->EndX = this->BeginX;
+ this->Size = 0;
}
void resize(size_type N) {
if (N < this->size()) {
this->destroy_range(this->begin()+N, this->end());
- this->setEnd(this->begin()+N);
+ this->set_size(N);
} else if (N > this->size()) {
if (this->capacity() < N)
this->grow(N);
for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
new (&*I) T();
- this->setEnd(this->begin()+N);
+ this->set_size(N);
}
}
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);
+ this->set_size(N);
} else if (N > this->size()) {
if (this->capacity() < N)
this->grow(N);
std::uninitialized_fill(this->end(), this->begin()+N, NV);
- this->setEnd(this->begin()+N);
+ this->set_size(N);
}
}
@@ -398,23 +394,23 @@ public:
void append(in_iter in_start, in_iter in_end) {
size_type NumInputs = std::distance(in_start, in_end);
// Grow allocated space if needed.
- if (NumInputs > size_type(this->capacity_ptr()-this->end()))
+ if (NumInputs > this->capacity() - this->size())
this->grow(this->size()+NumInputs);
// Copy the new elements over.
this->uninitialized_copy(in_start, in_end, this->end());
- this->setEnd(this->end() + NumInputs);
+ this->set_size(this->size() + NumInputs);
}
/// Add the specified range to the end of the SmallVector.
void append(size_type NumInputs, const T &Elt) {
// Grow allocated space if needed.
- if (NumInputs > size_type(this->capacity_ptr()-this->end()))
+ if (NumInputs > this->capacity() - this->size())
this->grow(this->size()+NumInputs);
// Copy the new elements over.
std::uninitialized_fill_n(this->end(), NumInputs, Elt);
- this->setEnd(this->end() + NumInputs);
+ this->set_size(this->size() + NumInputs);
}
void append(std::initializer_list<T> IL) {
@@ -428,7 +424,7 @@ public:
clear();
if (this->capacity() < NumElts)
this->grow(NumElts);
- this->setEnd(this->begin()+NumElts);
+ this->set_size(NumElts);
std::uninitialized_fill(this->begin(), this->end(), Elt);
}
@@ -475,7 +471,7 @@ public:
iterator I = std::move(E, this->end(), S);
// Drop the last elts.
this->destroy_range(I, this->end());
- this->setEnd(I);
+ this->set_size(I - this->begin());
return(N);
}
@@ -488,7 +484,7 @@ public:
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
assert(I <= this->end() && "Inserting past the end of the vector.");
- if (this->EndX >= this->CapacityX) {
+ if (this->size() >= this->capacity()) {
size_t EltNo = I-this->begin();
this->grow();
I = this->begin()+EltNo;
@@ -497,12 +493,12 @@ public:
::new ((void*) this->end()) T(::std::move(this->back()));
// Push everything else over.
std::move_backward(I, this->end()-1, this->end());
- this->setEnd(this->end()+1);
+ this->set_size(this->size() + 1);
// If we just moved the element we're inserting, be sure to update
// the reference.
T *EltPtr = &Elt;
- if (I <= EltPtr && EltPtr < this->EndX)
+ if (I <= EltPtr && EltPtr < this->end())
++EltPtr;
*I = ::std::move(*EltPtr);
@@ -518,7 +514,7 @@ public:
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
assert(I <= this->end() && "Inserting past the end of the vector.");
- if (this->EndX >= this->CapacityX) {
+ if (this->size() >= this->capacity()) {
size_t EltNo = I-this->begin();
this->grow();
I = this->begin()+EltNo;
@@ -526,12 +522,12 @@ public:
::new ((void*) this->end()) T(std::move(this->back()));
// Push everything else over.
std::move_backward(I, this->end()-1, this->end());
- this->setEnd(this->end()+1);
+ this->set_size(this->size() + 1);
// If we just moved the element we're inserting, be sure to update
// the reference.
const T *EltPtr = &Elt;
- if (I <= EltPtr && EltPtr < this->EndX)
+ if (I <= EltPtr && EltPtr < this->end())
++EltPtr;
*I = *EltPtr;
@@ -577,7 +573,7 @@ public:
// Move over the elements that we're about to overwrite.
T *OldEnd = this->end();
- this->setEnd(this->end() + NumToInsert);
+ this->set_size(this->size() + NumToInsert);
size_t NumOverwritten = OldEnd-I;
this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
@@ -634,7 +630,7 @@ public:
// Move over the elements that we're about to overwrite.
T *OldEnd = this->end();
- this->setEnd(this->end() + NumToInsert);
+ this->set_size(this->size() + NumToInsert);
size_t NumOverwritten = OldEnd-I;
this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
@@ -654,10 +650,10 @@ public:
}
template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
- if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+ if (LLVM_UNLIKELY(this->size() >= this->capacity()))
this->grow();
::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
- this->setEnd(this->end() + 1);
+ this->set_size(this->size() + 1);
}
SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
@@ -676,20 +672,6 @@ public:
return std::lexicographical_compare(this->begin(), this->end(),
RHS.begin(), RHS.end());
}
-
- /// Set the array size to \p N, which the current array must have enough
- /// capacity for.
- ///
- /// This does not construct or destroy any elements in the vector.
- ///
- /// Clients can use this in conjunction with capacity() to write past the end
- /// of the buffer when they know that more elements are available, and only
- /// update the size later. This avoids the cost of value initializing elements
- /// which will only be overwritten.
- void set_size(size_type N) {
- assert(N <= this->capacity());
- this->setEnd(this->begin() + N);
- }
};
template <typename T>
@@ -699,8 +681,8 @@ void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
// We can only avoid copying elements if neither vector is small.
if (!this->isSmall() && !RHS.isSmall()) {
std::swap(this->BeginX, RHS.BeginX);
- std::swap(this->EndX, RHS.EndX);
- std::swap(this->CapacityX, RHS.CapacityX);
+ std::swap(this->Size, RHS.Size);
+ std::swap(this->Capacity, RHS.Capacity);
return;
}
if (RHS.size() > this->capacity())
@@ -718,15 +700,15 @@ void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
if (this->size() > RHS.size()) {
size_t EltDiff = this->size() - RHS.size();
this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
- RHS.setEnd(RHS.end()+EltDiff);
+ RHS.set_size(RHS.size() + EltDiff);
this->destroy_range(this->begin()+NumShared, this->end());
- this->setEnd(this->begin()+NumShared);
+ this->set_size(NumShared);
} else if (RHS.size() > this->size()) {
size_t EltDiff = RHS.size() - this->size();
this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
- this->setEnd(this->end() + EltDiff);
+ this->set_size(this->size() + EltDiff);
this->destroy_range(RHS.begin()+NumShared, RHS.end());
- RHS.setEnd(RHS.begin()+NumShared);
+ RHS.set_size(NumShared);
}
}
@@ -752,7 +734,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::
this->destroy_range(NewEnd, this->end());
// Trim.
- this->setEnd(NewEnd);
+ this->set_size(RHSSize);
return *this;
}
@@ -762,7 +744,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::
if (this->capacity() < RHSSize) {
// Destroy current elements.
this->destroy_range(this->begin(), this->end());
- this->setEnd(this->begin());
+ this->set_size(0);
CurSize = 0;
this->grow(RHSSize);
} else if (CurSize) {
@@ -775,7 +757,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::
this->begin()+CurSize);
// Set end.
- this->setEnd(this->begin()+RHSSize);
+ this->set_size(RHSSize);
return *this;
}
@@ -789,8 +771,8 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
this->destroy_range(this->begin(), this->end());
if (!this->isSmall()) free(this->begin());
this->BeginX = RHS.BeginX;
- this->EndX = RHS.EndX;
- this->CapacityX = RHS.CapacityX;
+ this->Size = RHS.Size;
+ this->Capacity = RHS.Capacity;
RHS.resetToSmall();
return *this;
}
@@ -807,7 +789,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
// Destroy excess elements and trim the bounds.
this->destroy_range(NewEnd, this->end());
- this->setEnd(NewEnd);
+ this->set_size(RHSSize);
// Clear the RHS.
RHS.clear();
@@ -822,7 +804,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
if (this->capacity() < RHSSize) {
// Destroy current elements.
this->destroy_range(this->begin(), this->end());
- this->setEnd(this->begin());
+ this->set_size(0);
CurSize = 0;
this->grow(RHSSize);
} else if (CurSize) {
@@ -835,22 +817,23 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
this->begin()+CurSize);
// Set end.
- this->setEnd(this->begin()+RHSSize);
+ this->set_size(RHSSize);
RHS.clear();
return *this;
}
-/// Storage for the SmallVector elements which aren't contained in
-/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1'
-/// element is in the base class. This is specialized for the N=1 and N=0 cases
+/// Storage for the SmallVector elements. This is specialized for the N=0 case
/// to avoid allocating unnecessary storage.
template <typename T, unsigned N>
struct SmallVectorStorage {
- typename SmallVectorTemplateCommon<T>::U InlineElts[N - 1];
+ AlignedCharArrayUnion<T> InlineElts[N];
};
-template <typename T> struct SmallVectorStorage<T, 1> {};
-template <typename T> struct SmallVectorStorage<T, 0> {};
+
+/// We need the storage to be properly aligned even for small-size of 0 so that
+/// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is
+/// well-defined.
+template <typename T> struct alignas(alignof(T)) SmallVectorStorage<T, 0> {};
/// This is a 'vector' (really, a variable-sized array), optimized
/// for the case when the array is small. It contains some number of elements
@@ -861,13 +844,15 @@ template <typename T> struct SmallVectorStorage<T, 0> {};
/// Note that this does not attempt to be exception safe.
///
template <typename T, unsigned N>
-class SmallVector : public SmallVectorImpl<T> {
- /// Inline space for elements which aren't stored in the base class.
- SmallVectorStorage<T, N> Storage;
-
+class SmallVector : public SmallVectorImpl<T>, SmallVectorStorage<T, N> {
public:
SmallVector() : SmallVectorImpl<T>(N) {}
+ ~SmallVector() {
+ // Destroy the constructed elements in the vector.
+ this->destroy_range(this->begin(), this->end());
+ }
+
explicit SmallVector(size_t Size, const T &Value = T())
: SmallVectorImpl<T>(N) {
this->assign(Size, Value);
diff --git a/contrib/llvm/include/llvm/ADT/SparseMultiSet.h b/contrib/llvm/include/llvm/ADT/SparseMultiSet.h
index c91e0d70f65a..3c8637621510 100644
--- a/contrib/llvm/include/llvm/ADT/SparseMultiSet.h
+++ b/contrib/llvm/include/llvm/ADT/SparseMultiSet.h
@@ -211,7 +211,7 @@ public:
// The Sparse array doesn't actually need to be initialized, so malloc
// would be enough here, but that will cause tools like valgrind to
// complain about branching on uninitialized data.
- Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT)));
+ Sparse = static_cast<SparseT*>(safe_calloc(U, sizeof(SparseT)));
Universe = U;
}
diff --git a/contrib/llvm/include/llvm/ADT/SparseSet.h b/contrib/llvm/include/llvm/ADT/SparseSet.h
index 25ade8831922..74cc6dab8c74 100644
--- a/contrib/llvm/include/llvm/ADT/SparseSet.h
+++ b/contrib/llvm/include/llvm/ADT/SparseSet.h
@@ -22,6 +22,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
#include <cassert>
#include <cstdint>
#include <cstdlib>
@@ -163,7 +164,7 @@ public:
// The Sparse array doesn't actually need to be initialized, so malloc
// would be enough here, but that will cause tools like valgrind to
// complain about branching on uninitialized data.
- Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT)));
+ Sparse = static_cast<SparseT*>(safe_calloc(U, sizeof(SparseT)));
Universe = U;
}
diff --git a/contrib/llvm/include/llvm/ADT/Statistic.h b/contrib/llvm/include/llvm/ADT/Statistic.h
index d5ebba409c3d..90c2eefceb6c 100644
--- a/contrib/llvm/include/llvm/ADT/Statistic.h
+++ b/contrib/llvm/include/llvm/ADT/Statistic.h
@@ -26,15 +26,24 @@
#ifndef LLVM_ADT_STATISTIC_H
#define LLVM_ADT_STATISTIC_H
-#include "llvm/Support/Atomic.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Compiler.h"
#include <atomic>
#include <memory>
+#include <vector>
+
+// Determine whether statistics should be enabled. We must do it here rather
+// than in CMake because multi-config generators cannot determine this at
+// configure time.
+#if !defined(NDEBUG) || LLVM_FORCE_ENABLE_STATS
+#define LLVM_ENABLE_STATS 1
+#endif
namespace llvm {
class raw_ostream;
class raw_fd_ostream;
+class StringRef;
class Statistic {
public:
@@ -42,7 +51,7 @@ public:
const char *Name;
const char *Desc;
std::atomic<unsigned> Value;
- bool Initialized;
+ std::atomic<bool> Initialized;
unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
const char *getDebugType() const { return DebugType; }
@@ -61,7 +70,7 @@ public:
// Allow use of this class as the value itself.
operator unsigned() const { return getValue(); }
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
+#if LLVM_ENABLE_STATS
const Statistic &operator=(unsigned Val) {
Value.store(Val, std::memory_order_relaxed);
return init();
@@ -143,14 +152,12 @@ public:
void updateMax(unsigned V) {}
-#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
+#endif // LLVM_ENABLE_STATS
protected:
Statistic &init() {
- bool tmp = Initialized;
- sys::MemoryFence();
- if (!tmp) RegisterStatistic();
- TsanHappensAfter(this);
+ if (!Initialized.load(std::memory_order_acquire))
+ RegisterStatistic();
return *this;
}
@@ -160,21 +167,21 @@ protected:
// STATISTIC - A macro to make definition of statistics really simple. This
// automatically passes the DEBUG_TYPE of the file into the statistic.
#define STATISTIC(VARNAME, DESC) \
- static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, false}
+ static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, {false}}
-/// \brief Enable the collection and printing of statistics.
+/// Enable the collection and printing of statistics.
void EnableStatistics(bool PrintOnExit = true);
-/// \brief Check if statistics are enabled.
+/// Check if statistics are enabled.
bool AreStatisticsEnabled();
-/// \brief Return a file stream to print our output on.
+/// Return a file stream to print our output on.
std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile();
-/// \brief Print statistics to the file returned by CreateInfoOutputFile().
+/// Print statistics to the file returned by CreateInfoOutputFile().
void PrintStatistics();
-/// \brief Print statistics to the given output stream.
+/// Print statistics to the given output stream.
void PrintStatistics(raw_ostream &OS);
/// Print statistics in JSON format. This does include all global timers (\see
@@ -183,6 +190,30 @@ void PrintStatistics(raw_ostream &OS);
/// PrintStatisticsJSON().
void PrintStatisticsJSON(raw_ostream &OS);
+/// Get the statistics. This can be used to look up the value of
+/// statistics without needing to parse JSON.
+///
+/// This function does not prevent statistics being updated by other threads
+/// during it's execution. It will return the value at the point that it is
+/// read. However, it will prevent new statistics from registering until it
+/// completes.
+const std::vector<std::pair<StringRef, unsigned>> GetStatistics();
+
+/// Reset the statistics. This can be used to zero and de-register the
+/// statistics in order to measure a compilation.
+///
+/// When this function begins to call destructors prior to returning, all
+/// statistics will be zero and unregistered. However, that might not remain the
+/// case by the time this function finishes returning. Whether update from other
+/// threads are lost or merely deferred until during the function return is
+/// timing sensitive.
+///
+/// Callers who intend to use this to measure statistics for a single
+/// compilation should ensure that no compilations are in progress at the point
+/// this function is called and that only one compilation executes until calling
+/// GetStatistics().
+void ResetStatistics();
+
} // end namespace llvm
#endif // LLVM_ADT_STATISTIC_H
diff --git a/contrib/llvm/include/llvm/ADT/StringExtras.h b/contrib/llvm/include/llvm/ADT/StringExtras.h
index 60652f8c55c5..71b0e7527cb7 100644
--- a/contrib/llvm/include/llvm/ADT/StringExtras.h
+++ b/contrib/llvm/include/llvm/ADT/StringExtras.h
@@ -39,6 +39,16 @@ inline char hexdigit(unsigned X, bool LowerCase = false) {
return X < 10 ? '0' + X : HexChar + X - 10;
}
+/// Given an array of c-style strings terminated by a null pointer, construct
+/// a vector of StringRefs representing the same strings without the terminating
+/// null string.
+inline std::vector<StringRef> toStringRefArray(const char *const *Strings) {
+ std::vector<StringRef> Result;
+ while (*Strings)
+ Result.push_back(*Strings++);
+ return Result;
+}
+
/// Construct a string ref from a boolean.
inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); }
@@ -78,6 +88,26 @@ inline bool isAlpha(char C) {
/// lowercase letter as classified by "C" locale.
inline bool isAlnum(char C) { return isAlpha(C) || isDigit(C); }
+/// Checks whether character \p C is valid ASCII (high bit is zero).
+inline bool isASCII(char C) { return static_cast<unsigned char>(C) <= 127; }
+
+/// Checks whether all characters in S are ASCII.
+inline bool isASCII(llvm::StringRef S) {
+ for (char C : S)
+ if (LLVM_UNLIKELY(!isASCII(C)))
+ return false;
+ return true;
+}
+
+/// Checks whether character \p C is printable.
+///
+/// Locale-independent version of the C standard library isprint whose results
+/// may differ on different platforms.
+inline bool isPrint(char C) {
+ unsigned char UC = static_cast<unsigned char>(C);
+ return (0x20 <= UC) && (UC <= 0x7E);
+}
+
/// Returns the corresponding lowercase character if \p x is uppercase.
inline char toLower(char x) {
if (x >= 'A' && x <= 'Z')
@@ -157,7 +187,7 @@ inline std::string fromHex(StringRef Input) {
return Output;
}
-/// \brief Convert the string \p S to an integer of the specified type using
+/// Convert the string \p S to an integer of the specified type using
/// the radix \p Base. If \p Base is 0, auto-detects the radix.
/// Returns true if the number was successfully converted, false otherwise.
template <typename N> bool to_integer(StringRef S, N &Num, unsigned Base = 0) {
@@ -232,19 +262,6 @@ void SplitString(StringRef Source,
SmallVectorImpl<StringRef> &OutFragments,
StringRef Delimiters = " \t\n\v\f\r");
-/// HashString - Hash function for strings.
-///
-/// This is the Bernstein hash function.
-//
-// FIXME: Investigate whether a modified bernstein hash function performs
-// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
-// X*33+c -> X*33^c
-inline unsigned HashString(StringRef Str, unsigned Result = 0) {
- for (StringRef::size_type i = 0, e = Str.size(); i != e; ++i)
- Result = Result * 33 + (unsigned char)Str[i];
- return Result;
-}
-
/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th).
inline StringRef getOrdinalSuffix(unsigned Val) {
// It is critically important that we do this perfectly for
@@ -264,9 +281,13 @@ inline StringRef getOrdinalSuffix(unsigned Val) {
}
}
-/// PrintEscapedString - Print each character of the specified string, escaping
-/// it if it is not printable or if it is an escape char.
-void PrintEscapedString(StringRef Name, raw_ostream &Out);
+/// Print each character of the specified string, escaping it if it is not
+/// printable or if it is an escape char.
+void printEscapedString(StringRef Name, raw_ostream &Out);
+
+/// Print each character of the specified string, escaping HTML special
+/// characters.
+void printHTMLEscaped(StringRef String, raw_ostream &Out);
/// printLowerCase - Print each character as lowercase if it is uppercase.
void printLowerCase(StringRef String, raw_ostream &Out);
diff --git a/contrib/llvm/include/llvm/ADT/StringMap.h b/contrib/llvm/include/llvm/ADT/StringMap.h
index 6c2830b44914..a9f83d3f5091 100644
--- a/contrib/llvm/include/llvm/ADT/StringMap.h
+++ b/contrib/llvm/include/llvm/ADT/StringMap.h
@@ -37,12 +37,12 @@ template<typename ValueTy> class StringMapKeyIterator;
/// StringMapEntryBase - Shared base class of StringMapEntry instances.
class StringMapEntryBase {
- unsigned StrLen;
+ size_t StrLen;
public:
- explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {}
+ explicit StringMapEntryBase(size_t Len) : StrLen(Len) {}
- unsigned getKeyLength() const { return StrLen; }
+ size_t getKeyLength() const { return StrLen; }
};
/// StringMapImpl - This is the base class of StringMap that is shared among
@@ -127,10 +127,10 @@ class StringMapEntry : public StringMapEntryBase {
public:
ValueTy second;
- explicit StringMapEntry(unsigned strLen)
+ explicit StringMapEntry(size_t strLen)
: StringMapEntryBase(strLen), second() {}
template <typename... InitTy>
- StringMapEntry(unsigned strLen, InitTy &&... InitVals)
+ StringMapEntry(size_t strLen, InitTy &&... InitVals)
: StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
StringMapEntry(StringMapEntry &E) = delete;
@@ -155,19 +155,16 @@ public:
template <typename AllocatorTy, typename... InitTy>
static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
InitTy &&... InitVals) {
- unsigned KeyLength = Key.size();
+ size_t KeyLength = Key.size();
// Allocate a new item with space for the string at the end and a null
// terminator.
- unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
- KeyLength+1;
- unsigned Alignment = alignof(StringMapEntry);
+ size_t AllocSize = sizeof(StringMapEntry) + KeyLength + 1;
+ size_t Alignment = alignof(StringMapEntry);
StringMapEntry *NewItem =
static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
-
- if (NewItem == nullptr)
- report_bad_alloc_error("Allocation of StringMap entry failed.");
+ assert(NewItem && "Unhandled out-of-memory");
// Construct the value.
new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...);
@@ -203,8 +200,7 @@ public:
template<typename AllocatorTy>
void Destroy(AllocatorTy &Allocator) {
// Free memory referenced by the item.
- unsigned AllocSize =
- static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1;
+ size_t AllocSize = sizeof(StringMapEntry) + getKeyLength() + 1;
this->~StringMapEntry();
Allocator.Deallocate(static_cast<void *>(this), AllocSize);
}
diff --git a/contrib/llvm/include/llvm/ADT/StringRef.h b/contrib/llvm/include/llvm/ADT/StringRef.h
index f6c93a858db1..a5ba5b59b5a3 100644
--- a/contrib/llvm/include/llvm/ADT/StringRef.h
+++ b/contrib/llvm/include/llvm/ADT/StringRef.h
@@ -201,7 +201,7 @@ namespace llvm {
LLVM_NODISCARD
int compare_numeric(StringRef RHS) const;
- /// \brief Determine the edit distance between this string and another
+ /// Determine the edit distance between this string and another
/// string.
///
/// \param Other the string to compare this string against.
@@ -725,10 +725,7 @@ namespace llvm {
/// \returns The split substrings.
LLVM_NODISCARD
std::pair<StringRef, StringRef> split(char Separator) const {
- size_t Idx = find(Separator);
- if (Idx == npos)
- return std::make_pair(*this, StringRef());
- return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
+ return split(StringRef(&Separator, 1));
}
/// Split into two substrings around the first occurrence of a separator
@@ -749,6 +746,24 @@ namespace llvm {
return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
}
+ /// Split into two substrings around the last occurrence of a separator
+ /// string.
+ ///
+ /// If \p Separator is in the string, then the result is a pair (LHS, RHS)
+ /// such that (*this == LHS + Separator + RHS) is true and RHS is
+ /// minimal. If \p Separator is not in the string, then the result is a
+ /// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
+ ///
+ /// \param Separator - The string to split on.
+ /// \return - The split substrings.
+ LLVM_NODISCARD
+ std::pair<StringRef, StringRef> rsplit(StringRef Separator) const {
+ size_t Idx = rfind(Separator);
+ if (Idx == npos)
+ return std::make_pair(*this, StringRef());
+ return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
+ }
+
/// Split into substrings around the occurrences of a separator string.
///
/// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most
@@ -796,10 +811,7 @@ namespace llvm {
/// \return - The split substrings.
LLVM_NODISCARD
std::pair<StringRef, StringRef> rsplit(char Separator) const {
- size_t Idx = rfind(Separator);
- if (Idx == npos)
- return std::make_pair(*this, StringRef());
- return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
+ return rsplit(StringRef(&Separator, 1));
}
/// Return string with consecutive \p Char characters starting from the
@@ -855,6 +867,10 @@ namespace llvm {
/// constexpr StringLiteral S("test");
///
class StringLiteral : public StringRef {
+ private:
+ constexpr StringLiteral(const char *Str, size_t N) : StringRef(Str, N) {
+ }
+
public:
template <size_t N>
constexpr StringLiteral(const char (&Str)[N])
@@ -867,6 +883,12 @@ namespace llvm {
#endif
: StringRef(Str, N - 1) {
}
+
+ // Explicit construction for strings like "foo\0bar".
+ template <size_t N>
+ static constexpr StringLiteral withInnerNUL(const char (&Str)[N]) {
+ return StringLiteral(Str, N - 1);
+ }
};
/// @name StringRef Comparison Operators
@@ -902,7 +924,7 @@ namespace llvm {
/// @}
- /// \brief Compute a hash_code for a StringRef.
+ /// Compute a hash_code for a StringRef.
LLVM_NODISCARD
hash_code hash_value(StringRef S);
diff --git a/contrib/llvm/include/llvm/ADT/StringSwitch.h b/contrib/llvm/include/llvm/ADT/StringSwitch.h
index 75577b7738ba..b7860b98ce5d 100644
--- a/contrib/llvm/include/llvm/ADT/StringSwitch.h
+++ b/contrib/llvm/include/llvm/ADT/StringSwitch.h
@@ -20,7 +20,7 @@
namespace llvm {
-/// \brief A switch()-like statement whose cases are string literals.
+/// A switch()-like statement whose cases are string literals.
///
/// The StringSwitch class is a simple form of a switch() statement that
/// determines whether the given string matches one of the given string
@@ -41,216 +41,176 @@ namespace llvm {
/// \endcode
template<typename T, typename R = T>
class StringSwitch {
- /// \brief The string we are matching.
- StringRef Str;
+ /// The string we are matching.
+ const StringRef Str;
- /// \brief The pointer to the result of this switch statement, once known,
+ /// The pointer to the result of this switch statement, once known,
/// null before that.
- const T *Result;
+ Optional<T> Result;
public:
LLVM_ATTRIBUTE_ALWAYS_INLINE
explicit StringSwitch(StringRef S)
- : Str(S), Result(nullptr) { }
+ : Str(S), Result() { }
// StringSwitch is not copyable.
StringSwitch(const StringSwitch &) = delete;
+
+ // StringSwitch is not assignable due to 'Str' being 'const'.
void operator=(const StringSwitch &) = delete;
+ void operator=(StringSwitch &&other) = delete;
- StringSwitch(StringSwitch &&other) {
- *this = std::move(other);
- }
- StringSwitch &operator=(StringSwitch &&other) {
- Str = other.Str;
- Result = other.Result;
- return *this;
- }
+ StringSwitch(StringSwitch &&other)
+ : Str(other.Str), Result(std::move(other.Result)) { }
~StringSwitch() = default;
// Case-sensitive case matchers
- template<unsigned N>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch& Case(const char (&S)[N], const T& Value) {
- assert(N);
- if (!Result && N-1 == Str.size() &&
- (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) {
- Result = &Value;
+ StringSwitch &Case(StringLiteral S, T Value) {
+ if (!Result && Str == S) {
+ Result = std::move(Value);
}
return *this;
}
- template<unsigned N>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch& EndsWith(const char (&S)[N], const T &Value) {
- assert(N);
- if (!Result && Str.size() >= N-1 &&
- (N == 1 || std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0)) {
- Result = &Value;
+ StringSwitch& EndsWith(StringLiteral S, T Value) {
+ if (!Result && Str.endswith(S)) {
+ Result = std::move(Value);
}
return *this;
}
- template<unsigned N>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch& StartsWith(const char (&S)[N], const T &Value) {
- assert(N);
- if (!Result && Str.size() >= N-1 &&
- (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) {
- Result = &Value;
+ StringSwitch& StartsWith(StringLiteral S, T Value) {
+ if (!Result && Str.startswith(S)) {
+ Result = std::move(Value);
}
return *this;
}
- template<unsigned N0, unsigned N1>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const T& Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) {
return Case(S0, Value).Case(S1, Value);
}
- template<unsigned N0, unsigned N1, unsigned N2>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const T& Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ T Value) {
return Case(S0, Value).Cases(S1, S2, Value);
}
- template<unsigned N0, unsigned N1, unsigned N2, unsigned N3>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const T& Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, Value);
}
- template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const T& Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5, unsigned N6>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const char (&S6)[N6], const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5, unsigned N6, unsigned N7>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const char (&S6)[N6], const char (&S7)[N7],
- const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5, unsigned N6, unsigned N7, unsigned N8>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const char (&S6)[N6], const char (&S7)[N7],
- const char (&S8)[N8], const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, StringLiteral S8,
+ T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5, unsigned N6, unsigned N7, unsigned N8, unsigned N9>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const char (&S6)[N6], const char (&S7)[N7],
- const char (&S8)[N8], const char (&S9)[N9],
- const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, StringLiteral S8,
+ StringLiteral S9, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value);
}
// Case-insensitive case matchers.
- template <unsigned N>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CaseLower(const char (&S)[N],
- const T &Value) {
- if (!Result && Str.equals_lower(StringRef(S, N - 1)))
- Result = &Value;
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CaseLower(StringLiteral S, T Value) {
+ if (!Result && Str.equals_lower(S))
+ Result = std::move(Value);
return *this;
}
- template <unsigned N>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &EndsWithLower(const char (&S)[N],
- const T &Value) {
- if (!Result && Str.endswith_lower(StringRef(S, N - 1)))
- Result = &Value;
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &EndsWithLower(StringLiteral S, T Value) {
+ if (!Result && Str.endswith_lower(S))
+ Result = Value;
return *this;
}
- template <unsigned N>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &StartsWithLower(const char (&S)[N],
- const T &Value) {
- if (!Result && Str.startswith_lower(StringRef(S, N - 1)))
- Result = &Value;
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &StartsWithLower(StringLiteral S, T Value) {
+ if (!Result && Str.startswith_lower(S))
+ Result = std::move(Value);
return *this;
}
- template <unsigned N0, unsigned N1>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
- CasesLower(const char (&S0)[N0], const char (&S1)[N1], const T &Value) {
+
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) {
return CaseLower(S0, Value).CaseLower(S1, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
- CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
- const T &Value) {
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ T Value) {
return CaseLower(S0, Value).CasesLower(S1, S2, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
- CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
- const char (&S3)[N3], const T &Value) {
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, T Value) {
return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
- CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
- const char (&S3)[N3], const char (&S4)[N4], const T &Value) {
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, T Value) {
return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value);
}
+ LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
- R Default(const T &Value) const {
+ R Default(T Value) {
if (Result)
- return *Result;
+ return std::move(*Result);
return Value;
}
+ LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
- operator R() const {
+ operator R() {
assert(Result && "Fell off the end of a string-switch");
- return *Result;
+ return std::move(*Result);
}
};
diff --git a/contrib/llvm/include/llvm/ADT/TinyPtrVector.h b/contrib/llvm/include/llvm/ADT/TinyPtrVector.h
index 73573d65e2b3..1b8e9aa658c3 100644
--- a/contrib/llvm/include/llvm/ADT/TinyPtrVector.h
+++ b/contrib/llvm/include/llvm/ADT/TinyPtrVector.h
@@ -108,6 +108,12 @@ public:
return *this;
}
+ TinyPtrVector(std::initializer_list<EltTy> IL)
+ : Val(IL.size() == 0
+ ? PtrUnion()
+ : IL.size() == 1 ? PtrUnion(*IL.begin())
+ : PtrUnion(new VecTy(IL.begin(), IL.end()))) {}
+
/// Constructor from an ArrayRef.
///
/// This also is a constructor for individual array elements due to the single
diff --git a/contrib/llvm/include/llvm/ADT/Triple.h b/contrib/llvm/include/llvm/ADT/Triple.h
index 74fc8eb8ccbf..c95b16dd4e8c 100644
--- a/contrib/llvm/include/llvm/ADT/Triple.h
+++ b/contrib/llvm/include/llvm/ADT/Triple.h
@@ -101,6 +101,7 @@ public:
enum SubArchType {
NoSubArch,
+ ARMSubArch_v8_4a,
ARMSubArch_v8_3a,
ARMSubArch_v8_2a,
ARMSubArch_v8_1a,
@@ -144,7 +145,8 @@ public:
AMD,
Mesa,
SUSE,
- LastVendorType = SUSE
+ OpenEmbedded,
+ LastVendorType = OpenEmbedded
};
enum OSType {
UnknownOS,
@@ -202,9 +204,7 @@ public:
MSVC,
Itanium,
Cygnus,
- AMDOpenCL,
CoreCLR,
- OpenCL,
Simulator, // Simulator variants of other systems, e.g., Apple's iOS
LastEnvironmentType = Simulator
};
@@ -660,9 +660,29 @@ public:
return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be;
}
- /// Tests wether the target supports comdat
+ /// Tests whether the target is MIPS 32-bit (little and big endian).
+ bool isMIPS32() const {
+ return getArch() == Triple::mips || getArch() == Triple::mipsel;
+ }
+
+ /// Tests whether the target is MIPS 64-bit (little and big endian).
+ bool isMIPS64() const {
+ return getArch() == Triple::mips64 || getArch() == Triple::mips64el;
+ }
+
+ /// Tests whether the target is MIPS (little and big endian, 32- or 64-bit).
+ bool isMIPS() const {
+ return isMIPS32() || isMIPS64();
+ }
+
+ /// Tests whether the target supports comdat
bool supportsCOMDAT() const {
- return !isOSBinFormatMachO() && !isOSBinFormatWasm();
+ return !isOSBinFormatMachO();
+ }
+
+ /// Tests whether the target uses emulated TLS as default.
+ bool hasDefaultEmulatedTLS() const {
+ return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment();
}
/// @}
diff --git a/contrib/llvm/include/llvm/ADT/UniqueVector.h b/contrib/llvm/include/llvm/ADT/UniqueVector.h
index b17fb2392baf..c86bedd07687 100644
--- a/contrib/llvm/include/llvm/ADT/UniqueVector.h
+++ b/contrib/llvm/include/llvm/ADT/UniqueVector.h
@@ -72,16 +72,16 @@ public:
return Vector[ID - 1];
}
- /// \brief Return an iterator to the start of the vector.
+ /// Return an iterator to the start of the vector.
iterator begin() { return Vector.begin(); }
- /// \brief Return an iterator to the start of the vector.
+ /// Return an iterator to the start of the vector.
const_iterator begin() const { return Vector.begin(); }
- /// \brief Return an iterator to the end of the vector.
+ /// Return an iterator to the end of the vector.
iterator end() { return Vector.end(); }
- /// \brief Return an iterator to the end of the vector.
+ /// Return an iterator to the end of the vector.
const_iterator end() const { return Vector.end(); }
/// size - Returns the number of entries in the vector.
diff --git a/contrib/llvm/include/llvm/ADT/VariadicFunction.h b/contrib/llvm/include/llvm/ADT/VariadicFunction.h
index 403130c623eb..9028abe4c72c 100644
--- a/contrib/llvm/include/llvm/ADT/VariadicFunction.h
+++ b/contrib/llvm/include/llvm/ADT/VariadicFunction.h
@@ -53,7 +53,7 @@ namespace llvm {
#define LLVM_COMMA_JOIN31(x) LLVM_COMMA_JOIN30(x), x ## 30
#define LLVM_COMMA_JOIN32(x) LLVM_COMMA_JOIN31(x), x ## 31
-/// \brief Class which can simulate a type-safe variadic function.
+/// Class which can simulate a type-safe variadic function.
///
/// The VariadicFunction class template makes it easy to define
/// type-safe variadic functions where all arguments have the same
diff --git a/contrib/llvm/include/llvm/ADT/edit_distance.h b/contrib/llvm/include/llvm/ADT/edit_distance.h
index 06a01b18a9fb..b2e8ec5c3f6d 100644
--- a/contrib/llvm/include/llvm/ADT/edit_distance.h
+++ b/contrib/llvm/include/llvm/ADT/edit_distance.h
@@ -22,7 +22,7 @@
namespace llvm {
-/// \brief Determine the edit distance between two sequences.
+/// Determine the edit distance between two sequences.
///
/// \param FromArray the first sequence to compare.
///
diff --git a/contrib/llvm/include/llvm/ADT/ilist.h b/contrib/llvm/include/llvm/ADT/ilist.h
index a788f811e4c6..00bb6d528175 100644
--- a/contrib/llvm/include/llvm/ADT/ilist.h
+++ b/contrib/llvm/include/llvm/ADT/ilist.h
@@ -84,21 +84,11 @@ template <typename NodeTy>
struct ilist_node_traits : ilist_alloc_traits<NodeTy>,
ilist_callback_traits<NodeTy> {};
-/// Default template traits for intrusive list.
-///
-/// By inheriting from this, you can easily use default implementations for all
-/// common operations.
-///
-/// TODO: Remove this customization point. Specializing ilist_traits is
-/// already fully general.
-template <typename NodeTy>
-struct ilist_default_traits : public ilist_node_traits<NodeTy> {};
-
/// Template traits for intrusive list.
///
/// Customize callbacks and allocation semantics.
template <typename NodeTy>
-struct ilist_traits : public ilist_default_traits<NodeTy> {};
+struct ilist_traits : public ilist_node_traits<NodeTy> {};
/// Const traits should never be instantiated.
template <typename Ty> struct ilist_traits<const Ty> {};
@@ -178,9 +168,6 @@ template <class IntrusiveListT, class TraitsT>
class iplist_impl : public TraitsT, IntrusiveListT {
typedef IntrusiveListT base_list_type;
-protected:
- typedef iplist_impl iplist_impl_type;
-
public:
typedef typename base_list_type::pointer pointer;
typedef typename base_list_type::const_pointer const_pointer;
@@ -369,26 +356,26 @@ public:
using base_list_type::sort;
- /// \brief Get the previous node, or \c nullptr for the list head.
+ /// Get the previous node, or \c nullptr for the list head.
pointer getPrevNode(reference N) const {
auto I = N.getIterator();
if (I == begin())
return nullptr;
return &*std::prev(I);
}
- /// \brief Get the previous node, or \c nullptr for the list head.
+ /// Get the previous node, or \c nullptr for the list head.
const_pointer getPrevNode(const_reference N) const {
return getPrevNode(const_cast<reference >(N));
}
- /// \brief Get the next node, or \c nullptr for the list tail.
+ /// Get the next node, or \c nullptr for the list tail.
pointer getNextNode(reference N) const {
auto Next = std::next(N.getIterator());
if (Next == end())
return nullptr;
return &*Next;
}
- /// \brief Get the next node, or \c nullptr for the list tail.
+ /// Get the next node, or \c nullptr for the list tail.
const_pointer getNextNode(const_reference N) const {
return getNextNode(const_cast<reference >(N));
}
@@ -402,7 +389,7 @@ public:
template <class T, class... Options>
class iplist
: public iplist_impl<simple_ilist<T, Options...>, ilist_traits<T>> {
- typedef typename iplist::iplist_impl_type iplist_impl_type;
+ using iplist_impl_type = typename iplist::iplist_impl;
public:
iplist() = default;
diff --git a/contrib/llvm/include/llvm/ADT/ilist_node.h b/contrib/llvm/include/llvm/ADT/ilist_node.h
index 3362611697cb..dd0e6b4ec2b9 100644
--- a/contrib/llvm/include/llvm/ADT/ilist_node.h
+++ b/contrib/llvm/include/llvm/ADT/ilist_node.h
@@ -271,7 +271,7 @@ private:
public:
/// @name Adjacent Node Accessors
/// @{
- /// \brief Get the previous node, or \c nullptr for the list head.
+ /// Get the previous node, or \c nullptr for the list head.
NodeTy *getPrevNode() {
// Should be separated to a reused function, but then we couldn't use auto
// (and would need the type of the list).
@@ -280,12 +280,12 @@ public:
return List.getPrevNode(*static_cast<NodeTy *>(this));
}
- /// \brief Get the previous node, or \c nullptr for the list head.
+ /// Get the previous node, or \c nullptr for the list head.
const NodeTy *getPrevNode() const {
return const_cast<ilist_node_with_parent *>(this)->getPrevNode();
}
- /// \brief Get the next node, or \c nullptr for the list tail.
+ /// Get the next node, or \c nullptr for the list tail.
NodeTy *getNextNode() {
// Should be separated to a reused function, but then we couldn't use auto
// (and would need the type of the list).
@@ -294,7 +294,7 @@ public:
return List.getNextNode(*static_cast<NodeTy *>(this));
}
- /// \brief Get the next node, or \c nullptr for the list tail.
+ /// Get the next node, or \c nullptr for the list tail.
const NodeTy *getNextNode() const {
return const_cast<ilist_node_with_parent *>(this)->getNextNode();
}
diff --git a/contrib/llvm/include/llvm/ADT/ilist_node_options.h b/contrib/llvm/include/llvm/ADT/ilist_node_options.h
index c33df1eeb819..7ff4005f6757 100644
--- a/contrib/llvm/include/llvm/ADT/ilist_node_options.h
+++ b/contrib/llvm/include/llvm/ADT/ilist_node_options.h
@@ -11,7 +11,6 @@
#define LLVM_ADT_ILIST_NODE_OPTIONS_H
#include "llvm/Config/abi-breaking.h"
-#include "llvm/Config/llvm-config.h"
#include <type_traits>
diff --git a/contrib/llvm/include/llvm/ADT/iterator.h b/contrib/llvm/include/llvm/ADT/iterator.h
index 711f8f221620..549c5221173d 100644
--- a/contrib/llvm/include/llvm/ADT/iterator.h
+++ b/contrib/llvm/include/llvm/ADT/iterator.h
@@ -19,7 +19,7 @@
namespace llvm {
-/// \brief CRTP base class which implements the entire standard iterator facade
+/// CRTP base class which implements the entire standard iterator facade
/// in terms of a minimal subset of the interface.
///
/// Use this when it is reasonable to implement most of the iterator
@@ -183,7 +183,7 @@ public:
}
};
-/// \brief CRTP base class for adapting an iterator to a different type.
+/// CRTP base class for adapting an iterator to a different type.
///
/// This class can be used through CRTP to adapt one iterator into another.
/// Typically this is done through providing in the derived class a custom \c
@@ -274,7 +274,7 @@ public:
ReferenceT operator*() const { return *I; }
};
-/// \brief An iterator type that allows iterating over the pointees via some
+/// An iterator type that allows iterating over the pointees via some
/// other iterator.
///
/// The typical usage of this is to expose a type that iterates over Ts, but
@@ -288,7 +288,7 @@ template <typename WrappedIteratorT,
decltype(**std::declval<WrappedIteratorT>())>::type>
struct pointee_iterator
: iterator_adaptor_base<
- pointee_iterator<WrappedIteratorT>, WrappedIteratorT,
+ pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT,
typename std::iterator_traits<WrappedIteratorT>::iterator_category,
T> {
pointee_iterator() = default;
@@ -311,7 +311,7 @@ make_pointee_range(RangeT &&Range) {
template <typename WrappedIteratorT,
typename T = decltype(&*std::declval<WrappedIteratorT>())>
class pointer_iterator
- : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT>,
+ : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT, T>,
WrappedIteratorT, T> {
mutable T Ptr;
diff --git a/contrib/llvm/include/llvm/ADT/iterator_range.h b/contrib/llvm/include/llvm/ADT/iterator_range.h
index 3cbf6198eb60..2ba12866ecf3 100644
--- a/contrib/llvm/include/llvm/ADT/iterator_range.h
+++ b/contrib/llvm/include/llvm/ADT/iterator_range.h
@@ -24,7 +24,7 @@
namespace llvm {
-/// \brief A range adaptor for a pair of iterators.
+/// A range adaptor for a pair of iterators.
///
/// This just wraps two iterators into a range-compatible interface. Nothing
/// fancy at all.
@@ -47,7 +47,7 @@ public:
IteratorT end() const { return end_iterator; }
};
-/// \brief Convenience function for iterating over sub-ranges.
+/// Convenience function for iterating over sub-ranges.
///
/// This provides a bit of syntactic sugar to make using sub-ranges
/// in for loops a bit easier. Analogous to std::make_pair().
@@ -59,9 +59,10 @@ template <typename T> iterator_range<T> make_range(std::pair<T, T> p) {
return iterator_range<T>(std::move(p.first), std::move(p.second));
}
-template<typename T>
-iterator_range<decltype(begin(std::declval<T>()))> drop_begin(T &&t, int n) {
- return make_range(std::next(begin(t), n), end(t));
+template <typename T>
+iterator_range<decltype(adl_begin(std::declval<T>()))> drop_begin(T &&t,
+ int n) {
+ return make_range(std::next(adl_begin(t), n), adl_end(t));
}
}
diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h
index 362096b08e13..be3496bbd955 100644
--- a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -76,7 +76,7 @@ class Value;
///
/// See docs/AliasAnalysis.html for more information on the specific meanings
/// of these values.
-enum AliasResult {
+enum AliasResult : uint8_t {
/// The two locations do not alias at all.
///
/// This value is arranged to convert to false, while all other values
@@ -91,13 +91,16 @@ enum AliasResult {
MustAlias,
};
+/// << operator for AliasResult.
+raw_ostream &operator<<(raw_ostream &OS, AliasResult AR);
+
/// Flags indicating whether a memory access modifies or references memory.
///
/// This is no access at all, a modification, a reference, or both
/// a modification and a reference. These are specifically structured such that
/// they form a three bit matrix and bit-tests for 'mod' or 'ref' or 'must'
/// work with any of the possible values.
-enum class ModRefInfo {
+enum class ModRefInfo : uint8_t {
/// Must is provided for completeness, but no routines will return only
/// Must today. See definition of Must below.
Must = 0,
@@ -325,8 +328,8 @@ public:
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
/// A convenience wrapper around the primary \c alias interface.
- AliasResult alias(const Value *V1, uint64_t V1Size, const Value *V2,
- uint64_t V2Size) {
+ AliasResult alias(const Value *V1, LocationSize V1Size, const Value *V2,
+ LocationSize V2Size) {
return alias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size));
}
@@ -343,8 +346,8 @@ public:
}
/// A convenience wrapper around the \c isNoAlias helper interface.
- bool isNoAlias(const Value *V1, uint64_t V1Size, const Value *V2,
- uint64_t V2Size) {
+ bool isNoAlias(const Value *V1, LocationSize V1Size, const Value *V2,
+ LocationSize V2Size) {
return isNoAlias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size));
}
@@ -501,7 +504,7 @@ public:
/// getModRefInfo (for call sites) - A convenience wrapper.
ModRefInfo getModRefInfo(ImmutableCallSite CS, const Value *P,
- uint64_t Size) {
+ LocationSize Size) {
return getModRefInfo(CS, MemoryLocation(P, Size));
}
@@ -512,7 +515,8 @@ public:
}
/// getModRefInfo (for calls) - A convenience wrapper.
- ModRefInfo getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) {
+ ModRefInfo getModRefInfo(const CallInst *C, const Value *P,
+ LocationSize Size) {
return getModRefInfo(C, MemoryLocation(P, Size));
}
@@ -523,7 +527,8 @@ public:
}
/// getModRefInfo (for invokes) - A convenience wrapper.
- ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P, uint64_t Size) {
+ ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P,
+ LocationSize Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
}
@@ -532,7 +537,8 @@ public:
ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc);
/// getModRefInfo (for loads) - A convenience wrapper.
- ModRefInfo getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) {
+ ModRefInfo getModRefInfo(const LoadInst *L, const Value *P,
+ LocationSize Size) {
return getModRefInfo(L, MemoryLocation(P, Size));
}
@@ -541,7 +547,8 @@ public:
ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc);
/// getModRefInfo (for stores) - A convenience wrapper.
- ModRefInfo getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size) {
+ ModRefInfo getModRefInfo(const StoreInst *S, const Value *P,
+ LocationSize Size) {
return getModRefInfo(S, MemoryLocation(P, Size));
}
@@ -550,7 +557,8 @@ public:
ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc);
/// getModRefInfo (for fences) - A convenience wrapper.
- ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size) {
+ ModRefInfo getModRefInfo(const FenceInst *S, const Value *P,
+ LocationSize Size) {
return getModRefInfo(S, MemoryLocation(P, Size));
}
@@ -580,7 +588,8 @@ public:
ModRefInfo getModRefInfo(const VAArgInst *I, const MemoryLocation &Loc);
/// getModRefInfo (for va_args) - A convenience wrapper.
- ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P, uint64_t Size) {
+ ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P,
+ LocationSize Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
}
@@ -590,7 +599,7 @@ public:
/// getModRefInfo (for catchpads) - A convenience wrapper.
ModRefInfo getModRefInfo(const CatchPadInst *I, const Value *P,
- uint64_t Size) {
+ LocationSize Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
}
@@ -600,7 +609,7 @@ public:
/// getModRefInfo (for catchrets) - A convenience wrapper.
ModRefInfo getModRefInfo(const CatchReturnInst *I, const Value *P,
- uint64_t Size) {
+ LocationSize Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
}
@@ -646,7 +655,7 @@ public:
/// A convenience wrapper for constructing the memory location.
ModRefInfo getModRefInfo(const Instruction *I, const Value *P,
- uint64_t Size) {
+ LocationSize Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
}
@@ -659,7 +668,7 @@ public:
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
- /// \brief Return information about whether a particular call site modifies
+ /// Return information about whether a particular call site modifies
/// or reads the specified memory location \p MemLoc before instruction \p I
/// in a BasicBlock. An ordered basic block \p OBB can be used to speed up
/// instruction ordering queries inside the BasicBlock containing \p I.
@@ -669,9 +678,9 @@ public:
const MemoryLocation &MemLoc, DominatorTree *DT,
OrderedBasicBlock *OBB = nullptr);
- /// \brief A convenience wrapper to synthesize a memory location.
+ /// A convenience wrapper to synthesize a memory location.
ModRefInfo callCapturesBefore(const Instruction *I, const Value *P,
- uint64_t Size, DominatorTree *DT,
+ LocationSize Size, DominatorTree *DT,
OrderedBasicBlock *OBB = nullptr) {
return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB);
}
@@ -687,7 +696,7 @@ public:
/// A convenience wrapper synthesizing a memory location.
bool canBasicBlockModify(const BasicBlock &BB, const Value *P,
- uint64_t Size) {
+ LocationSize Size) {
return canBasicBlockModify(BB, MemoryLocation(P, Size));
}
@@ -702,7 +711,7 @@ public:
/// A convenience wrapper synthesizing a memory location.
bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2,
- const Value *Ptr, uint64_t Size,
+ const Value *Ptr, LocationSize Size,
const ModRefInfo Mode) {
return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode);
}
diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h
index cd2f631a01f4..0941814a56c3 100644
--- a/contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h
+++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h
@@ -56,7 +56,7 @@ public:
}
~AAEvaluator();
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
private:
diff --git a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h
index 7da3ebabb8a3..c9680ff40d1e 100644
--- a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h
+++ b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h
@@ -37,8 +37,8 @@ namespace llvm {
class AliasSetTracker;
class BasicBlock;
class LoadInst;
-class MemSetInst;
-class MemTransferInst;
+class AnyMemSetInst;
+class AnyMemTransferInst;
class raw_ostream;
class StoreInst;
class VAArgInst;
@@ -52,7 +52,7 @@ class AliasSet : public ilist_node<AliasSet> {
PointerRec **PrevInList = nullptr;
PointerRec *NextInList = nullptr;
AliasSet *AS = nullptr;
- uint64_t Size = 0;
+ LocationSize Size = 0;
AAMDNodes AAInfo;
public:
@@ -69,7 +69,7 @@ class AliasSet : public ilist_node<AliasSet> {
return &NextInList;
}
- bool updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) {
+ bool updateSizeAndAAInfo(LocationSize NewSize, const AAMDNodes &NewAAInfo) {
bool SizeChanged = false;
if (NewSize > Size) {
Size = NewSize;
@@ -91,7 +91,7 @@ class AliasSet : public ilist_node<AliasSet> {
return SizeChanged;
}
- uint64_t getSize() const { return Size; }
+ LocationSize getSize() const { return Size; }
/// Return the AAInfo, or null if there is no information or conflicting
/// information.
@@ -247,7 +247,7 @@ public:
value_type *operator->() const { return &operator*(); }
Value *getPointer() const { return CurNode->getValue(); }
- uint64_t getSize() const { return CurNode->getSize(); }
+ LocationSize getSize() const { return CurNode->getSize(); }
AAMDNodes getAAInfo() const { return CurNode->getAAInfo(); }
iterator& operator++() { // Preincrement
@@ -287,9 +287,8 @@ private:
void removeFromTracker(AliasSetTracker &AST);
- void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size,
- const AAMDNodes &AAInfo,
- bool KnownMustAlias = false);
+ void addPointer(AliasSetTracker &AST, PointerRec &Entry, LocationSize Size,
+ const AAMDNodes &AAInfo, bool KnownMustAlias = false);
void addUnknownInst(Instruction *I, AliasAnalysis &AA);
void removeUnknownInst(AliasSetTracker &AST, Instruction *I) {
@@ -309,8 +308,8 @@ private:
public:
/// Return true if the specified pointer "may" (or must) alias one of the
/// members in the set.
- bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo,
- AliasAnalysis &AA) const;
+ bool aliasesPointer(const Value *Ptr, LocationSize Size,
+ const AAMDNodes &AAInfo, AliasAnalysis &AA) const;
bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const;
};
@@ -364,12 +363,12 @@ public:
/// These methods return true if inserting the instruction resulted in the
/// addition of a new alias set (i.e., the pointer did not alias anything).
///
- void add(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); // Add a loc.
+ void add(Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo); // Add a loc
void add(LoadInst *LI);
void add(StoreInst *SI);
void add(VAArgInst *VAAI);
- void add(MemSetInst *MSI);
- void add(MemTransferInst *MTI);
+ void add(AnyMemSetInst *MSI);
+ void add(AnyMemTransferInst *MTI);
void add(Instruction *I); // Dispatch to one of the other add methods...
void add(BasicBlock &BB); // Add all instructions in basic block
void add(const AliasSetTracker &AST); // Add alias relations from another AST
@@ -384,12 +383,12 @@ public:
/// argument is non-null, this method sets the value to true if a new alias
/// set is created to contain the pointer (because the pointer didn't alias
/// anything).
- AliasSet &getAliasSetForPointer(Value *P, uint64_t Size,
+ AliasSet &getAliasSetForPointer(Value *P, LocationSize Size,
const AAMDNodes &AAInfo);
/// Return the alias set containing the location specified if one exists,
/// otherwise return null.
- AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size,
+ AliasSet *getAliasSetForPointerIfExists(const Value *P, LocationSize Size,
const AAMDNodes &AAInfo) {
return mergeAliasSetsForPointer(P, Size, AAInfo);
}
@@ -446,9 +445,9 @@ private:
return *Entry;
}
- AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo,
+ AliasSet &addPointer(Value *P, LocationSize Size, const AAMDNodes &AAInfo,
AliasSet::AccessLattice E);
- AliasSet *mergeAliasSetsForPointer(const Value *Ptr, uint64_t Size,
+ AliasSet *mergeAliasSetsForPointer(const Value *Ptr, LocationSize Size,
const AAMDNodes &AAInfo);
/// Merge all alias sets into a single set that is considered to alias any
diff --git a/contrib/llvm/include/llvm/Analysis/AssumptionCache.h b/contrib/llvm/include/llvm/Analysis/AssumptionCache.h
index c965e62a0216..46538b1fa86f 100644
--- a/contrib/llvm/include/llvm/Analysis/AssumptionCache.h
+++ b/contrib/llvm/include/llvm/Analysis/AssumptionCache.h
@@ -32,20 +32,20 @@ class Function;
class raw_ostream;
class Value;
-/// \brief A cache of @llvm.assume calls within a function.
+/// 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. Passes
/// that create new assumptions are required to call registerAssumption() to
-/// register any new @llvm.assume calls that they create. Deletions of
-/// @llvm.assume calls do not require special handling.
+/// register any new \@llvm.assume calls that they create. Deletions of
+/// \@llvm.assume calls do not require special handling.
class AssumptionCache {
- /// \brief The function for which this cache is handling assumptions.
+ /// 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
+ /// Vector of weak value handles to calls of the \@llvm.assume
/// intrinsic.
SmallVector<WeakTrackingVH, 4> AssumeHandles;
@@ -64,7 +64,7 @@ class AssumptionCache {
friend AffectedValueCallbackVH;
- /// \brief A map of values about which an assumption might be providing
+ /// A map of values about which an assumption might be providing
/// information to the relevant set of assumptions.
using AffectedValuesMap =
DenseMap<AffectedValueCallbackVH, SmallVector<WeakTrackingVH, 1>,
@@ -77,17 +77,17 @@ class AssumptionCache {
/// Copy affected values in the cache for OV to be affected values for NV.
void copyAffectedValuesInCache(Value *OV, Value *NV);
- /// \brief Flag tracking whether we have scanned the function yet.
+ /// 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 = false;
- /// \brief Scan the function for assumptions and add them to the cache.
+ /// 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
+ /// Construct an AssumptionCache from a function by scanning all of
/// its instructions.
AssumptionCache(Function &F) : F(F) {}
@@ -98,17 +98,17 @@ public:
return false;
}
- /// \brief Add an @llvm.assume intrinsic to this function's cache.
+ /// Add an \@llvm.assume intrinsic to this function's cache.
///
/// The call passed in must be an instruction within this function and must
/// not already be in the cache.
void registerAssumption(CallInst *CI);
- /// \brief Update the cache of values being affected by this assumption (i.e.
+ /// Update the cache of values being affected by this assumption (i.e.
/// the values about which this assumption provides information).
void updateAffectedValues(CallInst *CI);
- /// \brief Clear the cache of @llvm.assume intrinsics for a function.
+ /// Clear the cache of \@llvm.assume intrinsics for a function.
///
/// It will be re-scanned the next time it is requested.
void clear() {
@@ -117,7 +117,7 @@ public:
Scanned = false;
}
- /// \brief Access the list of assumption handles currently tracked for this
+ /// Access the list of assumption handles currently tracked for this
/// function.
///
/// Note that these produce weak handles that may be null. The caller must
@@ -131,7 +131,7 @@ public:
return AssumeHandles;
}
- /// \brief Access the list of assumptions which affect this value.
+ /// Access the list of assumptions which affect this value.
MutableArrayRef<WeakTrackingVH> assumptionsFor(const Value *V) {
if (!Scanned)
scanFunction();
@@ -144,7 +144,7 @@ public:
}
};
-/// \brief A function analysis which provides an \c AssumptionCache.
+/// 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.
@@ -161,7 +161,7 @@ public:
}
};
-/// \brief Printer pass for the \c AssumptionAnalysis results.
+/// Printer pass for the \c AssumptionAnalysis results.
class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> {
raw_ostream &OS;
@@ -171,7 +171,7 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief An immutable pass that tracks lazily created \c AssumptionCache
+/// An immutable pass that tracks lazily created \c AssumptionCache
/// objects.
///
/// This is essentially a workaround for the legacy pass manager's weaknesses
@@ -203,7 +203,7 @@ class AssumptionCacheTracker : public ImmutablePass {
FunctionCallsMap AssumptionCaches;
public:
- /// \brief Get the cached assumptions for a function.
+ /// Get the cached assumptions for a function.
///
/// If no assumptions are cached, this will scan the function. Otherwise, the
/// existing cache will be returned.
diff --git a/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
index 42e5e9714071..fa81539a9d6f 100644
--- a/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -55,26 +55,27 @@ class BasicAAResult : public AAResultBase<BasicAAResult> {
friend AAResultBase<BasicAAResult>;
const DataLayout &DL;
+ const Function &F;
const TargetLibraryInfo &TLI;
AssumptionCache &AC;
DominatorTree *DT;
LoopInfo *LI;
public:
- BasicAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI,
- AssumptionCache &AC, DominatorTree *DT = nullptr,
- LoopInfo *LI = nullptr)
- : AAResultBase(), DL(DL), TLI(TLI), AC(AC), DT(DT), LI(LI) {}
+ BasicAAResult(const DataLayout &DL, const Function &F,
+ const TargetLibraryInfo &TLI, AssumptionCache &AC,
+ DominatorTree *DT = nullptr, LoopInfo *LI = nullptr)
+ : AAResultBase(), DL(DL), F(F), TLI(TLI), AC(AC), DT(DT), LI(LI) {}
BasicAAResult(const BasicAAResult &Arg)
- : AAResultBase(Arg), DL(Arg.DL), TLI(Arg.TLI), AC(Arg.AC), DT(Arg.DT),
- LI(Arg.LI) {}
- BasicAAResult(BasicAAResult &&Arg)
- : AAResultBase(std::move(Arg)), DL(Arg.DL), TLI(Arg.TLI), AC(Arg.AC),
+ : AAResultBase(Arg), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), AC(Arg.AC),
DT(Arg.DT), LI(Arg.LI) {}
+ BasicAAResult(BasicAAResult &&Arg)
+ : AAResultBase(std::move(Arg)), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI),
+ AC(Arg.AC), DT(Arg.DT), LI(Arg.LI) {}
/// Handle invalidation events in the new pass manager.
- bool invalidate(Function &F, const PreservedAnalyses &PA,
+ bool invalidate(Function &Fn, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv);
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
@@ -94,7 +95,7 @@ public:
/// Returns the behavior when calling the given function. For use when the
/// call site is not known.
- FunctionModRefBehavior getModRefBehavior(const Function *F);
+ FunctionModRefBehavior getModRefBehavior(const Function *Fn);
private:
// A linear transformation of a Value; this class represents ZExt(SExt(V,
@@ -171,9 +172,9 @@ private:
static bool isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp,
const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject,
- uint64_t ObjectAccessSize);
+ LocationSize ObjectAccessSize);
- /// \brief A Heuristic for aliasGEP that searches for a constant offset
+ /// A Heuristic for aliasGEP that searches for a constant offset
/// between the variables.
///
/// GetLinearExpression has some limitations, as generally zext(%x + 1)
@@ -183,31 +184,33 @@ private:
/// the addition overflows.
bool
constantOffsetHeuristic(const SmallVectorImpl<VariableGEPIndex> &VarIndices,
- uint64_t V1Size, uint64_t V2Size, int64_t BaseOffset,
- AssumptionCache *AC, DominatorTree *DT);
+ LocationSize V1Size, LocationSize V2Size,
+ int64_t BaseOffset, AssumptionCache *AC,
+ DominatorTree *DT);
bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2);
void GetIndexDifference(SmallVectorImpl<VariableGEPIndex> &Dest,
const SmallVectorImpl<VariableGEPIndex> &Src);
- AliasResult aliasGEP(const GEPOperator *V1, uint64_t V1Size,
+ AliasResult aliasGEP(const GEPOperator *V1, LocationSize V1Size,
const AAMDNodes &V1AAInfo, const Value *V2,
- uint64_t V2Size, const AAMDNodes &V2AAInfo,
+ LocationSize V2Size, const AAMDNodes &V2AAInfo,
const Value *UnderlyingV1, const Value *UnderlyingV2);
- AliasResult aliasPHI(const PHINode *PN, uint64_t PNSize,
+ AliasResult aliasPHI(const PHINode *PN, LocationSize PNSize,
const AAMDNodes &PNAAInfo, const Value *V2,
- uint64_t V2Size, const AAMDNodes &V2AAInfo,
+ LocationSize V2Size, const AAMDNodes &V2AAInfo,
const Value *UnderV2);
- AliasResult aliasSelect(const SelectInst *SI, uint64_t SISize,
+ AliasResult aliasSelect(const SelectInst *SI, LocationSize SISize,
const AAMDNodes &SIAAInfo, const Value *V2,
- uint64_t V2Size, const AAMDNodes &V2AAInfo,
+ LocationSize V2Size, const AAMDNodes &V2AAInfo,
const Value *UnderV2);
- AliasResult aliasCheck(const Value *V1, uint64_t V1Size, AAMDNodes V1AATag,
- const Value *V2, uint64_t V2Size, AAMDNodes V2AATag,
+ AliasResult aliasCheck(const Value *V1, LocationSize V1Size,
+ AAMDNodes V1AATag, const Value *V2,
+ LocationSize V2Size, AAMDNodes V2AATag,
const Value *O1 = nullptr, const Value *O2 = nullptr);
};
diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h
index 89370cbeeea1..ca12db6208b8 100644
--- a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h
@@ -65,17 +65,17 @@ public:
/// floating points.
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
- /// \brief Returns the estimated profile count of \p BB.
+ /// Returns the estimated profile count of \p BB.
/// This computes the relative block frequency of \p BB and multiplies it by
/// the enclosing function's count (if available) and returns the value.
Optional<uint64_t> getBlockProfileCount(const BasicBlock *BB) const;
- /// \brief Returns the estimated profile count of \p Freq.
+ /// Returns the estimated profile count of \p Freq.
/// This uses the frequency \p Freq and multiplies it by
/// the enclosing function's count (if available) and returns the value.
Optional<uint64_t> getProfileCountFromFreq(uint64_t Freq) const;
- /// \brief Returns true if \p BB is an irreducible loop header
+ /// Returns true if \p BB is an irreducible loop header
/// block. Otherwise false.
bool isIrrLoopHeader(const BasicBlock *BB);
@@ -105,7 +105,7 @@ public:
void print(raw_ostream &OS) const;
};
-/// \brief Analysis pass which computes \c BlockFrequencyInfo.
+/// Analysis pass which computes \c BlockFrequencyInfo.
class BlockFrequencyAnalysis
: public AnalysisInfoMixin<BlockFrequencyAnalysis> {
friend AnalysisInfoMixin<BlockFrequencyAnalysis>;
@@ -113,14 +113,14 @@ class BlockFrequencyAnalysis
static AnalysisKey Key;
public:
- /// \brief Provide the result type for this analysis pass.
+ /// Provide the result type for this analysis pass.
using Result = BlockFrequencyInfo;
- /// \brief Run the analysis pass over a function and produce BFI.
+ /// Run the analysis pass over a function and produce BFI.
Result run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Printer pass for the \c BlockFrequencyInfo results.
+/// Printer pass for the \c BlockFrequencyInfo results.
class BlockFrequencyPrinterPass
: public PassInfoMixin<BlockFrequencyPrinterPass> {
raw_ostream &OS;
@@ -131,7 +131,7 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Legacy analysis pass which computes \c BlockFrequencyInfo.
+/// Legacy analysis pass which computes \c BlockFrequencyInfo.
class BlockFrequencyInfoWrapperPass : public FunctionPass {
BlockFrequencyInfo BFI;
diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
index 40c40b80bc89..25b2efd33c98 100644
--- a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
+++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -66,7 +66,7 @@ struct IrreducibleGraph;
// This is part of a workaround for a GCC 4.7 crash on lambdas.
template <class BT> struct BlockEdgesAdder;
-/// \brief Mass of a block.
+/// Mass of a block.
///
/// This class implements a sort of fixed-point fraction always between 0.0 and
/// 1.0. getMass() == std::numeric_limits<uint64_t>::max() indicates a value of
@@ -100,7 +100,7 @@ public:
bool operator!() const { return isEmpty(); }
- /// \brief Add another mass.
+ /// Add another mass.
///
/// Adds another mass, saturating at \a isFull() rather than overflowing.
BlockMass &operator+=(BlockMass X) {
@@ -109,7 +109,7 @@ public:
return *this;
}
- /// \brief Subtract another mass.
+ /// Subtract another mass.
///
/// Subtracts another mass, saturating at \a isEmpty() rather than
/// undeflowing.
@@ -131,7 +131,7 @@ public:
bool operator<(BlockMass X) const { return Mass < X.Mass; }
bool operator>(BlockMass X) const { return Mass > X.Mass; }
- /// \brief Convert to scaled number.
+ /// Convert to scaled number.
///
/// Convert to \a ScaledNumber. \a isFull() gives 1.0, while \a isEmpty()
/// gives slightly above 0.0.
@@ -164,7 +164,7 @@ template <> struct isPodLike<bfi_detail::BlockMass> {
static const bool value = true;
};
-/// \brief Base class for BlockFrequencyInfoImpl
+/// Base class for BlockFrequencyInfoImpl
///
/// BlockFrequencyInfoImplBase has supporting data structures and some
/// algorithms for BlockFrequencyInfoImplBase. Only algorithms that depend on
@@ -177,7 +177,7 @@ public:
using Scaled64 = ScaledNumber<uint64_t>;
using BlockMass = bfi_detail::BlockMass;
- /// \brief Representative of a block.
+ /// Representative of a block.
///
/// This is a simple wrapper around an index into the reverse-post-order
/// traversal of the blocks.
@@ -206,13 +206,13 @@ public:
}
};
- /// \brief Stats about a block itself.
+ /// Stats about a block itself.
struct FrequencyData {
Scaled64 Scaled;
uint64_t Integer;
};
- /// \brief Data about a loop.
+ /// Data about a loop.
///
/// Contains the data necessary to represent a loop as a pseudo-node once it's
/// packaged.
@@ -270,7 +270,7 @@ public:
}
};
- /// \brief Index of loop information.
+ /// Index of loop information.
struct WorkingData {
BlockNode Node; ///< This node.
LoopData *Loop = nullptr; ///< The loop this block is inside.
@@ -293,7 +293,7 @@ public:
return Loop->Parent->Parent;
}
- /// \brief Resolve a node to its representative.
+ /// Resolve a node to its representative.
///
/// Get the node currently representing Node, which could be a containing
/// loop.
@@ -320,7 +320,7 @@ public:
return L;
}
- /// \brief Get the appropriate mass for a node.
+ /// Get the appropriate mass for a node.
///
/// Get appropriate mass for Node. If Node is a loop-header (whose loop
/// has been packaged), returns the mass of its pseudo-node. If it's a
@@ -333,19 +333,19 @@ public:
return Loop->Parent->Mass;
}
- /// \brief Has ContainingLoop been packaged up?
+ /// Has ContainingLoop been packaged up?
bool isPackaged() const { return getResolvedNode() != Node; }
- /// \brief Has Loop been packaged up?
+ /// Has Loop been packaged up?
bool isAPackage() const { return isLoopHeader() && Loop->IsPackaged; }
- /// \brief Has Loop been packaged up twice?
+ /// Has Loop been packaged up twice?
bool isADoublePackage() const {
return isDoubleLoopHeader() && Loop->Parent->IsPackaged;
}
};
- /// \brief Unscaled probability weight.
+ /// Unscaled probability weight.
///
/// Probability weight for an edge in the graph (including the
/// successor/target node).
@@ -369,7 +369,7 @@ public:
: Type(Type), TargetNode(TargetNode), Amount(Amount) {}
};
- /// \brief Distribution of unscaled probability weight.
+ /// Distribution of unscaled probability weight.
///
/// Distribution of unscaled probability weight to a set of successors.
///
@@ -398,7 +398,7 @@ public:
add(Node, Amount, Weight::Backedge);
}
- /// \brief Normalize the distribution.
+ /// Normalize the distribution.
///
/// Combines multiple edges to the same \a Weight::TargetNode and scales
/// down so that \a Total fits into 32-bits.
@@ -413,26 +413,26 @@ public:
void add(const BlockNode &Node, uint64_t Amount, Weight::DistType Type);
};
- /// \brief Data about each block. This is used downstream.
+ /// Data about each block. This is used downstream.
std::vector<FrequencyData> Freqs;
- /// \brief Whether each block is an irreducible loop header.
+ /// Whether each block is an irreducible loop header.
/// This is used downstream.
SparseBitVector<> IsIrrLoopHeader;
- /// \brief Loop data: see initializeLoops().
+ /// Loop data: see initializeLoops().
std::vector<WorkingData> Working;
- /// \brief Indexed information about loops.
+ /// Indexed information about loops.
std::list<LoopData> Loops;
- /// \brief Virtual destructor.
+ /// Virtual destructor.
///
/// Need a virtual destructor to mask the compiler warning about
/// getBlockName().
virtual ~BlockFrequencyInfoImplBase() = default;
- /// \brief Add all edges out of a packaged loop to the distribution.
+ /// Add all edges out of a packaged loop to the distribution.
///
/// Adds all edges from LocalLoopHead to Dist. Calls addToDist() to add each
/// successor edge.
@@ -441,7 +441,7 @@ public:
bool addLoopSuccessorsToDist(const LoopData *OuterLoop, LoopData &Loop,
Distribution &Dist);
- /// \brief Add an edge to the distribution.
+ /// Add an edge to the distribution.
///
/// Adds an edge to Succ to Dist. If \c LoopHead.isValid(), then whether the
/// edge is local/exit/backedge is in the context of LoopHead. Otherwise,
@@ -457,7 +457,7 @@ public:
return *Working[Head.Index].Loop;
}
- /// \brief Analyze irreducible SCCs.
+ /// Analyze irreducible SCCs.
///
/// Separate irreducible SCCs from \c G, which is an explict graph of \c
/// OuterLoop (or the top-level function, if \c OuterLoop is \c nullptr).
@@ -468,7 +468,7 @@ public:
analyzeIrreducible(const bfi_detail::IrreducibleGraph &G, LoopData *OuterLoop,
std::list<LoopData>::iterator Insert);
- /// \brief Update a loop after packaging irreducible SCCs inside of it.
+ /// Update a loop after packaging irreducible SCCs inside of it.
///
/// Update \c OuterLoop. Before finding irreducible control flow, it was
/// partway through \a computeMassInLoop(), so \a LoopData::Exits and \a
@@ -476,7 +476,7 @@ public:
/// up need to be removed from \a OuterLoop::Nodes.
void updateLoopWithIrreducible(LoopData &OuterLoop);
- /// \brief Distribute mass according to a distribution.
+ /// Distribute mass according to a distribution.
///
/// Distributes the mass in Source according to Dist. If LoopHead.isValid(),
/// backedges and exits are stored in its entry in Loops.
@@ -485,7 +485,7 @@ public:
void distributeMass(const BlockNode &Source, LoopData *OuterLoop,
Distribution &Dist);
- /// \brief Compute the loop scale for a loop.
+ /// Compute the loop scale for a loop.
void computeLoopScale(LoopData &Loop);
/// Adjust the mass of all headers in an irreducible loop.
@@ -500,19 +500,19 @@ public:
void distributeIrrLoopHeaderMass(Distribution &Dist);
- /// \brief Package up a loop.
+ /// Package up a loop.
void packageLoop(LoopData &Loop);
- /// \brief Unwrap loops.
+ /// Unwrap loops.
void unwrapLoops();
- /// \brief Finalize frequency metrics.
+ /// Finalize frequency metrics.
///
/// Calculates final frequencies and cleans up no-longer-needed data
/// structures.
void finalizeMetrics();
- /// \brief Clear all memory.
+ /// Clear all memory.
void clear();
virtual std::string getBlockName(const BlockNode &Node) const;
@@ -560,7 +560,7 @@ template <> struct TypeMap<MachineBasicBlock> {
using LoopInfoT = MachineLoopInfo;
};
-/// \brief Get the name of a MachineBasicBlock.
+/// Get the name of a MachineBasicBlock.
///
/// Get the name of a MachineBasicBlock. It's templated so that including from
/// CodeGen is unnecessary (that would be a layering issue).
@@ -574,13 +574,13 @@ template <class BlockT> std::string getBlockName(const BlockT *BB) {
return (MachineName + "[" + BB->getName() + "]").str();
return MachineName.str();
}
-/// \brief Get the name of a BasicBlock.
+/// Get the name of a BasicBlock.
template <> inline std::string getBlockName(const BasicBlock *BB) {
assert(BB && "Unexpected nullptr");
return BB->getName().str();
}
-/// \brief Graph of irreducible control flow.
+/// Graph of irreducible control flow.
///
/// This graph is used for determining the SCCs in a loop (or top-level
/// function) that has irreducible control flow.
@@ -619,7 +619,7 @@ struct IrreducibleGraph {
std::vector<IrrNode> Nodes;
SmallDenseMap<uint32_t, IrrNode *, 4> Lookup;
- /// \brief Construct an explicit graph containing irreducible control flow.
+ /// Construct an explicit graph containing irreducible control flow.
///
/// Construct an explicit graph of the control flow in \c OuterLoop (or the
/// top-level function, if \c OuterLoop is \c nullptr). Uses \c
@@ -687,7 +687,7 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
} // end namespace bfi_detail
-/// \brief Shared implementation for block frequency analysis.
+/// Shared implementation for block frequency analysis.
///
/// This is a shared implementation of BlockFrequencyInfo and
/// MachineBlockFrequencyInfo, and calculates the relative frequencies of
@@ -878,12 +878,12 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
return RPOT[Node.Index];
}
- /// \brief Run (and save) a post-order traversal.
+ /// Run (and save) a post-order traversal.
///
/// Saves a reverse post-order traversal of all the nodes in \a F.
void initializeRPOT();
- /// \brief Initialize loop data.
+ /// Initialize loop data.
///
/// Build up \a Loops using \a LoopInfo. \a LoopInfo gives us a mapping from
/// each block to the deepest loop it's in, but we need the inverse. For each
@@ -892,7 +892,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
/// the loop that are not in sub-loops.
void initializeLoops();
- /// \brief Propagate to a block's successors.
+ /// Propagate to a block's successors.
///
/// In the context of distributing mass through \c OuterLoop, divide the mass
/// currently assigned to \c Node between its successors.
@@ -900,7 +900,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
/// \return \c true unless there's an irreducible backedge.
bool propagateMassToSuccessors(LoopData *OuterLoop, const BlockNode &Node);
- /// \brief Compute mass in a particular loop.
+ /// Compute mass in a particular loop.
///
/// Assign mass to \c Loop's header, and then for each block in \c Loop in
/// reverse post-order, distribute mass to its successors. Only visits nodes
@@ -910,7 +910,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
/// \return \c true unless there's an irreducible backedge.
bool computeMassInLoop(LoopData &Loop);
- /// \brief Try to compute mass in the top-level function.
+ /// Try to compute mass in the top-level function.
///
/// Assign mass to the entry block, and then for each block in reverse
/// post-order, distribute mass to its successors. Skips nodes that have
@@ -920,7 +920,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
/// \return \c true unless there's an irreducible backedge.
bool tryToComputeMassInFunction();
- /// \brief Compute mass in (and package up) irreducible SCCs.
+ /// Compute mass in (and package up) irreducible SCCs.
///
/// Find the irreducible SCCs in \c OuterLoop, add them to \a Loops (in front
/// of \c Insert), and call \a computeMassInLoop() on each of them.
@@ -935,7 +935,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
void computeIrreducibleMass(LoopData *OuterLoop,
std::list<LoopData>::iterator Insert);
- /// \brief Compute mass in all loops.
+ /// Compute mass in all loops.
///
/// For each loop bottom-up, call \a computeMassInLoop().
///
@@ -946,7 +946,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
/// \post \a computeMassInLoop() has returned \c true for every loop.
void computeMassInLoops();
- /// \brief Compute mass in the top-level function.
+ /// Compute mass in the top-level function.
///
/// Uses \a tryToComputeMassInFunction() and \a computeIrreducibleMass() to
/// compute mass in the top-level function.
@@ -994,7 +994,7 @@ public:
const BranchProbabilityInfoT &getBPI() const { return *BPI; }
- /// \brief Print the frequencies for the current function.
+ /// Print the frequencies for the current function.
///
/// Prints the frequencies for the blocks in the current function.
///
@@ -1030,8 +1030,9 @@ void BlockFrequencyInfoImpl<BT>::calculate(const FunctionT &F,
Nodes.clear();
// Initialize.
- DEBUG(dbgs() << "\nblock-frequency: " << F.getName() << "\n================="
- << std::string(F.getName().size(), '=') << "\n");
+ LLVM_DEBUG(dbgs() << "\nblock-frequency: " << F.getName()
+ << "\n================="
+ << std::string(F.getName().size(), '=') << "\n");
initializeRPOT();
initializeLoops();
@@ -1067,10 +1068,11 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() {
assert(RPOT.size() - 1 <= BlockNode::getMaxIndex() &&
"More nodes in function than Block Frequency Info supports");
- DEBUG(dbgs() << "reverse-post-order-traversal\n");
+ LLVM_DEBUG(dbgs() << "reverse-post-order-traversal\n");
for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) {
BlockNode Node = getNode(I);
- DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node) << "\n");
+ LLVM_DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node)
+ << "\n");
Nodes[*I] = Node;
}
@@ -1081,7 +1083,7 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() {
}
template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() {
- DEBUG(dbgs() << "loop-detection\n");
+ LLVM_DEBUG(dbgs() << "loop-detection\n");
if (LI->empty())
return;
@@ -1099,7 +1101,7 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() {
Loops.emplace_back(Parent, Header);
Working[Header.Index].Loop = &Loops.back();
- DEBUG(dbgs() << " - loop = " << getBlockName(Header) << "\n");
+ LLVM_DEBUG(dbgs() << " - loop = " << getBlockName(Header) << "\n");
for (const LoopT *L : *Loop)
Q.emplace_back(L, &Loops.back());
@@ -1128,8 +1130,8 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() {
Working[Index].Loop = HeaderData.Loop;
HeaderData.Loop->Nodes.push_back(Index);
- DEBUG(dbgs() << " - loop = " << getBlockName(Header)
- << ": member = " << getBlockName(Index) << "\n");
+ LLVM_DEBUG(dbgs() << " - loop = " << getBlockName(Header)
+ << ": member = " << getBlockName(Index) << "\n");
}
}
@@ -1150,10 +1152,10 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInLoops() {
template <class BT>
bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
// Compute mass in loop.
- DEBUG(dbgs() << "compute-mass-in-loop: " << getLoopName(Loop) << "\n");
+ LLVM_DEBUG(dbgs() << "compute-mass-in-loop: " << getLoopName(Loop) << "\n");
if (Loop.isIrreducible()) {
- DEBUG(dbgs() << "isIrreducible = true\n");
+ LLVM_DEBUG(dbgs() << "isIrreducible = true\n");
Distribution Dist;
unsigned NumHeadersWithWeight = 0;
Optional<uint64_t> MinHeaderWeight;
@@ -1165,14 +1167,14 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
IsIrrLoopHeader.set(Loop.Nodes[H].Index);
Optional<uint64_t> HeaderWeight = Block->getIrrLoopHeaderWeight();
if (!HeaderWeight) {
- DEBUG(dbgs() << "Missing irr loop header metadata on "
- << getBlockName(HeaderNode) << "\n");
+ LLVM_DEBUG(dbgs() << "Missing irr loop header metadata on "
+ << getBlockName(HeaderNode) << "\n");
HeadersWithoutWeight.insert(H);
continue;
}
- DEBUG(dbgs() << getBlockName(HeaderNode)
- << " has irr loop header weight " << HeaderWeight.getValue()
- << "\n");
+ LLVM_DEBUG(dbgs() << getBlockName(HeaderNode)
+ << " has irr loop header weight "
+ << HeaderWeight.getValue() << "\n");
NumHeadersWithWeight++;
uint64_t HeaderWeightValue = HeaderWeight.getValue();
if (!MinHeaderWeight || HeaderWeightValue < MinHeaderWeight)
@@ -1194,8 +1196,8 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
assert(!getBlock(HeaderNode)->getIrrLoopHeaderWeight() &&
"Shouldn't have a weight metadata");
uint64_t MinWeight = MinHeaderWeight.getValue();
- DEBUG(dbgs() << "Giving weight " << MinWeight
- << " to " << getBlockName(HeaderNode) << "\n");
+ LLVM_DEBUG(dbgs() << "Giving weight " << MinWeight << " to "
+ << getBlockName(HeaderNode) << "\n");
if (MinWeight)
Dist.addLocal(HeaderNode, MinWeight);
}
@@ -1224,7 +1226,7 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
template <class BT>
bool BlockFrequencyInfoImpl<BT>::tryToComputeMassInFunction() {
// Compute mass in function.
- DEBUG(dbgs() << "compute-mass-in-function\n");
+ LLVM_DEBUG(dbgs() << "compute-mass-in-function\n");
assert(!Working.empty() && "no blocks in function");
assert(!Working[0].isLoopHeader() && "entry block is a loop header");
@@ -1276,9 +1278,10 @@ template <class BT> struct BlockEdgesAdder {
template <class BT>
void BlockFrequencyInfoImpl<BT>::computeIrreducibleMass(
LoopData *OuterLoop, std::list<LoopData>::iterator Insert) {
- DEBUG(dbgs() << "analyze-irreducible-in-";
- if (OuterLoop) dbgs() << "loop: " << getLoopName(*OuterLoop) << "\n";
- else dbgs() << "function\n");
+ LLVM_DEBUG(dbgs() << "analyze-irreducible-in-";
+ if (OuterLoop) dbgs()
+ << "loop: " << getLoopName(*OuterLoop) << "\n";
+ else dbgs() << "function\n");
using namespace bfi_detail;
@@ -1304,7 +1307,7 @@ template <class BT>
bool
BlockFrequencyInfoImpl<BT>::propagateMassToSuccessors(LoopData *OuterLoop,
const BlockNode &Node) {
- DEBUG(dbgs() << " - node: " << getBlockName(Node) << "\n");
+ LLVM_DEBUG(dbgs() << " - node: " << getBlockName(Node) << "\n");
// Calculate probability for successors.
Distribution Dist;
if (auto *Loop = Working[Node.Index].getPackagedLoop()) {
diff --git a/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h b/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h
index 417b64978811..45277db46090 100644
--- a/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h
@@ -38,7 +38,7 @@ class raw_ostream;
class TargetLibraryInfo;
class Value;
-/// \brief Analysis providing branch probability information.
+/// Analysis providing branch probability information.
///
/// This is a function analysis which provides information on the relative
/// probabilities of each "edge" in the function's CFG where such an edge is
@@ -79,7 +79,7 @@ public:
void print(raw_ostream &OS) const;
- /// \brief Get an edge's probability, relative to other out-edges of the Src.
+ /// Get an edge's probability, relative to other out-edges of the Src.
///
/// This routine provides access to the fractional probability between zero
/// (0%) and one (100%) of this edge executing, relative to other edges
@@ -88,7 +88,7 @@ public:
BranchProbability getEdgeProbability(const BasicBlock *Src,
unsigned IndexInSuccessors) const;
- /// \brief Get the probability of going from Src to Dst.
+ /// Get the probability of going from Src to Dst.
///
/// It returns the sum of all probabilities for edges from Src to Dst.
BranchProbability getEdgeProbability(const BasicBlock *Src,
@@ -97,19 +97,19 @@ public:
BranchProbability getEdgeProbability(const BasicBlock *Src,
succ_const_iterator Dst) const;
- /// \brief Test if an edge is hot relative to other out-edges of the Src.
+ /// Test if an edge is hot relative to other out-edges of the Src.
///
/// Check whether this edge out of the source block is 'hot'. We define hot
/// as having a relative probability >= 80%.
bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const;
- /// \brief Retrieve the hot successor of a block if one exists.
+ /// Retrieve the hot successor of a block if one exists.
///
/// Given a basic block, look through its successors and if one exists for
/// which \see isEdgeHot would return true, return that successor block.
const BasicBlock *getHotSucc(const BasicBlock *BB) const;
- /// \brief Print an edge's probability.
+ /// Print an edge's probability.
///
/// Retrieves an edge's probability similarly to \see getEdgeProbability, but
/// then prints that probability to the provided stream. That stream is then
@@ -117,7 +117,7 @@ public:
raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src,
const BasicBlock *Dst) const;
- /// \brief Set the raw edge probability for the given edge.
+ /// Set the raw edge probability for the given edge.
///
/// This allows a pass to explicitly set the edge probability for an edge. It
/// can be used when updating the CFG to update and preserve the branch
@@ -179,13 +179,13 @@ private:
DenseMap<Edge, BranchProbability> Probs;
- /// \brief Track the last function we run over for printing.
+ /// Track the last function we run over for printing.
const Function *LastF;
- /// \brief Track the set of blocks directly succeeded by a returning block.
+ /// Track the set of blocks directly succeeded by a returning block.
SmallPtrSet<const BasicBlock *, 16> PostDominatedByUnreachable;
- /// \brief Track the set of blocks that always lead to a cold call.
+ /// Track the set of blocks that always lead to a cold call.
SmallPtrSet<const BasicBlock *, 16> PostDominatedByColdCall;
void updatePostDominatedByUnreachable(const BasicBlock *BB);
@@ -201,7 +201,7 @@ private:
bool calcInvokeHeuristics(const BasicBlock *BB);
};
-/// \brief Analysis pass which computes \c BranchProbabilityInfo.
+/// Analysis pass which computes \c BranchProbabilityInfo.
class BranchProbabilityAnalysis
: public AnalysisInfoMixin<BranchProbabilityAnalysis> {
friend AnalysisInfoMixin<BranchProbabilityAnalysis>;
@@ -209,14 +209,14 @@ class BranchProbabilityAnalysis
static AnalysisKey Key;
public:
- /// \brief Provide the result type for this analysis pass.
+ /// Provide the result type for this analysis pass.
using Result = BranchProbabilityInfo;
- /// \brief Run the analysis pass over a function and produce BPI.
+ /// Run the analysis pass over a function and produce BPI.
BranchProbabilityInfo run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Printer pass for the \c BranchProbabilityAnalysis results.
+/// Printer pass for the \c BranchProbabilityAnalysis results.
class BranchProbabilityPrinterPass
: public PassInfoMixin<BranchProbabilityPrinterPass> {
raw_ostream &OS;
@@ -227,7 +227,7 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Legacy analysis pass which computes \c BranchProbabilityInfo.
+/// Legacy analysis pass which computes \c BranchProbabilityInfo.
class BranchProbabilityInfoWrapperPass : public FunctionPass {
BranchProbabilityInfo BPI;
diff --git a/contrib/llvm/include/llvm/Analysis/CFG.h b/contrib/llvm/include/llvm/Analysis/CFG.h
index eab64176f0d7..cccdd1637411 100644
--- a/contrib/llvm/include/llvm/Analysis/CFG.h
+++ b/contrib/llvm/include/llvm/Analysis/CFG.h
@@ -49,7 +49,7 @@ unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ);
bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
bool AllowIdenticalEdges = false);
-/// \brief Determine whether instruction 'To' is reachable from 'From',
+/// Determine whether instruction 'To' is reachable from 'From',
/// returning true if uncertain.
///
/// Determine whether there is a path from From to To within a single function.
@@ -68,7 +68,7 @@ bool isPotentiallyReachable(const Instruction *From, const Instruction *To,
const DominatorTree *DT = nullptr,
const LoopInfo *LI = nullptr);
-/// \brief Determine whether block 'To' is reachable from 'From', returning
+/// Determine whether block 'To' is reachable from 'From', returning
/// true if uncertain.
///
/// Determine whether there is a path from From to To within a single function.
@@ -78,7 +78,7 @@ bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To,
const DominatorTree *DT = nullptr,
const LoopInfo *LI = nullptr);
-/// \brief Determine whether there is at least one path from a block in
+/// Determine whether there is at least one path from a block in
/// 'Worklist' to 'StopBB', returning true if uncertain.
///
/// Determine whether there is a path from at least one block in Worklist to
@@ -89,6 +89,73 @@ bool isPotentiallyReachableFromMany(SmallVectorImpl<BasicBlock *> &Worklist,
BasicBlock *StopBB,
const DominatorTree *DT = nullptr,
const LoopInfo *LI = nullptr);
+
+/// Return true if the control flow in \p RPOTraversal is irreducible.
+///
+/// This is a generic implementation to detect CFG irreducibility based on loop
+/// info analysis. It can be used for any kind of CFG (Loop, MachineLoop,
+/// Function, MachineFunction, etc.) by providing an RPO traversal (\p
+/// RPOTraversal) and the loop info analysis (\p LI) of the CFG. This utility
+/// function is only recommended when loop info analysis is available. If loop
+/// info analysis isn't available, please, don't compute it explicitly for this
+/// purpose. There are more efficient ways to detect CFG irreducibility that
+/// don't require recomputing loop info analysis (e.g., T1/T2 or Tarjan's
+/// algorithm).
+///
+/// Requirements:
+/// 1) GraphTraits must be implemented for NodeT type. It is used to access
+/// NodeT successors.
+// 2) \p RPOTraversal must be a valid reverse post-order traversal of the
+/// target CFG with begin()/end() iterator interfaces.
+/// 3) \p LI must be a valid LoopInfoBase that contains up-to-date loop
+/// analysis information of the CFG.
+///
+/// This algorithm uses the information about reducible loop back-edges already
+/// computed in \p LI. When a back-edge is found during the RPO traversal, the
+/// algorithm checks whether the back-edge is one of the reducible back-edges in
+/// loop info. If it isn't, the CFG is irreducible. For example, for the CFG
+/// below (canonical irreducible graph) loop info won't contain any loop, so the
+/// algorithm will return that the CFG is irreducible when checking the B <-
+/// -> C back-edge.
+///
+/// (A->B, A->C, B->C, C->B, C->D)
+/// A
+/// / \
+/// B<- ->C
+/// |
+/// D
+///
+template <class NodeT, class RPOTraversalT, class LoopInfoT,
+ class GT = GraphTraits<NodeT>>
+bool containsIrreducibleCFG(RPOTraversalT &RPOTraversal, const LoopInfoT &LI) {
+ /// Check whether the edge (\p Src, \p Dst) is a reducible loop backedge
+ /// according to LI. I.e., check if there exists a loop that contains Src and
+ /// where Dst is the loop header.
+ auto isProperBackedge = [&](NodeT Src, NodeT Dst) {
+ for (const auto *Lp = LI.getLoopFor(Src); Lp; Lp = Lp->getParentLoop()) {
+ if (Lp->getHeader() == Dst)
+ return true;
+ }
+ return false;
+ };
+
+ SmallPtrSet<NodeT, 32> Visited;
+ for (NodeT Node : RPOTraversal) {
+ Visited.insert(Node);
+ for (NodeT Succ : make_range(GT::child_begin(Node), GT::child_end(Node))) {
+ // Succ hasn't been visited yet
+ if (!Visited.count(Succ))
+ continue;
+ // We already visited Succ, thus Node->Succ must be a backedge. Check that
+ // the head matches what we have in the loop information. Otherwise, we
+ // have an irreducible graph.
+ if (!isProperBackedge(Node, Succ))
+ return true;
+ }
+ }
+
+ return false;
+}
} // End llvm namespace
#endif
diff --git a/contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h
index 6239d5309581..8ae72553ab94 100644
--- a/contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h
@@ -56,7 +56,7 @@ public:
/// Evict the given function from cache
void evict(const Function *Fn);
- /// \brief Get the alias summary for the given function
+ /// Get the alias summary for the given function
/// Return nullptr if the summary is not found or not available
const cflaa::AliasSummary *getAliasSummary(const Function &);
@@ -64,19 +64,19 @@ public:
AliasResult alias(const MemoryLocation &, const MemoryLocation &);
private:
- /// \brief Ensures that the given function is available in the cache.
+ /// Ensures that the given function is available in the cache.
/// Returns the appropriate entry from the cache.
const Optional<FunctionInfo> &ensureCached(const Function &);
- /// \brief Inserts the given Function into the cache.
+ /// Inserts the given Function into the cache.
void scan(const Function &);
- /// \brief Build summary for a given function
+ /// Build summary for a given function
FunctionInfo buildInfoFrom(const Function &);
const TargetLibraryInfo &TLI;
- /// \brief Cached mapping of Functions to their StratifiedSets.
+ /// Cached mapping of Functions to their StratifiedSets.
/// If a function's sets are currently being built, it is marked
/// in the cache as an Optional without a value. This way, if we
/// have any kind of recursion, it is discernable from a function
diff --git a/contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h
index ee9e29046af8..09e366f11e18 100644
--- a/contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h
@@ -55,16 +55,16 @@ public:
return false;
}
- /// \brief Inserts the given Function into the cache.
+ /// Inserts the given Function into the cache.
void scan(Function *Fn);
void evict(Function *Fn);
- /// \brief Ensures that the given function is available in the cache.
+ /// Ensures that the given function is available in the cache.
/// Returns the appropriate entry from the cache.
const Optional<FunctionInfo> &ensureCached(Function *Fn);
- /// \brief Get the alias summary for the given function
+ /// Get the alias summary for the given function
/// Return nullptr if the summary is not found or not available
const cflaa::AliasSummary *getAliasSummary(Function &Fn);
@@ -92,7 +92,7 @@ public:
private:
const TargetLibraryInfo &TLI;
- /// \brief Cached mapping of Functions to their StratifiedSets.
+ /// Cached mapping of Functions to their StratifiedSets.
/// If a function's sets are currently being built, it is marked
/// in the cache as an Optional without a value. This way, if we
/// have any kind of recursion, it is discernable from a function
diff --git a/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h b/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h
index 8123cbad22ff..5e83ea2a6e2b 100644
--- a/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ b/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -119,7 +119,7 @@ extern template class AllAnalysesOn<LazyCallGraph::SCC>;
extern template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
-/// \brief The CGSCC analysis manager.
+/// The CGSCC analysis manager.
///
/// See the documentation for the AnalysisManager template for detail
/// documentation. This type serves as a convenient way to refer to this
@@ -140,7 +140,7 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
-/// \brief The CGSCC pass manager.
+/// The CGSCC pass manager.
///
/// See the documentation for the PassManager template for details. It runs
/// a sequence of SCC passes over each SCC that the manager is run over. This
@@ -175,10 +175,10 @@ public:
explicit Result(CGSCCAnalysisManager &InnerAM, LazyCallGraph &G)
: InnerAM(&InnerAM), G(&G) {}
- /// \brief Accessor for the analysis manager.
+ /// Accessor for the analysis manager.
CGSCCAnalysisManager &getManager() { return *InnerAM; }
- /// \brief Handler for invalidation of the Module.
+ /// Handler for invalidation of the Module.
///
/// If the proxy analysis itself is preserved, then we assume that the set of
/// SCCs in the Module hasn't changed. Thus any pointers to SCCs in the
@@ -302,7 +302,7 @@ struct CGSCCUpdateResult {
&InlinedInternalEdges;
};
-/// \brief The core module pass which does a post-order walk of the SCCs and
+/// The core module pass which does a post-order walk of the SCCs and
/// runs a CGSCC pass over each one.
///
/// Designed to allow composition of a CGSCCPass(Manager) and
@@ -338,7 +338,7 @@ public:
return *this;
}
- /// \brief Runs the CGSCC pass across every SCC in the module.
+ /// Runs the CGSCC pass across every SCC in the module.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
// Setup the CGSCC analysis manager from its proxy.
CGSCCAnalysisManager &CGAM =
@@ -387,17 +387,17 @@ public:
do {
LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val();
if (InvalidRefSCCSet.count(RC)) {
- DEBUG(dbgs() << "Skipping an invalid RefSCC...\n");
+ LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n");
continue;
}
assert(CWorklist.empty() &&
"Should always start with an empty SCC worklist");
- DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC
- << "\n");
+ LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC
+ << "\n");
- // Push the initial SCCs in reverse post-order as we'll pop off the the
+ // Push the initial SCCs in reverse post-order as we'll pop off the
// back and so see this in post-order.
for (LazyCallGraph::SCC &C : llvm::reverse(*RC))
CWorklist.insert(&C);
@@ -409,12 +409,13 @@ public:
// other RefSCCs should be queued above, so we just need to skip both
// scenarios here.
if (InvalidSCCSet.count(C)) {
- DEBUG(dbgs() << "Skipping an invalid SCC...\n");
+ LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n");
continue;
}
if (&C->getOuterRefSCC() != RC) {
- DEBUG(dbgs() << "Skipping an SCC that is now part of some other "
- "RefSCC...\n");
+ LLVM_DEBUG(dbgs()
+ << "Skipping an SCC that is now part of some other "
+ "RefSCC...\n");
continue;
}
@@ -436,7 +437,8 @@ public:
// If the CGSCC pass wasn't able to provide a valid updated SCC,
// the current SCC may simply need to be skipped if invalid.
if (UR.InvalidatedSCCs.count(C)) {
- DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");
+ LLVM_DEBUG(dbgs()
+ << "Skipping invalidated root or island SCC!\n");
break;
}
// Check that we didn't miss any update scenario.
@@ -464,9 +466,10 @@ public:
// FIXME: If we ever start having RefSCC passes, we'll want to
// iterate there too.
if (UR.UpdatedC)
- DEBUG(dbgs() << "Re-running SCC passes after a refinement of the "
- "current SCC: "
- << *UR.UpdatedC << "\n");
+ LLVM_DEBUG(dbgs()
+ << "Re-running SCC passes after a refinement of the "
+ "current SCC: "
+ << *UR.UpdatedC << "\n");
// Note that both `C` and `RC` may at this point refer to deleted,
// invalid SCC and RefSCCs respectively. But we will short circuit
@@ -494,7 +497,7 @@ private:
CGSCCPassT Pass;
};
-/// \brief A function to deduce a function pass type and wrap it in the
+/// A function to deduce a function pass type and wrap it in the
/// templated adaptor.
template <typename CGSCCPassT>
ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
@@ -517,7 +520,7 @@ public:
public:
explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
- /// \brief Accessor for the analysis manager.
+ /// Accessor for the analysis manager.
FunctionAnalysisManager &getManager() { return *FAM; }
bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
@@ -552,7 +555,7 @@ LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR);
-/// \brief Adaptor that maps from a SCC to its functions.
+/// Adaptor that maps from a SCC to its functions.
///
/// Designed to allow composition of a FunctionPass(Manager) and
/// a CGSCCPassManager. Note that if this pass is constructed with a pointer
@@ -585,7 +588,7 @@ public:
return *this;
}
- /// \brief Runs the function pass across every function in the module.
+ /// Runs the function pass across every function in the module.
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
LazyCallGraph &CG, CGSCCUpdateResult &UR) {
// Setup the function analysis manager from its proxy.
@@ -601,7 +604,8 @@ public:
// a pointer we can overwrite.
LazyCallGraph::SCC *CurrentC = &C;
- DEBUG(dbgs() << "Running function passes across an SCC: " << C << "\n");
+ LLVM_DEBUG(dbgs() << "Running function passes across an SCC: " << C
+ << "\n");
PreservedAnalyses PA = PreservedAnalyses::all();
for (LazyCallGraph::Node *N : Nodes) {
@@ -652,7 +656,7 @@ private:
FunctionPassT Pass;
};
-/// \brief A function to deduce a function pass type and wrap it in the
+/// A function to deduce a function pass type and wrap it in the
/// templated adaptor.
template <typename FunctionPassT>
CGSCCToFunctionPassAdaptor<FunctionPassT>
@@ -757,9 +761,9 @@ public:
if (!F)
return false;
- DEBUG(dbgs() << "Found devirutalized call from "
- << CS.getParent()->getParent()->getName() << " to "
- << F->getName() << "\n");
+ LLVM_DEBUG(dbgs() << "Found devirutalized call from "
+ << CS.getParent()->getParent()->getName() << " to "
+ << F->getName() << "\n");
// We now have a direct call where previously we had an indirect call,
// so iterate to process this devirtualization site.
@@ -793,16 +797,18 @@ public:
// Otherwise, if we've already hit our max, we're done.
if (Iteration >= MaxIterations) {
- DEBUG(dbgs() << "Found another devirtualization after hitting the max "
- "number of repetitions ("
- << MaxIterations << ") on SCC: " << *C << "\n");
+ LLVM_DEBUG(
+ dbgs() << "Found another devirtualization after hitting the max "
+ "number of repetitions ("
+ << MaxIterations << ") on SCC: " << *C << "\n");
PA.intersect(std::move(PassPA));
break;
}
- DEBUG(dbgs()
- << "Repeating an SCC pass after finding a devirtualization in: "
- << *C << "\n");
+ LLVM_DEBUG(
+ dbgs()
+ << "Repeating an SCC pass after finding a devirtualization in: " << *C
+ << "\n");
// Move over the new call counts in preparation for iterating.
CallCounts = std::move(NewCallCounts);
@@ -824,7 +830,7 @@ private:
int MaxIterations;
};
-/// \brief A function to deduce a function pass type and wrap it in the
+/// A function to deduce a function pass type and wrap it in the
/// templated adaptor.
template <typename PassT>
DevirtSCCRepeatedPass<PassT> createDevirtSCCRepeatedPass(PassT Pass,
diff --git a/contrib/llvm/include/llvm/Analysis/CallGraph.h b/contrib/llvm/include/llvm/Analysis/CallGraph.h
index c5687def3ebe..f109cf2fac4d 100644
--- a/contrib/llvm/include/llvm/Analysis/CallGraph.h
+++ b/contrib/llvm/include/llvm/Analysis/CallGraph.h
@@ -66,7 +66,7 @@ class CallGraphNode;
class Module;
class raw_ostream;
-/// \brief The basic data container for the call graph of a \c Module of IR.
+/// The basic data container for the call graph of a \c Module of IR.
///
/// This class exposes both the interface to the call graph for a module of IR.
///
@@ -77,25 +77,25 @@ class CallGraph {
using FunctionMapTy =
std::map<const Function *, std::unique_ptr<CallGraphNode>>;
- /// \brief A map from \c Function* to \c CallGraphNode*.
+ /// A map from \c Function* to \c CallGraphNode*.
FunctionMapTy FunctionMap;
- /// \brief This node has edges to all external functions and those internal
+ /// This node has edges to all external functions and those internal
/// functions that have their address taken.
CallGraphNode *ExternalCallingNode;
- /// \brief This node has edges to it from all functions making indirect calls
+ /// This node has edges to it from all functions making indirect calls
/// or calling an external function.
std::unique_ptr<CallGraphNode> CallsExternalNode;
- /// \brief Replace the function represented by this node by another.
+ /// Replace the function represented by this node by another.
///
/// This does not rescan the body of the function, so it is suitable when
/// splicing the body of one function to another while also updating all
/// callers from the old function to the new.
void spliceFunction(const Function *From, const Function *To);
- /// \brief Add a function to the call graph, and link the node to all of the
+ /// Add a function to the call graph, and link the node to all of the
/// functions that it calls.
void addToCallGraph(Function *F);
@@ -110,7 +110,7 @@ public:
using iterator = FunctionMapTy::iterator;
using const_iterator = FunctionMapTy::const_iterator;
- /// \brief Returns the module the call graph corresponds to.
+ /// Returns the module the call graph corresponds to.
Module &getModule() const { return M; }
inline iterator begin() { return FunctionMap.begin(); }
@@ -118,21 +118,21 @@ public:
inline const_iterator begin() const { return FunctionMap.begin(); }
inline const_iterator end() const { return FunctionMap.end(); }
- /// \brief Returns the call graph node for the provided function.
+ /// Returns the call graph node for the provided function.
inline const CallGraphNode *operator[](const Function *F) const {
const_iterator I = FunctionMap.find(F);
assert(I != FunctionMap.end() && "Function not in callgraph!");
return I->second.get();
}
- /// \brief Returns the call graph node for the provided function.
+ /// Returns the call graph node for the provided function.
inline CallGraphNode *operator[](const Function *F) {
const_iterator I = FunctionMap.find(F);
assert(I != FunctionMap.end() && "Function not in callgraph!");
return I->second.get();
}
- /// \brief Returns the \c CallGraphNode which is used to represent
+ /// Returns the \c CallGraphNode which is used to represent
/// undetermined calls into the callgraph.
CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; }
@@ -145,7 +145,7 @@ public:
// modified.
//
- /// \brief Unlink the function from this module, returning it.
+ /// Unlink the function from this module, returning it.
///
/// Because this removes the function from the module, the call graph node is
/// destroyed. This is only valid if the function does not call any other
@@ -153,25 +153,25 @@ public:
/// this is to dropAllReferences before calling this.
Function *removeFunctionFromModule(CallGraphNode *CGN);
- /// \brief Similar to operator[], but this will insert a new CallGraphNode for
+ /// Similar to operator[], but this will insert a new CallGraphNode for
/// \c F if one does not already exist.
CallGraphNode *getOrInsertFunction(const Function *F);
};
-/// \brief A node in the call graph for a module.
+/// A node in the call graph for a module.
///
/// Typically represents a function in the call graph. There are also special
/// "null" nodes used to represent theoretical entries in the call graph.
class CallGraphNode {
public:
- /// \brief A pair of the calling instruction (a call or invoke)
+ /// A pair of the calling instruction (a call or invoke)
/// and the call graph node being called.
using CallRecord = std::pair<WeakTrackingVH, CallGraphNode *>;
public:
using CalledFunctionsVector = std::vector<CallRecord>;
- /// \brief Creates a node for the specified function.
+ /// Creates a node for the specified function.
inline CallGraphNode(Function *F) : F(F) {}
CallGraphNode(const CallGraphNode &) = delete;
@@ -184,7 +184,7 @@ public:
using iterator = std::vector<CallRecord>::iterator;
using const_iterator = std::vector<CallRecord>::const_iterator;
- /// \brief Returns the function that this call graph node represents.
+ /// Returns the function that this call graph node represents.
Function *getFunction() const { return F; }
inline iterator begin() { return CalledFunctions.begin(); }
@@ -194,17 +194,17 @@ public:
inline bool empty() const { return CalledFunctions.empty(); }
inline unsigned size() const { return (unsigned)CalledFunctions.size(); }
- /// \brief Returns the number of other CallGraphNodes in this CallGraph that
+ /// Returns the number of other CallGraphNodes in this CallGraph that
/// reference this node in their callee list.
unsigned getNumReferences() const { return NumReferences; }
- /// \brief Returns the i'th called function.
+ /// Returns the i'th called function.
CallGraphNode *operator[](unsigned i) const {
assert(i < CalledFunctions.size() && "Invalid index");
return CalledFunctions[i].second;
}
- /// \brief Print out this call graph node.
+ /// Print out this call graph node.
void dump() const;
void print(raw_ostream &OS) const;
@@ -213,7 +213,7 @@ public:
// modified
//
- /// \brief Removes all edges from this CallGraphNode to any functions it
+ /// Removes all edges from this CallGraphNode to any functions it
/// calls.
void removeAllCalledFunctions() {
while (!CalledFunctions.empty()) {
@@ -222,14 +222,14 @@ public:
}
}
- /// \brief Moves all the callee information from N to this node.
+ /// Moves all the callee information from N to this node.
void stealCalledFunctionsFrom(CallGraphNode *N) {
assert(CalledFunctions.empty() &&
"Cannot steal callsite information if I already have some");
std::swap(CalledFunctions, N->CalledFunctions);
}
- /// \brief Adds a function to the list of functions called by this one.
+ /// Adds a function to the list of functions called by this one.
void addCalledFunction(CallSite CS, CallGraphNode *M) {
assert(!CS.getInstruction() || !CS.getCalledFunction() ||
!CS.getCalledFunction()->isIntrinsic() ||
@@ -244,23 +244,23 @@ public:
CalledFunctions.pop_back();
}
- /// \brief Removes the edge in the node for the specified call site.
+ /// Removes the edge in the node for the specified call site.
///
/// Note that this method takes linear time, so it should be used sparingly.
void removeCallEdgeFor(CallSite CS);
- /// \brief Removes all call edges from this node to the specified callee
+ /// Removes all call edges from this node to the specified callee
/// function.
///
/// This takes more time to execute than removeCallEdgeTo, so it should not
/// be used unless necessary.
void removeAnyCallEdgeTo(CallGraphNode *Callee);
- /// \brief Removes one edge associated with a null callsite from this node to
+ /// Removes one edge associated with a null callsite from this node to
/// the specified callee function.
void removeOneAbstractEdgeTo(CallGraphNode *Callee);
- /// \brief Replaces the edge in the node for the specified call site with a
+ /// Replaces the edge in the node for the specified call site with a
/// new one.
///
/// Note that this method takes linear time, so it should be used sparingly.
@@ -273,18 +273,18 @@ private:
std::vector<CallRecord> CalledFunctions;
- /// \brief The number of times that this CallGraphNode occurs in the
+ /// The number of times that this CallGraphNode occurs in the
/// CalledFunctions array of this or other CallGraphNodes.
unsigned NumReferences = 0;
void DropRef() { --NumReferences; }
void AddRef() { ++NumReferences; }
- /// \brief A special function that should only be used by the CallGraph class.
+ /// A special function that should only be used by the CallGraph class.
void allReferencesDropped() { NumReferences = 0; }
};
-/// \brief An analysis pass to compute the \c CallGraph for a \c Module.
+/// An analysis pass to compute the \c CallGraph for a \c Module.
///
/// This class implements the concept of an analysis pass used by the \c
/// ModuleAnalysisManager to run an analysis over a module and cache the
@@ -295,16 +295,16 @@ class CallGraphAnalysis : public AnalysisInfoMixin<CallGraphAnalysis> {
static AnalysisKey Key;
public:
- /// \brief A formulaic type to inform clients of the result type.
+ /// A formulaic type to inform clients of the result type.
using Result = CallGraph;
- /// \brief Compute the \c CallGraph for the module \c M.
+ /// Compute the \c CallGraph for the module \c M.
///
/// The real work here is done in the \c CallGraph constructor.
CallGraph run(Module &M, ModuleAnalysisManager &) { return CallGraph(M); }
};
-/// \brief Printer pass for the \c CallGraphAnalysis results.
+/// Printer pass for the \c CallGraphAnalysis results.
class CallGraphPrinterPass : public PassInfoMixin<CallGraphPrinterPass> {
raw_ostream &OS;
@@ -314,7 +314,7 @@ public:
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
-/// \brief The \c ModulePass which wraps up a \c CallGraph and the logic to
+/// The \c ModulePass which wraps up a \c CallGraph and the logic to
/// build it.
///
/// This class exposes both the interface to the call graph container and the
@@ -330,7 +330,7 @@ public:
CallGraphWrapperPass();
~CallGraphWrapperPass() override;
- /// \brief The internal \c CallGraph around which the rest of this interface
+ /// The internal \c CallGraph around which the rest of this interface
/// is wrapped.
const CallGraph &getCallGraph() const { return *G; }
CallGraph &getCallGraph() { return *G; }
@@ -338,7 +338,7 @@ public:
using iterator = CallGraph::iterator;
using const_iterator = CallGraph::const_iterator;
- /// \brief Returns the module the call graph corresponds to.
+ /// Returns the module the call graph corresponds to.
Module &getModule() const { return G->getModule(); }
inline iterator begin() { return G->begin(); }
@@ -346,15 +346,15 @@ public:
inline const_iterator begin() const { return G->begin(); }
inline const_iterator end() const { return G->end(); }
- /// \brief Returns the call graph node for the provided function.
+ /// Returns the call graph node for the provided function.
inline const CallGraphNode *operator[](const Function *F) const {
return (*G)[F];
}
- /// \brief Returns the call graph node for the provided function.
+ /// Returns the call graph node for the provided function.
inline CallGraphNode *operator[](const Function *F) { return (*G)[F]; }
- /// \brief Returns the \c CallGraphNode which is used to represent
+ /// Returns the \c CallGraphNode which is used to represent
/// undetermined calls into the callgraph.
CallGraphNode *getExternalCallingNode() const {
return G->getExternalCallingNode();
@@ -369,7 +369,7 @@ public:
// modified.
//
- /// \brief Unlink the function from this module, returning it.
+ /// Unlink the function from this module, returning it.
///
/// Because this removes the function from the module, the call graph node is
/// destroyed. This is only valid if the function does not call any other
@@ -379,7 +379,7 @@ public:
return G->removeFunctionFromModule(CGN);
}
- /// \brief Similar to operator[], but this will insert a new CallGraphNode for
+ /// Similar to operator[], but this will insert a new CallGraphNode for
/// \c F if one does not already exist.
CallGraphNode *getOrInsertFunction(const Function *F) {
return G->getOrInsertFunction(F);
@@ -426,12 +426,14 @@ template <> struct GraphTraits<CallGraphNode *> {
template <> struct GraphTraits<const CallGraphNode *> {
using NodeRef = const CallGraphNode *;
using CGNPairTy = CallGraphNode::CallRecord;
+ using EdgeRef = const CallGraphNode::CallRecord &;
static NodeRef getEntryNode(const CallGraphNode *CGN) { return CGN; }
static const CallGraphNode *CGNGetValue(CGNPairTy P) { return P.second; }
using ChildIteratorType =
mapped_iterator<CallGraphNode::const_iterator, decltype(&CGNGetValue)>;
+ using ChildEdgeIteratorType = CallGraphNode::const_iterator;
static ChildIteratorType child_begin(NodeRef N) {
return ChildIteratorType(N->begin(), &CGNGetValue);
@@ -440,6 +442,13 @@ template <> struct GraphTraits<const CallGraphNode *> {
static ChildIteratorType child_end(NodeRef N) {
return ChildIteratorType(N->end(), &CGNGetValue);
}
+
+ static ChildEdgeIteratorType child_edge_begin(NodeRef N) {
+ return N->begin();
+ }
+ static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); }
+
+ static NodeRef edge_dest(EdgeRef E) { return E.second; }
};
template <>
diff --git a/contrib/llvm/include/llvm/Analysis/CaptureTracking.h b/contrib/llvm/include/llvm/Analysis/CaptureTracking.h
index 8d2c095d8585..7a869a51233a 100644
--- a/contrib/llvm/include/llvm/Analysis/CaptureTracking.h
+++ b/contrib/llvm/include/llvm/Analysis/CaptureTracking.h
@@ -46,7 +46,7 @@ namespace llvm {
/// to speed up capture-tracker queries.
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
bool StoreCaptures, const Instruction *I,
- DominatorTree *DT, bool IncludeI = false,
+ const DominatorTree *DT, bool IncludeI = false,
OrderedBasicBlock *OBB = nullptr);
/// This callback is used in conjunction with PointerMayBeCaptured. In
diff --git a/contrib/llvm/include/llvm/Analysis/CodeMetrics.h b/contrib/llvm/include/llvm/Analysis/CodeMetrics.h
index 9e861ac18825..752902238522 100644
--- a/contrib/llvm/include/llvm/Analysis/CodeMetrics.h
+++ b/contrib/llvm/include/llvm/Analysis/CodeMetrics.h
@@ -29,7 +29,7 @@ class DataLayout;
class TargetTransformInfo;
class Value;
-/// \brief Check whether a call will lower to something small.
+/// Check whether a call will lower to something small.
///
/// This tests checks whether this callsite will lower to something
/// significantly cheaper than a traditional call, often a single
@@ -37,64 +37,64 @@ class Value;
/// return true, so will this function.
bool callIsSmall(ImmutableCallSite CS);
-/// \brief Utility to calculate the size and a few similar metrics for a set
+/// Utility to calculate the size and a few similar metrics for a set
/// of basic blocks.
struct CodeMetrics {
- /// \brief True if this function contains a call to setjmp or other functions
+ /// True if this function contains a call to setjmp or other functions
/// with attribute "returns twice" without having the attribute itself.
bool exposesReturnsTwice = false;
- /// \brief True if this function calls itself.
+ /// True if this function calls itself.
bool isRecursive = false;
- /// \brief True if this function cannot be duplicated.
+ /// True if this function cannot be duplicated.
///
/// True if this function contains one or more indirect branches, or it contains
/// one or more 'noduplicate' instructions.
bool notDuplicatable = false;
- /// \brief True if this function contains a call to a convergent function.
+ /// True if this function contains a call to a convergent function.
bool convergent = false;
- /// \brief True if this function calls alloca (in the C sense).
+ /// True if this function calls alloca (in the C sense).
bool usesDynamicAlloca = false;
- /// \brief Number of instructions in the analyzed blocks.
+ /// Number of instructions in the analyzed blocks.
unsigned NumInsts = false;
- /// \brief Number of analyzed blocks.
+ /// Number of analyzed blocks.
unsigned NumBlocks = false;
- /// \brief Keeps track of basic block code size estimates.
+ /// Keeps track of basic block code size estimates.
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
- /// \brief Keep track of the number of calls to 'big' functions.
+ /// Keep track of the number of calls to 'big' functions.
unsigned NumCalls = false;
- /// \brief The number of calls to internal functions with a single caller.
+ /// The number of calls to internal functions with a single caller.
///
/// These are likely targets for future inlining, likely exposed by
/// interleaved devirtualization.
unsigned NumInlineCandidates = 0;
- /// \brief How many instructions produce vector values.
+ /// How many instructions produce vector values.
///
/// The inliner is more aggressive with inlining vector kernels.
unsigned NumVectorInsts = 0;
- /// \brief How many 'ret' instructions the blocks contain.
+ /// How many 'ret' instructions the blocks contain.
unsigned NumRets = 0;
- /// \brief Add information about a block to the current state.
+ /// Add information about a block to the current state.
void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI,
const SmallPtrSetImpl<const Value*> &EphValues);
- /// \brief Collect a loop's ephemeral values (those used only by an assume
+ /// Collect a loop's ephemeral values (those used only by an assume
/// or similar intrinsics in the loop).
static void collectEphemeralValues(const Loop *L, AssumptionCache *AC,
SmallPtrSetImpl<const Value *> &EphValues);
- /// \brief Collect a functions's ephemeral values (those used only by an
+ /// Collect a functions's ephemeral values (those used only by an
/// assume or similar intrinsics in the function).
static void collectEphemeralValues(const Function *L, AssumptionCache *AC,
SmallPtrSetImpl<const Value *> &EphValues);
diff --git a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h
index 6d4eef412525..192c1abddcd2 100644
--- a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h
+++ b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h
@@ -73,19 +73,19 @@ ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
Constant *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
-/// \brief Attempt to constant fold a binary operation with the specified
+/// Attempt to constant fold a binary operation with the specified
/// operands. If it fails, it returns a constant expression of the specified
/// operands.
Constant *ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS,
Constant *RHS, const DataLayout &DL);
-/// \brief Attempt to constant fold a select instruction with the specified
+/// Attempt to constant fold a select instruction with the specified
/// operands. The constant result is returned if successful; if not, null is
/// returned.
Constant *ConstantFoldSelectInstruction(Constant *Cond, Constant *V1,
Constant *V2);
-/// \brief Attempt to constant fold a cast with the specified operand. If it
+/// Attempt to constant fold a cast with the specified operand. If it
/// fails, it returns a constant expression of the specified operand.
Constant *ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy,
const DataLayout &DL);
@@ -96,25 +96,25 @@ Constant *ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy,
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
ArrayRef<unsigned> Idxs);
-/// \brief Attempt to constant fold an extractvalue instruction with the
+/// Attempt to constant fold an extractvalue instruction with the
/// specified operands and indices. The constant result is returned if
/// successful; if not, null is returned.
Constant *ConstantFoldExtractValueInstruction(Constant *Agg,
ArrayRef<unsigned> Idxs);
-/// \brief Attempt to constant fold an insertelement instruction with the
+/// Attempt to constant fold an insertelement instruction with the
/// specified operands and indices. The constant result is returned if
/// successful; if not, null is returned.
Constant *ConstantFoldInsertElementInstruction(Constant *Val,
Constant *Elt,
Constant *Idx);
-/// \brief Attempt to constant fold an extractelement instruction with the
+/// Attempt to constant fold an extractelement instruction with the
/// specified operands and indices. The constant result is returned if
/// successful; if not, null is returned.
Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx);
-/// \brief Attempt to constant fold a shufflevector instruction with the
+/// Attempt to constant fold a shufflevector instruction with the
/// specified operands and indices. The constant result is returned if
/// successful; if not, null is returned.
Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2,
@@ -147,7 +147,13 @@ Constant *ConstantFoldCall(ImmutableCallSite CS, Function *F,
ArrayRef<Constant *> Operands,
const TargetLibraryInfo *TLI = nullptr);
-/// \brief Check whether the given call has no side-effects.
+/// ConstantFoldLoadThroughBitcast - try to cast constant to destination type
+/// returning null if unsuccessful. Can cast pointer to pointer or pointer to
+/// integer and vice versa if their sizes are equal.
+Constant *ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
+ const DataLayout &DL);
+
+/// Check whether the given call has no side-effects.
/// Specifically checks for math routimes which sometimes set errno.
bool isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI);
}
diff --git a/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h b/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h
index 39f9c39c34e1..b7447a0547d5 100644
--- a/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h
+++ b/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h
@@ -20,7 +20,7 @@
namespace llvm {
-/// \brief Default traits class for extracting a graph from an analysis pass.
+/// Default traits class for extracting a graph from an analysis pass.
///
/// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
template <typename AnalysisT, typename GraphT = AnalysisT *>
@@ -36,7 +36,7 @@ public:
DOTGraphTraitsViewer(StringRef GraphName, char &ID)
: FunctionPass(ID), Name(GraphName) {}
- /// @brief Return true if this function should be processed.
+ /// Return true if this function should be processed.
///
/// An implementation of this class my override this function to indicate that
/// only certain functions should be viewed.
@@ -78,7 +78,7 @@ public:
DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
: FunctionPass(ID), Name(GraphName) {}
- /// @brief Return true if this function should be processed.
+ /// Return true if this function should be processed.
///
/// An implementation of this class my override this function to indicate that
/// only certain functions should be printed.
diff --git a/contrib/llvm/include/llvm/Analysis/DemandedBits.h b/contrib/llvm/include/llvm/Analysis/DemandedBits.h
index ab8668256ba2..d4384609762d 100644
--- a/contrib/llvm/include/llvm/Analysis/DemandedBits.h
+++ b/contrib/llvm/include/llvm/Analysis/DemandedBits.h
@@ -96,15 +96,15 @@ class DemandedBitsAnalysis : public AnalysisInfoMixin<DemandedBitsAnalysis> {
static AnalysisKey Key;
public:
- /// \brief Provide the result type for this analysis pass.
+ /// Provide the result type for this analysis pass.
using Result = DemandedBits;
- /// \brief Run the analysis pass over a function and produce demanded bits
+ /// Run the analysis pass over a function and produce demanded bits
/// information.
DemandedBits run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Printer pass for DemandedBits
+/// Printer pass for DemandedBits
class DemandedBitsPrinterPass : public PassInfoMixin<DemandedBitsPrinterPass> {
raw_ostream &OS;
diff --git a/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h
index 90f33b8c42e5..c8ec737a2cb9 100644
--- a/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h
@@ -557,6 +557,17 @@ template <typename T> class ArrayRef;
const SCEV *X,
const SCEV *Y) const;
+ /// isKnownLessThan - Compare to see if S is less than Size
+ /// Another wrapper for isKnownNegative(S - max(Size, 1)) with some extra
+ /// checking if S is an AddRec and we can prove lessthan using the loop
+ /// bounds.
+ bool isKnownLessThan(const SCEV *S, const SCEV *Size) const;
+
+ /// isKnownNonNegative - Compare to see if S is known not to be negative
+ /// Uses the fact that S comes from Ptr, which may be an inbound GEP,
+ /// Proving there is no wrapping going on.
+ bool isKnownNonNegative(const SCEV *S, const Value *Ptr) const;
+
/// collectUpperBound - All subscripts are the same type (on my machine,
/// an i64). The loop bound may be a smaller type. collectUpperBound
/// find the bound, if available, and zero extends it to the Type T.
@@ -914,7 +925,7 @@ template <typename T> class ArrayRef;
SmallVectorImpl<Subscript> &Pair);
}; // class DependenceInfo
- /// \brief AnalysisPass to compute dependence information in a function
+ /// AnalysisPass to compute dependence information in a function
class DependenceAnalysis : public AnalysisInfoMixin<DependenceAnalysis> {
public:
typedef DependenceInfo Result;
@@ -925,7 +936,7 @@ template <typename T> class ArrayRef;
friend struct AnalysisInfoMixin<DependenceAnalysis>;
}; // class DependenceAnalysis
- /// \brief Legacy pass manager pass to access dependence information
+ /// Legacy pass manager pass to access dependence information
class DependenceAnalysisWrapperPass : public FunctionPass {
public:
static char ID; // Class identification, replacement for typeinfo
diff --git a/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h
index aa2de571ba1b..328c8645d3c0 100644
--- a/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h
@@ -13,6 +13,8 @@
// better decisions.
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
+#define LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/Function.h"
@@ -35,14 +37,25 @@ public:
// Print all divergent branches in the function.
void print(raw_ostream &OS, const Module *) const override;
- // Returns true if V is divergent.
+ // Returns true if V is divergent at its definition.
+ //
+ // Even if this function returns false, V may still be divergent when used
+ // in a different basic block.
bool isDivergent(const Value *V) const { return DivergentValues.count(V); }
// Returns true if V is uniform/non-divergent.
+ //
+ // Even if this function returns true, V may still be divergent when used
+ // in a different basic block.
bool isUniform(const Value *V) const { return !isDivergent(V); }
+ // Keep the analysis results uptodate by removing an erased value.
+ void removeValue(const Value *V) { DivergentValues.erase(V); }
+
private:
// Stores all divergent values.
DenseSet<const Value *> DivergentValues;
};
} // End llvm namespace
+
+#endif //LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H \ No newline at end of file
diff --git a/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h b/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h
index a304dff18c79..d94c420d7177 100644
--- a/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h
+++ b/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h
@@ -19,6 +19,7 @@
#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/GenericDomTree.h"
@@ -179,7 +180,7 @@ extern template class DominanceFrontierBase<BasicBlock, false>;
extern template class DominanceFrontierBase<BasicBlock, true>;
extern template class ForwardDominanceFrontierBase<BasicBlock>;
-/// \brief Analysis pass which computes a \c DominanceFrontier.
+/// Analysis pass which computes a \c DominanceFrontier.
class DominanceFrontierAnalysis
: public AnalysisInfoMixin<DominanceFrontierAnalysis> {
friend AnalysisInfoMixin<DominanceFrontierAnalysis>;
@@ -187,14 +188,14 @@ class DominanceFrontierAnalysis
static AnalysisKey Key;
public:
- /// \brief Provide the result type for this analysis pass.
+ /// Provide the result type for this analysis pass.
using Result = DominanceFrontier;
- /// \brief Run the analysis pass over a function and produce a dominator tree.
+ /// Run the analysis pass over a function and produce a dominator tree.
DominanceFrontier run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Printer pass for the \c DominanceFrontier.
+/// Printer pass for the \c DominanceFrontier.
class DominanceFrontierPrinterPass
: public PassInfoMixin<DominanceFrontierPrinterPass> {
raw_ostream &OS;
diff --git a/contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h b/contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h
index dffb2e02b621..99224c0bf131 100644
--- a/contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h
+++ b/contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/DominanceFrontier.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GenericDomTree.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/contrib/llvm/include/llvm/Analysis/EHPersonalities.h b/contrib/llvm/include/llvm/Analysis/EHPersonalities.h
index 2c45ab4693e6..fe0e65b828ca 100644
--- a/contrib/llvm/include/llvm/Analysis/EHPersonalities.h
+++ b/contrib/llvm/include/llvm/Analysis/EHPersonalities.h
@@ -32,10 +32,11 @@ enum class EHPersonality {
MSVC_Win64SEH,
MSVC_CXX,
CoreCLR,
- Rust
+ Rust,
+ Wasm_CXX
};
-/// \brief See if the given exception handling personality function is one
+/// 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);
@@ -44,7 +45,7 @@ StringRef getEHPersonalityName(EHPersonality Pers);
EHPersonality getDefaultEHPersonality(const Triple &T);
-/// \brief Returns true if this personality function catches asynchronous
+/// Returns true if this personality function catches asynchronous
/// exceptions.
inline bool isAsynchronousEHPersonality(EHPersonality Pers) {
// The two SEH personality functions can catch asynch exceptions. We assume
@@ -59,7 +60,7 @@ inline bool isAsynchronousEHPersonality(EHPersonality Pers) {
llvm_unreachable("invalid enum");
}
-/// \brief Returns true if this is a personality function that invokes
+/// Returns true if this is a personality function that invokes
/// handler funclets (which must return to it).
inline bool isFuncletEHPersonality(EHPersonality Pers) {
switch (Pers) {
@@ -74,7 +75,23 @@ inline bool isFuncletEHPersonality(EHPersonality Pers) {
llvm_unreachable("invalid enum");
}
-/// \brief Return true if this personality may be safely removed if there
+/// Returns true if this personality uses scope-style EH IR instructions:
+/// catchswitch, catchpad/ret, and cleanuppad/ret.
+inline bool isScopedEHPersonality(EHPersonality Pers) {
+ switch (Pers) {
+ case EHPersonality::MSVC_CXX:
+ case EHPersonality::MSVC_X86SEH:
+ case EHPersonality::MSVC_Win64SEH:
+ case EHPersonality::CoreCLR:
+ case EHPersonality::Wasm_CXX:
+ return true;
+ default:
+ return false;
+ }
+ llvm_unreachable("invalid enum");
+}
+
+/// Return true if this personality may be safely removed if there
/// are no invoke instructions remaining in the current function.
inline bool isNoOpWithoutInvoke(EHPersonality Pers) {
switch (Pers) {
@@ -91,7 +108,7 @@ bool canSimplifyInvokeNoUnwind(const Function *F);
typedef TinyPtrVector<BasicBlock *> ColorVector;
-/// \brief If an EH funclet personality is in use (see isFuncletEHPersonality),
+/// If an EH funclet personality is in use (see isFuncletEHPersonality),
/// this will recompute which blocks are in which funclet. It is possible that
/// some blocks are in multiple funclets. Consider this analysis to be
/// expensive.
diff --git a/contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h b/contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h
index 8b1c10139de8..be3a28424cf5 100644
--- a/contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h
@@ -48,7 +48,7 @@ private:
public:
ICallPromotionAnalysis();
- /// \brief Returns reference to array of InstrProfValueData for the given
+ /// Returns reference to array of InstrProfValueData for the given
/// instruction \p I.
///
/// The \p NumVals, \p TotalCount and \p NumCandidates
diff --git a/contrib/llvm/include/llvm/Analysis/InlineCost.h b/contrib/llvm/include/llvm/Analysis/InlineCost.h
index 985f3880ed3a..8c412057fb81 100644
--- a/contrib/llvm/include/llvm/Analysis/InlineCost.h
+++ b/contrib/llvm/include/llvm/Analysis/InlineCost.h
@@ -52,7 +52,7 @@ const int NoreturnPenalty = 10000;
const unsigned TotalAllocaSizeRecursiveCaller = 1024;
}
-/// \brief Represents the cost of inlining a function.
+/// Represents the cost of inlining a function.
///
/// This supports special values for functions which should "always" or
/// "never" be inlined. Otherwise, the cost represents a unitless amount;
@@ -68,10 +68,10 @@ class InlineCost {
NeverInlineCost = INT_MAX
};
- /// \brief The estimated cost of inlining this callsite.
+ /// The estimated cost of inlining this callsite.
const int Cost;
- /// \brief The adjusted threshold against which this cost was computed.
+ /// The adjusted threshold against which this cost was computed.
const int Threshold;
// Trivial constructor, interesting logic in the factory functions below.
@@ -90,7 +90,7 @@ public:
return InlineCost(NeverInlineCost, 0);
}
- /// \brief Test whether the inline cost is low enough for inlining.
+ /// Test whether the inline cost is low enough for inlining.
explicit operator bool() const {
return Cost < Threshold;
}
@@ -99,20 +99,20 @@ public:
bool isNever() const { return Cost == NeverInlineCost; }
bool isVariable() const { return !isAlways() && !isNever(); }
- /// \brief Get the inline cost estimate.
+ /// Get the inline cost estimate.
/// It is an error to call this on an "always" or "never" InlineCost.
int getCost() const {
assert(isVariable() && "Invalid access of InlineCost");
return Cost;
}
- /// \brief Get the threshold against which the cost was computed
+ /// Get the threshold against which the cost was computed
int getThreshold() const {
assert(isVariable() && "Invalid access of InlineCost");
return Threshold;
}
- /// \brief Get the cost delta from the threshold for inlining.
+ /// Get the cost delta from the threshold for inlining.
/// Only valid if the cost is of the variable kind. Returns a negative
/// value if the cost is too high to inline.
int getCostDelta() const { return Threshold - getCost(); }
@@ -170,7 +170,7 @@ InlineParams getInlineParams(int Threshold);
/// line options. If -inline-threshold option is not explicitly passed,
/// the default threshold is computed from \p OptLevel and \p SizeOptLevel.
/// An \p OptLevel value above 3 is considered an aggressive optimization mode.
-/// \p SizeOptLevel of 1 corresponds to the the -Os flag and 2 corresponds to
+/// \p SizeOptLevel of 1 corresponds to the -Os flag and 2 corresponds to
/// the -Oz flag.
InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel);
@@ -178,7 +178,7 @@ InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel);
/// and the call/return instruction.
int getCallsiteCost(CallSite CS, const DataLayout &DL);
-/// \brief Get an InlineCost object representing the cost of inlining this
+/// Get an InlineCost object representing the cost of inlining this
/// callsite.
///
/// Note that a default threshold is passed into this function. This threshold
@@ -195,7 +195,7 @@ InlineCost getInlineCost(
Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI,
ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE = nullptr);
-/// \brief Get an InlineCost with the callee explicitly specified.
+/// Get an InlineCost with the callee explicitly specified.
/// This allows you to calculate the cost of inlining a function via a
/// pointer. This behaves exactly as the version with no explicit callee
/// parameter in all other respects.
@@ -207,7 +207,7 @@ getInlineCost(CallSite CS, Function *Callee, const InlineParams &Params,
Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI,
ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE);
-/// \brief Minimal filter to detect invalid constructs for inlining.
+/// Minimal filter to detect invalid constructs for inlining.
bool isInlineViable(Function &Callee);
}
diff --git a/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h b/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h
index edaf4e9025bc..6b1950733246 100644
--- a/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h
+++ b/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-/// \brief Compute iterated dominance frontiers using a linear time algorithm.
+/// Compute iterated dominance frontiers using a linear time algorithm.
///
/// The algorithm used here is based on:
///
@@ -32,7 +32,7 @@
namespace llvm {
-/// \brief Determine the iterated dominance frontier, given a set of defining
+/// Determine the iterated dominance frontier, given a set of defining
/// blocks, and optionally, a set of live-in blocks.
///
/// In turn, the results can be used to place phi nodes.
@@ -48,7 +48,7 @@ class IDFCalculator {
IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT)
: DT(DT), useLiveIn(false) {}
- /// \brief Give the IDF calculator the set of blocks in which the value is
+ /// Give the IDF calculator the set of blocks in which the value is
/// defined. This is equivalent to the set of starting blocks it should be
/// calculating the IDF for (though later gets pruned based on liveness).
///
@@ -57,7 +57,7 @@ class IDFCalculator {
DefBlocks = &Blocks;
}
- /// \brief Give the IDF calculator the set of blocks in which the value is
+ /// Give the IDF calculator the set of blocks in which the value is
/// live on entry to the block. This is used to prune the IDF calculation to
/// not include blocks where any phi insertion would be dead.
///
@@ -68,14 +68,14 @@ class IDFCalculator {
useLiveIn = true;
}
- /// \brief Reset the live-in block set to be empty, and tell the IDF
+ /// Reset the live-in block set to be empty, and tell the IDF
/// calculator to not use liveness anymore.
void resetLiveInBlocks() {
LiveInBlocks = nullptr;
useLiveIn = false;
}
- /// \brief Calculate iterated dominance frontiers
+ /// Calculate iterated dominance frontiers
///
/// This uses the linear-time phi algorithm based on DJ-graphs mentioned in
/// the file-level comment. It performs DF->IDF pruning using the live-in
diff --git a/contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h b/contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h
index 71ce0842f6a9..d1afb63d7e08 100644
--- a/contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h
@@ -75,7 +75,7 @@ private:
const LoopInfoT *LI;
};
-/// \brief This is an alternative analysis pass to
+/// This is an alternative analysis pass to
/// BlockFrequencyInfoWrapperPass. The difference is that with this pass the
/// block frequencies are not computed when the analysis pass is executed but
/// rather when the BFI result is explicitly requested by the analysis client.
@@ -109,10 +109,10 @@ public:
LazyBlockFrequencyInfoPass();
- /// \brief Compute and return the block frequencies.
+ /// Compute and return the block frequencies.
BlockFrequencyInfo &getBFI() { return LBFI.getCalculated(); }
- /// \brief Compute and return the block frequencies.
+ /// Compute and return the block frequencies.
const BlockFrequencyInfo &getBFI() const { return LBFI.getCalculated(); }
void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -126,7 +126,7 @@ public:
void print(raw_ostream &OS, const Module *M) const override;
};
-/// \brief Helper for client passes to initialize dependent passes for LBFI.
+/// Helper for client passes to initialize dependent passes for LBFI.
void initializeLazyBFIPassPass(PassRegistry &Registry);
}
#endif
diff --git a/contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h b/contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h
index e1d404b1ada2..9e6bcfedcbb9 100644
--- a/contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h
@@ -26,7 +26,7 @@ class Function;
class LoopInfo;
class TargetLibraryInfo;
-/// \brief This is an alternative analysis pass to
+/// This is an alternative analysis pass to
/// BranchProbabilityInfoWrapperPass. The difference is that with this pass the
/// branch probabilities are not computed when the analysis pass is executed but
/// rather when the BPI results is explicitly requested by the analysis client.
@@ -89,10 +89,10 @@ public:
LazyBranchProbabilityInfoPass();
- /// \brief Compute and return the branch probabilities.
+ /// Compute and return the branch probabilities.
BranchProbabilityInfo &getBPI() { return LBPI->getCalculated(); }
- /// \brief Compute and return the branch probabilities.
+ /// Compute and return the branch probabilities.
const BranchProbabilityInfo &getBPI() const { return LBPI->getCalculated(); }
void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -106,10 +106,10 @@ public:
void print(raw_ostream &OS, const Module *M) const override;
};
-/// \brief Helper for client passes to initialize dependent passes for LBPI.
+/// Helper for client passes to initialize dependent passes for LBPI.
void initializeLazyBPIPassPass(PassRegistry &Registry);
-/// \brief Simple trait class that provides a mapping between BPI passes and the
+/// Simple trait class that provides a mapping between BPI passes and the
/// corresponding BPInfo.
template <typename PassT> struct BPIPassTrait {
static PassT &getBPI(PassT *P) { return *P; }
diff --git a/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h b/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h
index 787c88cc6ec1..1a4fdb591427 100644
--- a/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h
@@ -113,6 +113,13 @@ public:
/// in LVI, so we need to pass it here as an argument.
void printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS);
+ /// Disables use of the DominatorTree within LVI.
+ void disableDT();
+
+ /// Enables use of the DominatorTree within LVI. Does nothing if the class
+ /// instance was initialized without a DT pointer.
+ void enableDT();
+
// For old PM pass. Delete once LazyValueInfoWrapperPass is gone.
void releaseMemory();
@@ -121,7 +128,7 @@ public:
FunctionAnalysisManager::Invalidator &Inv);
};
-/// \brief Analysis to compute lazy value information.
+/// Analysis to compute lazy value information.
class LazyValueAnalysis : public AnalysisInfoMixin<LazyValueAnalysis> {
public:
typedef LazyValueInfo Result;
diff --git a/contrib/llvm/include/llvm/Analysis/Lint.h b/contrib/llvm/include/llvm/Analysis/Lint.h
index 7c88b137ec3b..db5919fd91c7 100644
--- a/contrib/llvm/include/llvm/Analysis/Lint.h
+++ b/contrib/llvm/include/llvm/Analysis/Lint.h
@@ -26,12 +26,12 @@ class FunctionPass;
class Module;
class Function;
-/// @brief Create a lint pass.
+/// Create a lint pass.
///
/// Check a module or function.
FunctionPass *createLintPass();
-/// @brief Check a module.
+/// Check a module.
///
/// This should only be used for debugging, because it plays games with
/// PassManagers and stuff.
diff --git a/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
index 28154c873b70..0f3f2be9aeb4 100644
--- a/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -38,25 +38,25 @@ class SCEVUnionPredicate;
class LoopAccessInfo;
class OptimizationRemarkEmitter;
-/// \brief Collection of parameters shared beetween the Loop Vectorizer and the
+/// Collection of parameters shared beetween the Loop Vectorizer and the
/// Loop Access Analysis.
struct VectorizerParams {
- /// \brief Maximum SIMD width.
+ /// Maximum SIMD width.
static const unsigned MaxVectorWidth;
- /// \brief VF as overridden by the user.
+ /// VF as overridden by the user.
static unsigned VectorizationFactor;
- /// \brief Interleave factor as overridden by the user.
+ /// Interleave factor as overridden by the user.
static unsigned VectorizationInterleave;
- /// \brief True if force-vector-interleave was specified by the user.
+ /// True if force-vector-interleave was specified by the user.
static bool isInterleaveForced();
- /// \\brief When performing memory disambiguation checks at runtime do not
+ /// \When performing memory disambiguation checks at runtime do not
/// make more than this number of comparisons.
static unsigned RuntimeMemoryCheckThreshold;
};
-/// \brief Checks memory dependences among accesses to the same underlying
+/// Checks memory dependences among accesses to the same underlying
/// object to determine whether there vectorization is legal or not (and at
/// which vectorization factor).
///
@@ -94,12 +94,12 @@ class MemoryDepChecker {
public:
typedef PointerIntPair<Value *, 1, bool> MemAccessInfo;
typedef SmallVector<MemAccessInfo, 8> MemAccessInfoList;
- /// \brief Set of potential dependent memory accesses.
+ /// Set of potential dependent memory accesses.
typedef EquivalenceClasses<MemAccessInfo> DepCandidates;
- /// \brief Dependece between memory access instructions.
+ /// Dependece between memory access instructions.
struct Dependence {
- /// \brief The type of the dependence.
+ /// The type of the dependence.
enum DepType {
// No dependence.
NoDep,
@@ -127,36 +127,36 @@ public:
BackwardVectorizableButPreventsForwarding
};
- /// \brief String version of the types.
+ /// String version of the types.
static const char *DepName[];
- /// \brief Index of the source of the dependence in the InstMap vector.
+ /// Index of the source of the dependence in the InstMap vector.
unsigned Source;
- /// \brief Index of the destination of the dependence in the InstMap vector.
+ /// Index of the destination of the dependence in the InstMap vector.
unsigned Destination;
- /// \brief The type of the dependence.
+ /// The type of the dependence.
DepType Type;
Dependence(unsigned Source, unsigned Destination, DepType Type)
: Source(Source), Destination(Destination), Type(Type) {}
- /// \brief Return the source instruction of the dependence.
+ /// Return the source instruction of the dependence.
Instruction *getSource(const LoopAccessInfo &LAI) const;
- /// \brief Return the destination instruction of the dependence.
+ /// Return the destination instruction of the dependence.
Instruction *getDestination(const LoopAccessInfo &LAI) const;
- /// \brief Dependence types that don't prevent vectorization.
+ /// Dependence types that don't prevent vectorization.
static bool isSafeForVectorization(DepType Type);
- /// \brief Lexically forward dependence.
+ /// Lexically forward dependence.
bool isForward() const;
- /// \brief Lexically backward dependence.
+ /// Lexically backward dependence.
bool isBackward() const;
- /// \brief May be a lexically backward dependence type (includes Unknown).
+ /// May be a lexically backward dependence type (includes Unknown).
bool isPossiblyBackward() const;
- /// \brief Print the dependence. \p Instr is used to map the instruction
+ /// Print the dependence. \p Instr is used to map the instruction
/// indices to instructions.
void print(raw_ostream &OS, unsigned Depth,
const SmallVectorImpl<Instruction *> &Instrs) const;
@@ -167,7 +167,7 @@ public:
ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true),
RecordDependences(true) {}
- /// \brief Register the location (instructions are given increasing numbers)
+ /// Register the location (instructions are given increasing numbers)
/// of a write access.
void addAccess(StoreInst *SI) {
Value *Ptr = SI->getPointerOperand();
@@ -176,7 +176,7 @@ public:
++AccessIdx;
}
- /// \brief Register the location (instructions are given increasing numbers)
+ /// Register the location (instructions are given increasing numbers)
/// of a write access.
void addAccess(LoadInst *LI) {
Value *Ptr = LI->getPointerOperand();
@@ -185,29 +185,29 @@ public:
++AccessIdx;
}
- /// \brief Check whether the dependencies between the accesses are safe.
+ /// Check whether the dependencies between the accesses are safe.
///
/// Only checks sets with elements in \p CheckDeps.
bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoList &CheckDeps,
const ValueToValueMap &Strides);
- /// \brief No memory dependence was encountered that would inhibit
+ /// No memory dependence was encountered that would inhibit
/// vectorization.
bool isSafeForVectorization() const { return SafeForVectorization; }
- /// \brief The maximum number of bytes of a vector register we can vectorize
+ /// The maximum number of bytes of a vector register we can vectorize
/// the accesses safely with.
uint64_t getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
- /// \brief Return the number of elements that are safe to operate on
+ /// Return the number of elements that are safe to operate on
/// simultaneously, multiplied by the size of the element in bits.
uint64_t getMaxSafeRegisterWidth() const { return MaxSafeRegisterWidth; }
- /// \brief In same cases when the dependency check fails we can still
+ /// In same cases when the dependency check fails we can still
/// vectorize the loop with a dynamic array access check.
bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; }
- /// \brief Returns the memory dependences. If null is returned we exceeded
+ /// Returns the memory dependences. If null is returned we exceeded
/// the MaxDependences threshold and this information is not
/// available.
const SmallVectorImpl<Dependence> *getDependences() const {
@@ -216,13 +216,13 @@ public:
void clearDependences() { Dependences.clear(); }
- /// \brief The vector of memory access instructions. The indices are used as
+ /// The vector of memory access instructions. The indices are used as
/// instruction identifiers in the Dependence class.
const SmallVectorImpl<Instruction *> &getMemoryInstructions() const {
return InstMap;
}
- /// \brief Generate a mapping between the memory instructions and their
+ /// Generate a mapping between the memory instructions and their
/// indices according to program order.
DenseMap<Instruction *, unsigned> generateInstructionOrderMap() const {
DenseMap<Instruction *, unsigned> OrderMap;
@@ -233,7 +233,7 @@ public:
return OrderMap;
}
- /// \brief Find the set of instructions that read or write via \p Ptr.
+ /// Find the set of instructions that read or write via \p Ptr.
SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
bool isWrite) const;
@@ -247,42 +247,42 @@ private:
PredicatedScalarEvolution &PSE;
const Loop *InnermostLoop;
- /// \brief Maps access locations (ptr, read/write) to program order.
+ /// Maps access locations (ptr, read/write) to program order.
DenseMap<MemAccessInfo, std::vector<unsigned> > Accesses;
- /// \brief Memory access instructions in program order.
+ /// Memory access instructions in program order.
SmallVector<Instruction *, 16> InstMap;
- /// \brief The program order index to be used for the next instruction.
+ /// The program order index to be used for the next instruction.
unsigned AccessIdx;
// We can access this many bytes in parallel safely.
uint64_t MaxSafeDepDistBytes;
- /// \brief Number of elements (from consecutive iterations) that are safe to
+ /// Number of elements (from consecutive iterations) that are safe to
/// operate on simultaneously, multiplied by the size of the element in bits.
/// The size of the element is taken from the memory access that is most
/// restrictive.
uint64_t MaxSafeRegisterWidth;
- /// \brief If we see a non-constant dependence distance we can still try to
+ /// If we see a non-constant dependence distance we can still try to
/// vectorize this loop with runtime checks.
bool ShouldRetryWithRuntimeCheck;
- /// \brief No memory dependence was encountered that would inhibit
+ /// No memory dependence was encountered that would inhibit
/// vectorization.
bool SafeForVectorization;
- //// \brief True if Dependences reflects the dependences in the
+ //// True if Dependences reflects the dependences in the
//// loop. If false we exceeded MaxDependences and
//// Dependences is invalid.
bool RecordDependences;
- /// \brief Memory dependences collected during the analysis. Only valid if
+ /// Memory dependences collected during the analysis. Only valid if
/// RecordDependences is true.
SmallVector<Dependence, 8> Dependences;
- /// \brief Check whether there is a plausible dependence between the two
+ /// Check whether there is a plausible dependence between the two
/// accesses.
///
/// Access \p A must happen before \p B in program order. The two indices
@@ -298,7 +298,7 @@ private:
const MemAccessInfo &B, unsigned BIdx,
const ValueToValueMap &Strides);
- /// \brief Check whether the data dependence could prevent store-load
+ /// Check whether the data dependence could prevent store-load
/// forwarding.
///
/// \return false if we shouldn't vectorize at all or avoid larger
@@ -306,7 +306,7 @@ private:
bool couldPreventStoreLoadForward(uint64_t Distance, uint64_t TypeByteSize);
};
-/// \brief Holds information about the memory runtime legality checks to verify
+/// Holds information about the memory runtime legality checks to verify
/// that a group of pointers do not overlap.
class RuntimePointerChecking {
public:
@@ -355,13 +355,13 @@ public:
unsigned ASId, const ValueToValueMap &Strides,
PredicatedScalarEvolution &PSE);
- /// \brief No run-time memory checking is necessary.
+ /// No run-time memory checking is necessary.
bool empty() const { return Pointers.empty(); }
/// A grouping of pointers. A single memcheck is required between
/// two groups.
struct CheckingPtrGroup {
- /// \brief Create a new pointer checking group containing a single
+ /// Create a new pointer checking group containing a single
/// pointer, with index \p Index in RtCheck.
CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck)
: RtCheck(RtCheck), High(RtCheck.Pointers[Index].End),
@@ -369,7 +369,7 @@ public:
Members.push_back(Index);
}
- /// \brief Tries to add the pointer recorded in RtCheck at index
+ /// Tries to add the pointer recorded in RtCheck at index
/// \p Index to this pointer checking group. We can only add a pointer
/// to a checking group if we will still be able to get
/// the upper and lower bounds of the check. Returns true in case
@@ -390,7 +390,7 @@ public:
SmallVector<unsigned, 2> Members;
};
- /// \brief A memcheck which made up of a pair of grouped pointers.
+ /// A memcheck which made up of a pair of grouped pointers.
///
/// These *have* to be const for now, since checks are generated from
/// CheckingPtrGroups in LAI::addRuntimeChecks which is a const member
@@ -399,24 +399,24 @@ public:
typedef std::pair<const CheckingPtrGroup *, const CheckingPtrGroup *>
PointerCheck;
- /// \brief Generate the checks and store it. This also performs the grouping
+ /// Generate the checks and store it. This also performs the grouping
/// of pointers to reduce the number of memchecks necessary.
void generateChecks(MemoryDepChecker::DepCandidates &DepCands,
bool UseDependencies);
- /// \brief Returns the checks that generateChecks created.
+ /// Returns the checks that generateChecks created.
const SmallVector<PointerCheck, 4> &getChecks() const { return Checks; }
- /// \brief Decide if we need to add a check between two groups of pointers,
+ /// Decide if we need to add a check between two groups of pointers,
/// according to needsChecking.
bool needsChecking(const CheckingPtrGroup &M,
const CheckingPtrGroup &N) const;
- /// \brief Returns the number of run-time checks required according to
+ /// Returns the number of run-time checks required according to
/// needsChecking.
unsigned getNumberOfChecks() const { return Checks.size(); }
- /// \brief Print the list run-time memory checks necessary.
+ /// Print the list run-time memory checks necessary.
void print(raw_ostream &OS, unsigned Depth = 0) const;
/// Print \p Checks.
@@ -432,7 +432,7 @@ public:
/// Holds a partitioning of pointers into "check groups".
SmallVector<CheckingPtrGroup, 2> CheckingGroups;
- /// \brief Check if pointers are in the same partition
+ /// Check if pointers are in the same partition
///
/// \p PtrToPartition contains the partition number for pointers (-1 if the
/// pointer belongs to multiple partitions).
@@ -440,17 +440,17 @@ public:
arePointersInSamePartition(const SmallVectorImpl<int> &PtrToPartition,
unsigned PtrIdx1, unsigned PtrIdx2);
- /// \brief Decide whether we need to issue a run-time check for pointer at
+ /// 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 Return PointerInfo for pointer at index \p PtrIdx.
+ /// Return PointerInfo for pointer at index \p PtrIdx.
const PointerInfo &getPointerInfo(unsigned PtrIdx) const {
return Pointers[PtrIdx];
}
private:
- /// \brief Groups pointers such that a single memcheck is required
+ /// Groups pointers such that a single memcheck is required
/// between two different groups. This will clear the CheckingGroups vector
/// and re-compute it. We will only group dependecies if \p UseDependencies
/// is true, otherwise we will create a separate group for each pointer.
@@ -464,12 +464,12 @@ private:
/// Holds a pointer to the ScalarEvolution analysis.
ScalarEvolution *SE;
- /// \brief Set of run-time checks required to establish independence of
+ /// Set of run-time checks required to establish independence of
/// otherwise may-aliasing pointers in the loop.
SmallVector<PointerCheck, 4> Checks;
};
-/// \brief Drive the analysis of memory accesses in the loop
+/// 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
@@ -503,7 +503,7 @@ public:
return PtrRtChecking.get();
}
- /// \brief Number of memchecks required to prove independence of otherwise
+ /// Number of memchecks required to prove independence of otherwise
/// may-alias pointers.
unsigned getNumRuntimePointerChecks() const {
return PtrRtChecking->getNumberOfChecks();
@@ -521,7 +521,7 @@ public:
unsigned getNumStores() const { return NumStores; }
unsigned getNumLoads() const { return NumLoads;}
- /// \brief Add code that checks at runtime if the accessed arrays overlap.
+ /// 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
@@ -529,7 +529,7 @@ public:
std::pair<Instruction *, Instruction *>
addRuntimeChecks(Instruction *Loc) const;
- /// \brief Generete the instructions for the checks in \p PointerChecks.
+ /// Generete the instructions for the checks in \p PointerChecks.
///
/// Returns a pair of instructions where the first element is the first
/// instruction generated in possibly a sequence of instructions and the
@@ -539,32 +539,32 @@ public:
const SmallVectorImpl<RuntimePointerChecking::PointerCheck>
&PointerChecks) const;
- /// \brief The diagnostics report generated for the analysis. E.g. why we
+ /// The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.
const OptimizationRemarkAnalysis *getReport() const { return Report.get(); }
- /// \brief the Memory Dependence Checker which can determine the
+ /// the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
const MemoryDepChecker &getDepChecker() const { return *DepChecker; }
- /// \brief Return the list of instructions that use \p Ptr to read or write
+ /// Return the list of instructions that use \p Ptr to read or write
/// memory.
SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
bool isWrite) const {
return DepChecker->getInstructionsForAccess(Ptr, isWrite);
}
- /// \brief If an access has a symbolic strides, this maps the pointer value to
+ /// If an access has a symbolic strides, this maps the pointer value to
/// the stride symbol.
const ValueToValueMap &getSymbolicStrides() const { return SymbolicStrides; }
- /// \brief Pointer has a symbolic stride.
+ /// Pointer has a symbolic stride.
bool hasStride(Value *V) const { return StrideSet.count(V); }
- /// \brief Print the information about the memory accesses in the loop.
+ /// Print the information about the memory accesses in the loop.
void print(raw_ostream &OS, unsigned Depth = 0) const;
- /// \brief Checks existence of store to invariant address inside loop.
+ /// Checks existence of store to invariant address inside loop.
/// If the loop has any store to invariant address, then it returns true,
/// else returns false.
bool hasStoreToLoopInvariantAddress() const {
@@ -579,15 +579,15 @@ public:
const PredicatedScalarEvolution &getPSE() const { return *PSE; }
private:
- /// \brief Analyze the loop.
+ /// Analyze the loop.
void analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
const TargetLibraryInfo *TLI, DominatorTree *DT);
- /// \brief Check if the structure of the loop allows it to be analyzed by this
+ /// Check if the structure of the loop allows it to be analyzed by this
/// pass.
bool canAnalyzeLoop();
- /// \brief Save the analysis remark.
+ /// Save the analysis remark.
///
/// LAA does not directly emits the remarks. Instead it stores it which the
/// client can retrieve and presents as its own analysis
@@ -595,7 +595,7 @@ private:
OptimizationRemarkAnalysis &recordAnalysis(StringRef RemarkName,
Instruction *Instr = nullptr);
- /// \brief Collect memory access with loop invariant strides.
+ /// Collect memory access with loop invariant strides.
///
/// Looks for accesses like "a[i * StrideA]" where "StrideA" is loop
/// invariant.
@@ -607,7 +607,7 @@ private:
/// at runtime. Using std::unique_ptr to make using move ctor simpler.
std::unique_ptr<RuntimePointerChecking> PtrRtChecking;
- /// \brief the Memory Dependence Checker which can determine the
+ /// the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
std::unique_ptr<MemoryDepChecker> DepChecker;
@@ -618,28 +618,28 @@ private:
uint64_t MaxSafeDepDistBytes;
- /// \brief Cache the result of analyzeLoop.
+ /// Cache the result of analyzeLoop.
bool CanVecMem;
- /// \brief Indicator for storing to uniform addresses.
+ /// Indicator for storing to uniform addresses.
/// If a loop has write to a loop invariant address then it should be true.
bool StoreToLoopInvariantAddress;
- /// \brief The diagnostics report generated for the analysis. E.g. why we
+ /// The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.
std::unique_ptr<OptimizationRemarkAnalysis> Report;
- /// \brief If an access has a symbolic strides, this maps the pointer value to
+ /// If an access has a symbolic strides, this maps the pointer value to
/// the stride symbol.
ValueToValueMap SymbolicStrides;
- /// \brief Set of symbolic strides values.
+ /// Set of symbolic strides values.
SmallPtrSet<Value *, 8> StrideSet;
};
Value *stripIntegerCast(Value *V);
-/// \brief Return the SCEV corresponding to a pointer with the symbolic stride
+/// Return the SCEV corresponding to a pointer with the symbolic stride
/// replaced with constant one, assuming the SCEV predicate associated with
/// \p PSE is true.
///
@@ -653,7 +653,7 @@ const SCEV *replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE,
const ValueToValueMap &PtrToStride,
Value *Ptr, Value *OrigPtr = nullptr);
-/// \brief If the pointer has a constant stride return it in units of its
+/// If the pointer has a constant stride return it in units of its
/// element size. Otherwise return zero.
///
/// Ensure that it does not wrap in the address space, assuming the predicate
@@ -667,12 +667,26 @@ int64_t getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
const ValueToValueMap &StridesMap = ValueToValueMap(),
bool Assume = false, bool ShouldCheckWrap = true);
-/// \brief Returns true if the memory operations \p A and \p B are consecutive.
+/// Attempt to sort the pointers in \p VL and return the sorted indices
+/// in \p SortedIndices, if reordering is required.
+///
+/// Returns 'true' if sorting is legal, otherwise returns 'false'.
+///
+/// For example, for a given \p VL of memory accesses in program order, a[i+4],
+/// a[i+0], a[i+1] and a[i+7], this function will sort the \p VL and save the
+/// sorted indices in \p SortedIndices as a[i+0], a[i+1], a[i+4], a[i+7] and
+/// saves the mask for actual memory accesses in program order in
+/// \p SortedIndices as <1,2,0,3>
+bool sortPtrAccesses(ArrayRef<Value *> VL, const DataLayout &DL,
+ ScalarEvolution &SE,
+ SmallVectorImpl<unsigned> &SortedIndices);
+
+/// Returns true if the memory operations \p A and \p B are consecutive.
/// This is a simple API that does not depend on the analysis pass.
bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL,
ScalarEvolution &SE, bool CheckType = true);
-/// \brief This analysis provides dependence information for the memory accesses
+/// 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
@@ -691,7 +705,7 @@ public:
void getAnalysisUsage(AnalysisUsage &AU) const override;
- /// \brief Query the result of the loop access information for the loop \p L.
+ /// Query the result of the loop access information for the loop \p L.
///
/// If there is no cached result available run the analysis.
const LoopAccessInfo &getInfo(Loop *L);
@@ -701,11 +715,11 @@ public:
LoopAccessInfoMap.clear();
}
- /// \brief Print the result of the analysis when invoked with -analyze.
+ /// 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.
+ /// The cache.
DenseMap<Loop *, std::unique_ptr<LoopAccessInfo>> LoopAccessInfoMap;
// The used analysis passes.
@@ -716,7 +730,7 @@ private:
LoopInfo *LI;
};
-/// \brief This analysis provides dependence information for the memory
+/// 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
diff --git a/contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h b/contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h
index 417ee979ce97..00e562c4f31f 100644
--- a/contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h
+++ b/contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h
@@ -69,7 +69,7 @@ extern cl::opt<bool> EnableMSSALoopDependency;
extern template class AllAnalysesOn<Loop>;
extern template class AnalysisManager<Loop, LoopStandardAnalysisResults &>;
-/// \brief The loop analysis manager.
+/// The loop analysis manager.
///
/// See the documentation for the AnalysisManager template for detail
/// documentation. This typedef serves as a convenient way to refer to this
diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfo.h b/contrib/llvm/include/llvm/Analysis/LoopInfo.h
index 28afc39727fa..30b29d66a1d1 100644
--- a/contrib/llvm/include/llvm/Analysis/LoopInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/LoopInfo.h
@@ -178,6 +178,12 @@ public:
return DenseBlockSet;
}
+ /// Return a direct, immutable handle to the blocks set.
+ const SmallPtrSetImpl<const BlockT *> &getBlocksSet() const {
+ assert(!isInvalid() && "Loop not in a valid state!");
+ return DenseBlockSet;
+ }
+
/// Return true if this loop is no longer valid. The only valid use of this
/// helper is "assert(L.isInvalid())" or equivalent, since IsInvalid is set to
/// true by the destructor. In other words, if this accessor returns true,
@@ -255,6 +261,20 @@ public:
/// Otherwise return null.
BlockT *getExitBlock() const;
+ /// Return true if no exit block for the loop has a predecessor that is
+ /// outside the loop.
+ bool hasDedicatedExits() const;
+
+ /// Return all unique successor blocks of this loop.
+ /// These are the blocks _outside of the current loop_ which are branched to.
+ /// This assumes that loop exits are in canonical form, i.e. all exits are
+ /// dedicated exits.
+ void getUniqueExitBlocks(SmallVectorImpl<BlockT *> &ExitBlocks) const;
+
+ /// If getUniqueExitBlocks would return exactly one block, return that block.
+ /// Otherwise return null.
+ BlockT *getUniqueExitBlock() const;
+
/// Edge type.
typedef std::pair<const BlockT *, const BlockT *> Edge;
@@ -438,7 +458,7 @@ extern template class LoopBase<BasicBlock, Loop>;
/// in the CFG are necessarily loops.
class Loop : public LoopBase<BasicBlock, Loop> {
public:
- /// \brief A range representing the start and end location of a loop.
+ /// A range representing the start and end location of a loop.
class LocRange {
DebugLoc Start;
DebugLoc End;
@@ -452,7 +472,7 @@ public:
const DebugLoc &getStart() const { return Start; }
const DebugLoc &getEnd() const { return End; }
- /// \brief Check for null.
+ /// Check for null.
///
explicit operator bool() const { return Start && End; }
};
@@ -527,7 +547,7 @@ public:
///
/// If this loop contains the same llvm.loop metadata on each branch to the
/// header then the node is returned. If any latch instruction does not
- /// contain llvm.loop or or if multiple latches contain different nodes then
+ /// contain llvm.loop or if multiple latches contain different nodes then
/// 0 is returned.
MDNode *getLoopID() const;
/// Set the llvm.loop loop id metadata for this loop.
@@ -547,20 +567,6 @@ public:
/// unrolling pass is run more than once (which it generally is).
void setLoopAlreadyUnrolled();
- /// Return true if no exit block for the loop has a predecessor that is
- /// outside the loop.
- bool hasDedicatedExits() const;
-
- /// Return all unique successor blocks of this loop.
- /// These are the blocks _outside of the current loop_ which are branched to.
- /// This assumes that loop exits are in canonical form, i.e. all exits are
- /// dedicated exits.
- void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const;
-
- /// If getUniqueExitBlocks would return exactly one block, return that block.
- /// Otherwise return null.
- BasicBlock *getUniqueExitBlock() const;
-
void dump() const;
void dumpVerbose() const;
@@ -929,7 +935,7 @@ template <> struct GraphTraits<Loop *> {
static ChildIteratorType child_end(NodeRef N) { return N->end(); }
};
-/// \brief Analysis pass that exposes the \c LoopInfo for a function.
+/// Analysis pass that exposes the \c LoopInfo for a function.
class LoopAnalysis : public AnalysisInfoMixin<LoopAnalysis> {
friend AnalysisInfoMixin<LoopAnalysis>;
static AnalysisKey Key;
@@ -940,7 +946,7 @@ public:
LoopInfo run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Printer pass for the \c LoopAnalysis results.
+/// Printer pass for the \c LoopAnalysis results.
class LoopPrinterPass : public PassInfoMixin<LoopPrinterPass> {
raw_ostream &OS;
@@ -949,12 +955,12 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Verifier pass for the \c LoopAnalysis results.
+/// Verifier pass for the \c LoopAnalysis results.
struct LoopVerifierPass : public PassInfoMixin<LoopVerifierPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief The legacy pass manager's analysis pass to compute loop information.
+/// The legacy pass manager's analysis pass to compute loop information.
class LoopInfoWrapperPass : public FunctionPass {
LoopInfo LI;
@@ -968,7 +974,7 @@ public:
LoopInfo &getLoopInfo() { return LI; }
const LoopInfo &getLoopInfo() const { return LI; }
- /// \brief Calculate the natural loop information for a given function.
+ /// Calculate the natural loop information for a given function.
bool runOnFunction(Function &F) override;
void verifyAnalysis() const override;
diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h b/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h
index b3a16b5369f7..941389858868 100644
--- a/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h
+++ b/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h
@@ -82,6 +82,74 @@ BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const {
return nullptr;
}
+template <class BlockT, class LoopT>
+bool LoopBase<BlockT, LoopT>::hasDedicatedExits() const {
+ // Each predecessor of each exit block of a normal loop is contained
+ // within the loop.
+ SmallVector<BlockT *, 4> ExitBlocks;
+ getExitBlocks(ExitBlocks);
+ for (BlockT *EB : ExitBlocks)
+ for (BlockT *Predecessor : children<Inverse<BlockT *>>(EB))
+ if (!contains(Predecessor))
+ return false;
+ // All the requirements are met.
+ return true;
+}
+
+template <class BlockT, class LoopT>
+void LoopBase<BlockT, LoopT>::getUniqueExitBlocks(
+ SmallVectorImpl<BlockT *> &ExitBlocks) const {
+ typedef GraphTraits<BlockT *> BlockTraits;
+ typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits;
+
+ assert(hasDedicatedExits() &&
+ "getUniqueExitBlocks assumes the loop has canonical form exits!");
+
+ SmallVector<BlockT *, 32> SwitchExitBlocks;
+ for (BlockT *Block : this->blocks()) {
+ SwitchExitBlocks.clear();
+ for (BlockT *Successor : children<BlockT *>(Block)) {
+ // If block is inside the loop then it is not an exit block.
+ if (contains(Successor))
+ continue;
+
+ BlockT *FirstPred = *InvBlockTraits::child_begin(Successor);
+
+ // If current basic block is this exit block's first predecessor then only
+ // insert exit block in to the output ExitBlocks vector. This ensures that
+ // same exit block is not inserted twice into ExitBlocks vector.
+ if (Block != FirstPred)
+ continue;
+
+ // If a terminator has more then two successors, for example SwitchInst,
+ // then it is possible that there are multiple edges from current block to
+ // one exit block.
+ if (std::distance(BlockTraits::child_begin(Block),
+ BlockTraits::child_end(Block)) <= 2) {
+ ExitBlocks.push_back(Successor);
+ continue;
+ }
+
+ // In case of multiple edges from current block to exit block, collect
+ // only one edge in ExitBlocks. Use switchExitBlocks to keep track of
+ // duplicate edges.
+ if (!is_contained(SwitchExitBlocks, Successor)) {
+ SwitchExitBlocks.push_back(Successor);
+ ExitBlocks.push_back(Successor);
+ }
+ }
+ }
+}
+
+template <class BlockT, class LoopT>
+BlockT *LoopBase<BlockT, LoopT>::getUniqueExitBlock() const {
+ SmallVector<BlockT *, 8> UniqueExitBlocks;
+ getUniqueExitBlocks(UniqueExitBlocks);
+ if (UniqueExitBlocks.size() == 1)
+ return UniqueExitBlocks[0];
+ return nullptr;
+}
+
/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_).
template <class BlockT, class LoopT>
void LoopBase<BlockT, LoopT>::getExitEdges(
@@ -572,8 +640,8 @@ void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
template <typename T>
bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) {
- std::sort(BB1.begin(), BB1.end());
- std::sort(BB2.begin(), BB2.end());
+ llvm::sort(BB1.begin(), BB1.end());
+ llvm::sort(BB2.begin(), BB2.end());
return BB1 == BB2;
}
@@ -617,6 +685,15 @@ static void compareLoops(const LoopT *L, const LoopT *OtherL,
std::vector<BlockT *> OtherBBs = OtherL->getBlocks();
assert(compareVectors(BBs, OtherBBs) &&
"Mismatched basic blocks in the loops!");
+
+ const SmallPtrSetImpl<const BlockT *> &BlocksSet = L->getBlocksSet();
+ const SmallPtrSetImpl<const BlockT *> &OtherBlocksSet = L->getBlocksSet();
+ assert(BlocksSet.size() == OtherBlocksSet.size() &&
+ std::all_of(BlocksSet.begin(), BlocksSet.end(),
+ [&OtherBlocksSet](const BlockT *BB) {
+ return OtherBlocksSet.count(BB);
+ }) &&
+ "Mismatched basic blocks in BlocksSets!");
}
#endif
@@ -636,6 +713,9 @@ void LoopInfoBase<BlockT, LoopT>::verify(
LoopT *L = Entry.second;
assert(Loops.count(L) && "orphaned loop");
assert(L->contains(BB) && "orphaned block");
+ for (LoopT *ChildLoop : *L)
+ assert(!ChildLoop->contains(BB) &&
+ "BBMap should point to the innermost loop containing BB");
}
// Recompute LoopInfo to verify loops structure.
diff --git a/contrib/llvm/include/llvm/Analysis/LoopIterator.h b/contrib/llvm/include/llvm/Analysis/LoopIterator.h
index 461f74351821..91c54b23029b 100644
--- a/contrib/llvm/include/llvm/Analysis/LoopIterator.h
+++ b/contrib/llvm/include/llvm/Analysis/LoopIterator.h
@@ -168,6 +168,25 @@ public:
}
};
+/// Wrapper class to LoopBlocksDFS that provides a standard begin()/end()
+/// interface for the DFS reverse post-order traversal of blocks in a loop body.
+class LoopBlocksRPO {
+private:
+ LoopBlocksDFS DFS;
+
+public:
+ LoopBlocksRPO(Loop *Container) : DFS(Container) {}
+
+ /// Traverse the loop blocks and store the DFS result.
+ void perform(LoopInfo *LI) {
+ DFS.perform(LI);
+ }
+
+ /// Reverse iterate over the cached postorder blocks.
+ LoopBlocksDFS::RPOIterator begin() const { return DFS.beginRPO(); }
+ LoopBlocksDFS::RPOIterator end() const { return DFS.endRPO(); }
+};
+
/// Specialize po_iterator_storage to record postorder numbers.
template<> class po_iterator_storage<LoopBlocksTraversal, true> {
LoopBlocksTraversal &LBT;
diff --git a/contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h b/contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h
index 80f3e5fdcd43..f45bf0b223b8 100644
--- a/contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h
+++ b/contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h
@@ -57,7 +57,7 @@ public:
using Base::visit;
private:
- /// \brief A cache of pointer bases and constant-folded offsets corresponding
+ /// A cache of pointer bases and constant-folded offsets corresponding
/// to GEP (or derived from GEP) instructions.
///
/// In order to find the base pointer one needs to perform non-trivial
@@ -65,11 +65,11 @@ private:
/// results saved.
DenseMap<Value *, SimplifiedAddress> SimplifiedAddresses;
- /// \brief SCEV expression corresponding to number of currently simulated
+ /// SCEV expression corresponding to number of currently simulated
/// iteration.
const SCEV *IterationNumber;
- /// \brief A Value->Constant map for keeping values that we managed to
+ /// A Value->Constant map for keeping values that we managed to
/// constant-fold on the given iteration.
///
/// While we walk the loop instructions, we build up and maintain a mapping
diff --git a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h
index 7d53e34938b7..5418128f16ef 100644
--- a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h
+++ b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -53,33 +53,33 @@ class Type;
class UndefValue;
class Value;
-/// \brief Tests if a value is a call or invoke to a library function that
+/// Tests if a value is a call or invoke to a library function that
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
/// like).
bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast = false);
-/// \brief Tests if a value is a call or invoke to a function that returns a
+/// Tests if a value is a call or invoke to a function that returns a
/// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions).
bool isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast = false);
-/// \brief Tests if a value is a call or invoke to a library function that
+/// Tests if a value is a call or invoke to a library function that
/// allocates uninitialized memory (such as malloc).
bool isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast = false);
-/// \brief Tests if a value is a call or invoke to a library function that
+/// Tests if a value is a call or invoke to a library function that
/// allocates zero-filled memory (such as calloc).
bool isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast = false);
-/// \brief Tests if a value is a call or invoke to a library function that
+/// Tests if a value is a call or invoke to a library function that
/// allocates memory similar to malloc or calloc.
bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast = false);
-/// \brief Tests if a value is a call or invoke to a library function that
+/// Tests if a value is a call or invoke to a library function that
/// allocates memory (either malloc, calloc, or strdup like).
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast = false);
@@ -170,14 +170,14 @@ struct ObjectSizeOpts {
bool NullIsUnknownSize = false;
};
-/// \brief Compute the size of the object pointed by Ptr. Returns true and the
+/// Compute the size of the object pointed by Ptr. Returns true and the
/// object size in Size if successful, and false otherwise. In this context, by
/// object we mean the region of memory starting at Ptr to the end of the
/// underlying object pointed to by Ptr.
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {});
-/// Try to turn a call to @llvm.objectsize into an integer value of the given
+/// Try to turn a call to \@llvm.objectsize into an integer value of the given
/// Type. Returns null on failure.
/// If MustSucceed is true, this function will not return null, and may return
/// conservative values governed by the second argument of the call to
@@ -189,7 +189,7 @@ ConstantInt *lowerObjectSizeCall(IntrinsicInst *ObjectSize,
using SizeOffsetType = std::pair<APInt, APInt>;
-/// \brief Evaluate the size and offset of an object pointed to by a Value*
+/// Evaluate the size and offset of an object pointed to by a Value*
/// statically. Fails if size or offset are not known at compile time.
class ObjectSizeOffsetVisitor
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
@@ -248,7 +248,7 @@ private:
using SizeOffsetEvalType = std::pair<Value *, Value *>;
-/// \brief Evaluate the size and offset of an object pointed to by a Value*.
+/// Evaluate the size and offset of an object pointed to by a Value*.
/// May create code to compute the result at run-time.
class ObjectSizeOffsetEvaluator
: public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
diff --git a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
index c2974525a6ff..1c6ec98dfedc 100644
--- a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
@@ -26,6 +26,7 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/PredIteratorCache.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
@@ -302,7 +303,7 @@ private:
/// The maximum size of the dereferences of the pointer.
///
/// May be UnknownSize if the sizes are unknown.
- uint64_t Size = MemoryLocation::UnknownSize;
+ LocationSize Size = MemoryLocation::UnknownSize;
/// The AA tags associated with dereferences of the pointer.
///
/// The members may be null if there are no tags or conflicting tags.
@@ -314,7 +315,10 @@ private:
/// Cache storing single nonlocal def for the instruction.
/// It is set when nonlocal def would be found in function returning only
/// local dependencies.
- DenseMap<Instruction *, NonLocalDepResult> NonLocalDefsCache;
+ DenseMap<AssertingVH<const Value>, NonLocalDepResult> NonLocalDefsCache;
+ using ReverseNonLocalDefsCacheTy =
+ DenseMap<Instruction *, SmallPtrSet<const Value*, 4>>;
+ ReverseNonLocalDefsCacheTy ReverseNonLocalDefsCache;
/// This map stores the cached results of doing a pointer lookup at the
/// bottom of a block.
diff --git a/contrib/llvm/include/llvm/Analysis/MemoryLocation.h b/contrib/llvm/include/llvm/Analysis/MemoryLocation.h
index c1080742e83a..6b680000312c 100644
--- a/contrib/llvm/include/llvm/Analysis/MemoryLocation.h
+++ b/contrib/llvm/include/llvm/Analysis/MemoryLocation.h
@@ -27,8 +27,16 @@ class LoadInst;
class StoreInst;
class MemTransferInst;
class MemIntrinsic;
+class AtomicMemTransferInst;
+class AtomicMemIntrinsic;
+class AnyMemTransferInst;
+class AnyMemIntrinsic;
class TargetLibraryInfo;
+// Represents the size of a MemoryLocation. Logically, it's an
+// Optional<uint64_t>, with a special UnknownSize value from `MemoryLocation`.
+using LocationSize = uint64_t;
+
/// Representation for a specific memory location.
///
/// This abstraction can be used to represent a specific location in memory.
@@ -55,7 +63,7 @@ public:
/// virtual address space, because there are restrictions on stepping out of
/// one object and into another. See
/// http://llvm.org/docs/LangRef.html#pointeraliasing
- uint64_t Size;
+ LocationSize Size;
/// The metadata nodes which describes the aliasing of the location (each
/// member is null if that kind of information is unavailable).
@@ -90,17 +98,21 @@ public:
/// Return a location representing the source of a memory transfer.
static MemoryLocation getForSource(const MemTransferInst *MTI);
+ static MemoryLocation getForSource(const AtomicMemTransferInst *MTI);
+ static MemoryLocation getForSource(const AnyMemTransferInst *MTI);
/// Return a location representing the destination of a memory set or
/// transfer.
static MemoryLocation getForDest(const MemIntrinsic *MI);
+ static MemoryLocation getForDest(const AtomicMemIntrinsic *MI);
+ static MemoryLocation getForDest(const AnyMemIntrinsic *MI);
/// Return a location representing a particular argument of a call.
static MemoryLocation getForArgument(ImmutableCallSite CS, unsigned ArgIdx,
const TargetLibraryInfo &TLI);
explicit MemoryLocation(const Value *Ptr = nullptr,
- uint64_t Size = UnknownSize,
+ LocationSize Size = UnknownSize,
const AAMDNodes &AATags = AAMDNodes())
: Ptr(Ptr), Size(Size), AATags(AATags) {}
@@ -110,7 +122,7 @@ public:
return Copy;
}
- MemoryLocation getWithNewSize(uint64_t NewSize) const {
+ MemoryLocation getWithNewSize(LocationSize NewSize) const {
MemoryLocation Copy(*this);
Copy.Size = NewSize;
return Copy;
@@ -137,7 +149,7 @@ template <> struct DenseMapInfo<MemoryLocation> {
}
static unsigned getHashValue(const MemoryLocation &Val) {
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
- DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^
+ DenseMapInfo<LocationSize>::getHashValue(Val.Size) ^
DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags);
}
static bool isEqual(const MemoryLocation &LHS, const MemoryLocation &RHS) {
diff --git a/contrib/llvm/include/llvm/Analysis/MemorySSA.h b/contrib/llvm/include/llvm/Analysis/MemorySSA.h
index d19f08453ee6..d445e4430e5c 100644
--- a/contrib/llvm/include/llvm/Analysis/MemorySSA.h
+++ b/contrib/llvm/include/llvm/Analysis/MemorySSA.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief This file exposes an interface to building/using memory SSA to
+/// This file exposes an interface to building/using memory SSA to
/// walk memory instructions using a use/def graph.
///
/// Memory SSA class builds an SSA form that links together memory access
@@ -93,6 +93,7 @@
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include <algorithm>
@@ -118,10 +119,10 @@ struct DefsOnlyTag {};
} // end namespace MSSAHelpers
-enum {
+enum : unsigned {
// Used to signify what the default invalid ID is for MemoryAccess's
// getID()
- INVALID_MEMORYACCESS_ID = 0
+ INVALID_MEMORYACCESS_ID = -1U
};
template <class T> class memoryaccess_def_iterator_base;
@@ -129,7 +130,7 @@ using memoryaccess_def_iterator = memoryaccess_def_iterator_base<MemoryAccess>;
using const_memoryaccess_def_iterator =
memoryaccess_def_iterator_base<const MemoryAccess>;
-// \brief The base for all memory accesses. All memory accesses in a block are
+// The base for all memory accesses. All memory accesses in a block are
// linked together using an intrusive list.
class MemoryAccess
: public DerivedUser,
@@ -158,11 +159,11 @@ public:
void print(raw_ostream &OS) const;
void dump() const;
- /// \brief The user iterators for a memory access
+ /// The user iterators for a memory access
using iterator = user_iterator;
using const_iterator = const_user_iterator;
- /// \brief This iterator walks over all of the defs in a given
+ /// This iterator walks over all of the defs in a given
/// MemoryAccess. For MemoryPhi nodes, this walks arguments. For
/// MemoryUse/MemoryDef, this walks the defining access.
memoryaccess_def_iterator defs_begin();
@@ -170,7 +171,7 @@ public:
memoryaccess_def_iterator defs_end();
const_memoryaccess_def_iterator defs_end() const;
- /// \brief Get the iterators for the all access list and the defs only list
+ /// Get the iterators for the all access list and the defs only list
/// We default to the all access list.
AllAccessType::self_iterator getIterator() {
return this->AllAccessType::getIterator();
@@ -204,11 +205,11 @@ protected:
friend class MemoryUse;
friend class MemoryUseOrDef;
- /// \brief Used by MemorySSA to change the block of a MemoryAccess when it is
+ /// Used by MemorySSA to change the block of a MemoryAccess when it is
/// moved.
void setBlock(BasicBlock *BB) { Block = BB; }
- /// \brief Used for debugging and tracking things about MemoryAccesses.
+ /// Used for debugging and tracking things about MemoryAccesses.
/// Guaranteed unique among MemoryAccesses, no guarantees otherwise.
inline unsigned getID() const;
@@ -217,16 +218,24 @@ protected:
: DerivedUser(Type::getVoidTy(C), Vty, nullptr, NumOperands, DeleteValue),
Block(BB) {}
+ // Use deleteValue() to delete a generic MemoryAccess.
+ ~MemoryAccess() = default;
+
private:
BasicBlock *Block;
};
+template <>
+struct ilist_alloc_traits<MemoryAccess> {
+ static void deleteNode(MemoryAccess *MA) { MA->deleteValue(); }
+};
+
inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) {
MA.print(OS);
return OS;
}
-/// \brief Class that has the common methods + fields of memory uses/defs. It's
+/// Class that has the common methods + fields of memory uses/defs. It's
/// a little awkward to have, but there are many cases where we want either a
/// use or def, and there are many cases where uses are needed (defs aren't
/// acceptable), and vice-versa.
@@ -239,10 +248,10 @@ public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
- /// \brief Get the instruction that this MemoryUse represents.
- Instruction *getMemoryInst() const { return MemoryInst; }
+ /// Get the instruction that this MemoryUse represents.
+ Instruction *getMemoryInst() const { return MemoryInstruction; }
- /// \brief Get the access that produces the memory state used by this Use.
+ /// Get the access that produces the memory state used by this Use.
MemoryAccess *getDefiningAccess() const { return getOperand(0); }
static bool classof(const Value *MA) {
@@ -255,7 +264,13 @@ public:
inline MemoryAccess *getOptimized() const;
inline void setOptimized(MemoryAccess *);
- /// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
+ // Retrieve AliasResult type of the optimized access. Ideally this would be
+ // returned by the caching walker and may go away in the future.
+ Optional<AliasResult> getOptimizedAccessType() const {
+ return OptimizedAccessAlias;
+ }
+
+ /// Reset the ID of what this MemoryUse was optimized to, causing it to
/// be rewalked by the walker if necessary.
/// This really should only be called by tests.
inline void resetOptimized();
@@ -266,20 +281,31 @@ protected:
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB)
- : MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInst(MI) {
+ : MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInstruction(MI),
+ OptimizedAccessAlias(MayAlias) {
setDefiningAccess(DMA);
}
- void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
+ // Use deleteValue() to delete a generic MemoryUseOrDef.
+ ~MemoryUseOrDef() = default;
+
+ void setOptimizedAccessType(Optional<AliasResult> AR) {
+ OptimizedAccessAlias = AR;
+ }
+
+ void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false,
+ Optional<AliasResult> AR = MayAlias) {
if (!Optimized) {
setOperand(0, DMA);
return;
}
setOptimized(DMA);
+ setOptimizedAccessType(AR);
}
private:
- Instruction *MemoryInst;
+ Instruction *MemoryInstruction;
+ Optional<AliasResult> OptimizedAccessAlias;
};
template <>
@@ -287,7 +313,7 @@ struct OperandTraits<MemoryUseOrDef>
: public FixedNumOperandTraits<MemoryUseOrDef, 1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
-/// \brief Represents read-only accesses to memory
+/// Represents read-only accesses to memory
///
/// In particular, the set of Instructions that will be represented by
/// MemoryUse's is exactly the set of Instructions for which
@@ -331,14 +357,14 @@ protected:
private:
static void deleteMe(DerivedUser *Self);
- unsigned int OptimizedID = 0;
+ unsigned OptimizedID = INVALID_MEMORYACCESS_ID;
};
template <>
struct OperandTraits<MemoryUse> : public FixedNumOperandTraits<MemoryUse, 1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess)
-/// \brief Represents a read-write access to memory, whether it is a must-alias,
+/// Represents a read-write access to memory, whether it is a must-alias,
/// or a may-alias.
///
/// In particular, the set of Instructions that will be represented by
@@ -369,7 +395,9 @@ public:
OptimizedID = getDefiningAccess()->getID();
}
- MemoryAccess *getOptimized() const { return Optimized; }
+ MemoryAccess *getOptimized() const {
+ return cast_or_null<MemoryAccess>(Optimized);
+ }
bool isOptimized() const {
return getOptimized() && getDefiningAccess() &&
@@ -388,15 +416,15 @@ private:
static void deleteMe(DerivedUser *Self);
const unsigned ID;
- MemoryAccess *Optimized = nullptr;
- unsigned int OptimizedID = INVALID_MEMORYACCESS_ID;
+ unsigned OptimizedID = INVALID_MEMORYACCESS_ID;
+ WeakVH Optimized;
};
template <>
struct OperandTraits<MemoryDef> : public FixedNumOperandTraits<MemoryDef, 1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess)
-/// \brief Represents phi nodes for memory accesses.
+/// Represents phi nodes for memory accesses.
///
/// These have the same semantic as regular phi nodes, with the exception that
/// only one phi will ever exist in a given basic block.
@@ -476,10 +504,10 @@ public:
const_op_range incoming_values() const { return operands(); }
- /// \brief Return the number of incoming edges
+ /// Return the number of incoming edges
unsigned getNumIncomingValues() const { return getNumOperands(); }
- /// \brief Return incoming value number x
+ /// Return incoming value number x
MemoryAccess *getIncomingValue(unsigned I) const { return getOperand(I); }
void setIncomingValue(unsigned I, MemoryAccess *V) {
assert(V && "PHI node got a null value!");
@@ -489,17 +517,17 @@ public:
static unsigned getOperandNumForIncomingValue(unsigned I) { return I; }
static unsigned getIncomingValueNumForOperand(unsigned I) { return I; }
- /// \brief Return incoming basic block number @p i.
+ /// Return incoming basic block number @p i.
BasicBlock *getIncomingBlock(unsigned I) const { return block_begin()[I]; }
- /// \brief Return incoming basic block corresponding
+ /// Return incoming basic block corresponding
/// to an operand of the PHI.
BasicBlock *getIncomingBlock(const Use &U) const {
assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?");
return getIncomingBlock(unsigned(&U - op_begin()));
}
- /// \brief Return incoming basic block corresponding
+ /// Return incoming basic block corresponding
/// to value use iterator.
BasicBlock *getIncomingBlock(MemoryAccess::const_user_iterator I) const {
return getIncomingBlock(I.getUse());
@@ -510,7 +538,7 @@ public:
block_begin()[I] = BB;
}
- /// \brief Add an incoming value to the end of the PHI list
+ /// Add an incoming value to the end of the PHI list
void addIncoming(MemoryAccess *V, BasicBlock *BB) {
if (getNumOperands() == ReservedSpace)
growOperands(); // Get more space!
@@ -520,7 +548,7 @@ public:
setIncomingBlock(getNumOperands() - 1, BB);
}
- /// \brief Return the first index of the specified basic
+ /// Return the first index of the specified basic
/// block in the value list for this PHI. Returns -1 if no instance.
int getBasicBlockIndex(const BasicBlock *BB) const {
for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
@@ -529,12 +557,53 @@ public:
return -1;
}
- Value *getIncomingValueForBlock(const BasicBlock *BB) const {
+ MemoryAccess *getIncomingValueForBlock(const BasicBlock *BB) const {
int Idx = getBasicBlockIndex(BB);
assert(Idx >= 0 && "Invalid basic block argument!");
return getIncomingValue(Idx);
}
+ // After deleting incoming position I, the order of incoming may be changed.
+ void unorderedDeleteIncoming(unsigned I) {
+ unsigned E = getNumOperands();
+ assert(I < E && "Cannot remove out of bounds Phi entry.");
+ // MemoryPhi must have at least two incoming values, otherwise the MemoryPhi
+ // itself should be deleted.
+ assert(E >= 2 && "Cannot only remove incoming values in MemoryPhis with "
+ "at least 2 values.");
+ setIncomingValue(I, getIncomingValue(E - 1));
+ setIncomingBlock(I, block_begin()[E - 1]);
+ setOperand(E - 1, nullptr);
+ block_begin()[E - 1] = nullptr;
+ setNumHungOffUseOperands(getNumOperands() - 1);
+ }
+
+ // After deleting entries that satisfy Pred, remaining entries may have
+ // changed order.
+ template <typename Fn> void unorderedDeleteIncomingIf(Fn &&Pred) {
+ for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
+ if (Pred(getIncomingValue(I), getIncomingBlock(I))) {
+ unorderedDeleteIncoming(I);
+ E = getNumOperands();
+ --I;
+ }
+ assert(getNumOperands() >= 1 &&
+ "Cannot remove all incoming blocks in a MemoryPhi.");
+ }
+
+ // After deleting incoming block BB, the incoming blocks order may be changed.
+ void unorderedDeleteIncomingBlock(const BasicBlock *BB) {
+ unorderedDeleteIncomingIf(
+ [&](const MemoryAccess *, const BasicBlock *B) { return BB == B; });
+ }
+
+ // After deleting incoming memory access MA, the incoming accesses order may
+ // be changed.
+ void unorderedDeleteIncomingValue(const MemoryAccess *MA) {
+ unorderedDeleteIncomingIf(
+ [&](const MemoryAccess *M, const BasicBlock *) { return MA == M; });
+ }
+
static bool classof(const Value *V) {
return V->getValueID() == MemoryPhiVal;
}
@@ -546,7 +615,7 @@ public:
protected:
friend class MemorySSA;
- /// \brief this is more complicated than the generic
+ /// this is more complicated than the generic
/// User::allocHungoffUses, because we have to allocate Uses for the incoming
/// values and pointers to the incoming blocks, all in one allocation.
void allocHungoffUses(unsigned N) {
@@ -558,7 +627,7 @@ private:
const unsigned ID;
unsigned ReservedSpace;
- /// \brief This grows the operand list in response to a push_back style of
+ /// This grows the operand list in response to a push_back style of
/// operation. This grows the number of ops by 1.5 times.
void growOperands() {
unsigned E = getNumOperands();
@@ -607,7 +676,7 @@ inline void MemoryUseOrDef::resetOptimized() {
template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess)
-/// \brief Encapsulates MemorySSA, including all data associated with memory
+/// Encapsulates MemorySSA, including all data associated with memory
/// accesses.
class MemorySSA {
public:
@@ -616,7 +685,7 @@ public:
MemorySSAWalker *getWalker();
- /// \brief Given a memory Mod/Ref'ing instruction, get the MemorySSA
+ /// Given a memory Mod/Ref'ing instruction, get the MemorySSA
/// access associated with it. If passed a basic block gets the memory phi
/// node that exists for that block, if there is one. Otherwise, this will get
/// a MemoryUseOrDef.
@@ -626,7 +695,7 @@ public:
void dump() const;
void print(raw_ostream &) const;
- /// \brief Return true if \p MA represents the live on entry value
+ /// Return true if \p MA represents the live on entry value
///
/// Loads and stores from pointer arguments and other global values may be
/// defined by memory operations that do not occur in the current function, so
@@ -650,14 +719,14 @@ public:
using DefsList =
simple_ilist<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
- /// \brief Return the list of MemoryAccess's for a given basic block.
+ /// Return the list of MemoryAccess's for a given basic block.
///
/// This list is not modifiable by the user.
const AccessList *getBlockAccesses(const BasicBlock *BB) const {
return getWritableBlockAccesses(BB);
}
- /// \brief Return the list of MemoryDef's and MemoryPhi's for a given basic
+ /// Return the list of MemoryDef's and MemoryPhi's for a given basic
/// block.
///
/// This list is not modifiable by the user.
@@ -665,19 +734,19 @@ public:
return getWritableBlockDefs(BB);
}
- /// \brief Given two memory accesses in the same basic block, determine
+ /// Given two memory accesses in the same basic block, determine
/// whether MemoryAccess \p A dominates MemoryAccess \p B.
bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const;
- /// \brief Given two memory accesses in potentially different blocks,
+ /// Given two memory accesses in potentially different blocks,
/// determine whether MemoryAccess \p A dominates MemoryAccess \p B.
bool dominates(const MemoryAccess *A, const MemoryAccess *B) const;
- /// \brief Given a MemoryAccess and a Use, determine whether MemoryAccess \p A
+ /// Given a MemoryAccess and a Use, determine whether MemoryAccess \p A
/// dominates Use \p B.
bool dominates(const MemoryAccess *A, const Use &B) const;
- /// \brief Verify that MemorySSA is self consistent (IE definitions dominate
+ /// Verify that MemorySSA is self consistent (IE definitions dominate
/// all uses, uses appear in the right places). This is used by unit tests.
void verifyMemorySSA() const;
@@ -694,6 +763,7 @@ protected:
void verifyDefUses(Function &F) const;
void verifyDomination(Function &F) const;
void verifyOrdering(Function &F) const;
+ void verifyDominationNumbers(const Function &F) const;
// This is used by the use optimizer and updater.
AccessList *getWritableBlockAccesses(const BasicBlock *BB) const {
@@ -712,7 +782,7 @@ protected:
// relies on the updater to fixup what it breaks, so it is not public.
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where);
- void moveTo(MemoryUseOrDef *What, BasicBlock *BB, InsertionPlace Point);
+ void moveTo(MemoryAccess *What, BasicBlock *BB, InsertionPlace Point);
// Rename the dominator tree branch rooted at BB.
void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal,
@@ -748,8 +818,7 @@ private:
MemoryPhi *createMemoryPhi(BasicBlock *BB);
MemoryUseOrDef *createNewAccess(Instruction *);
MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace);
- void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &,
- const DenseMap<const BasicBlock *, unsigned int> &);
+ void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &);
MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool);
void renameSuccessorPhis(BasicBlock *, MemoryAccess *, bool);
void renamePass(DomTreeNode *, MemoryAccess *IncomingVal,
@@ -773,7 +842,7 @@ private:
// corresponding list is empty.
AccessMap PerBlockAccesses;
DefsMap PerBlockDefs;
- std::unique_ptr<MemoryAccess> LiveOnEntryDef;
+ std::unique_ptr<MemoryAccess, ValueDeleter> LiveOnEntryDef;
// Domination mappings
// Note that the numbering is local to a block, even though the map is
@@ -831,7 +900,7 @@ public:
Result run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Printer pass for \c MemorySSA.
+/// Printer pass for \c MemorySSA.
class MemorySSAPrinterPass : public PassInfoMixin<MemorySSAPrinterPass> {
raw_ostream &OS;
@@ -841,12 +910,12 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Verifier pass for \c MemorySSA.
+/// Verifier pass for \c MemorySSA.
struct MemorySSAVerifierPass : PassInfoMixin<MemorySSAVerifierPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Legacy analysis pass which computes \c MemorySSA.
+/// Legacy analysis pass which computes \c MemorySSA.
class MemorySSAWrapperPass : public FunctionPass {
public:
MemorySSAWrapperPass();
@@ -867,7 +936,7 @@ private:
std::unique_ptr<MemorySSA> MSSA;
};
-/// \brief This is the generic walker interface for walkers of MemorySSA.
+/// This is the generic walker interface for walkers of MemorySSA.
/// Walkers are used to be able to further disambiguate the def-use chains
/// MemorySSA gives you, or otherwise produce better info than MemorySSA gives
/// you.
@@ -885,7 +954,7 @@ public:
using MemoryAccessSet = SmallVector<MemoryAccess *, 8>;
- /// \brief Given a memory Mod/Ref/ModRef'ing instruction, calling this
+ /// Given a memory Mod/Ref/ModRef'ing instruction, calling this
/// will give you the nearest dominating MemoryAccess that Mod's the location
/// the instruction accesses (by skipping any def which AA can prove does not
/// alias the location(s) accessed by the instruction given).
@@ -917,7 +986,7 @@ public:
/// but takes a MemoryAccess instead of an Instruction.
virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) = 0;
- /// \brief Given a potentially clobbering memory access and a new location,
+ /// Given a potentially clobbering memory access and a new location,
/// calling this will give you the nearest dominating clobbering MemoryAccess
/// (by skipping non-aliasing def links).
///
@@ -931,7 +1000,7 @@ public:
virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
const MemoryLocation &) = 0;
- /// \brief Given a memory access, invalidate anything this walker knows about
+ /// Given a memory access, invalidate anything this walker knows about
/// that access.
/// This API is used by walkers that store information to perform basic cache
/// invalidation. This will be called by MemorySSA at appropriate times for
@@ -946,7 +1015,7 @@ protected:
MemorySSA *MSSA;
};
-/// \brief A MemorySSAWalker that does no alias queries, or anything else. It
+/// A MemorySSAWalker that does no alias queries, or anything else. It
/// simply returns the links as they were constructed by the builder.
class DoNothingMemorySSAWalker final : public MemorySSAWalker {
public:
@@ -962,7 +1031,7 @@ public:
using MemoryAccessPair = std::pair<MemoryAccess *, MemoryLocation>;
using ConstMemoryAccessPair = std::pair<const MemoryAccess *, MemoryLocation>;
-/// \brief Iterator base class used to implement const and non-const iterators
+/// Iterator base class used to implement const and non-const iterators
/// over the defining accesses of a MemoryAccess.
template <class T>
class memoryaccess_def_iterator_base
@@ -1035,7 +1104,7 @@ inline const_memoryaccess_def_iterator MemoryAccess::defs_end() const {
return const_memoryaccess_def_iterator();
}
-/// \brief GraphTraits for a MemoryAccess, which walks defs in the normal case,
+/// GraphTraits for a MemoryAccess, which walks defs in the normal case,
/// and uses in the inverse case.
template <> struct GraphTraits<MemoryAccess *> {
using NodeRef = MemoryAccess *;
@@ -1055,7 +1124,7 @@ template <> struct GraphTraits<Inverse<MemoryAccess *>> {
static ChildIteratorType child_end(NodeRef N) { return N->user_end(); }
};
-/// \brief Provide an iterator that walks defs, giving both the memory access,
+/// Provide an iterator that walks defs, giving both the memory access,
/// and the current pointer location, updating the pointer location as it
/// changes due to phi node translation.
///
diff --git a/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h
index b36b2f01dac6..38f08c1eebdc 100644
--- a/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h
+++ b/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// \file
-// \brief An automatic updater for MemorySSA that handles arbitrary insertion,
+// An automatic updater for MemorySSA that handles arbitrary insertion,
// deletion, and moves. It performs phi insertion where necessary, and
// automatically updates the MemorySSA IR to be correct.
// While updating loads or removing instructions is often easy enough to not
@@ -33,6 +33,7 @@
#define LLVM_ANALYSIS_MEMORYSSAUPDATER_H
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/IR/BasicBlock.h"
@@ -43,6 +44,7 @@
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
@@ -58,8 +60,13 @@ class raw_ostream;
class MemorySSAUpdater {
private:
MemorySSA *MSSA;
- SmallVector<MemoryPhi *, 8> InsertedPHIs;
+
+ /// We use WeakVH rather than a costly deletion to deal with dangling pointers.
+ /// MemoryPhis are created eagerly and sometimes get zapped shortly afterwards.
+ SmallVector<WeakVH, 16> InsertedPHIs;
+
SmallPtrSet<BasicBlock *, 8> VisitedBlocks;
+ SmallSet<AssertingVH<MemoryPhi>, 8> NonOptPhis;
public:
MemorySSAUpdater(MemorySSA *MSSA) : MSSA(MSSA) {}
@@ -86,6 +93,45 @@ public:
void moveAfter(MemoryUseOrDef *What, MemoryUseOrDef *Where);
void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB,
MemorySSA::InsertionPlace Where);
+ /// `From` block was spliced into `From` and `To`.
+ /// Move all accesses from `From` to `To` starting at instruction `Start`.
+ /// `To` is newly created BB, so empty of MemorySSA::MemoryAccesses.
+ /// Edges are already updated, so successors of `To` with MPhi nodes need to
+ /// update incoming block.
+ /// |------| |------|
+ /// | From | | From |
+ /// | | |------|
+ /// | | ||
+ /// | | => \/
+ /// | | |------| <- Start
+ /// | | | To |
+ /// |------| |------|
+ void moveAllAfterSpliceBlocks(BasicBlock *From, BasicBlock *To,
+ Instruction *Start);
+ /// `From` block was merged into `To`. All instructions were moved and
+ /// `From` is an empty block with successor edges; `From` is about to be
+ /// deleted. Move all accesses from `From` to `To` starting at instruction
+ /// `Start`. `To` may have multiple successors, `From` has a single
+ /// predecessor. `From` may have successors with MPhi nodes, replace their
+ /// incoming block with `To`.
+ /// |------| |------|
+ /// | To | | To |
+ /// |------| | |
+ /// || => | |
+ /// \/ | |
+ /// |------| | | <- Start
+ /// | From | | |
+ /// |------| |------|
+ void moveAllAfterMergeBlocks(BasicBlock *From, BasicBlock *To,
+ Instruction *Start);
+ /// BasicBlock Old had New, an empty BasicBlock, added directly before it,
+ /// and the predecessors in Preds that used to point to Old, now point to
+ /// New. If New is the only predecessor, move Old's Phi, if present, to New.
+ /// Otherwise, add a new Phi in New with appropriate incoming values, and
+ /// update the incoming values in Old's Phi node too, if present.
+ void
+ wireOldPredecessorsToNewImmediatePredecessor(BasicBlock *Old, BasicBlock *New,
+ ArrayRef<BasicBlock *> Preds);
// The below are utility functions. Other than creation of accesses to pass
// to insertDef, and removeAccess to remove accesses, you should generally
@@ -93,7 +139,7 @@ public:
// the edge cases right, and the above calls already operate in near-optimal
// time bounds.
- /// \brief Create a MemoryAccess in MemorySSA at a specified point in a block,
+ /// Create a MemoryAccess in MemorySSA at a specified point in a block,
/// with a specified clobbering definition.
///
/// Returns the new MemoryAccess.
@@ -110,7 +156,7 @@ public:
const BasicBlock *BB,
MemorySSA::InsertionPlace Point);
- /// \brief Create a MemoryAccess in MemorySSA before or after an existing
+ /// Create a MemoryAccess in MemorySSA before or after an existing
/// MemoryAccess.
///
/// Returns the new MemoryAccess.
@@ -127,7 +173,7 @@ public:
MemoryAccess *Definition,
MemoryAccess *InsertPt);
- /// \brief Remove a MemoryAccess from MemorySSA, including updating all
+ /// Remove a MemoryAccess from MemorySSA, including updating all
/// definitions and uses.
/// This should be called when a memory instruction that has a MemoryAccess
/// associated with it is erased from the program. For example, if a store or
@@ -135,18 +181,45 @@ public:
/// on the MemoryAccess for that store/load.
void removeMemoryAccess(MemoryAccess *);
+ /// Remove MemoryAccess for a given instruction, if a MemoryAccess exists.
+ /// This should be called when an instruction (load/store) is deleted from
+ /// the program.
+ void removeMemoryAccess(const Instruction *I) {
+ if (MemoryAccess *MA = MSSA->getMemoryAccess(I))
+ removeMemoryAccess(MA);
+ }
+
+ /// Remove all MemoryAcceses in a set of BasicBlocks about to be deleted.
+ /// Assumption we make here: all uses of deleted defs and phi must either
+ /// occur in blocks about to be deleted (thus will be deleted as well), or
+ /// they occur in phis that will simply lose an incoming value.
+ /// Deleted blocks still have successor info, but their predecessor edges and
+ /// Phi nodes may already be updated. Instructions in DeadBlocks should be
+ /// deleted after this call.
+ void removeBlocks(const SmallPtrSetImpl<BasicBlock *> &DeadBlocks);
+
+ /// Get handle on MemorySSA.
+ MemorySSA* getMemorySSA() const { return MSSA; }
+
private:
// Move What before Where in the MemorySSA IR.
template <class WhereType>
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, WhereType Where);
+ // Move all memory accesses from `From` to `To` starting at `Start`.
+ // Restrictions apply, see public wrappers of this method.
+ void moveAllAccesses(BasicBlock *From, BasicBlock *To, Instruction *Start);
MemoryAccess *getPreviousDef(MemoryAccess *);
MemoryAccess *getPreviousDefInBlock(MemoryAccess *);
- MemoryAccess *getPreviousDefFromEnd(BasicBlock *);
- MemoryAccess *getPreviousDefRecursive(BasicBlock *);
+ MemoryAccess *
+ getPreviousDefFromEnd(BasicBlock *,
+ DenseMap<BasicBlock *, TrackingVH<MemoryAccess>> &);
+ MemoryAccess *
+ getPreviousDefRecursive(BasicBlock *,
+ DenseMap<BasicBlock *, TrackingVH<MemoryAccess>> &);
MemoryAccess *recursePhi(MemoryAccess *Phi);
template <class RangeType>
MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands);
- void fixupDefs(const SmallVectorImpl<MemoryAccess *> &);
+ void fixupDefs(const SmallVectorImpl<WeakVH> &);
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Analysis/MustExecute.h b/contrib/llvm/include/llvm/Analysis/MustExecute.h
new file mode 100644
index 000000000000..8daf156567cd
--- /dev/null
+++ b/contrib/llvm/include/llvm/Analysis/MustExecute.h
@@ -0,0 +1,64 @@
+//===- MustExecute.h - Is an instruction known to execute--------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// Contains a collection of routines for determining if a given instruction is
+/// guaranteed to execute if a given point in control flow is reached. The most
+/// common example is an instruction within a loop being provably executed if we
+/// branch to the header of it's containing loop.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_MUSTEXECUTE_H
+#define LLVM_ANALYSIS_MUSTEXECUTE_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Analysis/EHPersonalities.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instruction.h"
+
+namespace llvm {
+
+class Instruction;
+class DominatorTree;
+class Loop;
+
+/// Captures loop safety information.
+/// It keep information for loop & its header may throw exception or otherwise
+/// exit abnormaly on any iteration of the loop which might actually execute
+/// at runtime. The primary way to consume this infromation is via
+/// isGuaranteedToExecute below, but some callers bailout or fallback to
+/// alternate reasoning if a loop contains any implicit control flow.
+struct LoopSafetyInfo {
+ bool MayThrow = false; // The current loop contains an instruction which
+ // may throw.
+ bool HeaderMayThrow = false; // Same as previous, but specific to loop header
+ // Used to update funclet bundle operands.
+ DenseMap<BasicBlock *, ColorVector> BlockColors;
+
+ LoopSafetyInfo() = default;
+};
+
+/// Computes safety information for a loop checks loop body & header for
+/// the possibility of may throw exception, it takes LoopSafetyInfo and loop as
+/// argument. Updates safety information in LoopSafetyInfo argument.
+/// Note: This is defined to clear and reinitialize an already initialized
+/// LoopSafetyInfo. Some callers rely on this fact.
+void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *);
+
+/// Returns true if the instruction in a loop is guaranteed to execute at least
+/// once (under the assumption that the loop is entered).
+bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT,
+ const Loop *CurLoop,
+ const LoopSafetyInfo *SafetyInfo);
+
+}
+
+#endif
diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h
index db524ff64ecd..559c77c30811 100644
--- a/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h
+++ b/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h
@@ -29,7 +29,7 @@
namespace llvm {
namespace objcarc {
-/// \brief This is a simple alias analysis implementation that uses knowledge
+/// This is a simple alias analysis implementation that uses knowledge
/// of ARC constructs to answer queries.
///
/// TODO: This class could be generalized to know about other ObjC-specific
diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h b/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h
index e80412a30564..07beb0bb60a3 100644
--- a/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h
+++ b/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h
@@ -34,6 +34,7 @@
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
namespace llvm {
@@ -43,10 +44,10 @@ class raw_ostream;
namespace llvm {
namespace objcarc {
-/// \brief A handy option to enable/disable all ARC Optimizations.
+/// A handy option to enable/disable all ARC Optimizations.
extern bool EnableARCOpts;
-/// \brief Test if the given module looks interesting to run ARC optimization
+/// Test if the given module looks interesting to run ARC optimization
/// on.
inline bool ModuleHasARC(const Module &M) {
return
@@ -71,7 +72,7 @@ inline bool ModuleHasARC(const Module &M) {
M.getNamedValue("clang.arc.use");
}
-/// \brief This is a wrapper around getUnderlyingObject which also knows how to
+/// This is a wrapper around getUnderlyingObject which also knows how to
/// look through objc_retain and objc_autorelease calls, which we know to return
/// their argument verbatim.
inline const Value *GetUnderlyingObjCPtr(const Value *V,
@@ -86,6 +87,18 @@ inline const Value *GetUnderlyingObjCPtr(const Value *V,
return V;
}
+/// A wrapper for GetUnderlyingObjCPtr used for results memoization.
+inline const Value *
+GetUnderlyingObjCPtrCached(const Value *V, const DataLayout &DL,
+ DenseMap<const Value *, WeakTrackingVH> &Cache) {
+ if (auto InCache = Cache.lookup(V))
+ return InCache;
+
+ const Value *Computed = GetUnderlyingObjCPtr(V, DL);
+ Cache[V] = const_cast<Value *>(Computed);
+ return Computed;
+}
+
/// The RCIdentity root of a value \p V is a dominating value U for which
/// retaining or releasing U is equivalent to retaining or releasing V. In other
/// words, ARC operations on \p V are equivalent to ARC operations on \p U.
@@ -119,7 +132,7 @@ inline Value *GetRCIdentityRoot(Value *V) {
return const_cast<Value *>(GetRCIdentityRoot((const Value *)V));
}
-/// \brief Assuming the given instruction is one of the special calls such as
+/// Assuming the given instruction is one of the special calls such as
/// objc_retain or objc_release, return the RCIdentity root of the argument of
/// the call.
inline Value *GetArgRCIdentityRoot(Value *Inst) {
@@ -136,7 +149,7 @@ inline bool IsNoopInstruction(const Instruction *I) {
cast<GetElementPtrInst>(I)->hasAllZeroIndices());
}
-/// \brief Test whether the given value is possible a retainable object pointer.
+/// Test whether the given value is possible a retainable object pointer.
inline bool IsPotentialRetainableObjPtr(const Value *Op) {
// Pointers to static or stack storage are not valid retainable object
// pointers.
@@ -181,7 +194,7 @@ inline bool IsPotentialRetainableObjPtr(const Value *Op,
return true;
}
-/// \brief Helper for GetARCInstKind. Determines what kind of construct CS
+/// Helper for GetARCInstKind. Determines what kind of construct CS
/// is.
inline ARCInstKind GetCallSiteClass(ImmutableCallSite CS) {
for (ImmutableCallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
@@ -192,7 +205,7 @@ inline ARCInstKind GetCallSiteClass(ImmutableCallSite CS) {
return CS.onlyReadsMemory() ? ARCInstKind::None : ARCInstKind::Call;
}
-/// \brief Return true if this value refers to a distinct and identifiable
+/// Return true if this value refers to a distinct and identifiable
/// object.
///
/// This is similar to AliasAnalysis's isIdentifiedObject, except that it uses
diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h b/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h
index 02ff03578238..0b92d8b48356 100644
--- a/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h
+++ b/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h
@@ -18,7 +18,7 @@ namespace objcarc {
/// \enum ARCInstKind
///
-/// \brief Equivalence classes of instructions in the ARC Model.
+/// Equivalence classes of instructions in the ARC Model.
///
/// Since we do not have "instructions" to represent ARC concepts in LLVM IR,
/// we instead operate on equivalence classes of instructions.
@@ -57,32 +57,32 @@ enum class ARCInstKind {
raw_ostream &operator<<(raw_ostream &OS, const ARCInstKind Class);
-/// \brief Test if the given class is a kind of user.
+/// Test if the given class is a kind of user.
bool IsUser(ARCInstKind Class);
-/// \brief Test if the given class is objc_retain or equivalent.
+/// Test if the given class is objc_retain or equivalent.
bool IsRetain(ARCInstKind Class);
-/// \brief Test if the given class is objc_autorelease or equivalent.
+/// Test if the given class is objc_autorelease or equivalent.
bool IsAutorelease(ARCInstKind Class);
-/// \brief Test if the given class represents instructions which return their
+/// Test if the given class represents instructions which return their
/// argument verbatim.
bool IsForwarding(ARCInstKind Class);
-/// \brief Test if the given class represents instructions which do nothing if
+/// Test if the given class represents instructions which do nothing if
/// passed a null pointer.
bool IsNoopOnNull(ARCInstKind Class);
-/// \brief Test if the given class represents instructions which are always safe
+/// Test if the given class represents instructions which are always safe
/// to mark with the "tail" keyword.
bool IsAlwaysTail(ARCInstKind Class);
-/// \brief Test if the given class represents instructions which are never safe
+/// Test if the given class represents instructions which are never safe
/// to mark with the "tail" keyword.
bool IsNeverTail(ARCInstKind Class);
-/// \brief Test if the given class represents instructions which are always safe
+/// Test if the given class represents instructions which are always safe
/// to mark with the nounwind attribute.
bool IsNoThrow(ARCInstKind Class);
@@ -90,11 +90,11 @@ bool IsNoThrow(ARCInstKind Class);
/// autoreleasepool pop.
bool CanInterruptRV(ARCInstKind Class);
-/// \brief Determine if F is one of the special known Functions. If it isn't,
+/// Determine if F is one of the special known Functions. If it isn't,
/// return ARCInstKind::CallOrUser.
ARCInstKind GetFunctionClass(const Function *F);
-/// \brief Determine which objc runtime call instruction class V belongs to.
+/// Determine which objc runtime call instruction class V belongs to.
///
/// This is similar to GetARCInstKind except that it only detects objc
/// runtime calls. This allows it to be faster.
diff --git a/contrib/llvm/include/llvm/Analysis/ObjectUtils.h b/contrib/llvm/include/llvm/Analysis/ObjectUtils.h
deleted file mode 100644
index 2ad3b1717009..000000000000
--- a/contrib/llvm/include/llvm/Analysis/ObjectUtils.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- Analysis/ObjectUtils.h - analysis utils for object files -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_OBJECT_UTILS_H
-#define LLVM_ANALYSIS_OBJECT_UTILS_H
-
-#include "llvm/IR/GlobalVariable.h"
-
-namespace llvm {
-
-/// True if GV can be left out of the object symbol table. This is the case
-/// for linkonce_odr values whose address is not significant. While legal, it is
-/// not normally profitable to omit them from the .o symbol table. Using this
-/// analysis makes sense when the information can be passed down to the linker
-/// or we are in LTO.
-inline bool canBeOmittedFromSymbolTable(const GlobalValue *GV) {
- if (!GV->hasLinkOnceODRLinkage())
- return false;
-
- // We assume that anyone who sets global unnamed_addr on a non-constant knows
- // what they're doing.
- if (GV->hasGlobalUnnamedAddr())
- return true;
-
- // If it is a non constant variable, it needs to be uniqued across shared
- // objects.
- if (auto *Var = dyn_cast<GlobalVariable>(GV))
- if (!Var->isConstant())
- return false;
-
- return GV->hasAtLeastLocalUnnamedAddr();
-}
-
-}
-
-#endif
diff --git a/contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h b/contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
index 26f32acdcda5..fa838696e2f8 100644
--- a/contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
+++ b/contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
@@ -40,7 +40,7 @@ public:
OptimizationRemarkEmitter(const Function *F, BlockFrequencyInfo *BFI)
: F(F), BFI(BFI) {}
- /// \brief This variant can be used to generate ORE on demand (without the
+ /// This variant can be used to generate ORE on demand (without the
/// analysis pass).
///
/// Note that this ctor has a very different cost depending on whether
@@ -66,11 +66,11 @@ public:
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv);
- /// \brief Output the remark via the diagnostic handler and to the
+ /// Output the remark via the diagnostic handler and to the
/// optimization record file.
void emit(DiagnosticInfoOptimizationBase &OptDiag);
- /// \brief Take a lambda that returns a remark which will be emitted. Second
+ /// Take a lambda that returns a remark which will be emitted. Second
/// argument is only used to restrict this to functions.
template <typename T>
void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
@@ -85,7 +85,7 @@ public:
}
}
- /// \brief Whether we allow for extra compile-time budget to perform more
+ /// Whether we allow for extra compile-time budget to perform more
/// analysis to produce fewer false positives.
///
/// This is useful when reporting missed optimizations. In this case we can
@@ -112,7 +112,7 @@ private:
/// Similar but use value from \p OptDiag and update hotness there.
void computeHotness(DiagnosticInfoIROptimization &OptDiag);
- /// \brief Only allow verbose messages if we know we're filtering by hotness
+ /// Only allow verbose messages if we know we're filtering by hotness
/// (BFI is only set in this case).
bool shouldEmitVerbose() { return BFI != nullptr; }
@@ -120,7 +120,7 @@ private:
void operator=(const OptimizationRemarkEmitter &) = delete;
};
-/// \brief Add a small namespace to avoid name clashes with the classes used in
+/// Add a small namespace to avoid name clashes with the classes used in
/// the streaming interface. We want these to be short for better
/// write/readability.
namespace ore {
@@ -158,10 +158,10 @@ class OptimizationRemarkEmitterAnalysis
static AnalysisKey Key;
public:
- /// \brief Provide the result typedef for this analysis pass.
+ /// Provide the result typedef for this analysis pass.
typedef OptimizationRemarkEmitter Result;
- /// \brief Run the analysis pass over a function and produce BFI.
+ /// Run the analysis pass over a function and produce BFI.
Result run(Function &F, FunctionAnalysisManager &AM);
};
}
diff --git a/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h b/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h
index 2e716af1f60d..0776aa626005 100644
--- a/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h
+++ b/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h
@@ -33,28 +33,28 @@ class BasicBlock;
class OrderedBasicBlock {
private:
- /// \brief Map a instruction to its position in a BasicBlock.
+ /// Map a instruction to its position in a BasicBlock.
SmallDenseMap<const Instruction *, unsigned, 32> NumberedInsts;
- /// \brief Keep track of last instruction inserted into \p NumberedInsts.
+ /// Keep track of last instruction inserted into \p NumberedInsts.
/// It speeds up queries for uncached instructions by providing a start point
/// for new queries in OrderedBasicBlock::comesBefore.
BasicBlock::const_iterator LastInstFound;
- /// \brief The position/number to tag the next instruction to be found.
+ /// The position/number to tag the next instruction to be found.
unsigned NextInstPos;
- /// \brief The source BasicBlock to map.
+ /// The source BasicBlock to map.
const BasicBlock *BB;
- /// \brief Given no cached results, find if \p A comes before \p B in \p BB.
+ /// Given no cached results, find if \p A comes before \p B in \p BB.
/// Cache and number out instruction while walking \p BB.
bool comesBefore(const Instruction *A, const Instruction *B);
public:
OrderedBasicBlock(const BasicBlock *BasicB);
- /// \brief Find out whether \p A dominates \p B, meaning whether \p A
+ /// Find out whether \p A dominates \p B, meaning whether \p A
/// comes before \p B in \p BB. This is a simplification that considers
/// cached instruction positions and ignores other basic blocks, being
/// only relevant to compare relative instructions positions inside \p BB.
diff --git a/contrib/llvm/include/llvm/Analysis/PHITransAddr.h b/contrib/llvm/include/llvm/Analysis/PHITransAddr.h
index f0f34f3a51f5..0a335b6be6c7 100644
--- a/contrib/llvm/include/llvm/Analysis/PHITransAddr.h
+++ b/contrib/llvm/include/llvm/Analysis/PHITransAddr.h
@@ -43,7 +43,7 @@ class PHITransAddr {
/// TLI - The target library info if known, otherwise null.
const TargetLibraryInfo *TLI;
- /// A cache of @llvm.assume calls used by SimplifyInstruction.
+ /// A cache of \@llvm.assume calls used by SimplifyInstruction.
AssumptionCache *AC;
/// InstInputs - The inputs for our symbolic address.
diff --git a/contrib/llvm/include/llvm/Analysis/Passes.h b/contrib/llvm/include/llvm/Analysis/Passes.h
index 6d8f14fa32f9..09b28a0b0884 100644
--- a/contrib/llvm/include/llvm/Analysis/Passes.h
+++ b/contrib/llvm/include/llvm/Analysis/Passes.h
@@ -96,6 +96,14 @@ namespace llvm {
//
FunctionPass *createMemDerefPrinter();
+ //===--------------------------------------------------------------------===//
+ //
+ // createMustExecutePrinter - This pass collects information about which
+ // instructions within a loop are guaranteed to execute if the loop header is
+ // entered and prints it with -analyze.
+ //
+ FunctionPass *createMustExecutePrinter();
+
}
#endif
diff --git a/contrib/llvm/include/llvm/Analysis/PhiValues.h b/contrib/llvm/include/llvm/Analysis/PhiValues.h
new file mode 100644
index 000000000000..6607b329c04f
--- /dev/null
+++ b/contrib/llvm/include/llvm/Analysis/PhiValues.h
@@ -0,0 +1,143 @@
+//===- PhiValues.h - Phi Value Analysis -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PhiValues class, and associated passes, which can be
+// used to find the underlying values of the phis in a function, i.e. the
+// non-phi values that can be found by traversing the phi graph.
+//
+// This information is computed lazily and cached. If new phis are added to the
+// function they are handled correctly, but if an existing phi has its operands
+// modified PhiValues has to be notified by calling invalidateValue.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_PHIVALUES_H
+#define LLVM_ANALYSIS_PHIVALUES_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Pass.h"
+
+namespace llvm {
+
+class Use;
+class Value;
+class PHINode;
+class Function;
+
+/// Class for calculating and caching the underlying values of phis in a
+/// function.
+///
+/// Initially the PhiValues is empty, and gets incrementally populated whenever
+/// it is queried.
+class PhiValues {
+public:
+ using ValueSet = SmallPtrSet<Value *, 4>;
+
+ /// Construct an empty PhiValues.
+ PhiValues(const Function &F) : F(F) {}
+
+ /// Get the underlying values of a phi.
+ ///
+ /// This returns the cached value if PN has previously been processed,
+ /// otherwise it processes it first.
+ const ValueSet &getValuesForPhi(const PHINode *PN);
+
+ /// Notify PhiValues that the cached information using V is no longer valid
+ ///
+ /// Whenever a phi has its operands modified the cached values for that phi
+ /// (and the phis that use that phi) become invalid. A user of PhiValues has
+ /// to notify it of this by calling invalidateValue on either the operand or
+ /// the phi, which will then clear the relevant cached information.
+ void invalidateValue(const Value *V);
+
+ /// Free the memory used by this class.
+ void releaseMemory();
+
+ /// Print out the values currently in the cache.
+ void print(raw_ostream &OS) const;
+
+ /// Handle invalidation events in the new pass manager.
+ bool invalidate(Function &, const PreservedAnalyses &,
+ FunctionAnalysisManager::Invalidator &);
+
+private:
+ using PhiSet = SmallPtrSet<const PHINode *, 4>;
+ using ConstValueSet = SmallPtrSet<const Value *, 4>;
+
+ /// The next depth number to be used by processPhi.
+ unsigned int NextDepthNumber = 1;
+
+ /// Depth numbers of phis. Phis with the same depth number are part of the
+ /// same strongly connected component.
+ DenseMap<const PHINode *, unsigned int> DepthMap;
+
+ /// Non-phi values reachable from each component.
+ DenseMap<unsigned int, ValueSet> NonPhiReachableMap;
+
+ /// All values reachable from each component.
+ DenseMap<unsigned int, ConstValueSet> ReachableMap;
+
+ /// The function that the PhiValues is for.
+ const Function &F;
+
+ /// Process a phi so that its entries in the depth and reachable maps are
+ /// fully populated.
+ void processPhi(const PHINode *PN, SmallVector<const PHINode *, 8> &Stack);
+};
+
+/// The analysis pass which yields a PhiValues
+///
+/// The analysis does nothing by itself, and just returns an empty PhiValues
+/// which will get filled in as it's used.
+class PhiValuesAnalysis : public AnalysisInfoMixin<PhiValuesAnalysis> {
+ friend AnalysisInfoMixin<PhiValuesAnalysis>;
+ static AnalysisKey Key;
+
+public:
+ using Result = PhiValues;
+ PhiValues run(Function &F, FunctionAnalysisManager &);
+};
+
+/// A pass for printing the PhiValues for a function.
+///
+/// This pass doesn't print whatever information the PhiValues happens to hold,
+/// but instead first uses the PhiValues to analyze all the phis in the function
+/// so the complete information is printed.
+class PhiValuesPrinterPass : public PassInfoMixin<PhiValuesPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit PhiValuesPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+/// Wrapper pass for the legacy pass manager
+class PhiValuesWrapperPass : public FunctionPass {
+ std::unique_ptr<PhiValues> Result;
+
+public:
+ static char ID;
+ PhiValuesWrapperPass();
+
+ PhiValues &getResult() { return *Result; }
+ const PhiValues &getResult() const { return *Result; }
+
+ bool runOnFunction(Function &F) override;
+ void releaseMemory() override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/Analysis/PostDominators.h b/contrib/llvm/include/llvm/Analysis/PostDominators.h
index 381e65539c4e..f2dc8d135d71 100644
--- a/contrib/llvm/include/llvm/Analysis/PostDominators.h
+++ b/contrib/llvm/include/llvm/Analysis/PostDominators.h
@@ -26,15 +26,18 @@ class raw_ostream;
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to
/// compute the post-dominator tree.
-struct PostDominatorTree : public PostDomTreeBase<BasicBlock> {
+class PostDominatorTree : public PostDomTreeBase<BasicBlock> {
+public:
using Base = PostDomTreeBase<BasicBlock>;
+ PostDominatorTree() = default;
+ explicit PostDominatorTree(Function &F) { recalculate(F); }
/// Handle invalidation explicitly.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
};
-/// \brief Analysis pass which computes a \c PostDominatorTree.
+/// Analysis pass which computes a \c PostDominatorTree.
class PostDominatorTreeAnalysis
: public AnalysisInfoMixin<PostDominatorTreeAnalysis> {
friend AnalysisInfoMixin<PostDominatorTreeAnalysis>;
@@ -42,15 +45,15 @@ class PostDominatorTreeAnalysis
static AnalysisKey Key;
public:
- /// \brief Provide the result type for this analysis pass.
+ /// Provide the result type for this analysis pass.
using Result = PostDominatorTree;
- /// \brief Run the analysis pass over a function and produce a post dominator
+ /// Run the analysis pass over a function and produce a post dominator
/// tree.
PostDominatorTree run(Function &F, FunctionAnalysisManager &);
};
-/// \brief Printer pass for the \c PostDominatorTree.
+/// Printer pass for the \c PostDominatorTree.
class PostDominatorTreePrinterPass
: public PassInfoMixin<PostDominatorTreePrinterPass> {
raw_ostream &OS;
@@ -75,6 +78,8 @@ struct PostDominatorTreeWrapperPass : public FunctionPass {
bool runOnFunction(Function &F) override;
+ void verifyAnalysis() const override;
+
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
diff --git a/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h b/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h
index 293033458429..58b67e74ba51 100644
--- a/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h
@@ -31,7 +31,7 @@ class BasicBlock;
class BlockFrequencyInfo;
class CallSite;
class ProfileSummary;
-/// \brief Analysis providing profile information.
+/// Analysis providing profile information.
///
/// This is an immutable analysis pass that provides ability to query global
/// (program-level) profile information. The main APIs are isHotCount and
@@ -59,16 +59,16 @@ public:
ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
: M(Arg.M), Summary(std::move(Arg.Summary)) {}
- /// \brief Returns true if profile summary is available.
+ /// Returns true if profile summary is available.
bool hasProfileSummary() { return computeSummary(); }
- /// \brief Returns true if module \c M has sample profile.
+ /// Returns true if module \c M has sample profile.
bool hasSampleProfile() {
return hasProfileSummary() &&
Summary->getKind() == ProfileSummary::PSK_Sample;
}
- /// \brief Returns true if module \c M has instrumentation profile.
+ /// Returns true if module \c M has instrumentation profile.
bool hasInstrumentationProfile() {
return hasProfileSummary() &&
Summary->getKind() == ProfileSummary::PSK_Instr;
@@ -90,31 +90,37 @@ public:
BlockFrequencyInfo *BFI);
/// Returns true if the working set size of the code is considered huge.
bool hasHugeWorkingSetSize();
- /// \brief Returns true if \p F has hot function entry.
+ /// Returns true if \p F has hot function entry.
bool isFunctionEntryHot(const Function *F);
/// Returns true if \p F contains hot code.
bool isFunctionHotInCallGraph(const Function *F, BlockFrequencyInfo &BFI);
- /// \brief Returns true if \p F has cold function entry.
+ /// Returns true if \p F has cold function entry.
bool isFunctionEntryCold(const Function *F);
/// Returns true if \p F contains only cold code.
bool isFunctionColdInCallGraph(const Function *F, BlockFrequencyInfo &BFI);
- /// \brief Returns true if \p F is a hot function.
+ /// Returns true if \p F is a hot function.
bool isHotCount(uint64_t C);
- /// \brief Returns true if count \p C is considered cold.
+ /// Returns true if count \p C is considered cold.
bool isColdCount(uint64_t C);
- /// \brief Returns true if BasicBlock \p B is considered hot.
+ /// Returns true if BasicBlock \p B is considered hot.
bool isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
- /// \brief Returns true if BasicBlock \p B is considered cold.
+ /// Returns true if BasicBlock \p B is considered cold.
bool isColdBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
- /// \brief Returns true if CallSite \p CS is considered hot.
+ /// Returns true if CallSite \p CS is considered hot.
bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
- /// \brief Returns true if Callsite \p CS is considered cold.
+ /// Returns true if Callsite \p CS is considered cold.
bool isColdCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
- /// \brief Returns HotCountThreshold if set.
+ /// Returns HotCountThreshold if set. Recompute HotCountThreshold
+ /// if not set.
+ uint64_t getOrCompHotCountThreshold();
+ /// Returns ColdCountThreshold if set. Recompute HotCountThreshold
+ /// if not set.
+ uint64_t getOrCompColdCountThreshold();
+ /// Returns HotCountThreshold if set.
uint64_t getHotCountThreshold() {
return HotCountThreshold ? HotCountThreshold.getValue() : 0;
}
- /// \brief Returns ColdCountThreshold if set.
+ /// Returns ColdCountThreshold if set.
uint64_t getColdCountThreshold() {
return ColdCountThreshold ? ColdCountThreshold.getValue() : 0;
}
@@ -152,7 +158,7 @@ private:
static AnalysisKey Key;
};
-/// \brief Printer pass that uses \c ProfileSummaryAnalysis.
+/// Printer pass that uses \c ProfileSummaryAnalysis.
class ProfileSummaryPrinterPass
: public PassInfoMixin<ProfileSummaryPrinterPass> {
raw_ostream &OS;
diff --git a/contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h b/contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h
index 9f156a1a6029..b34b25c75040 100644
--- a/contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h
+++ b/contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h
@@ -47,7 +47,7 @@ namespace llvm {
namespace detail {
-/// \brief Implementation of non-dependent functionality for \c PtrUseVisitor.
+/// Implementation of non-dependent functionality for \c PtrUseVisitor.
///
/// See \c PtrUseVisitor for the public interface and detailed comments about
/// usage. This class is just a helper base class which is not templated and
@@ -55,7 +55,7 @@ namespace detail {
/// PtrUseVisitor.
class PtrUseVisitorBase {
public:
- /// \brief This class provides information about the result of a visit.
+ /// This class provides information about the result of a visit.
///
/// After walking all the users (recursively) of a pointer, the basic
/// infrastructure records some commonly useful information such as escape
@@ -64,7 +64,7 @@ public:
public:
PtrInfo() : AbortedInfo(nullptr, false), EscapedInfo(nullptr, false) {}
- /// \brief Reset the pointer info, clearing all state.
+ /// Reset the pointer info, clearing all state.
void reset() {
AbortedInfo.setPointer(nullptr);
AbortedInfo.setInt(false);
@@ -72,37 +72,37 @@ public:
EscapedInfo.setInt(false);
}
- /// \brief Did we abort the visit early?
+ /// Did we abort the visit early?
bool isAborted() const { return AbortedInfo.getInt(); }
- /// \brief Is the pointer escaped at some point?
+ /// Is the pointer escaped at some point?
bool isEscaped() const { return EscapedInfo.getInt(); }
- /// \brief Get the instruction causing the visit to abort.
+ /// Get the instruction causing the visit to abort.
/// \returns a pointer to the instruction causing the abort if one is
/// available; otherwise returns null.
Instruction *getAbortingInst() const { return AbortedInfo.getPointer(); }
- /// \brief Get the instruction causing the pointer to escape.
+ /// Get the instruction causing the pointer to escape.
/// \returns a pointer to the instruction which escapes the pointer if one
/// is available; otherwise returns null.
Instruction *getEscapingInst() const { return EscapedInfo.getPointer(); }
- /// \brief Mark the visit as aborted. Intended for use in a void return.
+ /// Mark the visit as aborted. Intended for use in a void return.
/// \param I The instruction which caused the visit to abort, if available.
void setAborted(Instruction *I = nullptr) {
AbortedInfo.setInt(true);
AbortedInfo.setPointer(I);
}
- /// \brief Mark the pointer as escaped. Intended for use in a void return.
+ /// Mark the pointer as escaped. Intended for use in a void return.
/// \param I The instruction which escapes the pointer, if available.
void setEscaped(Instruction *I = nullptr) {
EscapedInfo.setInt(true);
EscapedInfo.setPointer(I);
}
- /// \brief Mark the pointer as escaped, and the visit as aborted. Intended
+ /// Mark the pointer as escaped, and the visit as aborted. Intended
/// for use in a void return.
/// \param I The instruction which both escapes the pointer and aborts the
/// visit, if available.
@@ -121,10 +121,10 @@ protected:
/// \name Visitation infrastructure
/// @{
- /// \brief The info collected about the pointer being visited thus far.
+ /// The info collected about the pointer being visited thus far.
PtrInfo PI;
- /// \brief A struct of the data needed to visit a particular use.
+ /// A struct of the data needed to visit a particular use.
///
/// This is used to maintain a worklist fo to-visit uses. This is used to
/// make the visit be iterative rather than recursive.
@@ -135,10 +135,10 @@ protected:
APInt Offset;
};
- /// \brief The worklist of to-visit uses.
+ /// The worklist of to-visit uses.
SmallVector<UseToVisit, 8> Worklist;
- /// \brief A set of visited uses to break cycles in unreachable code.
+ /// A set of visited uses to break cycles in unreachable code.
SmallPtrSet<Use *, 8> VisitedUses;
/// @}
@@ -147,14 +147,14 @@ protected:
/// This state is reset for each instruction visited.
/// @{
- /// \brief The use currently being visited.
+ /// The use currently being visited.
Use *U;
- /// \brief True if we have a known constant offset for the use currently
+ /// True if we have a known constant offset for the use currently
/// being visited.
bool IsOffsetKnown;
- /// \brief The constant offset of the use if that is known.
+ /// The constant offset of the use if that is known.
APInt Offset;
/// @}
@@ -163,13 +163,13 @@ protected:
/// class, we can't create instances directly of this class.
PtrUseVisitorBase(const DataLayout &DL) : DL(DL) {}
- /// \brief Enqueue the users of this instruction in the visit worklist.
+ /// Enqueue the users of this instruction in the visit worklist.
///
/// This will visit the users with the same offset of the current visit
/// (including an unknown offset if that is the current state).
void enqueueUsers(Instruction &I);
- /// \brief Walk the operands of a GEP and adjust the offset as appropriate.
+ /// Walk the operands of a GEP and adjust the offset as appropriate.
///
/// This routine does the heavy lifting of the pointer walk by computing
/// offsets and looking through GEPs.
@@ -178,7 +178,7 @@ protected:
} // end namespace detail
-/// \brief A base class for visitors over the uses of a pointer value.
+/// A base class for visitors over the uses of a pointer value.
///
/// Once constructed, a user can call \c visit on a pointer value, and this
/// will walk its uses and visit each instruction using an InstVisitor. It also
@@ -216,7 +216,7 @@ public:
"Must pass the derived type to this template!");
}
- /// \brief Recursively visit the uses of the given pointer.
+ /// Recursively visit the uses of the given pointer.
/// \returns An info struct about the pointer. See \c PtrInfo for details.
PtrInfo visitPtr(Instruction &I) {
// This must be a pointer type. Get an integer type suitable to hold
@@ -275,7 +275,7 @@ protected:
enqueueUsers(GEPI);
}
- // No-op intrinsics which we know don't escape the pointer to to logic in
+ // No-op intrinsics which we know don't escape the pointer to logic in
// some other function.
void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) {}
void visitMemIntrinsic(MemIntrinsic &I) {}
diff --git a/contrib/llvm/include/llvm/Analysis/RegionInfo.h b/contrib/llvm/include/llvm/Analysis/RegionInfo.h
index 719622359949..27f6cc197927 100644
--- a/contrib/llvm/include/llvm/Analysis/RegionInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/RegionInfo.h
@@ -42,6 +42,7 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
@@ -62,7 +63,7 @@ class DominanceFrontier;
class DominatorTree;
class Loop;
class LoopInfo;
-struct PostDominatorTree;
+class PostDominatorTree;
class Region;
template <class RegionTr> class RegionBase;
class RegionInfo;
@@ -102,7 +103,7 @@ struct RegionTraits<Function> {
}
};
-/// @brief Marker class to iterate over the elements of a Region in flat mode.
+/// Marker class to iterate over the elements of a Region in flat mode.
///
/// The class is used to either iterate in Flat mode or by not using it to not
/// iterate in Flat mode. During a Flat mode iteration all Regions are entered
@@ -112,7 +113,7 @@ struct RegionTraits<Function> {
template <class GraphType>
class FlatIt {};
-/// @brief A RegionNode represents a subregion or a BasicBlock that is part of a
+/// A RegionNode represents a subregion or a BasicBlock that is part of a
/// Region.
template <class Tr>
class RegionNodeBase {
@@ -135,12 +136,12 @@ private:
/// RegionNode.
PointerIntPair<BlockT *, 1, bool> entry;
- /// @brief The parent Region of this RegionNode.
+ /// The parent Region of this RegionNode.
/// @see getParent()
RegionT *parent;
protected:
- /// @brief Create a RegionNode.
+ /// Create a RegionNode.
///
/// @param Parent The parent of this RegionNode.
/// @param Entry The entry BasicBlock of the RegionNode. If this
@@ -156,7 +157,7 @@ public:
RegionNodeBase(const RegionNodeBase &) = delete;
RegionNodeBase &operator=(const RegionNodeBase &) = delete;
- /// @brief Get the parent Region of this RegionNode.
+ /// Get the parent Region of this RegionNode.
///
/// The parent Region is the Region this RegionNode belongs to. If for
/// example a BasicBlock is element of two Regions, there exist two
@@ -166,7 +167,7 @@ public:
/// @return Get the parent Region of this RegionNode.
inline RegionT *getParent() const { return parent; }
- /// @brief Get the entry BasicBlock of this RegionNode.
+ /// Get the entry BasicBlock of this RegionNode.
///
/// If this RegionNode represents a BasicBlock this is just the BasicBlock
/// itself, otherwise we return the entry BasicBlock of the Subregion
@@ -174,7 +175,7 @@ public:
/// @return The entry BasicBlock of this RegionNode.
inline BlockT *getEntry() const { return entry.getPointer(); }
- /// @brief Get the content of this RegionNode.
+ /// Get the content of this RegionNode.
///
/// This can be either a BasicBlock or a subregion. Before calling getNodeAs()
/// check the type of the content with the isSubRegion() function call.
@@ -182,7 +183,7 @@ public:
/// @return The content of this RegionNode.
template <class T> inline T *getNodeAs() const;
- /// @brief Is this RegionNode a subregion?
+ /// Is this RegionNode a subregion?
///
/// @return True if it contains a subregion. False if it contains a
/// BasicBlock.
@@ -190,7 +191,7 @@ public:
};
//===----------------------------------------------------------------------===//
-/// @brief A single entry single exit Region.
+/// A single entry single exit Region.
///
/// A Region is a connected subgraph of a control flow graph that has exactly
/// two connections to the remaining graph. It can be used to analyze or
@@ -301,7 +302,7 @@ class RegionBase : public RegionNodeBase<Tr> {
void verifyRegionNest() const;
public:
- /// @brief Create a new region.
+ /// Create a new region.
///
/// @param Entry The entry basic block of the region.
/// @param Exit The exit basic block of the region.
@@ -318,25 +319,25 @@ public:
/// Delete the Region and all its subregions.
~RegionBase();
- /// @brief Get the entry BasicBlock of the Region.
+ /// Get the entry BasicBlock of the Region.
/// @return The entry BasicBlock of the region.
BlockT *getEntry() const {
return RegionNodeBase<Tr>::getEntry();
}
- /// @brief Replace the entry basic block of the region with the new basic
+ /// Replace the entry basic block of the region with the new basic
/// block.
///
/// @param BB The new entry basic block of the region.
void replaceEntry(BlockT *BB);
- /// @brief Replace the exit basic block of the region with the new basic
+ /// Replace the exit basic block of the region with the new basic
/// block.
///
/// @param BB The new exit basic block of the region.
void replaceExit(BlockT *BB);
- /// @brief Recursively replace the entry basic block of the region.
+ /// Recursively replace the entry basic block of the region.
///
/// This function replaces the entry basic block with a new basic block. It
/// also updates all child regions that have the same entry basic block as
@@ -345,7 +346,7 @@ public:
/// @param NewEntry The new entry basic block.
void replaceEntryRecursive(BlockT *NewEntry);
- /// @brief Recursively replace the exit basic block of the region.
+ /// Recursively replace the exit basic block of the region.
///
/// This function replaces the exit basic block with a new basic block. It
/// also updates all child regions that have the same exit basic block as
@@ -354,38 +355,38 @@ public:
/// @param NewExit The new exit basic block.
void replaceExitRecursive(BlockT *NewExit);
- /// @brief Get the exit BasicBlock of the Region.
+ /// Get the exit BasicBlock of the Region.
/// @return The exit BasicBlock of the Region, NULL if this is the TopLevel
/// Region.
BlockT *getExit() const { return exit; }
- /// @brief Get the parent of the Region.
+ /// Get the parent of the Region.
/// @return The parent of the Region or NULL if this is a top level
/// Region.
RegionT *getParent() const {
return RegionNodeBase<Tr>::getParent();
}
- /// @brief Get the RegionNode representing the current Region.
+ /// Get the RegionNode representing the current Region.
/// @return The RegionNode representing the current Region.
RegionNodeT *getNode() const {
return const_cast<RegionNodeT *>(
reinterpret_cast<const RegionNodeT *>(this));
}
- /// @brief Get the nesting level of this Region.
+ /// Get the nesting level of this Region.
///
/// An toplevel Region has depth 0.
///
/// @return The depth of the region.
unsigned getDepth() const;
- /// @brief Check if a Region is the TopLevel region.
+ /// Check if a Region is the TopLevel region.
///
/// The toplevel region represents the whole function.
bool isTopLevelRegion() const { return exit == nullptr; }
- /// @brief Return a new (non-canonical) region, that is obtained by joining
+ /// Return a new (non-canonical) region, that is obtained by joining
/// this region with its predecessors.
///
/// @return A region also starting at getEntry(), but reaching to the next
@@ -393,43 +394,43 @@ public:
/// NULL if such a basic block does not exist.
RegionT *getExpandedRegion() const;
- /// @brief Return the first block of this region's single entry edge,
+ /// Return the first block of this region's single entry edge,
/// if existing.
///
/// @return The BasicBlock starting this region's single entry edge,
/// else NULL.
BlockT *getEnteringBlock() const;
- /// @brief Return the first block of this region's single exit edge,
+ /// Return the first block of this region's single exit edge,
/// if existing.
///
/// @return The BasicBlock starting this region's single exit edge,
/// else NULL.
BlockT *getExitingBlock() const;
- /// @brief Collect all blocks of this region's single exit edge, if existing.
+ /// Collect all blocks of this region's single exit edge, if existing.
///
/// @return True if this region contains all the predecessors of the exit.
bool getExitingBlocks(SmallVectorImpl<BlockT *> &Exitings) const;
- /// @brief Is this a simple region?
+ /// Is this a simple region?
///
/// A region is simple if it has exactly one exit and one entry edge.
///
/// @return True if the Region is simple.
bool isSimple() const;
- /// @brief Returns the name of the Region.
+ /// Returns the name of the Region.
/// @return The Name of the Region.
std::string getNameStr() const;
- /// @brief Return the RegionInfo object, that belongs to this Region.
+ /// Return the RegionInfo object, that belongs to this Region.
RegionInfoT *getRegionInfo() const { return RI; }
/// PrintStyle - Print region in difference ways.
enum PrintStyle { PrintNone, PrintBB, PrintRN };
- /// @brief Print the region.
+ /// Print the region.
///
/// @param OS The output stream the Region is printed to.
/// @param printTree Print also the tree of subregions.
@@ -438,17 +439,17 @@ public:
PrintStyle Style = PrintNone) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- /// @brief Print the region to stderr.
+ /// Print the region to stderr.
void dump() const;
#endif
- /// @brief Check if the region contains a BasicBlock.
+ /// Check if the region contains a BasicBlock.
///
/// @param BB The BasicBlock that might be contained in this Region.
/// @return True if the block is contained in the region otherwise false.
bool contains(const BlockT *BB) const;
- /// @brief Check if the region contains another region.
+ /// Check if the region contains another region.
///
/// @param SubRegion The region that might be contained in this Region.
/// @return True if SubRegion is contained in the region otherwise false.
@@ -462,14 +463,14 @@ public:
SubRegion->getExit() == getExit());
}
- /// @brief Check if the region contains an Instruction.
+ /// Check if the region contains an Instruction.
///
/// @param Inst The Instruction that might be contained in this region.
/// @return True if the Instruction is contained in the region otherwise
/// false.
bool contains(const InstT *Inst) const { return contains(Inst->getParent()); }
- /// @brief Check if the region contains a loop.
+ /// Check if the region contains a loop.
///
/// @param L The loop that might be contained in this region.
/// @return True if the loop is contained in the region otherwise false.
@@ -478,7 +479,7 @@ public:
/// In that case true is returned.
bool contains(const LoopT *L) const;
- /// @brief Get the outermost loop in the region that contains a loop.
+ /// Get the outermost loop in the region that contains a loop.
///
/// Find for a Loop L the outermost loop OuterL that is a parent loop of L
/// and is itself contained in the region.
@@ -488,7 +489,7 @@ public:
/// exist or if the region describes the whole function.
LoopT *outermostLoopInRegion(LoopT *L) const;
- /// @brief Get the outermost loop in the region that contains a basic block.
+ /// Get the outermost loop in the region that contains a basic block.
///
/// Find for a basic block BB the outermost loop L that contains BB and is
/// itself contained in the region.
@@ -499,13 +500,13 @@ public:
/// exist or if the region describes the whole function.
LoopT *outermostLoopInRegion(LoopInfoT *LI, BlockT *BB) const;
- /// @brief Get the subregion that starts at a BasicBlock
+ /// Get the subregion that starts at a BasicBlock
///
/// @param BB The BasicBlock the subregion should start.
/// @return The Subregion if available, otherwise NULL.
RegionT *getSubRegionNode(BlockT *BB) const;
- /// @brief Get the RegionNode for a BasicBlock
+ /// Get the RegionNode for a BasicBlock
///
/// @param BB The BasicBlock at which the RegionNode should start.
/// @return If available, the RegionNode that represents the subregion
@@ -513,38 +514,38 @@ public:
/// representing BB.
RegionNodeT *getNode(BlockT *BB) const;
- /// @brief Get the BasicBlock RegionNode for a BasicBlock
+ /// Get the BasicBlock RegionNode for a BasicBlock
///
/// @param BB The BasicBlock for which the RegionNode is requested.
/// @return The RegionNode representing the BB.
RegionNodeT *getBBNode(BlockT *BB) const;
- /// @brief Add a new subregion to this Region.
+ /// Add a new subregion to this Region.
///
/// @param SubRegion The new subregion that will be added.
/// @param moveChildren Move the children of this region, that are also
/// contained in SubRegion into SubRegion.
void addSubRegion(RegionT *SubRegion, bool moveChildren = false);
- /// @brief Remove a subregion from this Region.
+ /// Remove a subregion from this Region.
///
/// The subregion is not deleted, as it will probably be inserted into another
/// region.
/// @param SubRegion The SubRegion that will be removed.
RegionT *removeSubRegion(RegionT *SubRegion);
- /// @brief Move all direct child nodes of this Region to another Region.
+ /// Move all direct child nodes of this Region to another Region.
///
/// @param To The Region the child nodes will be transferred to.
void transferChildrenTo(RegionT *To);
- /// @brief Verify if the region is a correct region.
+ /// Verify if the region is a correct region.
///
/// Check if this is a correctly build Region. This is an expensive check, as
/// the complete CFG of the Region will be walked.
void verifyRegion() const;
- /// @brief Clear the cache for BB RegionNodes.
+ /// Clear the cache for BB RegionNodes.
///
/// After calling this function the BasicBlock RegionNodes will be stored at
/// different memory locations. RegionNodes obtained before this function is
@@ -620,12 +621,12 @@ public:
using block_range = iterator_range<block_iterator>;
using const_block_range = iterator_range<const_block_iterator>;
- /// @brief Returns a range view of the basic blocks in the region.
+ /// Returns a range view of the basic blocks in the region.
inline block_range blocks() {
return block_range(block_begin(), block_end());
}
- /// @brief Returns a range view of the basic blocks in the region.
+ /// Returns a range view of the basic blocks in the region.
///
/// This is the 'const' version of the range view.
inline const_block_range blocks() const {
@@ -667,7 +668,7 @@ template <class Tr>
inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase<Tr> &Node);
//===----------------------------------------------------------------------===//
-/// @brief Analysis that detects all canonical Regions.
+/// Analysis that detects all canonical Regions.
///
/// The RegionInfo pass detects all canonical regions in a function. The Regions
/// are connected using the parent relation. This builds a Program Structure
@@ -725,7 +726,7 @@ class RegionInfoBase {
BBtoRegionMap BBtoRegion;
protected:
- /// \brief Update refences to a RegionInfoT held by the RegionT managed here
+ /// Update refences to a RegionInfoT held by the RegionT managed here
///
/// This is a post-move helper. Regions hold references to the owning
/// RegionInfo object. After a move these need to be fixed.
@@ -739,7 +740,7 @@ protected:
}
private:
- /// \brief Wipe this region tree's state without releasing any resources.
+ /// Wipe this region 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.
@@ -811,40 +812,40 @@ public:
void releaseMemory();
- /// @brief Get the smallest region that contains a BasicBlock.
+ /// Get the smallest region that contains a BasicBlock.
///
/// @param BB The basic block.
/// @return The smallest region, that contains BB or NULL, if there is no
/// region containing BB.
RegionT *getRegionFor(BlockT *BB) const;
- /// @brief Set the smallest region that surrounds a basic block.
+ /// Set the smallest region that surrounds a basic block.
///
/// @param BB The basic block surrounded by a region.
/// @param R The smallest region that surrounds BB.
void setRegionFor(BlockT *BB, RegionT *R);
- /// @brief A shortcut for getRegionFor().
+ /// A shortcut for getRegionFor().
///
/// @param BB The basic block.
/// @return The smallest region, that contains BB or NULL, if there is no
/// region containing BB.
RegionT *operator[](BlockT *BB) const;
- /// @brief Return the exit of the maximal refined region, that starts at a
+ /// Return the exit of the maximal refined region, that starts at a
/// BasicBlock.
///
/// @param BB The BasicBlock the refined region starts.
BlockT *getMaxRegionExit(BlockT *BB) const;
- /// @brief Find the smallest region that contains two regions.
+ /// Find the smallest region that contains two regions.
///
/// @param A The first region.
/// @param B The second region.
/// @return The smallest region containing A and B.
RegionT *getCommonRegion(RegionT *A, RegionT *B) const;
- /// @brief Find the smallest region that contains two basic blocks.
+ /// Find the smallest region that contains two basic blocks.
///
/// @param A The first basic block.
/// @param B The second basic block.
@@ -853,13 +854,13 @@ public:
return getCommonRegion(getRegionFor(A), getRegionFor(B));
}
- /// @brief Find the smallest region that contains a set of regions.
+ /// Find the smallest region that contains a set of regions.
///
/// @param Regions A vector of regions.
/// @return The smallest region that contains all regions in Regions.
RegionT *getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const;
- /// @brief Find the smallest region that contains a set of basic blocks.
+ /// Find the smallest region that contains a set of basic blocks.
///
/// @param BBs A vector of basic blocks.
/// @return The smallest region that contains all basic blocks in BBS.
@@ -867,7 +868,7 @@ public:
RegionT *getTopLevelRegion() const { return TopLevelRegion; }
- /// @brief Clear the Node Cache for all Regions.
+ /// Clear the Node Cache for all Regions.
///
/// @see Region::clearNodeCache()
void clearNodeCache() {
@@ -930,12 +931,12 @@ public:
DominanceFrontier *DF);
#ifndef NDEBUG
- /// @brief Opens a viewer to show the GraphViz visualization of the regions.
+ /// Opens a viewer to show the GraphViz visualization of the regions.
///
/// Useful during debugging as an alternative to dump().
void view();
- /// @brief Opens a viewer to show the GraphViz visualization of this region
+ /// Opens a viewer to show the GraphViz visualization of this region
/// without instructions in the BasicBlocks.
///
/// Useful during debugging as an alternative to dump().
@@ -967,7 +968,7 @@ public:
//@}
};
-/// \brief Analysis pass that exposes the \c RegionInfo for a function.
+/// Analysis pass that exposes the \c RegionInfo for a function.
class RegionInfoAnalysis : public AnalysisInfoMixin<RegionInfoAnalysis> {
friend AnalysisInfoMixin<RegionInfoAnalysis>;
@@ -979,7 +980,7 @@ public:
RegionInfo run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Printer pass for the \c RegionInfo.
+/// Printer pass for the \c RegionInfo.
class RegionInfoPrinterPass : public PassInfoMixin<RegionInfoPrinterPass> {
raw_ostream &OS;
@@ -989,7 +990,7 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Verifier pass for the \c RegionInfo.
+/// Verifier pass for the \c RegionInfo.
struct RegionInfoVerifierPass : PassInfoMixin<RegionInfoVerifierPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
diff --git a/contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h b/contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h
index eb6baac2d5e4..5904214aa925 100644
--- a/contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h
+++ b/contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h
@@ -22,6 +22,7 @@
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -674,7 +675,7 @@ typename Tr::RegionT *RegionInfoBase<Tr>::createRegion(BlockT *entry,
#ifdef EXPENSIVE_CHECKS
region->verifyRegion();
#else
- DEBUG(region->verifyRegion());
+ LLVM_DEBUG(region->verifyRegion());
#endif
updateStatistics(region);
diff --git a/contrib/llvm/include/llvm/Analysis/RegionIterator.h b/contrib/llvm/include/llvm/Analysis/RegionIterator.h
index 4f823cc82210..4fd92fcde20b 100644
--- a/contrib/llvm/include/llvm/Analysis/RegionIterator.h
+++ b/contrib/llvm/include/llvm/Analysis/RegionIterator.h
@@ -26,7 +26,7 @@ namespace llvm {
class BasicBlock;
//===----------------------------------------------------------------------===//
-/// @brief Hierarchical RegionNode successor iterator.
+/// Hierarchical RegionNode successor iterator.
///
/// This iterator iterates over all successors of a RegionNode.
///
@@ -102,7 +102,7 @@ public:
using Self = RNSuccIterator<NodeRef, BlockT, RegionT>;
using value_type = typename super::value_type;
- /// @brief Create begin iterator of a RegionNode.
+ /// Create begin iterator of a RegionNode.
inline RNSuccIterator(NodeRef node)
: Node(node, node->isSubRegion() ? ItRgBegin : ItBB),
BItor(BlockTraits::child_begin(node->getEntry())) {
@@ -115,7 +115,7 @@ public:
advanceRegionSucc();
}
- /// @brief Create an end iterator.
+ /// Create an end iterator.
inline RNSuccIterator(NodeRef node, bool)
: Node(node, node->isSubRegion() ? ItRgEnd : ItBB),
BItor(BlockTraits::child_end(node->getEntry())) {}
@@ -158,7 +158,7 @@ public:
};
//===----------------------------------------------------------------------===//
-/// @brief Flat RegionNode iterator.
+/// Flat RegionNode iterator.
///
/// The Flat Region iterator will iterate over all BasicBlock RegionNodes that
/// are contained in the Region and its subregions. This is close to a virtual
@@ -177,7 +177,7 @@ public:
using Self = RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>;
using value_type = typename super::value_type;
- /// @brief Create the iterator from a RegionNode.
+ /// Create the iterator from a RegionNode.
///
/// Note that the incoming node must be a bb node, otherwise it will trigger
/// an assertion when we try to get a BasicBlock.
@@ -193,7 +193,7 @@ public:
++Itor;
}
- /// @brief Create an end iterator
+ /// Create an end iterator
inline RNSuccIterator(NodeRef node, bool)
: Node(node), Itor(BlockTraits::child_end(node->getEntry())) {
assert(!Node->isSubRegion() &&
diff --git a/contrib/llvm/include/llvm/Analysis/RegionPass.h b/contrib/llvm/include/llvm/Analysis/RegionPass.h
index 515b362e5407..b3da91c89cbd 100644
--- a/contrib/llvm/include/llvm/Analysis/RegionPass.h
+++ b/contrib/llvm/include/llvm/Analysis/RegionPass.h
@@ -28,7 +28,7 @@ class RGPassManager;
class Function;
//===----------------------------------------------------------------------===//
-/// @brief A pass that runs on each Region in a function.
+/// A pass that runs on each Region in a function.
///
/// RegionPass is managed by RGPassManager.
class RegionPass : public Pass {
@@ -39,7 +39,7 @@ public:
/// @name To be implemented by every RegionPass
///
//@{
- /// @brief Run the pass on a specific Region
+ /// Run the pass on a specific Region
///
/// Accessing regions not contained in the current region is not allowed.
///
@@ -49,7 +49,7 @@ public:
/// @return True if the pass modifies this Region.
virtual bool runOnRegion(Region *R, RGPassManager &RGM) = 0;
- /// @brief Get a pass to print the LLVM IR in the region.
+ /// Get a pass to print the LLVM IR in the region.
///
/// @param O The output stream to print the Region.
/// @param Banner The banner to separate different printed passes.
@@ -85,7 +85,7 @@ protected:
bool skipRegion(Region &R) const;
};
-/// @brief The pass manager to schedule RegionPasses.
+/// The pass manager to schedule RegionPasses.
class RGPassManager : public FunctionPass, public PMDataManager {
std::deque<Region*> RQ;
bool skipThisRegion;
@@ -97,7 +97,7 @@ public:
static char ID;
explicit RGPassManager();
- /// @brief Execute all of the passes scheduled for execution.
+ /// Execute all of the passes scheduled for execution.
///
/// @return True if any of the passes modifies the function.
bool runOnFunction(Function &F) override;
@@ -111,10 +111,10 @@ public:
PMDataManager *getAsPMDataManager() override { return this; }
Pass *getAsPass() override { return this; }
- /// @brief Print passes managed by this manager.
+ /// Print passes managed by this manager.
void dumpPassStructure(unsigned Offset) override;
- /// @brief Get passes contained by this manager.
+ /// Get passes contained by this manager.
Pass *getContainedPass(unsigned N) {
assert(N < PassVector.size() && "Pass number out of range!");
Pass *FP = static_cast<Pass *>(PassVector[N]);
diff --git a/contrib/llvm/include/llvm/Analysis/RegionPrinter.h b/contrib/llvm/include/llvm/Analysis/RegionPrinter.h
index 8f0035cfd8e6..e132eaea5674 100644
--- a/contrib/llvm/include/llvm/Analysis/RegionPrinter.h
+++ b/contrib/llvm/include/llvm/Analysis/RegionPrinter.h
@@ -26,7 +26,7 @@ namespace llvm {
FunctionPass *createRegionOnlyPrinterPass();
#ifndef NDEBUG
- /// @brief Open a viewer to display the GraphViz vizualization of the analysis
+ /// Open a viewer to display the GraphViz vizualization of the analysis
/// result.
///
/// Practical to call in the debugger.
@@ -35,7 +35,7 @@ namespace llvm {
/// @param RI The analysis to display.
void viewRegion(llvm::RegionInfo *RI);
- /// @brief Analyze the regions of a function and open its GraphViz
+ /// Analyze the regions of a function and open its GraphViz
/// visualization in a viewer.
///
/// Useful to call in the debugger.
@@ -46,7 +46,7 @@ namespace llvm {
/// @param F Function to analyze.
void viewRegion(const llvm::Function *F);
- /// @brief Open a viewer to display the GraphViz vizualization of the analysis
+ /// Open a viewer to display the GraphViz vizualization of the analysis
/// result.
///
/// Useful to call in the debugger.
@@ -55,7 +55,7 @@ namespace llvm {
/// @param RI The analysis to display.
void viewRegionOnly(llvm::RegionInfo *RI);
- /// @brief Analyze the regions of a function and open its GraphViz
+ /// Analyze the regions of a function and open its GraphViz
/// visualization in a viewer.
///
/// Useful to call in the debugger.
diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h
index 21b72f3e13c2..89918e3c205b 100644
--- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -587,7 +587,9 @@ public:
const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS);
const SCEV *getUMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS);
+ const SCEV *getSMinExpr(SmallVectorImpl<const SCEV *> &Operands);
const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS);
+ const SCEV *getUMinExpr(SmallVectorImpl<const SCEV *> &Operands);
const SCEV *getUnknown(Value *V);
const SCEV *getCouldNotCompute();
@@ -650,6 +652,10 @@ public:
/// then perform a umin operation with them.
const SCEV *getUMinFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS);
+ /// Promote the operands to the wider of the types using zero-extension, and
+ /// then perform a umin operation with them. N-ary function.
+ const SCEV *getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops);
+
/// Transitively follow the chain of pointer-type operands until reaching a
/// SCEV that does not have a single pointer operand. This returns a
/// SCEVUnknown pointer for well-formed pointer-type expressions, but corner
@@ -678,7 +684,7 @@ public:
const SCEV *LHS, const SCEV *RHS);
/// Test whether the backedge of the loop is protected by a conditional
- /// between LHS and RHS. This is used to to eliminate casts.
+ /// between LHS and RHS. This is used to eliminate casts.
bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
@@ -764,6 +770,12 @@ public:
/// loop bodies.
void forgetLoop(const Loop *L);
+ // This method invokes forgetLoop for the outermost loop of the given loop
+ // \p L, making ScalarEvolution forget about all this subtree. This needs to
+ // be done whenever we make a transform that may affect the parameters of the
+ // outer loop, such as exit counts for branches.
+ void forgetTopmostLoop(const Loop *L);
+
/// This method should be called by the client when it has changed a value
/// in a way that may effect its value, or which may disconnect it from a
/// def-use chain linking it to a loop.
@@ -829,11 +841,56 @@ public:
/// Test if the given expression is known to be non-zero.
bool isKnownNonZero(const SCEV *S);
+ /// Splits SCEV expression \p S into two SCEVs. One of them is obtained from
+ /// \p S by substitution of all AddRec sub-expression related to loop \p L
+ /// with initial value of that SCEV. The second is obtained from \p S by
+ /// substitution of all AddRec sub-expressions related to loop \p L with post
+ /// increment of this AddRec in the loop \p L. In both cases all other AddRec
+ /// sub-expressions (not related to \p L) remain the same.
+ /// If the \p S contains non-invariant unknown SCEV the function returns
+ /// CouldNotCompute SCEV in both values of std::pair.
+ /// For example, for SCEV S={0, +, 1}<L1> + {0, +, 1}<L2> and loop L=L1
+ /// the function returns pair:
+ /// first = {0, +, 1}<L2>
+ /// second = {1, +, 1}<L1> + {0, +, 1}<L2>
+ /// We can see that for the first AddRec sub-expression it was replaced with
+ /// 0 (initial value) for the first element and to {1, +, 1}<L1> (post
+ /// increment value) for the second one. In both cases AddRec expression
+ /// related to L2 remains the same.
+ std::pair<const SCEV *, const SCEV *> SplitIntoInitAndPostInc(const Loop *L,
+ const SCEV *S);
+
+ /// We'd like to check the predicate on every iteration of the most dominated
+ /// loop between loops used in LHS and RHS.
+ /// To do this we use the following list of steps:
+ /// 1. Collect set S all loops on which either LHS or RHS depend.
+ /// 2. If S is non-empty
+ /// a. Let PD be the element of S which is dominated by all other elements.
+ /// b. Let E(LHS) be value of LHS on entry of PD.
+ /// To get E(LHS), we should just take LHS and replace all AddRecs that are
+ /// attached to PD on with their entry values.
+ /// Define E(RHS) in the same way.
+ /// c. Let B(LHS) be value of L on backedge of PD.
+ /// To get B(LHS), we should just take LHS and replace all AddRecs that are
+ /// attached to PD on with their backedge values.
+ /// Define B(RHS) in the same way.
+ /// d. Note that E(LHS) and E(RHS) are automatically available on entry of PD,
+ /// so we can assert on that.
+ /// e. Return true if isLoopEntryGuardedByCond(Pred, E(LHS), E(RHS)) &&
+ /// isLoopBackedgeGuardedByCond(Pred, B(LHS), B(RHS))
+ bool isKnownViaInduction(ICmpInst::Predicate Pred, const SCEV *LHS,
+ const SCEV *RHS);
+
/// Test if the given expression is known to satisfy the condition described
/// by Pred, LHS, and RHS.
bool isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *LHS,
const SCEV *RHS);
+ /// Test if the condition described by Pred, LHS, RHS is known to be true on
+ /// every iteration of the loop of the recurrency LHS.
+ bool isKnownOnEveryIteration(ICmpInst::Predicate Pred,
+ const SCEVAddRecExpr *LHS, const SCEV *RHS);
+
/// Return true if, for all loop invariant X, the predicate "LHS `Pred` X"
/// is monotonically increasing or decreasing. In the former case set
/// `Increasing` to true and in the latter case set `Increasing` to false.
@@ -1040,7 +1097,7 @@ private:
/// The target library information for the target we are targeting.
TargetLibraryInfo &TLI;
- /// The tracker for @llvm.assume intrinsics in this function.
+ /// The tracker for \@llvm.assume intrinsics in this function.
AssumptionCache &AC;
/// The dominator tree.
@@ -1094,6 +1151,12 @@ private:
/// Mark predicate values currently being processed by isImpliedCond.
SmallPtrSet<Value *, 6> PendingLoopPredicates;
+ /// Mark SCEVUnknown Phis currently being processed by getRangeRef.
+ SmallPtrSet<const PHINode *, 6> PendingPhiRanges;
+
+ // Mark SCEVUnknown Phis currently being processed by isImpliedViaMerge.
+ SmallPtrSet<const PHINode *, 6> PendingMerges;
+
/// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of
/// conditions dominating the backedge of a loop.
bool WalkingBEDominatingConds = false;
@@ -1240,7 +1303,7 @@ private:
/// If we allowed SCEV predicates to be generated when populating this
/// vector, this information can contain them and therefore a
/// SCEVPredicate argument should be added to getExact.
- const SCEV *getExact(ScalarEvolution *SE,
+ const SCEV *getExact(const Loop *L, ScalarEvolution *SE,
SCEVUnionPredicate *Predicates = nullptr) const;
/// Return the number of times this loop exit may fall through to the back
@@ -1424,8 +1487,7 @@ private:
bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
- /// execute if its exit condition were a conditional branch of ExitCond,
- /// TBB, and FBB.
+ /// execute if its exit condition were a conditional branch of ExitCond.
///
/// \p ControlsExit is true if ExitCond directly controls the exit
/// branch. In this case, we can assume that the loop exits only if the
@@ -1435,15 +1497,14 @@ private:
/// If \p AllowPredicates is set, this call will try to use a minimal set of
/// SCEV predicates in order to return an exact answer.
ExitLimit computeExitLimitFromCond(const Loop *L, Value *ExitCond,
- BasicBlock *TBB, BasicBlock *FBB,
- bool ControlsExit,
+ bool ExitIfTrue, bool ControlsExit,
bool AllowPredicates = false);
// Helper functions for computeExitLimitFromCond to avoid exponential time
// complexity.
class ExitLimitCache {
- // It may look like we need key on the whole (L, TBB, FBB, ControlsExit,
+ // It may look like we need key on the whole (L, ExitIfTrue, ControlsExit,
// AllowPredicates) tuple, but recursive calls to
// computeExitLimitFromCondCached from computeExitLimitFromCondImpl only
// vary the in \c ExitCond and \c ControlsExit parameters. We remember the
@@ -1451,43 +1512,39 @@ private:
SmallDenseMap<PointerIntPair<Value *, 1>, ExitLimit> TripCountMap;
const Loop *L;
- BasicBlock *TBB;
- BasicBlock *FBB;
+ bool ExitIfTrue;
bool AllowPredicates;
public:
- ExitLimitCache(const Loop *L, BasicBlock *TBB, BasicBlock *FBB,
- bool AllowPredicates)
- : L(L), TBB(TBB), FBB(FBB), AllowPredicates(AllowPredicates) {}
+ ExitLimitCache(const Loop *L, bool ExitIfTrue, bool AllowPredicates)
+ : L(L), ExitIfTrue(ExitIfTrue), AllowPredicates(AllowPredicates) {}
- Optional<ExitLimit> find(const Loop *L, Value *ExitCond, BasicBlock *TBB,
- BasicBlock *FBB, bool ControlsExit,
- bool AllowPredicates);
+ Optional<ExitLimit> find(const Loop *L, Value *ExitCond, bool ExitIfTrue,
+ bool ControlsExit, bool AllowPredicates);
- void insert(const Loop *L, Value *ExitCond, BasicBlock *TBB,
- BasicBlock *FBB, bool ControlsExit, bool AllowPredicates,
- const ExitLimit &EL);
+ void insert(const Loop *L, Value *ExitCond, bool ExitIfTrue,
+ bool ControlsExit, bool AllowPredicates, const ExitLimit &EL);
};
using ExitLimitCacheTy = ExitLimitCache;
ExitLimit computeExitLimitFromCondCached(ExitLimitCacheTy &Cache,
const Loop *L, Value *ExitCond,
- BasicBlock *TBB, BasicBlock *FBB,
+ bool ExitIfTrue,
bool ControlsExit,
bool AllowPredicates);
ExitLimit computeExitLimitFromCondImpl(ExitLimitCacheTy &Cache, const Loop *L,
- Value *ExitCond, BasicBlock *TBB,
- BasicBlock *FBB, bool ControlsExit,
+ Value *ExitCond, bool ExitIfTrue,
+ bool ControlsExit,
bool AllowPredicates);
/// Compute the number of times the backedge of the specified loop will
/// execute if its exit condition were a conditional branch of the ICmpInst
- /// ExitCond, TBB, and FBB. If AllowPredicates is set, this call will try
+ /// ExitCond and ExitIfTrue. If AllowPredicates is set, this call will try
/// to use a minimal set of SCEV predicates in order to return an exact
/// answer.
ExitLimit computeExitLimitFromICmp(const Loop *L, ICmpInst *ExitCond,
- BasicBlock *TBB, BasicBlock *FBB,
+ bool ExitIfTrue,
bool IsSubExpr,
bool AllowPredicates = false);
@@ -1591,8 +1648,8 @@ private:
/// Test whether the condition described by Pred, LHS, and RHS is true.
/// Use only simple non-recursive types of checks, such as range analysis etc.
- bool isKnownViaSimpleReasoning(ICmpInst::Predicate Pred,
- const SCEV *LHS, const SCEV *RHS);
+ bool isKnownViaNonRecursiveReasoning(ICmpInst::Predicate Pred,
+ const SCEV *LHS, const SCEV *RHS);
/// Test whether the condition described by Pred, LHS, and RHS is true
/// whenever the condition described by Pred, FoundLHS, and FoundRHS is
@@ -1625,6 +1682,18 @@ private:
const SCEV *FoundLHS,
const SCEV *FoundRHS);
+ /// Test whether the condition described by Pred, LHS, and RHS is true
+ /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
+ /// true.
+ ///
+ /// This routine tries to figure out predicate for Phis which are SCEVUnknown
+ /// if it is true for every possible incoming value from their respective
+ /// basic blocks.
+ bool isImpliedViaMerge(ICmpInst::Predicate Pred,
+ const SCEV *LHS, const SCEV *RHS,
+ const SCEV *FoundLHS, const SCEV *FoundRHS,
+ unsigned Depth);
+
/// If we know that the specified Phi is in the header of its containing
/// loop, we know the loop executes a constant number of times, and the PHI
/// node is just a recurrence involving constants, fold it.
@@ -1764,10 +1833,22 @@ private:
const SCEV *getOrCreateMulExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags);
+ /// Return x if \p Val is f(x) where f is a 1-1 function.
+ const SCEV *stripInjectiveFunctions(const SCEV *Val) const;
+
+ /// Find all of the loops transitively used in \p S, and fill \p LoopsUsed.
+ /// A loop is considered "used" by an expression if it contains
+ /// an add rec on said loop.
+ void getUsedLoops(const SCEV *S, SmallPtrSetImpl<const Loop *> &LoopsUsed);
+
/// Find all of the loops transitively used in \p S, and update \c LoopUsers
/// accordingly.
void addToLoopUseLists(const SCEV *S);
+ /// Try to match the pattern generated by getURemExpr(A, B). If successful,
+ /// Assign A and B to LHS and RHS, respectively.
+ bool matchURem(const SCEV *Expr, const SCEV *&LHS, const SCEV *&RHS);
+
FoldingSet<SCEV> UniqueSCEVs;
FoldingSet<SCEVPredicate> UniquePreds;
BumpPtrAllocator SCEVAllocator;
diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h
index 3df04e98bd24..58d42680d6bc 100644
--- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h
+++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h
@@ -321,7 +321,7 @@ namespace llvm {
/// Arrange for there to be a cast of V to Ty at IP, reusing an existing
/// cast if a suitable one exists, moving an existing cast if a suitable one
- /// exists but isn't in the right place, or or creating a new one.
+ /// exists but isn't in the right place, or creating a new one.
Value *ReuseOrCreateCast(Value *V, Type *Ty,
Instruction::CastOps Op,
BasicBlock::iterator IP);
@@ -335,6 +335,7 @@ namespace llvm {
Value *expandAddToGEP(const SCEV *const *op_begin,
const SCEV *const *op_end,
PointerType *PTy, Type *Ty, Value *V);
+ Value *expandAddToGEP(const SCEV *Op, PointerType *PTy, Type *Ty, Value *V);
/// Find a previous Value in ExprValueMap for expand.
ScalarEvolution::ValueOffsetPair
diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
index acf83455cdcd..42e76094eb2b 100644
--- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -350,9 +350,7 @@ class Type;
/// Return an expression representing the value of this expression
/// one iteration of the loop ahead.
- const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const {
- return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
- }
+ const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const SCEV *S) {
diff --git a/contrib/llvm/include/llvm/Analysis/SparsePropagation.h b/contrib/llvm/include/llvm/Analysis/SparsePropagation.h
index 1b8df03b3a1b..defcf96afb25 100644
--- a/contrib/llvm/include/llvm/Analysis/SparsePropagation.h
+++ b/contrib/llvm/include/llvm/Analysis/SparsePropagation.h
@@ -238,7 +238,7 @@ SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getValueState(LatticeKey Key) {
// If this value is untracked, don't add it to the map.
if (LV == LatticeFunc->getUntrackedVal())
return LV;
- return ValueState[Key] = LV;
+ return ValueState[Key] = std::move(LV);
}
template <class LatticeKey, class LatticeVal, class KeyInfo>
@@ -250,7 +250,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::UpdateState(LatticeKey Key,
// Update the state of the given LatticeKey and add its corresponding LLVM
// value to the work list.
- ValueState[Key] = LV;
+ ValueState[Key] = std::move(LV);
if (Value *V = KeyInfo::getValueFromLatticeKey(Key))
ValueWorkList.push_back(V);
}
@@ -260,7 +260,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::MarkBlockExecutable(
BasicBlock *BB) {
if (!BBExecutable.insert(BB).second)
return;
- DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << "\n");
+ LLVM_DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << "\n");
BBWorkList.push_back(BB); // Add the block to the work list!
}
@@ -270,8 +270,8 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::markEdgeExecutable(
if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second)
return; // This edge is already known to be executable!
- DEBUG(dbgs() << "Marking Edge Executable: " << Source->getName() << " -> "
- << Dest->getName() << "\n");
+ LLVM_DEBUG(dbgs() << "Marking Edge Executable: " << Source->getName()
+ << " -> " << Dest->getName() << "\n");
if (BBExecutable.count(Dest)) {
// The destination is already executable, but we just made an edge
@@ -318,7 +318,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors(
Constant *C =
dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal(
- BCValue, BI->getCondition()->getType()));
+ std::move(BCValue), BI->getCondition()->getType()));
if (!C || !isa<ConstantInt>(C)) {
// Non-constant values can go either way.
Succs[0] = Succs[1] = true;
@@ -360,7 +360,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors(
return;
Constant *C = dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal(
- SCValue, SI.getCondition()->getType()));
+ std::move(SCValue), SI.getCondition()->getType()));
if (!C || !isa<ConstantInt>(C)) {
// All destinations are executable!
Succs.assign(TI.getNumSuccessors(), true);
@@ -408,7 +408,8 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitPHINode(PHINode &PN) {
LatticeFunc->ComputeInstructionState(PN, ChangedValues, *this);
for (auto &ChangedValue : ChangedValues)
if (ChangedValue.second != LatticeFunc->getUntrackedVal())
- UpdateState(ChangedValue.first, ChangedValue.second);
+ UpdateState(std::move(ChangedValue.first),
+ std::move(ChangedValue.second));
return;
}
@@ -477,7 +478,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::Solve() {
Value *V = ValueWorkList.back();
ValueWorkList.pop_back();
- DEBUG(dbgs() << "\nPopped off V-WL: " << *V << "\n");
+ LLVM_DEBUG(dbgs() << "\nPopped off V-WL: " << *V << "\n");
// "V" got into the work list because it made a transition. See if any
// users are both live and in need of updating.
@@ -492,7 +493,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::Solve() {
BasicBlock *BB = BBWorkList.back();
BBWorkList.pop_back();
- DEBUG(dbgs() << "\nPopped off BBWL: " << *BB);
+ LLVM_DEBUG(dbgs() << "\nPopped off BBWL: " << *BB);
// Notify all instructions in this basic block that they are newly
// executable.
diff --git a/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h b/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h
new file mode 100644
index 000000000000..87f4a0100b38
--- /dev/null
+++ b/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h
@@ -0,0 +1,52 @@
+//===- SyntheticCountsUtils.h - utilities for count propagation--*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines utilities for synthetic counts propagation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_SYNTHETIC_COUNTS_UTILS_H
+#define LLVM_ANALYSIS_SYNTHETIC_COUNTS_UTILS_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Support/ScaledNumber.h"
+
+namespace llvm {
+
+class CallGraph;
+class Function;
+
+/// Class with methods to propagate synthetic entry counts.
+///
+/// This class is templated on the type of the call graph and designed to work
+/// with the traditional per-module callgraph and the summary callgraphs used in
+/// ThinLTO. This contains only static methods and alias templates.
+template <typename CallGraphType> class SyntheticCountsUtils {
+public:
+ using Scaled64 = ScaledNumber<uint64_t>;
+ using CGT = GraphTraits<CallGraphType>;
+ using NodeRef = typename CGT::NodeRef;
+ using EdgeRef = typename CGT::EdgeRef;
+ using SccTy = std::vector<NodeRef>;
+
+ using GetRelBBFreqTy = function_ref<Optional<Scaled64>(EdgeRef)>;
+ using GetCountTy = function_ref<uint64_t(NodeRef)>;
+ using AddCountTy = function_ref<void(NodeRef, uint64_t)>;
+
+ static void propagate(const CallGraphType &CG, GetRelBBFreqTy GetRelBBFreq,
+ GetCountTy GetCount, AddCountTy AddCount);
+
+private:
+ static void propagateFromSCC(const SccTy &SCC, GetRelBBFreqTy GetRelBBFreq,
+ GetCountTy GetCount, AddCountTy AddCount);
+};
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index a461ed813b9b..f94debba9c52 100644
--- a/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -119,6 +119,12 @@ TLI_DEFINE_STRING_INTERNAL("_ZdaPv")
/// void operator delete[](void*, nothrow);
TLI_DEFINE_ENUM_INTERNAL(ZdaPvRKSt9nothrow_t)
TLI_DEFINE_STRING_INTERNAL("_ZdaPvRKSt9nothrow_t")
+/// void operator delete[](void*, align_val_t);
+TLI_DEFINE_ENUM_INTERNAL(ZdaPvSt11align_val_t)
+TLI_DEFINE_STRING_INTERNAL("_ZdaPvSt11align_val_t")
+/// void operator delete[](void*, align_val_t, nothrow)
+TLI_DEFINE_ENUM_INTERNAL(ZdaPvSt11align_val_tRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZdaPvSt11align_val_tRKSt9nothrow_t")
/// void operator delete[](void*, unsigned int);
TLI_DEFINE_ENUM_INTERNAL(ZdaPvj)
TLI_DEFINE_STRING_INTERNAL("_ZdaPvj")
@@ -131,6 +137,12 @@ TLI_DEFINE_STRING_INTERNAL("_ZdlPv")
/// void operator delete(void*, nothrow);
TLI_DEFINE_ENUM_INTERNAL(ZdlPvRKSt9nothrow_t)
TLI_DEFINE_STRING_INTERNAL("_ZdlPvRKSt9nothrow_t")
+/// void operator delete(void*, align_val_t)
+TLI_DEFINE_ENUM_INTERNAL(ZdlPvSt11align_val_t)
+TLI_DEFINE_STRING_INTERNAL("_ZdlPvSt11align_val_t")
+/// void operator delete(void*, align_val_t, nothrow)
+TLI_DEFINE_ENUM_INTERNAL(ZdlPvSt11align_val_tRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZdlPvSt11align_val_tRKSt9nothrow_t")
/// void operator delete(void*, unsigned int);
TLI_DEFINE_ENUM_INTERNAL(ZdlPvj)
TLI_DEFINE_STRING_INTERNAL("_ZdlPvj")
@@ -143,24 +155,48 @@ TLI_DEFINE_STRING_INTERNAL("_Znaj")
/// void *new[](unsigned int, nothrow);
TLI_DEFINE_ENUM_INTERNAL(ZnajRKSt9nothrow_t)
TLI_DEFINE_STRING_INTERNAL("_ZnajRKSt9nothrow_t")
+/// void *new[](unsigned int, align_val_t)
+TLI_DEFINE_ENUM_INTERNAL(ZnajSt11align_val_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnajSt11align_val_t")
+/// void *new[](unsigned int, align_val_t, nothrow)
+TLI_DEFINE_ENUM_INTERNAL(ZnajSt11align_val_tRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnajSt11align_val_tRKSt9nothrow_t")
/// void *new[](unsigned long);
TLI_DEFINE_ENUM_INTERNAL(Znam)
TLI_DEFINE_STRING_INTERNAL("_Znam")
/// void *new[](unsigned long, nothrow);
TLI_DEFINE_ENUM_INTERNAL(ZnamRKSt9nothrow_t)
TLI_DEFINE_STRING_INTERNAL("_ZnamRKSt9nothrow_t")
+/// void *new[](unsigned long, align_val_t)
+TLI_DEFINE_ENUM_INTERNAL(ZnamSt11align_val_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnamSt11align_val_t")
+/// void *new[](unsigned long, align_val_t, nothrow)
+TLI_DEFINE_ENUM_INTERNAL(ZnamSt11align_val_tRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnamSt11align_val_tRKSt9nothrow_t")
/// void *new(unsigned int);
TLI_DEFINE_ENUM_INTERNAL(Znwj)
TLI_DEFINE_STRING_INTERNAL("_Znwj")
/// void *new(unsigned int, nothrow);
TLI_DEFINE_ENUM_INTERNAL(ZnwjRKSt9nothrow_t)
TLI_DEFINE_STRING_INTERNAL("_ZnwjRKSt9nothrow_t")
+/// void *new(unsigned int, align_val_t)
+TLI_DEFINE_ENUM_INTERNAL(ZnwjSt11align_val_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnwjSt11align_val_t")
+/// void *new(unsigned int, align_val_t, nothrow)
+TLI_DEFINE_ENUM_INTERNAL(ZnwjSt11align_val_tRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnwjSt11align_val_tRKSt9nothrow_t")
/// void *new(unsigned long);
TLI_DEFINE_ENUM_INTERNAL(Znwm)
TLI_DEFINE_STRING_INTERNAL("_Znwm")
/// void *new(unsigned long, nothrow);
TLI_DEFINE_ENUM_INTERNAL(ZnwmRKSt9nothrow_t)
TLI_DEFINE_STRING_INTERNAL("_ZnwmRKSt9nothrow_t")
+/// void *new(unsigned long, align_val_t)
+TLI_DEFINE_ENUM_INTERNAL(ZnwmSt11align_val_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnwmSt11align_val_t")
+/// void *new(unsigned long, align_val_t, nothrow)
+TLI_DEFINE_ENUM_INTERNAL(ZnwmSt11align_val_tRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnwmSt11align_val_tRKSt9nothrow_t")
/// double __acos_finite(double x);
TLI_DEFINE_ENUM_INTERNAL(acos_finite)
TLI_DEFINE_STRING_INTERNAL("__acos_finite")
@@ -601,12 +637,18 @@ TLI_DEFINE_STRING_INTERNAL("ffsll")
/// int fgetc(FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fgetc)
TLI_DEFINE_STRING_INTERNAL("fgetc")
+/// int fgetc_unlocked(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fgetc_unlocked)
+TLI_DEFINE_STRING_INTERNAL("fgetc_unlocked")
/// int fgetpos(FILE *stream, fpos_t *pos);
TLI_DEFINE_ENUM_INTERNAL(fgetpos)
TLI_DEFINE_STRING_INTERNAL("fgetpos")
/// char *fgets(char *s, int n, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fgets)
TLI_DEFINE_STRING_INTERNAL("fgets")
+/// char *fgets_unlocked(char *s, int n, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fgets_unlocked)
+TLI_DEFINE_STRING_INTERNAL("fgets_unlocked")
/// int fileno(FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fileno)
TLI_DEFINE_STRING_INTERNAL("fileno")
@@ -673,12 +715,21 @@ TLI_DEFINE_STRING_INTERNAL("fprintf")
/// int fputc(int c, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fputc)
TLI_DEFINE_STRING_INTERNAL("fputc")
+/// int fputc_unlocked(int c, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fputc_unlocked)
+TLI_DEFINE_STRING_INTERNAL("fputc_unlocked")
/// int fputs(const char *s, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fputs)
TLI_DEFINE_STRING_INTERNAL("fputs")
+/// int fputs_unlocked(const char *s, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fputs_unlocked)
+TLI_DEFINE_STRING_INTERNAL("fputs_unlocked")
/// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fread)
TLI_DEFINE_STRING_INTERNAL("fread")
+/// size_t fread_unlocked(void *ptr, size_t size, size_t nitems, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fread_unlocked)
+TLI_DEFINE_STRING_INTERNAL("fread_unlocked")
/// void free(void *ptr);
TLI_DEFINE_ENUM_INTERNAL(free)
TLI_DEFINE_STRING_INTERNAL("free")
@@ -736,6 +787,9 @@ TLI_DEFINE_STRING_INTERNAL("funlockfile")
/// size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fwrite)
TLI_DEFINE_STRING_INTERNAL("fwrite")
+/// size_t fwrite_unlocked(const void *ptr, size_t size, size_t nitems, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fwrite_unlocked)
+TLI_DEFINE_STRING_INTERNAL("fwrite_unlocked")
/// int getc(FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(getc)
TLI_DEFINE_STRING_INTERNAL("getc")
@@ -745,6 +799,9 @@ TLI_DEFINE_STRING_INTERNAL("getc_unlocked")
/// int getchar(void);
TLI_DEFINE_ENUM_INTERNAL(getchar)
TLI_DEFINE_STRING_INTERNAL("getchar")
+/// int getchar_unlocked(void);
+TLI_DEFINE_ENUM_INTERNAL(getchar_unlocked)
+TLI_DEFINE_STRING_INTERNAL("getchar_unlocked")
/// char *getenv(const char *name);
TLI_DEFINE_ENUM_INTERNAL(getenv)
TLI_DEFINE_STRING_INTERNAL("getenv")
@@ -950,9 +1007,15 @@ TLI_DEFINE_STRING_INTERNAL("printf")
/// int putc(int c, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(putc)
TLI_DEFINE_STRING_INTERNAL("putc")
+/// int putc_unlocked(int c, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(putc_unlocked)
+TLI_DEFINE_STRING_INTERNAL("putc_unlocked")
/// int putchar(int c);
TLI_DEFINE_ENUM_INTERNAL(putchar)
TLI_DEFINE_STRING_INTERNAL("putchar")
+/// int putchar_unlocked(int c);
+TLI_DEFINE_ENUM_INTERNAL(putchar_unlocked)
+TLI_DEFINE_STRING_INTERNAL("putchar_unlocked")
/// int puts(const char *s);
TLI_DEFINE_ENUM_INTERNAL(puts)
TLI_DEFINE_STRING_INTERNAL("puts")
diff --git a/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h b/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h
index c20f20cfbe4d..59657cca40f5 100644
--- a/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -49,7 +49,7 @@ class Type;
class User;
class Value;
-/// \brief Information about a load/store intrinsic defined by the target.
+/// Information about a load/store intrinsic defined by the target.
struct MemIntrinsicInfo {
/// This is the pointer that the intrinsic is loading from or storing to.
/// If this is non-null, then analysis/optimization passes can assume that
@@ -73,18 +73,18 @@ struct MemIntrinsicInfo {
}
};
-/// \brief This pass provides access to the codegen interfaces that are needed
+/// This pass provides access to the codegen interfaces that are needed
/// for IR-level transformations.
class TargetTransformInfo {
public:
- /// \brief Construct a TTI object using a type implementing the \c Concept
+ /// Construct a TTI object using a type implementing the \c Concept
/// API below.
///
/// 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 Construct a baseline TTI object using a minimal implementation of
+ /// Construct a baseline TTI object using a minimal implementation of
/// the \c Concept API below.
///
/// The TTI implementation will reflect the information in the DataLayout
@@ -99,7 +99,7 @@ public:
// out-of-line.
~TargetTransformInfo();
- /// \brief Handle the invalidation of this information.
+ /// 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,
@@ -114,7 +114,7 @@ public:
/// \name Generic Target Information
/// @{
- /// \brief The kind of cost model.
+ /// The kind of cost model.
///
/// There are several different cost models that can be customized by the
/// target. The normalization of each cost model may be target specific.
@@ -124,7 +124,7 @@ public:
TCK_CodeSize ///< Instruction code size.
};
- /// \brief Query the cost of a specified instruction.
+ /// Query the cost of a specified instruction.
///
/// Clients should use this interface to query the cost of an existing
/// instruction. The instruction must have a valid parent (basic block).
@@ -145,7 +145,7 @@ public:
llvm_unreachable("Unknown instruction cost kind");
}
- /// \brief Underlying constants for 'cost' values in this interface.
+ /// Underlying constants for 'cost' values in this interface.
///
/// Many APIs in this interface return a cost. This enum defines the
/// fundamental values that should be used to interpret (and produce) those
@@ -169,7 +169,7 @@ public:
TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86.
};
- /// \brief Estimate the cost of a specific operation when lowered.
+ /// Estimate the cost of a specific operation when lowered.
///
/// Note that this is designed to work on an arbitrary synthetic opcode, and
/// thus work for hypothetical queries before an instruction has even been
@@ -185,7 +185,7 @@ public:
/// comments for a detailed explanation of the cost values.
int getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy = nullptr) const;
- /// \brief Estimate the cost of a GEP operation when lowered.
+ /// 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
@@ -193,14 +193,14 @@ public:
int getGEPCost(Type *PointeeType, const Value *Ptr,
ArrayRef<const Value *> Operands) const;
- /// \brief Estimate the cost of a EXT operation when lowered.
+ /// Estimate the cost of a EXT 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 EXT operation.
int getExtCost(const Instruction *I, const Value *Src) const;
- /// \brief Estimate the cost of a function call when lowered.
+ /// Estimate the cost of a function call when lowered.
///
/// The contract for this is the same as \c getOperationCost except that it
/// supports an interface that provides extra information specific to call
@@ -211,13 +211,13 @@ public:
/// The latter is only interesting for varargs function types.
int getCallCost(FunctionType *FTy, int NumArgs = -1) const;
- /// \brief Estimate the cost of calling a specific function when lowered.
+ /// 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.
int getCallCost(const Function *F, int NumArgs = -1) const;
- /// \brief Estimate the cost of calling a specific function when lowered.
+ /// Estimate the cost of calling a specific function when lowered.
///
/// This overload allows specifying a set of candidate argument values.
int getCallCost(const Function *F, ArrayRef<const Value *> Arguments) const;
@@ -230,13 +230,13 @@ public:
/// individual classes of instructions would be better.
unsigned getInliningThresholdMultiplier() const;
- /// \brief Estimate the cost of an intrinsic when lowered.
+ /// Estimate the cost of an intrinsic when lowered.
///
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) const;
- /// \brief Estimate the cost of an intrinsic when lowered.
+ /// Estimate the cost of an intrinsic when lowered.
///
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
@@ -248,7 +248,7 @@ public:
unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI,
unsigned &JTSize) const;
- /// \brief Estimate the cost of a given IR user when lowered.
+ /// Estimate the cost of a given IR user when lowered.
///
/// This can estimate the cost of either a ConstantExpr or Instruction when
/// lowered. It has two primary advantages over the \c getOperationCost and
@@ -271,7 +271,7 @@ public:
/// comments for a detailed explanation of the cost values.
int getUserCost(const User *U, ArrayRef<const Value *> Operands) const;
- /// \brief This is a helper function which calls the two-argument getUserCost
+ /// This is a helper function which calls the two-argument getUserCost
/// with \p Operands which are the current operands U has.
int getUserCost(const User *U) const {
SmallVector<const Value *, 4> Operands(U->value_op_begin(),
@@ -279,14 +279,14 @@ public:
return getUserCost(U, Operands);
}
- /// \brief Return true if branch divergence exists.
+ /// 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.
bool hasBranchDivergence() const;
- /// \brief Returns whether V is a source of divergence.
+ /// Returns whether V is a source of divergence.
///
/// This function provides the target-dependent information for
/// the target-independent DivergenceAnalysis. DivergenceAnalysis first
@@ -294,7 +294,7 @@ public:
/// starting with the sources of divergence.
bool isSourceOfDivergence(const Value *V) const;
- // \brief Returns true for the target specific
+ // Returns true for the target specific
// set of operations which produce uniform result
// even taking non-unform arguments
bool isAlwaysUniform(const Value *V) const;
@@ -308,7 +308,7 @@ public:
/// compared to the same memory location accessed through a pointer with a
/// different address space.
//
- /// This is for for targets with different pointer representations which can
+ /// This is for targets with different pointer representations which can
/// be converted with the addrspacecast instruction. If a pointer is converted
/// to this address space, optimizations should attempt to replace the access
/// with the source address space.
@@ -317,7 +317,7 @@ public:
/// optimize away.
unsigned getFlatAddressSpace() const;
- /// \brief Test whether calls to a function lower to actual program function
+ /// Test whether calls to a function lower to actual program function
/// calls.
///
/// The idea is to test whether the program is likely to require a 'call'
@@ -422,9 +422,16 @@ public:
bool AllowPeeling;
/// Allow unrolling of all the iterations of the runtime loop remainder.
bool UnrollRemainder;
+ /// Allow unroll and jam. Used to enable unroll and jam for the target.
+ bool UnrollAndJam;
+ /// Threshold for unroll and jam, for inner loop size. The 'Threshold'
+ /// value above is used during unroll and jam for the outer loop size.
+ /// This value is used in the same manner to limit the size of the inner
+ /// loop.
+ unsigned UnrollAndJamInnerLoopThreshold;
};
- /// \brief Get target-customized preferences for the generic loop unrolling
+ /// Get target-customized preferences for the generic loop unrolling
/// transformation. The caller will initialize UP with the current
/// target-independent defaults.
void getUnrollingPreferences(Loop *L, ScalarEvolution &,
@@ -435,7 +442,7 @@ public:
/// \name Scalar Target Information
/// @{
- /// \brief Flags indicating the kind of support for population count.
+ /// Flags indicating the kind of support for population count.
///
/// Compared to the SW implementation, HW support is supposed to
/// significantly boost the performance when the population is dense, and it
@@ -445,18 +452,18 @@ public:
/// considered as "Slow".
enum PopcntSupportKind { PSK_Software, PSK_SlowHardware, PSK_FastHardware };
- /// \brief Return true if the specified immediate is legal add immediate, that
+ /// 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.
bool isLegalAddImmediate(int64_t Imm) const;
- /// \brief Return true if the specified immediate is legal icmp immediate,
+ /// Return true if the specified immediate is legal icmp immediate,
/// that is the target has icmp instructions which can compare a register
/// against the immediate without having to materialize the immediate into a
/// register.
bool isLegalICmpImmediate(int64_t Imm) const;
- /// \brief Return true if the addressing mode represented by AM is legal for
+ /// 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.
@@ -467,16 +474,25 @@ public:
unsigned AddrSpace = 0,
Instruction *I = nullptr) const;
- /// \brief Return true if LSR cost of C1 is lower than C1.
+ /// Return true if LSR cost of C1 is lower than C1.
bool isLSRCostLess(TargetTransformInfo::LSRCost &C1,
TargetTransformInfo::LSRCost &C2) const;
- /// \brief Return true if the target supports masked load/store
+ /// Return true if the target can fuse a compare and branch.
+ /// Loop-strength-reduction (LSR) uses that knowledge to adjust its cost
+ /// calculation for the instructions in a loop.
+ bool canMacroFuseCmp() const;
+
+ /// \return True is LSR should make efforts to create/preserve post-inc
+ /// addressing mode expressions.
+ bool shouldFavorPostInc() const;
+
+ /// Return true if the target supports masked load/store
/// AVX2 and AVX-512 targets allow masks for consecutive load and store
bool isLegalMaskedStore(Type *DataType) const;
bool isLegalMaskedLoad(Type *DataType) const;
- /// \brief Return true if the target supports masked gather/scatter
+ /// Return true if the target supports masked gather/scatter
/// AVX-512 fully supports gather and scatter for vectors with 32 and 64
/// bits scalar type.
bool isLegalMaskedScatter(Type *DataType) const;
@@ -499,7 +515,7 @@ public:
/// Return true if target doesn't mind addresses in vectors.
bool prefersVectorizedAddressing() const;
- /// \brief Return the cost of the scaling factor used in the addressing
+ /// Return the cost of the scaling factor used in the addressing
/// mode represented by AM for this target, for a load/store
/// of the specified type.
/// If the AM is supported, the return value must be >= 0.
@@ -509,38 +525,44 @@ public:
bool HasBaseReg, int64_t Scale,
unsigned AddrSpace = 0) const;
- /// \brief Return true if the loop strength reduce pass should make
+ /// Return true if the loop strength reduce pass should make
/// Instruction* based TTI queries to isLegalAddressingMode(). This is
/// needed on SystemZ, where e.g. a memcpy can only have a 12 bit unsigned
/// immediate offset and no index register.
bool LSRWithInstrQueries() const;
- /// \brief Return true if it's free to truncate a value of type Ty1 to type
+ /// 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.
bool isTruncateFree(Type *Ty1, Type *Ty2) const;
- /// \brief Return true if it is profitable to hoist instruction in the
+ /// 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.
+ bool useAA() const;
+
+ /// Return true if this type is legal.
bool isTypeLegal(Type *Ty) const;
- /// \brief Returns the target's jmp_buf alignment in bytes.
+ /// Returns the target's jmp_buf alignment in bytes.
unsigned getJumpBufAlignment() const;
- /// \brief Returns the target's jmp_buf size in bytes.
+ /// Returns the target's jmp_buf size in bytes.
unsigned getJumpBufSize() const;
- /// \brief Return true if switches should be turned into lookup tables for the
+ /// Return true if switches should be turned into lookup tables for the
/// target.
bool shouldBuildLookupTables() const;
- /// \brief Return true if switches should be turned into lookup tables
+ /// Return true if switches should be turned into lookup tables
/// containing this constant value for the target.
bool shouldBuildLookupTablesForConstant(Constant *C) const;
+ /// Return true if the input function which is cold at all call sites,
+ /// should use coldcc calling convention.
+ bool useColdCCForColdCall(Function &F) const;
+
unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) const;
unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
@@ -551,10 +573,10 @@ public:
/// the scalarization cost of a load/store.
bool supportsEfficientVectorElementLoadStore() const;
- /// \brief Don't restrict interleaved unrolling to small loops.
+ /// Don't restrict interleaved unrolling to small loops.
bool enableAggressiveInterleaving(bool LoopHasReductions) const;
- /// \brief If not nullptr, enable inline expansion of memcmp. IsZeroCmp is
+ /// If not nullptr, enable inline expansion of memcmp. IsZeroCmp is
/// true if this is the expansion of memcmp(p1, p2, s) == 0.
struct MemCmpExpansionOptions {
// The list of available load sizes (in bytes), sorted in decreasing order.
@@ -562,10 +584,10 @@ public:
};
const MemCmpExpansionOptions *enableMemCmpExpansion(bool IsZeroCmp) const;
- /// \brief Enable matching of interleaved access groups.
+ /// Enable matching of interleaved access groups.
bool enableInterleavedAccessVectorization() const;
- /// \brief Indicate that it is potentially unsafe to automatically vectorize
+ /// Indicate that it is potentially unsafe to automatically vectorize
/// floating-point operations because the semantics of vector and scalar
/// floating-point semantics may differ. For example, ARM NEON v7 SIMD math
/// does not support IEEE-754 denormal numbers, while depending on the
@@ -574,16 +596,16 @@ public:
/// operations, shuffles, or casts.
bool isFPVectorizationPotentiallyUnsafe() const;
- /// \brief Determine if the target supports unaligned memory accesses.
+ /// Determine if the target supports unaligned memory accesses.
bool allowsMisalignedMemoryAccesses(LLVMContext &Context,
unsigned BitWidth, unsigned AddressSpace = 0,
unsigned Alignment = 1,
bool *Fast = nullptr) const;
- /// \brief Return hardware support for population count.
+ /// Return hardware support for population count.
PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
- /// \brief Return true if the hardware has a fast square-root instruction.
+ /// Return true if the hardware has a fast square-root instruction.
bool haveFastSqrt(Type *Ty) const;
/// Return true if it is faster to check if a floating-point value is NaN
@@ -592,15 +614,15 @@ public:
/// generally as cheap as checking for ordered/unordered.
bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) const;
- /// \brief Return the expected cost of supporting the floating point operation
+ /// Return the expected cost of supporting the floating point operation
/// of the specified type.
int getFPOpCost(Type *Ty) const;
- /// \brief Return the expected cost of materializing for the given integer
+ /// Return the expected cost of materializing for the given integer
/// immediate of the specified type.
int getIntImmCost(const APInt &Imm, Type *Ty) const;
- /// \brief Return the expected cost of materialization for the given integer
+ /// 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.
int getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
@@ -608,7 +630,7 @@ public:
int getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
Type *Ty) const;
- /// \brief Return the expected cost for the given integer when optimising
+ /// Return the expected cost for the given integer when optimising
/// for size. This is different than the other integer immediate cost
/// functions in that it is subtarget agnostic. This is useful when you e.g.
/// target one ISA such as Aarch32 but smaller encodings could be possible
@@ -622,11 +644,14 @@ public:
/// \name Vector Target Information
/// @{
- /// \brief The various kinds of shuffle patterns for vector queries.
+ /// The various kinds of shuffle patterns for vector queries.
enum ShuffleKind {
SK_Broadcast, ///< Broadcast element 0 to all other elements.
SK_Reverse, ///< Reverse the order of the vector.
- SK_Alternate, ///< Choose alternate elements from vector.
+ SK_Select, ///< Selects elements from the corresponding lane of
+ ///< either source operand. This is equivalent to a
+ ///< vector select with a constant condition operand.
+ SK_Transpose, ///< Transpose two vectors.
SK_InsertSubvector, ///< InsertSubvector. Index indicates start offset.
SK_ExtractSubvector,///< ExtractSubvector Index indicates start offset.
SK_PermuteTwoSrc, ///< Merge elements from two source vectors into one
@@ -635,7 +660,7 @@ public:
///< shuffle mask.
};
- /// \brief Additional information about an operand's possible values.
+ /// 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).
@@ -643,7 +668,7 @@ public:
OK_NonUniformConstantValue // Operand is a non uniform constant value.
};
- /// \brief Additional properties of an operand's values.
+ /// Additional properties of an operand's values.
enum OperandValueProperties { OP_None = 0, OP_PowerOf2 = 1 };
/// \return The number of scalar or vector registers that the target has.
@@ -657,6 +682,19 @@ public:
/// \return The width of the smallest vector register type.
unsigned getMinVectorRegisterBitWidth() const;
+ /// \return True if the vectorization factor should be chosen to
+ /// make the vector of the smallest element type match the size of a
+ /// vector register. For wider element types, this could result in
+ /// creating vectors that span multiple vector registers.
+ /// If false, the vectorization factor will be chosen based on the
+ /// size of the widest element type.
+ bool shouldMaximizeVectorBandwidth(bool OptSize) const;
+
+ /// \return The minimum vectorization factor for types of given element
+ /// bit width, or 0 if there is no mimimum VF. The returned value only
+ /// applies when shouldMaximizeVectorBandwidth returns true.
+ unsigned getMinimumVF(unsigned ElemWidth) const;
+
/// \return True if it should be considered for address type promotion.
/// \p AllowPromotionWithoutCommonHeader Set true if promoting \p I is
/// profitable without finding other extensions fed by the same input.
@@ -701,10 +739,20 @@ public:
/// and the number of execution units in the CPU.
unsigned getMaxInterleaveFactor(unsigned VF) const;
- /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc.
- /// \p Args is an optional argument which holds the instruction operands
- /// values so the TTI can analyize those values searching for special
- /// cases\optimizations based on those values.
+ /// This is an approximation of reciprocal throughput of a math/logic op.
+ /// A higher cost indicates less expected throughput.
+ /// From Agner Fog's guides, reciprocal throughput is "the average number of
+ /// clock cycles per instruction when the instructions are not part of a
+ /// limiting dependency chain."
+ /// Therefore, costs should be scaled to account for multiple execution units
+ /// on the target that can process this type of instruction. For example, if
+ /// there are 5 scalar integer units and 2 vector integer units that can
+ /// calculate an 'add' in a single cycle, this model should indicate that the
+ /// cost of the vector add instruction is 2.5 times the cost of the scalar
+ /// add instruction.
+ /// \p Args is an optional argument which holds the instruction operands
+ /// values so the TTI can analyze those values searching for special
+ /// cases or optimizations based on those values.
int getArithmeticInstrCost(
unsigned Opcode, Type *Ty, OperandValueKind Opd1Info = OK_AnyValue,
OperandValueKind Opd2Info = OK_AnyValue,
@@ -773,7 +821,7 @@ public:
ArrayRef<unsigned> Indices, unsigned Alignment,
unsigned AddressSpace) const;
- /// \brief Calculate the cost of performing a vector reduction.
+ /// Calculate the cost of performing a vector reduction.
///
/// This is the cost of reducing the vector value of type \p Ty to a scalar
/// value using the operation denoted by \p Opcode. The form of the reduction
@@ -867,6 +915,21 @@ public:
bool areInlineCompatible(const Function *Caller,
const Function *Callee) const;
+ /// The type of load/store indexing.
+ enum MemIndexedMode {
+ MIM_Unindexed, ///< No indexing.
+ MIM_PreInc, ///< Pre-incrementing.
+ MIM_PreDec, ///< Pre-decrementing.
+ MIM_PostInc, ///< Post-incrementing.
+ MIM_PostDec ///< Post-decrementing.
+ };
+
+ /// \returns True if the specified indexed load for the given type is legal.
+ bool isIndexedLoadLegal(enum MemIndexedMode Mode, Type *Ty) const;
+
+ /// \returns True if the specified indexed store for the given type is legal.
+ bool isIndexedStoreLegal(enum MemIndexedMode Mode, Type *Ty) const;
+
/// \returns The bitwidth of the largest vector type that should be used to
/// load/store in the given address space.
unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const;
@@ -918,19 +981,19 @@ public:
/// @}
private:
- /// \brief Estimate the latency of specified instruction.
+ /// Estimate the latency of specified instruction.
/// Returns 1 as the default value.
int getInstructionLatency(const Instruction *I) const;
- /// \brief Returns the expected throughput cost of the instruction.
+ /// Returns the expected throughput cost of the instruction.
/// Returns -1 if the cost is unknown.
int getInstructionThroughput(const Instruction *I) const;
- /// \brief The abstract base class used to type erase specific TTI
+ /// 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
+ /// The template model for the base class which wraps a concrete
/// implementation in a type erased interface.
template <typename T> class Model;
@@ -974,6 +1037,8 @@ public:
Instruction *I) = 0;
virtual bool isLSRCostLess(TargetTransformInfo::LSRCost &C1,
TargetTransformInfo::LSRCost &C2) = 0;
+ virtual bool canMacroFuseCmp() = 0;
+ virtual bool shouldFavorPostInc() const = 0;
virtual bool isLegalMaskedStore(Type *DataType) = 0;
virtual bool isLegalMaskedLoad(Type *DataType) = 0;
virtual bool isLegalMaskedScatter(Type *DataType) = 0;
@@ -987,11 +1052,13 @@ public:
virtual bool LSRWithInstrQueries() = 0;
virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0;
virtual bool isProfitableToHoist(Instruction *I) = 0;
+ virtual bool useAA() = 0;
virtual bool isTypeLegal(Type *Ty) = 0;
virtual unsigned getJumpBufAlignment() = 0;
virtual unsigned getJumpBufSize() = 0;
virtual bool shouldBuildLookupTables() = 0;
virtual bool shouldBuildLookupTablesForConstant(Constant *C) = 0;
+ virtual bool useColdCCForColdCall(Function &F) = 0;
virtual unsigned
getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) = 0;
virtual unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
@@ -1021,6 +1088,8 @@ public:
virtual unsigned getNumberOfRegisters(bool Vector) = 0;
virtual unsigned getRegisterBitWidth(bool Vector) const = 0;
virtual unsigned getMinVectorRegisterBitWidth() = 0;
+ virtual bool shouldMaximizeVectorBandwidth(bool OptSize) const = 0;
+ virtual unsigned getMinimumVF(unsigned ElemWidth) const = 0;
virtual bool shouldConsiderAddressTypePromotion(
const Instruction &I, bool &AllowPromotionWithoutCommonHeader) = 0;
virtual unsigned getCacheLineSize() = 0;
@@ -1088,6 +1157,8 @@ public:
unsigned RemainingBytes, unsigned SrcAlign, unsigned DestAlign) const = 0;
virtual bool areInlineCompatible(const Function *Caller,
const Function *Callee) const = 0;
+ virtual bool isIndexedLoadLegal(MemIndexedMode Mode, Type *Ty) const = 0;
+ virtual bool isIndexedStoreLegal(MemIndexedMode Mode,Type *Ty) const = 0;
virtual unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const = 0;
virtual bool isLegalToVectorizeLoad(LoadInst *LI) const = 0;
virtual bool isLegalToVectorizeStore(StoreInst *SI) const = 0;
@@ -1192,6 +1263,12 @@ public:
TargetTransformInfo::LSRCost &C2) override {
return Impl.isLSRCostLess(C1, C2);
}
+ bool canMacroFuseCmp() override {
+ return Impl.canMacroFuseCmp();
+ }
+ bool shouldFavorPostInc() const override {
+ return Impl.shouldFavorPostInc();
+ }
bool isLegalMaskedStore(Type *DataType) override {
return Impl.isLegalMaskedStore(DataType);
}
@@ -1228,6 +1305,7 @@ public:
bool isProfitableToHoist(Instruction *I) override {
return Impl.isProfitableToHoist(I);
}
+ bool useAA() override { return Impl.useAA(); }
bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); }
unsigned getJumpBufAlignment() override { return Impl.getJumpBufAlignment(); }
unsigned getJumpBufSize() override { return Impl.getJumpBufSize(); }
@@ -1237,6 +1315,10 @@ public:
bool shouldBuildLookupTablesForConstant(Constant *C) override {
return Impl.shouldBuildLookupTablesForConstant(C);
}
+ bool useColdCCForColdCall(Function &F) override {
+ return Impl.useColdCCForColdCall(F);
+ }
+
unsigned getScalarizationOverhead(Type *Ty, bool Insert,
bool Extract) override {
return Impl.getScalarizationOverhead(Ty, Insert, Extract);
@@ -1304,6 +1386,12 @@ public:
unsigned getMinVectorRegisterBitWidth() override {
return Impl.getMinVectorRegisterBitWidth();
}
+ bool shouldMaximizeVectorBandwidth(bool OptSize) const override {
+ return Impl.shouldMaximizeVectorBandwidth(OptSize);
+ }
+ unsigned getMinimumVF(unsigned ElemWidth) const override {
+ return Impl.getMinimumVF(ElemWidth);
+ }
bool shouldConsiderAddressTypePromotion(
const Instruction &I, bool &AllowPromotionWithoutCommonHeader) override {
return Impl.shouldConsiderAddressTypePromotion(
@@ -1442,6 +1530,12 @@ public:
const Function *Callee) const override {
return Impl.areInlineCompatible(Caller, Callee);
}
+ bool isIndexedLoadLegal(MemIndexedMode Mode, Type *Ty) const override {
+ return Impl.isIndexedLoadLegal(Mode, Ty, getDataLayout());
+ }
+ bool isIndexedStoreLegal(MemIndexedMode Mode, Type *Ty) const override {
+ return Impl.isIndexedStoreLegal(Mode, Ty, getDataLayout());
+ }
unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const override {
return Impl.getLoadStoreVecRegBitWidth(AddrSpace);
}
@@ -1489,7 +1583,7 @@ template <typename T>
TargetTransformInfo::TargetTransformInfo(T Impl)
: TTIImpl(new Model<T>(Impl)) {}
-/// \brief Analysis pass providing the \c TargetTransformInfo.
+/// 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
@@ -1504,13 +1598,13 @@ class TargetIRAnalysis : public AnalysisInfoMixin<TargetIRAnalysis> {
public:
typedef TargetTransformInfo Result;
- /// \brief Default construct a target IR analysis.
+ /// 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.
+ /// 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.
@@ -1536,7 +1630,7 @@ private:
friend AnalysisInfoMixin<TargetIRAnalysis>;
static AnalysisKey Key;
- /// \brief The callback used to produce a result.
+ /// 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.
@@ -1548,11 +1642,11 @@ private:
/// the external TargetMachine, and that reference needs to never dangle.
std::function<Result(const Function &)> TTICallback;
- /// \brief Helper function used as the callback in the default constructor.
+ /// Helper function used as the callback in the default constructor.
static Result getDefaultTTI(const Function &F);
};
-/// \brief Wrapper pass for TargetTransformInfo.
+/// Wrapper pass for TargetTransformInfo.
///
/// This pass can be constructed from a TTI object which it stores internally
/// and is queried by passes.
@@ -1565,7 +1659,7 @@ class TargetTransformInfoWrapperPass : public ImmutablePass {
public:
static char ID;
- /// \brief We must provide a default constructor for the pass but it should
+ /// 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.
@@ -1576,7 +1670,7 @@ public:
TargetTransformInfo &getTTI(const Function &F);
};
-/// \brief Create an analysis pass wrapper around a TTI object.
+/// Create an analysis pass wrapper around a TTI object.
///
/// This analysis pass just holds the TTI instance and makes it available to
/// clients.
diff --git a/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index 4c37402278ef..e14e2bd44034 100644
--- a/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -27,7 +27,7 @@
namespace llvm {
-/// \brief Base class for use as a mix-in that aids implementing
+/// Base class for use as a mix-in that aids implementing
/// a TargetTransformInfo-compatible class.
class TargetTransformInfoImplBase {
protected:
@@ -155,6 +155,7 @@ public:
case Intrinsic::sideeffect:
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_label:
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
case Intrinsic::lifetime_start:
@@ -246,6 +247,10 @@ public:
C2.ScaleCost, C2.ImmCost, C2.SetupCost);
}
+ bool canMacroFuseCmp() { return false; }
+
+ bool shouldFavorPostInc() const { return false; }
+
bool isLegalMaskedStore(Type *DataType) { return false; }
bool isLegalMaskedLoad(Type *DataType) { return false; }
@@ -275,6 +280,8 @@ public:
bool isProfitableToHoist(Instruction *I) { return true; }
+ bool useAA() { return false; }
+
bool isTypeLegal(Type *Ty) { return false; }
unsigned getJumpBufAlignment() { return 0; }
@@ -284,6 +291,8 @@ public:
bool shouldBuildLookupTables() { return true; }
bool shouldBuildLookupTablesForConstant(Constant *C) { return true; }
+ bool useColdCCForColdCall(Function &F) { return false; }
+
unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) {
return 0;
}
@@ -343,6 +352,10 @@ public:
unsigned getMinVectorRegisterBitWidth() { return 128; }
+ bool shouldMaximizeVectorBandwidth(bool OptSize) const { return false; }
+
+ unsigned getMinimumVF(unsigned ElemWidth) const { return 0; }
+
bool
shouldConsiderAddressTypePromotion(const Instruction &I,
bool &AllowPromotionWithoutCommonHeader) {
@@ -507,6 +520,16 @@ public:
Callee->getFnAttribute("target-features"));
}
+ bool isIndexedLoadLegal(TTI::MemIndexedMode Mode, Type *Ty,
+ const DataLayout &DL) const {
+ return false;
+ }
+
+ bool isIndexedStoreLegal(TTI::MemIndexedMode Mode, Type *Ty,
+ const DataLayout &DL) const {
+ return false;
+ }
+
unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const { return 128; }
bool isLegalToVectorizeLoad(LoadInst *LI) const { return true; }
@@ -629,7 +652,7 @@ protected:
}
};
-/// \brief CRTP base class for use as a mix-in that aids implementing
+/// CRTP base class for use as a mix-in that aids implementing
/// a TargetTransformInfo-compatible class.
template <typename T>
class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase {
diff --git a/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h b/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h
index 422e153a5a78..6764563f6830 100644
--- a/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h
+++ b/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h
@@ -35,13 +35,13 @@ struct DevirtCallSite {
CallSite CS;
};
-/// Given a call to the intrinsic @llvm.type.test, find all devirtualizable
+/// Given a call to the intrinsic \@llvm.type.test, find all devirtualizable
/// call sites based on the call and return them in DevirtCalls.
void findDevirtualizableCallsForTypeTest(
SmallVectorImpl<DevirtCallSite> &DevirtCalls,
SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI);
-/// Given a call to the intrinsic @llvm.type.checked.load, find all
+/// Given a call to the intrinsic \@llvm.type.checked.load, find all
/// devirtualizable call sites based on the call and return them in DevirtCalls.
void findDevirtualizableCallsForTypeCheckedLoad(
SmallVectorImpl<DevirtCallSite> &DevirtCalls,
diff --git a/contrib/llvm/include/llvm/Analysis/Utils/Local.h b/contrib/llvm/include/llvm/Analysis/Utils/Local.h
new file mode 100644
index 000000000000..b4141bbff28d
--- /dev/null
+++ b/contrib/llvm/include/llvm/Analysis/Utils/Local.h
@@ -0,0 +1,91 @@
+//===- Local.h - Functions to perform local transformations -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This family of functions perform various local transformations to the
+// program.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_UTILS_LOCAL_H
+#define LLVM_ANALYSIS_UTILS_LOCAL_H
+
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/GetElementPtrTypeIterator.h"
+
+namespace llvm {
+
+/// Given a getelementptr instruction/constantexpr, emit the code necessary to
+/// compute the offset from the base pointer (without adding in the base
+/// pointer). Return the result as a signed integer of intptr size.
+/// When NoAssumptions is true, no assumptions about index computation not
+/// overflowing is made.
+template <typename IRBuilderTy>
+Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP,
+ bool NoAssumptions = false) {
+ GEPOperator *GEPOp = cast<GEPOperator>(GEP);
+ Type *IntPtrTy = DL.getIntPtrType(GEP->getType());
+ Value *Result = Constant::getNullValue(IntPtrTy);
+
+ // If the GEP is inbounds, we know that none of the addressing operations will
+ // overflow in an unsigned sense.
+ bool isInBounds = GEPOp->isInBounds() && !NoAssumptions;
+
+ // Build a mask for high order bits.
+ unsigned IntPtrWidth = IntPtrTy->getScalarType()->getIntegerBitWidth();
+ uint64_t PtrSizeMask =
+ std::numeric_limits<uint64_t>::max() >> (64 - IntPtrWidth);
+
+ gep_type_iterator GTI = gep_type_begin(GEP);
+ for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e;
+ ++i, ++GTI) {
+ Value *Op = *i;
+ uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask;
+ if (Constant *OpC = dyn_cast<Constant>(Op)) {
+ if (OpC->isZeroValue())
+ continue;
+
+ // Handle a struct index, which adds its field offset to the pointer.
+ if (StructType *STy = GTI.getStructTypeOrNull()) {
+ if (OpC->getType()->isVectorTy())
+ OpC = OpC->getSplatValue();
+
+ uint64_t OpValue = cast<ConstantInt>(OpC)->getZExtValue();
+ Size = DL.getStructLayout(STy)->getElementOffset(OpValue);
+
+ if (Size)
+ Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size),
+ GEP->getName()+".offs");
+ continue;
+ }
+
+ Constant *Scale = ConstantInt::get(IntPtrTy, Size);
+ Constant *OC = ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/);
+ Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/);
+ // Emit an add instruction.
+ Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs");
+ continue;
+ }
+ // Convert to correct type.
+ if (Op->getType() != IntPtrTy)
+ Op = Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c");
+ if (Size != 1) {
+ // We'll let instcombine(mul) convert this to a shl if possible.
+ Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size),
+ GEP->getName()+".idx", isInBounds /*NUW*/);
+ }
+
+ // Emit an add instruction.
+ Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs");
+ }
+ return Result;
+}
+
+}
+
+#endif // LLVM_TRANSFORMS_UTILS_LOCAL_H
diff --git a/contrib/llvm/include/llvm/Analysis/ValueLattice.h b/contrib/llvm/include/llvm/Analysis/ValueLattice.h
index 18a43aafa8ca..0744ca617e48 100644
--- a/contrib/llvm/include/llvm/Analysis/ValueLattice.h
+++ b/contrib/llvm/include/llvm/Analysis/ValueLattice.h
@@ -49,14 +49,73 @@ class ValueLatticeElement {
overdefined
};
- /// Val: This stores the current lattice value along with the Constant* for
- /// the constant if this is a 'constant' or 'notconstant' value.
ValueLatticeElementTy Tag;
- Constant *Val;
- ConstantRange Range;
+
+ /// The union either stores a pointer to a constant or a constant range,
+ /// associated to the lattice element. We have to ensure that Range is
+ /// initialized or destroyed when changing state to or from constantrange.
+ union {
+ Constant *ConstVal;
+ ConstantRange Range;
+ };
public:
- ValueLatticeElement() : Tag(undefined), Val(nullptr), Range(1, true) {}
+ // Const and Range are initialized on-demand.
+ ValueLatticeElement() : Tag(undefined) {}
+
+ /// Custom destructor to ensure Range is properly destroyed, when the object
+ /// is deallocated.
+ ~ValueLatticeElement() {
+ switch (Tag) {
+ case overdefined:
+ case undefined:
+ case constant:
+ case notconstant:
+ break;
+ case constantrange:
+ Range.~ConstantRange();
+ break;
+ };
+ }
+
+ /// Custom copy constructor, to ensure Range gets initialized when
+ /// copying a constant range lattice element.
+ ValueLatticeElement(const ValueLatticeElement &Other) : Tag(undefined) {
+ *this = Other;
+ }
+
+ /// Custom assignment operator, to ensure Range gets initialized when
+ /// assigning a constant range lattice element.
+ ValueLatticeElement &operator=(const ValueLatticeElement &Other) {
+ // If we change the state of this from constant range to non constant range,
+ // destroy Range.
+ if (isConstantRange() && !Other.isConstantRange())
+ Range.~ConstantRange();
+
+ // If we change the state of this from a valid ConstVal to another a state
+ // without a valid ConstVal, zero the pointer.
+ if ((isConstant() || isNotConstant()) && !Other.isConstant() &&
+ !Other.isNotConstant())
+ ConstVal = nullptr;
+
+ switch (Other.Tag) {
+ case constantrange:
+ if (!isConstantRange())
+ new (&Range) ConstantRange(Other.Range);
+ else
+ Range = Other.Range;
+ break;
+ case constant:
+ case notconstant:
+ ConstVal = Other.ConstVal;
+ break;
+ case overdefined:
+ case undefined:
+ break;
+ }
+ Tag = Other.Tag;
+ return *this;
+ }
static ValueLatticeElement get(Constant *C) {
ValueLatticeElement Res;
@@ -89,12 +148,12 @@ public:
Constant *getConstant() const {
assert(isConstant() && "Cannot get the constant of a non-constant!");
- return Val;
+ return ConstVal;
}
Constant *getNotConstant() const {
assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
- return Val;
+ return ConstVal;
}
const ConstantRange &getConstantRange() const {
@@ -104,10 +163,10 @@ public:
}
Optional<APInt> asConstantInteger() const {
- if (isConstant() && isa<ConstantInt>(Val)) {
- return cast<ConstantInt>(Val)->getValue();
- } else if (isConstantRange() && Range.isSingleElement()) {
- return *Range.getSingleElement();
+ if (isConstant() && isa<ConstantInt>(getConstant())) {
+ return cast<ConstantInt>(getConstant())->getValue();
+ } else if (isConstantRange() && getConstantRange().isSingleElement()) {
+ return *getConstantRange().getSingleElement();
}
return None;
}
@@ -116,6 +175,10 @@ private:
void markOverdefined() {
if (isOverdefined())
return;
+ if (isConstant() || isNotConstant())
+ ConstVal = nullptr;
+ if (isConstantRange())
+ Range.~ConstantRange();
Tag = overdefined;
}
@@ -132,7 +195,7 @@ private:
"Marking constant with different value");
assert(isUndefined());
Tag = constant;
- Val = V;
+ ConstVal = V;
}
void markNotConstant(Constant *V) {
@@ -150,7 +213,7 @@ private:
"Marking !constant with different value");
assert(isUndefined() || isConstant());
Tag = notconstant;
- Val = V;
+ ConstVal = V;
}
void markConstantRange(ConstantRange NewR) {
@@ -168,7 +231,7 @@ private:
markOverdefined();
else {
Tag = constantrange;
- Range = std::move(NewR);
+ new (&Range) ConstantRange(std::move(NewR));
}
}
@@ -189,14 +252,14 @@ public:
}
if (isConstant()) {
- if (RHS.isConstant() && Val == RHS.Val)
+ if (RHS.isConstant() && getConstant() == RHS.getConstant())
return false;
markOverdefined();
return true;
}
if (isNotConstant()) {
- if (RHS.isNotConstant() && Val == RHS.Val)
+ if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant())
return false;
markOverdefined();
return true;
@@ -209,9 +272,11 @@ public:
markOverdefined();
return true;
}
- ConstantRange NewR = Range.unionWith(RHS.getConstantRange());
+ ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
if (NewR.isFullSet())
markOverdefined();
+ else if (NewR == getConstantRange())
+ return false;
else
markConstantRange(std::move(NewR));
return true;
@@ -223,24 +288,32 @@ public:
return cast<ConstantInt>(getConstant());
}
- bool satisfiesPredicate(CmpInst::Predicate Pred,
- const ValueLatticeElement &Other) const {
- // TODO: share with LVI getPredicateResult.
-
+ /// Compares this symbolic value with Other using Pred and returns either
+ /// true, false or undef constants, or nullptr if the comparison cannot be
+ /// evaluated.
+ Constant *getCompare(CmpInst::Predicate Pred, Type *Ty,
+ const ValueLatticeElement &Other) const {
if (isUndefined() || Other.isUndefined())
- return true;
+ return UndefValue::get(Ty);
- if (isConstant() && Other.isConstant() && Pred == CmpInst::FCMP_OEQ)
- return getConstant() == Other.getConstant();
+ if (isConstant() && Other.isConstant())
+ return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant());
// Integer constants are represented as ConstantRanges with single
// elements.
if (!isConstantRange() || !Other.isConstantRange())
- return false;
+ return nullptr;
const auto &CR = getConstantRange();
const auto &OtherCR = Other.getConstantRange();
- return ConstantRange::makeSatisfyingICmpRegion(Pred, OtherCR).contains(CR);
+ if (ConstantRange::makeSatisfyingICmpRegion(Pred, OtherCR).contains(CR))
+ return ConstantInt::getTrue(Ty);
+ if (ConstantRange::makeSatisfyingICmpRegion(
+ CmpInst::getInversePredicate(Pred), OtherCR)
+ .contains(CR))
+ return ConstantInt::getFalse(Ty);
+
+ return nullptr;
}
};
diff --git a/contrib/llvm/include/llvm/Analysis/ValueTracking.h b/contrib/llvm/include/llvm/Analysis/ValueTracking.h
index 1fdb3cff5372..e6a219a8045b 100644
--- a/contrib/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/contrib/llvm/include/llvm/Analysis/ValueTracking.h
@@ -101,6 +101,12 @@ class Value;
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
+ /// Return true if the two given values are negation.
+ /// Currently can recoginze Value pair:
+ /// 1: <X, Y> if X = sub (0, Y) or Y = sub (0, X)
+ /// 2: <X, Y> if X = sub (A, B) and Y = sub (B, A)
+ bool isKnownNegation(const Value *X, const Value *Y, bool NeedNSW = false);
+
/// Returns true if the give value is known to be non-negative.
bool isKnownNonNegative(const Value *V, const DataLayout &DL,
unsigned Depth = 0,
@@ -276,6 +282,22 @@ class Value;
/// pointer, return 'len+1'. If we can't, return 0.
uint64_t GetStringLength(const Value *V, unsigned CharSize = 8);
+ /// This function returns call pointer argument that is considered the same by
+ /// aliasing rules. You CAN'T use it to replace one value with another.
+ const Value *getArgumentAliasingToReturnedPointer(ImmutableCallSite CS);
+ inline Value *getArgumentAliasingToReturnedPointer(CallSite CS) {
+ return const_cast<Value *>(
+ getArgumentAliasingToReturnedPointer(ImmutableCallSite(CS)));
+ }
+
+ // {launder,strip}.invariant.group returns pointer that aliases its argument,
+ // and it only captures pointer by returning it.
+ // These intrinsics are not marked as nocapture, because returning is
+ // considered as capture. The arguments are not marked as returned neither,
+ // because it would make it useless.
+ bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
+ ImmutableCallSite CS);
+
/// This method strips off any GEP address adjustments and pointer casts from
/// the specified value, returning the original object being addressed. Note
/// that the returned value has pointer type if the specified value does. If
@@ -288,7 +310,7 @@ class Value;
return GetUnderlyingObject(const_cast<Value *>(V), DL, MaxLookup);
}
- /// \brief This method is similar to GetUnderlyingObject except that it can
+ /// This method is similar to GetUnderlyingObject except that it can
/// look through phi and select instructions and return multiple objects.
///
/// If LoopInfo is passed, loop phis are further analyzed. If a pointer
@@ -384,6 +406,11 @@ class Value;
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
+ OverflowResult computeOverflowForSignedMul(const Value *LHS, const Value *RHS,
+ const DataLayout &DL,
+ AssumptionCache *AC,
+ const Instruction *CxtI,
+ const DominatorTree *DT);
OverflowResult computeOverflowForUnsignedAdd(const Value *LHS,
const Value *RHS,
const DataLayout &DL,
@@ -401,6 +428,16 @@ class Value;
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
+ OverflowResult computeOverflowForUnsignedSub(const Value *LHS, const Value *RHS,
+ const DataLayout &DL,
+ AssumptionCache *AC,
+ const Instruction *CxtI,
+ const DominatorTree *DT);
+ OverflowResult computeOverflowForSignedSub(const Value *LHS, const Value *RHS,
+ const DataLayout &DL,
+ AssumptionCache *AC,
+ const Instruction *CxtI,
+ const DominatorTree *DT);
/// Returns true if the arithmetic part of the \p II 's result is
/// used only along the paths control dependent on the computation
@@ -423,6 +460,13 @@ class Value;
/// though division by zero might cause undefined behavior.
bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I);
+ /// Returns true if this block does not contain a potential implicit exit.
+ /// This is equivelent to saying that all instructions within the basic block
+ /// are guaranteed to transfer execution to their successor within the basic
+ /// block. This has the same assumptions w.r.t. undefined behavior as the
+ /// instruction variant of this function.
+ bool isGuaranteedToTransferExecutionToSuccessor(const BasicBlock *BB);
+
/// Return true if this function can prove that the instruction I
/// is executed for every iteration of the loop L.
///
@@ -454,7 +498,7 @@ class Value;
/// the parent of I.
bool programUndefinedIfFullPoison(const Instruction *PoisonI);
- /// \brief Specific patterns of select instructions we can match.
+ /// Specific patterns of select instructions we can match.
enum SelectPatternFlavor {
SPF_UNKNOWN = 0,
SPF_SMIN, /// Signed minimum
@@ -467,7 +511,7 @@ class Value;
SPF_NABS /// Negated absolute value
};
- /// \brief Behavior when a floating point min/max is given one NaN and one
+ /// Behavior when a floating point min/max is given one NaN and one
/// non-NaN as input.
enum SelectPatternNaNBehavior {
SPNB_NA = 0, /// NaN behavior not applicable.
@@ -486,15 +530,18 @@ class Value;
/// fcmp; select, does the fcmp have to be
/// ordered?
- /// \brief Return true if \p SPF is a min or a max pattern.
+ /// Return true if \p SPF is a min or a max pattern.
static bool isMinOrMax(SelectPatternFlavor SPF) {
- return !(SPF == SPF_UNKNOWN || SPF == SPF_ABS || SPF == SPF_NABS);
+ return SPF != SPF_UNKNOWN && SPF != SPF_ABS && SPF != SPF_NABS;
}
};
/// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind
/// and providing the out parameter results if we successfully match.
///
+ /// For ABS/NABS, LHS will be set to the input to the abs idiom. RHS will be
+ /// the negation instruction from the idiom.
+ ///
/// If CastOp is not nullptr, also match MIN/MAX idioms where the type does
/// not match that of the original select. If this is the case, the cast
/// operation (one of Trunc,SExt,Zext) that must be done to transform the
@@ -521,6 +568,19 @@ class Value;
return Result;
}
+ /// Return the canonical comparison predicate for the specified
+ /// minimum/maximum flavor.
+ CmpInst::Predicate getMinMaxPred(SelectPatternFlavor SPF,
+ bool Ordered = false);
+
+ /// Return the inverse minimum/maximum flavor of the specified flavor.
+ /// For example, signed minimum is the inverse of signed maximum.
+ SelectPatternFlavor getInverseMinMaxFlavor(SelectPatternFlavor SPF);
+
+ /// Return the canonical inverse comparison predicate for the specified
+ /// minimum/maximum flavor.
+ CmpInst::Predicate getInverseMinMaxPred(SelectPatternFlavor SPF);
+
/// Return true if RHS is known to be implied true by LHS. Return false if
/// RHS is known to be implied false by LHS. Otherwise, return None if no
/// implication can be made.
diff --git a/contrib/llvm/include/llvm/Analysis/VectorUtils.h b/contrib/llvm/include/llvm/Analysis/VectorUtils.h
index 6315e8408f05..9fde36d61091 100644
--- a/contrib/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/contrib/llvm/include/llvm/Analysis/VectorUtils.h
@@ -33,50 +33,50 @@ namespace Intrinsic {
enum ID : unsigned;
}
-/// \brief Identify if the intrinsic is trivially vectorizable.
+/// Identify if the intrinsic is trivially vectorizable.
/// This method returns true if the intrinsic's argument types are all
/// scalars for the scalar form of the intrinsic and all vectors for
/// the vector form of the intrinsic.
bool isTriviallyVectorizable(Intrinsic::ID ID);
-/// \brief Identifies if the intrinsic has a scalar operand. It checks for
+/// Identifies if the intrinsic has a scalar operand. It checks for
/// ctlz,cttz and powi special intrinsics whose argument is scalar.
bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, unsigned ScalarOpdIdx);
-/// \brief Returns intrinsic ID for call.
+/// Returns intrinsic ID for call.
/// For the input call instruction it finds mapping intrinsic and returns
/// its intrinsic ID, in case it does not found it return not_intrinsic.
Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI,
const TargetLibraryInfo *TLI);
-/// \brief Find the operand of the GEP that should be checked for consecutive
+/// Find the operand of the GEP that should be checked for consecutive
/// stores. This ignores trailing indices that have no effect on the final
/// pointer.
unsigned getGEPInductionOperand(const GetElementPtrInst *Gep);
-/// \brief If the argument is a GEP, then returns the operand identified by
+/// If the argument is a GEP, then returns the operand identified by
/// getGEPInductionOperand. However, if there is some other non-loop-invariant
/// operand, it returns that instead.
Value *stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp);
-/// \brief If a value has only one user that is a CastInst, return it.
+/// If a value has only one user that is a CastInst, return it.
Value *getUniqueCastUse(Value *Ptr, Loop *Lp, Type *Ty);
-/// \brief Get the stride of a pointer access in a loop. Looks for symbolic
+/// Get the stride of a pointer access in a loop. Looks for symbolic
/// strides "a[i*stride]". Returns the symbolic stride, or null otherwise.
Value *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp);
-/// \brief Given a vector and an element number, see if the scalar value is
+/// Given a vector and an element number, see if the scalar value is
/// already around as a register, for example if it were inserted then extracted
/// from the vector.
Value *findScalarElement(Value *V, unsigned EltNo);
-/// \brief Get splat value if the input is a splat vector or return nullptr.
+/// Get splat value if the input is a splat vector or return nullptr.
/// The value may be extracted from a splat constants vector or from
/// a sequence of instructions that broadcast a single value into a vector.
const Value *getSplatValue(const Value *V);
-/// \brief Compute a map of integer instructions to their minimum legal type
+/// Compute a map of integer instructions to their minimum legal type
/// size.
///
/// C semantics force sub-int-sized values (e.g. i8, i16) to be promoted to int
@@ -124,7 +124,7 @@ computeMinimumValueSizes(ArrayRef<BasicBlock*> Blocks,
/// This function always sets a (possibly null) value for each K in Kinds.
Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL);
-/// \brief Create an interleave shuffle mask.
+/// Create an interleave shuffle mask.
///
/// This function creates a shuffle mask for interleaving \p NumVecs vectors of
/// vectorization factor \p VF into a single wide vector. The mask is of the
@@ -138,7 +138,7 @@ Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL);
Constant *createInterleaveMask(IRBuilder<> &Builder, unsigned VF,
unsigned NumVecs);
-/// \brief Create a stride shuffle mask.
+/// Create a stride shuffle mask.
///
/// This function creates a shuffle mask whose elements begin at \p Start and
/// are incremented by \p Stride. The mask can be used to deinterleave an
@@ -153,7 +153,7 @@ Constant *createInterleaveMask(IRBuilder<> &Builder, unsigned VF,
Constant *createStrideMask(IRBuilder<> &Builder, unsigned Start,
unsigned Stride, unsigned VF);
-/// \brief Create a sequential shuffle mask.
+/// Create a sequential shuffle mask.
///
/// This function creates shuffle mask whose elements are sequential and begin
/// at \p Start. The mask contains \p NumInts integers and is padded with \p
@@ -167,7 +167,7 @@ Constant *createStrideMask(IRBuilder<> &Builder, unsigned Start,
Constant *createSequentialMask(IRBuilder<> &Builder, unsigned Start,
unsigned NumInts, unsigned NumUndefs);
-/// \brief Concatenate a list of vectors.
+/// Concatenate a list of vectors.
///
/// This function generates code that concatenate the vectors in \p Vecs into a
/// single large vector. The number of vectors should be greater than one, and
diff --git a/contrib/llvm/include/llvm/AsmParser/Parser.h b/contrib/llvm/include/llvm/AsmParser/Parser.h
index 5f02e488e5b1..285a7c022a24 100644
--- a/contrib/llvm/include/llvm/AsmParser/Parser.h
+++ b/contrib/llvm/include/llvm/AsmParser/Parser.h
@@ -21,50 +21,95 @@ namespace llvm {
class Constant;
class LLVMContext;
class Module;
+class ModuleSummaryIndex;
struct SlotMapping;
class SMDiagnostic;
class Type;
-/// This function is the main interface to the LLVM Assembly Parser. It parses
+/// This function is a main interface to the LLVM Assembly Parser. It parses
/// an ASCII file that (presumably) contains LLVM Assembly code. It returns a
/// Module (intermediate representation) with the corresponding features. Note
/// that this does not verify that the generated Module is valid, so you should
/// run the verifier after parsing the file to check that it is okay.
-/// \brief Parse LLVM Assembly from a file
+/// Parse LLVM Assembly from a file
/// \param Filename The name of the file to parse
-/// \param Error Error result info.
+/// \param Err Error result info.
/// \param Context Context in which to allocate globals info.
/// \param Slots The optional slot mapping that will be initialized during
/// parsing.
/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier.
/// This option should only be set to false by llvm-as
/// for use inside the LLVM testuite!
+/// \param DataLayoutString Override datalayout in the llvm assembly.
std::unique_ptr<Module>
-parseAssemblyFile(StringRef Filename, SMDiagnostic &Error, LLVMContext &Context,
- SlotMapping *Slots = nullptr, bool UpgradeDebugInfo = true);
+parseAssemblyFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context,
+ SlotMapping *Slots = nullptr, bool UpgradeDebugInfo = true,
+ StringRef DataLayoutString = "");
/// The function is a secondary interface to the LLVM Assembly Parser. It parses
/// an ASCII string that (presumably) contains LLVM Assembly code. It returns a
/// Module (intermediate representation) with the corresponding features. Note
/// that this does not verify that the generated Module is valid, so you should
/// run the verifier after parsing the file to check that it is okay.
-/// \brief Parse LLVM Assembly from a string
+/// Parse LLVM Assembly from a string
/// \param AsmString The string containing assembly
-/// \param Error Error result info.
+/// \param Err Error result info.
/// \param Context Context in which to allocate globals info.
/// \param Slots The optional slot mapping that will be initialized during
/// parsing.
/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier.
/// This option should only be set to false by llvm-as
/// for use inside the LLVM testuite!
+/// \param DataLayoutString Override datalayout in the llvm assembly.
std::unique_ptr<Module> parseAssemblyString(StringRef AsmString,
- SMDiagnostic &Error,
+ SMDiagnostic &Err,
LLVMContext &Context,
SlotMapping *Slots = nullptr,
- bool UpgradeDebugInfo = true);
+ bool UpgradeDebugInfo = true,
+ StringRef DataLayoutString = "");
+
+/// Holds the Module and ModuleSummaryIndex returned by the interfaces
+/// that parse both.
+struct ParsedModuleAndIndex {
+ std::unique_ptr<Module> Mod;
+ std::unique_ptr<ModuleSummaryIndex> Index;
+};
+
+/// This function is a main interface to the LLVM Assembly Parser. It parses
+/// an ASCII file that (presumably) contains LLVM Assembly code, including
+/// a module summary. It returns a Module (intermediate representation) and
+/// a ModuleSummaryIndex with the corresponding features. Note that this does
+/// not verify that the generated Module or Index are valid, so you should
+/// run the verifier after parsing the file to check that they are okay.
+/// Parse LLVM Assembly from a file
+/// \param Filename The name of the file to parse
+/// \param Err Error result info.
+/// \param Context Context in which to allocate globals info.
+/// \param Slots The optional slot mapping that will be initialized during
+/// parsing.
+/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier.
+/// This option should only be set to false by llvm-as
+/// for use inside the LLVM testuite!
+/// \param DataLayoutString Override datalayout in the llvm assembly.
+ParsedModuleAndIndex
+parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err,
+ LLVMContext &Context, SlotMapping *Slots = nullptr,
+ bool UpgradeDebugInfo = true,
+ StringRef DataLayoutString = "");
+
+/// This function is a main interface to the LLVM Assembly Parser. It parses
+/// an ASCII file that (presumably) contains LLVM Assembly code for a module
+/// summary. It returns a a ModuleSummaryIndex with the corresponding features.
+/// Note that this does not verify that the generated Index is valid, so you
+/// should run the verifier after parsing the file to check that it is okay.
+/// Parse LLVM Assembly Index from a file
+/// \param Filename The name of the file to parse
+/// \param Err Error result info.
+std::unique_ptr<ModuleSummaryIndex>
+parseSummaryIndexAssemblyFile(StringRef Filename, SMDiagnostic &Err);
/// parseAssemblyFile and parseAssemblyString are wrappers around this function.
-/// \brief Parse LLVM Assembly from a MemoryBuffer.
+/// Parse LLVM Assembly from a MemoryBuffer.
/// \param F The MemoryBuffer containing assembly
/// \param Err Error result info.
/// \param Slots The optional slot mapping that will be initialized during
@@ -72,10 +117,40 @@ std::unique_ptr<Module> parseAssemblyString(StringRef AsmString,
/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier.
/// This option should only be set to false by llvm-as
/// for use inside the LLVM testuite!
+/// \param DataLayoutString Override datalayout in the llvm assembly.
std::unique_ptr<Module> parseAssembly(MemoryBufferRef F, SMDiagnostic &Err,
LLVMContext &Context,
SlotMapping *Slots = nullptr,
- bool UpgradeDebugInfo = true);
+ bool UpgradeDebugInfo = true,
+ StringRef DataLayoutString = "");
+
+/// Parse LLVM Assembly including the summary index from a MemoryBuffer.
+///
+/// \param F The MemoryBuffer containing assembly with summary
+/// \param Err Error result info.
+/// \param Slots The optional slot mapping that will be initialized during
+/// parsing.
+/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier.
+/// This option should only be set to false by llvm-as
+/// for use inside the LLVM testuite!
+/// \param DataLayoutString Override datalayout in the llvm assembly.
+///
+/// parseAssemblyFileWithIndex is a wrapper around this function.
+ParsedModuleAndIndex parseAssemblyWithIndex(MemoryBufferRef F,
+ SMDiagnostic &Err,
+ LLVMContext &Context,
+ SlotMapping *Slots = nullptr,
+ bool UpgradeDebugInfo = true,
+ StringRef DataLayoutString = "");
+
+/// Parse LLVM Assembly for summary index from a MemoryBuffer.
+///
+/// \param F The MemoryBuffer containing assembly with summary
+/// \param Err Error result info.
+///
+/// parseSummaryIndexAssemblyFile is a wrapper around this function.
+std::unique_ptr<ModuleSummaryIndex>
+parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err);
/// This function is the low-level interface to the LLVM Assembly Parser.
/// This is kept as an independent function instead of being inlined into
@@ -84,6 +159,7 @@ std::unique_ptr<Module> parseAssembly(MemoryBufferRef F, SMDiagnostic &Err,
///
/// \param F The MemoryBuffer containing assembly
/// \param M The module to add data to.
+/// \param Index The index to add data to.
/// \param Err Error result info.
/// \param Slots The optional slot mapping that will be initialized during
/// parsing.
@@ -91,9 +167,11 @@ std::unique_ptr<Module> parseAssembly(MemoryBufferRef F, SMDiagnostic &Err,
/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier.
/// This option should only be set to false by llvm-as
/// for use inside the LLVM testuite!
-bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err,
- SlotMapping *Slots = nullptr,
- bool UpgradeDebugInfo = true);
+/// \param DataLayoutString Override datalayout in the llvm assembly.
+bool parseAssemblyInto(MemoryBufferRef F, Module *M, ModuleSummaryIndex *Index,
+ SMDiagnostic &Err, SlotMapping *Slots = nullptr,
+ bool UpgradeDebugInfo = true,
+ StringRef DataLayoutString = "");
/// Parse a type and a constant value in the given string.
///
diff --git a/contrib/llvm/include/llvm/BinaryFormat/COFF.h b/contrib/llvm/include/llvm/BinaryFormat/COFF.h
index a55c544dfe90..7b973c03cc80 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/COFF.h
+++ b/contrib/llvm/include/llvm/BinaryFormat/COFF.h
@@ -110,6 +110,9 @@ enum MachineTypes : unsigned {
IMAGE_FILE_MACHINE_POWERPC = 0x1F0,
IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1,
IMAGE_FILE_MACHINE_R4000 = 0x166,
+ IMAGE_FILE_MACHINE_RISCV32 = 0x5032,
+ IMAGE_FILE_MACHINE_RISCV64 = 0x5064,
+ IMAGE_FILE_MACHINE_RISCV128 = 0x5128,
IMAGE_FILE_MACHINE_SH3 = 0x1A2,
IMAGE_FILE_MACHINE_SH3DSP = 0x1A3,
IMAGE_FILE_MACHINE_SH4 = 0x1A6,
@@ -460,7 +463,7 @@ union Auxiliary {
AuxiliarySectionDefinition SectionDefinition;
};
-/// @brief The Import Directory Table.
+/// The Import Directory Table.
///
/// There is a single array of these and one entry per imported DLL.
struct ImportDirectoryTableEntry {
@@ -471,7 +474,7 @@ struct ImportDirectoryTableEntry {
uint32_t ImportAddressTableRVA;
};
-/// @brief The PE32 Import Lookup Table.
+/// The PE32 Import Lookup Table.
///
/// There is an array of these for each imported DLL. It represents either
/// the ordinal to import from the target DLL, or a name to lookup and import
@@ -482,32 +485,32 @@ struct ImportDirectoryTableEntry {
struct ImportLookupTableEntry32 {
uint32_t data;
- /// @brief Is this entry specified by ordinal, or name?
+ /// Is this entry specified by ordinal, or name?
bool isOrdinal() const { return data & 0x80000000; }
- /// @brief Get the ordinal value of this entry. isOrdinal must be true.
+ /// Get the ordinal value of this entry. isOrdinal must be true.
uint16_t getOrdinal() const {
assert(isOrdinal() && "ILT entry is not an ordinal!");
return data & 0xFFFF;
}
- /// @brief Set the ordinal value and set isOrdinal to true.
+ /// Set the ordinal value and set isOrdinal to true.
void setOrdinal(uint16_t o) {
data = o;
data |= 0x80000000;
}
- /// @brief Get the Hint/Name entry RVA. isOrdinal must be false.
+ /// Get the Hint/Name entry RVA. isOrdinal must be false.
uint32_t getHintNameRVA() const {
assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
return data;
}
- /// @brief Set the Hint/Name entry RVA and set isOrdinal to false.
+ /// Set the Hint/Name entry RVA and set isOrdinal to false.
void setHintNameRVA(uint32_t rva) { data = rva; }
};
-/// @brief The DOS compatible header at the front of all PEs.
+/// The DOS compatible header at the front of all PEs.
struct DOSHeader {
uint16_t Magic;
uint16_t UsedBytesInTheLastPage;
diff --git a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def
index 3ade3ea0d338..57e259615d0c 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -12,15 +12,15 @@
//===----------------------------------------------------------------------===//
// TODO: Add other DW-based macros.
-#if !(defined HANDLE_DW_TAG || defined HANDLE_DW_AT || \
- defined HANDLE_DW_FORM || defined HANDLE_DW_OP || \
- defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \
- defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \
- defined HANDLE_DW_CC || defined HANDLE_DW_LNS || \
- defined HANDLE_DW_LNE || defined HANDLE_DW_LNCT || \
- defined HANDLE_DW_MACRO || defined HANDLE_DW_RLE || \
- defined HANDLE_DW_CFA || defined HANDLE_DW_APPLE_PROPERTY || \
- defined HANDLE_DW_UT || defined HANDLE_DWARF_SECTION)
+#if !( \
+ defined HANDLE_DW_TAG || defined HANDLE_DW_AT || defined HANDLE_DW_FORM || \
+ defined HANDLE_DW_OP || defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \
+ defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \
+ defined HANDLE_DW_CC || defined HANDLE_DW_LNS || defined HANDLE_DW_LNE || \
+ defined HANDLE_DW_LNCT || defined HANDLE_DW_MACRO || \
+ defined HANDLE_DW_RLE || defined HANDLE_DW_CFA || \
+ defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \
+ defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX)
#error "Missing macro definition of HANDLE_DW*"
#endif
@@ -96,6 +96,10 @@
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME)
#endif
+#ifndef HANDLE_DW_IDX
+#define HANDLE_DW_IDX(ID, NAME)
+#endif
+
HANDLE_DW_TAG(0x0000, null, 2, DWARF)
HANDLE_DW_TAG(0x0001, array_type, 2, DWARF)
HANDLE_DW_TAG(0x0002, class_type, 2, DWARF)
@@ -704,6 +708,7 @@ HANDLE_DW_CC(0x03, nocall)
HANDLE_DW_CC(0x04, pass_by_reference)
HANDLE_DW_CC(0x05, pass_by_value)
// Vendor extensions:
+HANDLE_DW_CC(0x40, GNU_renesas_sh)
HANDLE_DW_CC(0x41, GNU_borland_fastcall_i386)
HANDLE_DW_CC(0xb0, BORLAND_safecall)
HANDLE_DW_CC(0xb1, BORLAND_stdcall)
@@ -713,6 +718,22 @@ HANDLE_DW_CC(0xb4, BORLAND_msreturn)
HANDLE_DW_CC(0xb5, BORLAND_thiscall)
HANDLE_DW_CC(0xb6, BORLAND_fastcall)
HANDLE_DW_CC(0xc0, LLVM_vectorcall)
+HANDLE_DW_CC(0xc1, LLVM_Win64)
+HANDLE_DW_CC(0xc2, LLVM_X86_64SysV)
+HANDLE_DW_CC(0xc3, LLVM_AAPCS)
+HANDLE_DW_CC(0xc4, LLVM_AAPCS_VFP)
+HANDLE_DW_CC(0xc5, LLVM_IntelOclBicc)
+HANDLE_DW_CC(0xc6, LLVM_SpirFunction)
+HANDLE_DW_CC(0xc7, LLVM_OpenCLKernel)
+HANDLE_DW_CC(0xc8, LLVM_Swift)
+HANDLE_DW_CC(0xc9, LLVM_PreserveMost)
+HANDLE_DW_CC(0xca, LLVM_PreserveAll)
+HANDLE_DW_CC(0xcb, LLVM_X86RegCall)
+// From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently
+// generated by any toolchain. It is used internally to GDB to indicate OpenCL C
+// functions that have been compiled with the IBM XL C for OpenCL compiler and use
+// a non-platform calling convention for passing OpenCL C vector types.
+HANDLE_DW_CC(0xff, GDB_IBM_OpenCL)
// Line Number Extended Opcode Encodings
HANDLE_DW_LNE(0x01, end_sequence)
@@ -743,6 +764,9 @@ HANDLE_DW_LNCT(0x02, directory_index)
HANDLE_DW_LNCT(0x03, timestamp)
HANDLE_DW_LNCT(0x04, size)
HANDLE_DW_LNCT(0x05, MD5)
+// A vendor extension until http://dwarfstd.org/ShowIssue.php?issue=180201.1 is
+// accepted and incorporated into the next DWARF standard.
+HANDLE_DW_LNCT(0x2001, LLVM_source)
// DWARF v5 Macro information.
HANDLE_DW_MACRO(0x01, define)
@@ -836,14 +860,17 @@ HANDLE_DWARF_SECTION(DebugAranges, ".debug_aranges", "debug-aranges")
HANDLE_DWARF_SECTION(DebugInfo, ".debug_info", "debug-info")
HANDLE_DWARF_SECTION(DebugTypes, ".debug_types", "debug-types")
HANDLE_DWARF_SECTION(DebugLine, ".debug_line", "debug-line")
+HANDLE_DWARF_SECTION(DebugLineStr, ".debug_line_str", "debug-line-str")
HANDLE_DWARF_SECTION(DebugLoc, ".debug_loc", "debug-loc")
HANDLE_DWARF_SECTION(DebugFrame, ".debug_frame", "debug-frame")
HANDLE_DWARF_SECTION(DebugMacro, ".debug_macro", "debug-macro")
-HANDLE_DWARF_SECTION(DebugRanges, ".debug_ranges", "debug-ranges")
+HANDLE_DWARF_SECTION(DebugNames, ".debug_names", "debug-names")
HANDLE_DWARF_SECTION(DebugPubnames, ".debug_pubnames", "debug-pubnames")
HANDLE_DWARF_SECTION(DebugPubtypes, ".debug_pubtypes", "debug-pubtypes")
HANDLE_DWARF_SECTION(DebugGnuPubnames, ".debug_gnu_pubnames", "debug-gnu-pubnames")
HANDLE_DWARF_SECTION(DebugGnuPubtypes, ".debug_gnu_pubtypes", "debug-gnu-pubtypes")
+HANDLE_DWARF_SECTION(DebugRanges, ".debug_ranges", "debug-ranges")
+HANDLE_DWARF_SECTION(DebugRnglists, ".debug_rnglists", "debug-rnglists")
HANDLE_DWARF_SECTION(DebugStr, ".debug_str", "debug-str")
HANDLE_DWARF_SECTION(DebugStrOffsets, ".debug_str_offsets", "debug-str-offsets")
HANDLE_DWARF_SECTION(DebugCUIndex, ".debug_cu_index", "debug-cu-index")
@@ -855,6 +882,12 @@ HANDLE_DWARF_SECTION(AppleNamespaces, ".apple_namespaces", "apple-namespaces")
HANDLE_DWARF_SECTION(AppleObjC, ".apple_objc", "apple-objc")
HANDLE_DWARF_SECTION(GdbIndex, ".gdb_index", "gdb-index")
+HANDLE_DW_IDX(0x01, compile_unit)
+HANDLE_DW_IDX(0x02, type_unit)
+HANDLE_DW_IDX(0x03, die_offset)
+HANDLE_DW_IDX(0x04, parent)
+HANDLE_DW_IDX(0x05, type_hash)
+
#undef HANDLE_DW_TAG
#undef HANDLE_DW_AT
@@ -874,3 +907,4 @@ HANDLE_DWARF_SECTION(GdbIndex, ".gdb_index", "gdb-index")
#undef HANDLE_DW_APPLE_PROPERTY
#undef HANDLE_DW_UT
#undef HANDLE_DWARF_SECTION
+#undef HANDLE_DW_IDX
diff --git a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h
index a0e5367b412c..9036f405eaea 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -20,8 +20,12 @@
#ifndef LLVM_BINARYFORMAT_DWARF_H
#define LLVM_BINARYFORMAT_DWARF_H
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadicDetails.h"
namespace llvm {
class StringRef;
@@ -57,6 +61,9 @@ enum LLVMConstants : uint32_t {
DWARF_VENDOR_MIPS = 6
};
+/// Constants that define the DWARF format as 32 or 64 bit.
+enum DwarfFormat : uint8_t { DWARF32, DWARF64 };
+
/// Special ID values that distinguish a CIE from a FDE in DWARF CFI.
/// Not inside an enum because a 64-bit value is needed.
/// @{
@@ -125,7 +132,7 @@ enum LocationAtom {
DW_OP_LLVM_fragment = 0x1000 ///< Only used in LLVM metadata.
};
-enum TypeKind {
+enum TypeKind : uint8_t {
#define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) DW_ATE_##NAME = ID,
#include "llvm/BinaryFormat/Dwarf.def"
DW_ATE_lo_user = 0x80,
@@ -325,6 +332,13 @@ enum UnitType : unsigned char {
DW_UT_hi_user = 0xff
};
+enum Index {
+#define HANDLE_DW_IDX(ID, NAME) DW_IDX_##NAME = ID,
+#include "llvm/BinaryFormat/Dwarf.def"
+ DW_IDX_lo_user = 0x2000,
+ DW_IDX_hi_user = 0x3fff
+};
+
inline bool isUnitType(uint8_t UnitType) {
switch (UnitType) {
case DW_UT_compile:
@@ -354,13 +368,16 @@ inline bool isUnitType(dwarf::Tag T) {
// Constants for the DWARF v5 Accelerator Table Proposal
enum AcceleratorTable {
// Data layout descriptors.
- DW_ATOM_null = 0u, // Marker as the end of a list of atoms.
+ DW_ATOM_null = 0u, /// Marker as the end of a list of atoms.
DW_ATOM_die_offset = 1u, // DIE offset in the debug_info section.
DW_ATOM_cu_offset = 2u, // Offset of the compile unit header that contains the
// item in question.
DW_ATOM_die_tag = 3u, // A tag entry.
DW_ATOM_type_flags = 4u, // Set of flags for a type.
+ DW_ATOM_type_type_flags = 5u, // Dsymutil type extension.
+ DW_ATOM_qual_name_hash = 6u, // Dsymutil qualified hash extension.
+
// DW_ATOM_type_flags values.
// Always set for C++, only set for ObjC if this is the @implementation for a
@@ -390,8 +407,8 @@ enum GDBIndexEntryLinkage { GIEL_EXTERNAL, GIEL_STATIC };
/// \defgroup DwarfConstantsDumping Dwarf constants dumping functions
///
/// All these functions map their argument's value back to the
-/// corresponding enumerator name or return nullptr if the value isn't
-/// known.
+/// corresponding enumerator name or return an empty StringRef if the value
+/// isn't known.
///
/// @{
StringRef TagString(unsigned Tag);
@@ -410,16 +427,17 @@ StringRef CaseString(unsigned Case);
StringRef ConventionString(unsigned Convention);
StringRef InlineCodeString(unsigned Code);
StringRef ArrayOrderString(unsigned Order);
-StringRef DiscriminantString(unsigned Discriminant);
StringRef LNStandardString(unsigned Standard);
StringRef LNExtendedString(unsigned Encoding);
StringRef MacinfoString(unsigned Encoding);
+StringRef RangeListEncodingString(unsigned Encoding);
StringRef CallFrameString(unsigned Encoding);
StringRef ApplePropertyString(unsigned);
StringRef UnitTypeString(unsigned);
StringRef AtomTypeString(unsigned Atom);
StringRef GDBIndexEntryKindString(GDBIndexEntryKind Kind);
StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage);
+StringRef IndexString(unsigned Idx);
/// @}
/// \defgroup DwarfConstantsParsing Dwarf constants parsing functions
@@ -471,6 +489,49 @@ unsigned AttributeEncodingVendor(TypeKind E);
unsigned LanguageVendor(SourceLanguage L);
/// @}
+/// A helper struct providing information about the byte size of DW_FORM
+/// values that vary in size depending on the DWARF version, address byte
+/// size, or DWARF32/DWARF64.
+struct FormParams {
+ uint16_t Version;
+ uint8_t AddrSize;
+ DwarfFormat Format;
+
+ /// The definition of the size of form DW_FORM_ref_addr depends on the
+ /// version. In DWARF v2 it's the size of an address; after that, it's the
+ /// size of a reference.
+ uint8_t getRefAddrByteSize() const {
+ if (Version == 2)
+ return AddrSize;
+ return getDwarfOffsetByteSize();
+ }
+
+ /// The size of a reference is determined by the DWARF 32/64-bit format.
+ uint8_t getDwarfOffsetByteSize() const {
+ switch (Format) {
+ case DwarfFormat::DWARF32:
+ return 4;
+ case DwarfFormat::DWARF64:
+ return 8;
+ }
+ llvm_unreachable("Invalid Format value");
+ }
+
+ explicit operator bool() const { return Version && AddrSize; }
+};
+
+/// Get the fixed byte size for a given form.
+///
+/// If the form has a fixed byte size, then an Optional with a value will be
+/// returned. If the form is always encoded using a variable length storage
+/// format (ULEB or SLEB numbers or blocks) then None will be returned.
+///
+/// \param Form DWARF form to get the fixed byte size for.
+/// \param Params DWARF parameters to help interpret forms.
+/// \returns Optional<uint8_t> value with the fixed byte size or None if
+/// \p Form doesn't have a fixed byte size.
+Optional<uint8_t> getFixedFormByteSize(dwarf::Form Form, FormParams Params);
+
/// Tells whether the specified form is defined in the specified version,
/// or is an extension if extensions are allowed.
bool isValidFormForVersion(Form F, unsigned Version, bool ExtensionsOk = true);
@@ -479,6 +540,10 @@ bool isValidFormForVersion(Form F, unsigned Version, bool ExtensionsOk = true);
/// for attribute Attr.
StringRef AttributeValueString(uint16_t Attr, unsigned Val);
+/// Returns the symbolic string representing Val when used as a value
+/// for atom Atom.
+StringRef AtomValueString(uint16_t Atom, unsigned Val);
+
/// Describes an entry of the various gnu_pub* debug sections.
///
/// The gnu_pub* kind looks like:
@@ -514,14 +579,46 @@ private:
};
};
-/// Constants that define the DWARF format as 32 or 64 bit.
-enum DwarfFormat : uint8_t { DWARF32, DWARF64 };
+template <typename Enum> struct EnumTraits : public std::false_type {};
-/// The Bernstein hash function used by the accelerator tables.
-uint32_t djbHash(StringRef Buffer);
+template <> struct EnumTraits<Attribute> : public std::true_type {
+ static constexpr char Type[3] = "AT";
+ static constexpr StringRef (*StringFn)(unsigned) = &AttributeString;
+};
+template <> struct EnumTraits<Form> : public std::true_type {
+ static constexpr char Type[5] = "FORM";
+ static constexpr StringRef (*StringFn)(unsigned) = &FormEncodingString;
+};
+
+template <> struct EnumTraits<Index> : public std::true_type {
+ static constexpr char Type[4] = "IDX";
+ static constexpr StringRef (*StringFn)(unsigned) = &IndexString;
+};
+
+template <> struct EnumTraits<Tag> : public std::true_type {
+ static constexpr char Type[4] = "TAG";
+ static constexpr StringRef (*StringFn)(unsigned) = &TagString;
+};
} // End of namespace dwarf
+/// Dwarf constants format_provider
+///
+/// Specialization of the format_provider template for dwarf enums. Unlike the
+/// dumping functions above, these format unknown enumerator values as
+/// DW_TYPE_unknown_1234 (e.g. DW_TAG_unknown_ffff).
+template <typename Enum>
+struct format_provider<
+ Enum, typename std::enable_if<dwarf::EnumTraits<Enum>::value>::type> {
+ static void format(const Enum &E, raw_ostream &OS, StringRef Style) {
+ StringRef Str = dwarf::EnumTraits<Enum>::StringFn(E);
+ if (Str.empty()) {
+ OS << "DW_" << dwarf::EnumTraits<Enum>::Type << "_unknown_"
+ << llvm::format("%x", E);
+ } else
+ OS << Str;
+ }
+};
} // End of namespace llvm
#endif
diff --git a/contrib/llvm/include/llvm/BinaryFormat/DynamicTags.def b/contrib/llvm/include/llvm/BinaryFormat/DynamicTags.def
new file mode 100644
index 000000000000..2e15cc30fca7
--- /dev/null
+++ b/contrib/llvm/include/llvm/BinaryFormat/DynamicTags.def
@@ -0,0 +1,216 @@
+#ifndef DYNAMIC_TAG
+#error "DYNAMIC_TAG must be defined"
+#endif
+
+// Add separate macros for the architecture specific tags and the markers
+// such as DT_HIOS, etc. to allow using this file to in other contexts.
+// For example we can use it to generate a stringification switch statement.
+
+#ifndef HEXAGON_DYNAMIC_TAG
+#define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value)
+#define HEXAGON_DYNAMIC_TAG_DEFINED
+#endif
+
+#ifndef MIPS_DYNAMIC_TAG
+#define MIPS_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value)
+#define MIPS_DYNAMIC_TAG_DEFINED
+#endif
+
+#ifndef PPC64_DYNAMIC_TAG
+#define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value)
+#define PPC64_DYNAMIC_TAG_DEFINED
+#endif
+
+#ifndef DYNAMIC_TAG_MARKER
+#define DYNAMIC_TAG_MARKER(name, value) DYNAMIC_TAG(name, value)
+#define DYNAMIC_TAG_MARKER_DEFINED
+#endif
+
+DYNAMIC_TAG(NULL, 0) // Marks end of dynamic array.
+DYNAMIC_TAG(NEEDED, 1) // String table offset of needed library.
+DYNAMIC_TAG(PLTRELSZ, 2) // Size of relocation entries in PLT.
+DYNAMIC_TAG(PLTGOT, 3) // Address associated with linkage table.
+DYNAMIC_TAG(HASH, 4) // Address of symbolic hash table.
+DYNAMIC_TAG(STRTAB, 5) // Address of dynamic string table.
+DYNAMIC_TAG(SYMTAB, 6) // Address of dynamic symbol table.
+DYNAMIC_TAG(RELA, 7) // Address of relocation table (Rela entries).
+DYNAMIC_TAG(RELASZ, 8) // Size of Rela relocation table.
+DYNAMIC_TAG(RELAENT, 9) // Size of a Rela relocation entry.
+DYNAMIC_TAG(STRSZ, 10) // Total size of the string table.
+DYNAMIC_TAG(SYMENT, 11) // Size of a symbol table entry.
+DYNAMIC_TAG(INIT, 12) // Address of initialization function.
+DYNAMIC_TAG(FINI, 13) // Address of termination function.
+DYNAMIC_TAG(SONAME, 14) // String table offset of a shared objects name.
+DYNAMIC_TAG(RPATH, 15) // String table offset of library search path.
+DYNAMIC_TAG(SYMBOLIC, 16) // Changes symbol resolution algorithm.
+DYNAMIC_TAG(REL, 17) // Address of relocation table (Rel entries).
+DYNAMIC_TAG(RELSZ, 18) // Size of Rel relocation table.
+DYNAMIC_TAG(RELENT, 19) // Size of a Rel relocation entry.
+DYNAMIC_TAG(PLTREL, 20) // Type of relocation entry used for linking.
+DYNAMIC_TAG(DEBUG, 21) // Reserved for debugger.
+DYNAMIC_TAG(TEXTREL, 22) // Relocations exist for non-writable segments.
+DYNAMIC_TAG(JMPREL, 23) // Address of relocations associated with PLT.
+DYNAMIC_TAG(BIND_NOW, 24) // Process all relocations before execution.
+DYNAMIC_TAG(INIT_ARRAY, 25) // Pointer to array of initialization functions.
+DYNAMIC_TAG(FINI_ARRAY, 26) // Pointer to array of termination functions.
+DYNAMIC_TAG(INIT_ARRAYSZ, 27) // Size of DT_INIT_ARRAY.
+DYNAMIC_TAG(FINI_ARRAYSZ, 28) // Size of DT_FINI_ARRAY.
+DYNAMIC_TAG(RUNPATH, 29) // String table offset of lib search path.
+DYNAMIC_TAG(FLAGS, 30) // Flags.
+DYNAMIC_TAG_MARKER(ENCODING, 32) // Values from here to DT_LOOS follow the rules
+ // for the interpretation of the d_un union.
+
+DYNAMIC_TAG(PREINIT_ARRAY, 32) // Pointer to array of preinit functions.
+DYNAMIC_TAG(PREINIT_ARRAYSZ, 33) // Size of the DT_PREINIT_ARRAY array.
+
+DYNAMIC_TAG(SYMTAB_SHNDX, 34) // Address of the SHT_SYMTAB_SHNDX section.
+
+// Experimental support for SHT_RELR sections. For details, see proposal
+// at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
+DYNAMIC_TAG(RELRSZ, 35) // Size of Relr relocation table.
+DYNAMIC_TAG(RELR, 36) // Address of relocation table (Relr entries).
+DYNAMIC_TAG(RELRENT, 37) // Size of a Relr relocation entry.
+
+DYNAMIC_TAG_MARKER(LOOS, 0x60000000) // Start of environment specific tags.
+DYNAMIC_TAG_MARKER(HIOS, 0x6FFFFFFF) // End of environment specific tags.
+DYNAMIC_TAG_MARKER(LOPROC, 0x70000000) // Start of processor specific tags.
+DYNAMIC_TAG_MARKER(HIPROC, 0x7FFFFFFF) // End of processor specific tags.
+
+// Android packed relocation section tags.
+// https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#31
+DYNAMIC_TAG(ANDROID_REL, 0x6000000F)
+DYNAMIC_TAG(ANDROID_RELSZ, 0x60000010)
+DYNAMIC_TAG(ANDROID_RELA, 0x60000011)
+DYNAMIC_TAG(ANDROID_RELASZ, 0x60000012)
+
+// Android's experimental support for SHT_RELR sections.
+// https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#253
+DYNAMIC_TAG(ANDROID_RELR, 0x6FFFE000) // Address of relocation table (Relr entries).
+DYNAMIC_TAG(ANDROID_RELRSZ, 0x6FFFE001) // Size of Relr relocation table.
+DYNAMIC_TAG(ANDROID_RELRENT, 0x6FFFE003) // Size of a Relr relocation entry.
+
+DYNAMIC_TAG(GNU_HASH, 0x6FFFFEF5) // Reference to the GNU hash table.
+DYNAMIC_TAG(TLSDESC_PLT, 0x6FFFFEF6) // Location of PLT entry for TLS
+ // descriptor resolver calls.
+DYNAMIC_TAG(TLSDESC_GOT, 0x6FFFFEF7) // Location of GOT entry used by TLS
+ // descriptor resolver PLT entry.
+DYNAMIC_TAG(RELACOUNT, 0x6FFFFFF9) // ELF32_Rela count.
+DYNAMIC_TAG(RELCOUNT, 0x6FFFFFFA) // ELF32_Rel count.
+
+DYNAMIC_TAG(FLAGS_1, 0X6FFFFFFB) // Flags_1.
+
+DYNAMIC_TAG(VERSYM, 0x6FFFFFF0) // The address of .gnu.version section.
+DYNAMIC_TAG(VERDEF, 0X6FFFFFFC) // The address of the version definition
+ // table.
+DYNAMIC_TAG(VERDEFNUM, 0X6FFFFFFD) // The number of entries in DT_VERDEF.
+DYNAMIC_TAG(VERNEED, 0X6FFFFFFE) // The address of the version dependency
+ // table.
+DYNAMIC_TAG(VERNEEDNUM, 0X6FFFFFFF) // The number of entries in DT_VERNEED.
+
+// Hexagon specific dynamic table entries
+HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000)
+HEXAGON_DYNAMIC_TAG(HEXAGON_VER, 0x70000001)
+HEXAGON_DYNAMIC_TAG(HEXAGON_PLT, 0x70000002)
+
+// Mips specific dynamic table entry tags.
+
+MIPS_DYNAMIC_TAG(MIPS_RLD_VERSION, 0x70000001) // 32 bit version number for
+ // runtime linker interface.
+MIPS_DYNAMIC_TAG(MIPS_TIME_STAMP, 0x70000002) // Time stamp.
+MIPS_DYNAMIC_TAG(MIPS_ICHECKSUM, 0x70000003) // Checksum of external strings
+ // and common sizes.
+MIPS_DYNAMIC_TAG(MIPS_IVERSION, 0x70000004) // Index of version string
+ // in string table.
+MIPS_DYNAMIC_TAG(MIPS_FLAGS, 0x70000005) // 32 bits of flags.
+MIPS_DYNAMIC_TAG(MIPS_BASE_ADDRESS, 0x70000006) // Base address of the segment.
+MIPS_DYNAMIC_TAG(MIPS_MSYM, 0x70000007) // Address of .msym section.
+MIPS_DYNAMIC_TAG(MIPS_CONFLICT, 0x70000008) // Address of .conflict section.
+MIPS_DYNAMIC_TAG(MIPS_LIBLIST, 0x70000009) // Address of .liblist section.
+MIPS_DYNAMIC_TAG(MIPS_LOCAL_GOTNO, 0x7000000a) // Number of local global offset
+ // table entries.
+MIPS_DYNAMIC_TAG(MIPS_CONFLICTNO, 0x7000000b) // Number of entries
+ // in the .conflict section.
+MIPS_DYNAMIC_TAG(MIPS_LIBLISTNO, 0x70000010) // Number of entries
+ // in the .liblist section.
+MIPS_DYNAMIC_TAG(MIPS_SYMTABNO, 0x70000011) // Number of entries
+ // in the .dynsym section.
+MIPS_DYNAMIC_TAG(MIPS_UNREFEXTNO, 0x70000012) // Index of first external dynamic
+ // symbol not referenced locally.
+MIPS_DYNAMIC_TAG(MIPS_GOTSYM, 0x70000013) // Index of first dynamic symbol
+ // in global offset table.
+MIPS_DYNAMIC_TAG(MIPS_HIPAGENO, 0x70000014) // Number of page table entries
+ // in global offset table.
+MIPS_DYNAMIC_TAG(MIPS_RLD_MAP, 0x70000016) // Address of run time loader map
+ // used for debugging.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_CLASS, 0x70000017) // Delta C++ class definition.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_CLASS_NO, 0x70000018) // Number of entries
+ // in DT_MIPS_DELTA_CLASS.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_INSTANCE, 0x70000019) // Delta C++ class instances.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_INSTANCE_NO, 0x7000001A) // Number of entries
+ // in DT_MIPS_DELTA_INSTANCE.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_RELOC, 0x7000001B) // Delta relocations.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_RELOC_NO, 0x7000001C) // Number of entries
+ // in DT_MIPS_DELTA_RELOC.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_SYM, 0x7000001D) // Delta symbols that Delta
+ // relocations refer to.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_SYM_NO, 0x7000001E) // Number of entries
+ // in DT_MIPS_DELTA_SYM.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_CLASSSYM, 0x70000020) // Delta symbols that hold
+ // class declarations.
+MIPS_DYNAMIC_TAG(MIPS_DELTA_CLASSSYM_NO, 0x70000021) // Number of entries
+ // in DT_MIPS_DELTA_CLASSSYM.
+
+MIPS_DYNAMIC_TAG(MIPS_CXX_FLAGS, 0x70000022) // Flags indicating information
+ // about C++ flavor.
+MIPS_DYNAMIC_TAG(MIPS_PIXIE_INIT, 0x70000023) // Pixie information.
+MIPS_DYNAMIC_TAG(MIPS_SYMBOL_LIB, 0x70000024) // Address of .MIPS.symlib
+MIPS_DYNAMIC_TAG(MIPS_LOCALPAGE_GOTIDX, 0x70000025) // The GOT index of the first PTE
+ // for a segment
+MIPS_DYNAMIC_TAG(MIPS_LOCAL_GOTIDX, 0x70000026) // The GOT index of the first PTE
+ // for a local symbol
+MIPS_DYNAMIC_TAG(MIPS_HIDDEN_GOTIDX, 0x70000027) // The GOT index of the first PTE
+ // for a hidden symbol
+MIPS_DYNAMIC_TAG(MIPS_PROTECTED_GOTIDX, 0x70000028) // The GOT index of the first PTE
+ // for a protected symbol
+MIPS_DYNAMIC_TAG(MIPS_OPTIONS, 0x70000029) // Address of `.MIPS.options'.
+MIPS_DYNAMIC_TAG(MIPS_INTERFACE, 0x7000002A) // Address of `.interface'.
+MIPS_DYNAMIC_TAG(MIPS_DYNSTR_ALIGN, 0x7000002B) // Unknown.
+MIPS_DYNAMIC_TAG(MIPS_INTERFACE_SIZE, 0x7000002C) // Size of the .interface section.
+MIPS_DYNAMIC_TAG(MIPS_RLD_TEXT_RESOLVE_ADDR, 0x7000002D) // Size of rld_text_resolve
+ // function stored in the GOT.
+MIPS_DYNAMIC_TAG(MIPS_PERF_SUFFIX, 0x7000002E) // Default suffix of DSO to be added
+ // by rld on dlopen() calls.
+MIPS_DYNAMIC_TAG(MIPS_COMPACT_SIZE, 0x7000002F) // Size of compact relocation
+ // section (O32).
+MIPS_DYNAMIC_TAG(MIPS_GP_VALUE, 0x70000030) // GP value for auxiliary GOTs.
+MIPS_DYNAMIC_TAG(MIPS_AUX_DYNAMIC, 0x70000031) // Address of auxiliary .dynamic.
+MIPS_DYNAMIC_TAG(MIPS_PLTGOT, 0x70000032) // Address of the base of the PLTGOT.
+MIPS_DYNAMIC_TAG(MIPS_RWPLT, 0x70000034) // Points to the base
+ // of a writable PLT.
+MIPS_DYNAMIC_TAG(MIPS_RLD_MAP_REL, 0x70000035) // Relative offset of run time loader
+ // map, used for debugging.
+
+// PPC64 specific dynamic table entries.
+PPC64_DYNAMIC_TAG(PPC64_GLINK, 0x70000000) // Address of 32 bytes before the
+ // first glink lazy resolver stub.
+
+// Sun machine-independent extensions.
+DYNAMIC_TAG(AUXILIARY, 0x7FFFFFFD) // Shared object to load before self
+DYNAMIC_TAG(FILTER, 0x7FFFFFFF) // Shared object to get values from
+
+
+#ifdef DYNAMIC_TAG_MARKER_DEFINED
+#undef DYNAMIC_TAG_MARKER
+#endif
+#ifdef MIPS_DYNAMIC_TAG_DEFINED
+#undef MIPS_DYNAMIC_TAG
+#undef MIPS_DYNAMIC_TAG_DEFINED
+#endif
+#ifdef HEXAGON_DYNAMIC_TAG_DEFINED
+#undef HEXAGON_DYNAMIC_TAG
+#undef HEXAGON_DYNAMIC_TAG_DEFINED
+#endif
+#ifdef PPC64_DYNAMIC_TAG_DEFINED
+#undef PPC64_DYNAMIC_TAG
+#undef PPC64_DYNAMIC_TAG_DEFINED
+#endif
diff --git a/contrib/llvm/include/llvm/BinaryFormat/ELF.h b/contrib/llvm/include/llvm/BinaryFormat/ELF.h
index c902972d93bd..0f3f1939ce68 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/contrib/llvm/include/llvm/BinaryFormat/ELF.h
@@ -312,11 +312,6 @@ enum {
EM_RISCV = 243, // RISC-V
EM_LANAI = 244, // Lanai 32-bit processor
EM_BPF = 247, // Linux kernel bpf virtual machine
-
- // A request has been made to the maintainer of the official registry for
- // such numbers for an official value for WebAssembly. As soon as one is
- // allocated, this enum will be updated to use it.
- EM_WEBASSEMBLY = 0x4157, // WebAssembly architecture
};
// Object file classes.
@@ -644,18 +639,78 @@ enum {
#include "ELFRelocs/Sparc.def"
};
-// ELF Relocation types for WebAssembly
-enum {
-#include "ELFRelocs/WebAssembly.def"
-};
-
// AMDGPU specific e_flags.
enum : unsigned {
- // AMDGPU machine architectures.
- EF_AMDGPU_ARCH_NONE = 0x00000000, // None/unknown.
- EF_AMDGPU_ARCH_R600 = 0x00000001, // AMD HD2XXX-HD6XXX GPUs.
- EF_AMDGPU_ARCH_GCN = 0x00000002, // AMD GCN GFX6+ GPUs.
- EF_AMDGPU_ARCH = 0x0000000f // EF_AMDGPU_ARCH_XXX selection mask.
+ // Processor selection mask for EF_AMDGPU_MACH_* values.
+ EF_AMDGPU_MACH = 0x0ff,
+
+ // Not specified processor.
+ EF_AMDGPU_MACH_NONE = 0x000,
+
+ // R600-based processors.
+
+ // Radeon HD 2000/3000 Series (R600).
+ EF_AMDGPU_MACH_R600_R600 = 0x001,
+ EF_AMDGPU_MACH_R600_R630 = 0x002,
+ EF_AMDGPU_MACH_R600_RS880 = 0x003,
+ EF_AMDGPU_MACH_R600_RV670 = 0x004,
+ // Radeon HD 4000 Series (R700).
+ EF_AMDGPU_MACH_R600_RV710 = 0x005,
+ EF_AMDGPU_MACH_R600_RV730 = 0x006,
+ EF_AMDGPU_MACH_R600_RV770 = 0x007,
+ // Radeon HD 5000 Series (Evergreen).
+ EF_AMDGPU_MACH_R600_CEDAR = 0x008,
+ EF_AMDGPU_MACH_R600_CYPRESS = 0x009,
+ EF_AMDGPU_MACH_R600_JUNIPER = 0x00a,
+ EF_AMDGPU_MACH_R600_REDWOOD = 0x00b,
+ EF_AMDGPU_MACH_R600_SUMO = 0x00c,
+ // Radeon HD 6000 Series (Northern Islands).
+ EF_AMDGPU_MACH_R600_BARTS = 0x00d,
+ EF_AMDGPU_MACH_R600_CAICOS = 0x00e,
+ EF_AMDGPU_MACH_R600_CAYMAN = 0x00f,
+ EF_AMDGPU_MACH_R600_TURKS = 0x010,
+
+ // Reserved for R600-based processors.
+ EF_AMDGPU_MACH_R600_RESERVED_FIRST = 0x011,
+ EF_AMDGPU_MACH_R600_RESERVED_LAST = 0x01f,
+
+ // First/last R600-based processors.
+ EF_AMDGPU_MACH_R600_FIRST = EF_AMDGPU_MACH_R600_R600,
+ EF_AMDGPU_MACH_R600_LAST = EF_AMDGPU_MACH_R600_TURKS,
+
+ // AMDGCN-based processors.
+
+ // AMDGCN GFX6.
+ EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020,
+ EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021,
+ // AMDGCN GFX7.
+ EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022,
+ EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023,
+ EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024,
+ EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025,
+ EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026,
+ // AMDGCN GFX8.
+ EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028,
+ EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029,
+ EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a,
+ EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b,
+ // AMDGCN GFX9.
+ EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
+ EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d,
+ EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e,
+ EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f,
+
+ // Reserved for AMDGCN-based processors.
+ EF_AMDGPU_MACH_AMDGCN_RESERVED0 = 0x027,
+ EF_AMDGPU_MACH_AMDGCN_RESERVED1 = 0x030,
+
+ // First/last AMDGCN-based processors.
+ EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600,
+ EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX906,
+
+ // Indicates if the xnack target feature is enabled for all code contained in
+ // the object.
+ EF_AMDGPU_XNACK = 0x100,
};
// ELF Relocation types for AMDGPU
@@ -714,36 +769,46 @@ enum {
// Section types.
enum : unsigned {
- SHT_NULL = 0, // No associated section (inactive entry).
- SHT_PROGBITS = 1, // Program-defined contents.
- SHT_SYMTAB = 2, // Symbol table.
- SHT_STRTAB = 3, // String table.
- SHT_RELA = 4, // Relocation entries; explicit addends.
- SHT_HASH = 5, // Symbol hash table.
- SHT_DYNAMIC = 6, // Information for dynamic linking.
- SHT_NOTE = 7, // Information about the file.
- SHT_NOBITS = 8, // Data occupies no space in the file.
- SHT_REL = 9, // Relocation entries; no explicit addends.
- SHT_SHLIB = 10, // Reserved.
- SHT_DYNSYM = 11, // Symbol table.
- SHT_INIT_ARRAY = 14, // Pointers to initialization functions.
- SHT_FINI_ARRAY = 15, // Pointers to termination functions.
- SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions.
- SHT_GROUP = 17, // Section group.
- SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries.
- SHT_LOOS = 0x60000000, // Lowest operating system-specific type.
+ SHT_NULL = 0, // No associated section (inactive entry).
+ SHT_PROGBITS = 1, // Program-defined contents.
+ SHT_SYMTAB = 2, // Symbol table.
+ SHT_STRTAB = 3, // String table.
+ SHT_RELA = 4, // Relocation entries; explicit addends.
+ SHT_HASH = 5, // Symbol hash table.
+ SHT_DYNAMIC = 6, // Information for dynamic linking.
+ SHT_NOTE = 7, // Information about the file.
+ SHT_NOBITS = 8, // Data occupies no space in the file.
+ SHT_REL = 9, // Relocation entries; no explicit addends.
+ SHT_SHLIB = 10, // Reserved.
+ SHT_DYNSYM = 11, // Symbol table.
+ SHT_INIT_ARRAY = 14, // Pointers to initialization functions.
+ SHT_FINI_ARRAY = 15, // Pointers to termination functions.
+ SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions.
+ SHT_GROUP = 17, // Section group.
+ SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries.
+ // Experimental support for SHT_RELR sections. For details, see proposal
+ // at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
+ SHT_RELR = 19, // Relocation entries; only offsets.
+ SHT_LOOS = 0x60000000, // Lowest operating system-specific type.
// Android packed relocation section types.
// https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#37
SHT_ANDROID_REL = 0x60000001,
SHT_ANDROID_RELA = 0x60000002,
- SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table.
- SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes.
- SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table.
- SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions.
- SHT_GNU_verneed = 0x6ffffffe, // GNU version references.
- SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table.
- SHT_HIOS = 0x6fffffff, // Highest operating system-specific type.
- SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type.
+ SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table.
+ SHT_LLVM_LINKER_OPTIONS = 0x6fff4c01, // LLVM Linker Options.
+ SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c02, // LLVM Call Graph Profile.
+ SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols
+ // for safe ICF.
+ // Android's experimental support for SHT_RELR sections.
+ // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512
+ SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets.
+ SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes.
+ SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table.
+ SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions.
+ SHT_GNU_verneed = 0x6ffffffe, // GNU version references.
+ SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table.
+ SHT_HIOS = 0x6fffffff, // Highest operating system-specific type.
+ SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type.
// Fixme: All this is duplicated in MCSectionELF. Why??
// Exception Index table
SHT_ARM_EXIDX = 0x70000001U,
@@ -753,18 +818,18 @@ enum : unsigned {
SHT_ARM_ATTRIBUTES = 0x70000003U,
SHT_ARM_DEBUGOVERLAY = 0x70000004U,
SHT_ARM_OVERLAYSECTION = 0x70000005U,
- SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in
- // this section based on their sizes
- SHT_X86_64_UNWIND = 0x70000001, // Unwind information
+ SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in
+ // this section based on their sizes
+ SHT_X86_64_UNWIND = 0x70000001, // Unwind information
- SHT_MIPS_REGINFO = 0x70000006, // Register usage information
- SHT_MIPS_OPTIONS = 0x7000000d, // General options
- SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section.
- SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information.
+ SHT_MIPS_REGINFO = 0x70000006, // Register usage information
+ SHT_MIPS_OPTIONS = 0x7000000d, // General options
+ SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section.
+ SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information.
- SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type.
- SHT_LOUSER = 0x80000000, // Lowest type reserved for applications.
- SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
+ SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type.
+ SHT_LOUSER = 0x80000000, // Lowest type reserved for applications.
+ SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
};
// Section flags.
@@ -1000,6 +1065,9 @@ struct Elf32_Rela {
}
};
+// Relocation entry without explicit addend or info (relative relocations only).
+typedef Elf32_Word Elf32_Relr; // offset/bitmap for relative relocations
+
// Relocation entry, without explicit addend.
struct Elf64_Rel {
Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr).
@@ -1033,6 +1101,9 @@ struct Elf64_Rela {
}
};
+// Relocation entry without explicit addend or info (relative relocations only).
+typedef Elf64_Xword Elf64_Relr; // offset/bitmap for relative relocations
+
// Program header for ELF32.
struct Elf32_Phdr {
Elf32_Word p_type; // Type of segment
@@ -1096,9 +1167,6 @@ enum {
PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table.
PT_MIPS_OPTIONS = 0x70000002, // Options segment.
PT_MIPS_ABIFLAGS = 0x70000003, // Abiflags segment.
-
- // WebAssembly program header types.
- PT_WEBASSEMBLY_FUNCTIONS = PT_LOPROC + 0, // Function definitions.
};
// Segment flag bits.
@@ -1130,154 +1198,9 @@ struct Elf64_Dyn {
// Dynamic table entry tags.
enum {
- DT_NULL = 0, // Marks end of dynamic array.
- DT_NEEDED = 1, // String table offset of needed library.
- DT_PLTRELSZ = 2, // Size of relocation entries in PLT.
- DT_PLTGOT = 3, // Address associated with linkage table.
- DT_HASH = 4, // Address of symbolic hash table.
- DT_STRTAB = 5, // Address of dynamic string table.
- DT_SYMTAB = 6, // Address of dynamic symbol table.
- DT_RELA = 7, // Address of relocation table (Rela entries).
- DT_RELASZ = 8, // Size of Rela relocation table.
- DT_RELAENT = 9, // Size of a Rela relocation entry.
- DT_STRSZ = 10, // Total size of the string table.
- DT_SYMENT = 11, // Size of a symbol table entry.
- DT_INIT = 12, // Address of initialization function.
- DT_FINI = 13, // Address of termination function.
- DT_SONAME = 14, // String table offset of a shared objects name.
- DT_RPATH = 15, // String table offset of library search path.
- DT_SYMBOLIC = 16, // Changes symbol resolution algorithm.
- DT_REL = 17, // Address of relocation table (Rel entries).
- DT_RELSZ = 18, // Size of Rel relocation table.
- DT_RELENT = 19, // Size of a Rel relocation entry.
- DT_PLTREL = 20, // Type of relocation entry used for linking.
- DT_DEBUG = 21, // Reserved for debugger.
- DT_TEXTREL = 22, // Relocations exist for non-writable segments.
- DT_JMPREL = 23, // Address of relocations associated with PLT.
- DT_BIND_NOW = 24, // Process all relocations before execution.
- DT_INIT_ARRAY = 25, // Pointer to array of initialization functions.
- DT_FINI_ARRAY = 26, // Pointer to array of termination functions.
- DT_INIT_ARRAYSZ = 27, // Size of DT_INIT_ARRAY.
- DT_FINI_ARRAYSZ = 28, // Size of DT_FINI_ARRAY.
- DT_RUNPATH = 29, // String table offset of lib search path.
- DT_FLAGS = 30, // Flags.
- DT_ENCODING = 32, // Values from here to DT_LOOS follow the rules
- // for the interpretation of the d_un union.
-
- DT_PREINIT_ARRAY = 32, // Pointer to array of preinit functions.
- DT_PREINIT_ARRAYSZ = 33, // Size of the DT_PREINIT_ARRAY array.
-
- DT_LOOS = 0x60000000, // Start of environment specific tags.
- DT_HIOS = 0x6FFFFFFF, // End of environment specific tags.
- DT_LOPROC = 0x70000000, // Start of processor specific tags.
- DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags.
-
- // Android packed relocation section tags.
- // https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#31
- DT_ANDROID_REL = 0x6000000F,
- DT_ANDROID_RELSZ = 0x60000010,
- DT_ANDROID_RELA = 0x60000011,
- DT_ANDROID_RELASZ = 0x60000012,
-
- DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table.
- DT_TLSDESC_PLT =
- 0x6FFFFEF6, // Location of PLT entry for TLS descriptor resolver calls.
- DT_TLSDESC_GOT = 0x6FFFFEF7, // Location of GOT entry used by TLS descriptor
- // resolver PLT entry.
- DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count.
- DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count.
-
- DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1.
- DT_VERSYM = 0x6FFFFFF0, // The address of .gnu.version section.
- DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table.
- DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF.
- DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table.
- DT_VERNEEDNUM = 0X6FFFFFFF, // The number of entries in DT_VERNEED.
-
- // Hexagon specific dynamic table entries
- DT_HEXAGON_SYMSZ = 0x70000000,
- DT_HEXAGON_VER = 0x70000001,
- DT_HEXAGON_PLT = 0x70000002,
-
- // Mips specific dynamic table entry tags.
- DT_MIPS_RLD_VERSION = 0x70000001, // 32 bit version number for runtime
- // linker interface.
- DT_MIPS_TIME_STAMP = 0x70000002, // Time stamp.
- DT_MIPS_ICHECKSUM = 0x70000003, // Checksum of external strings
- // and common sizes.
- DT_MIPS_IVERSION = 0x70000004, // Index of version string
- // in string table.
- DT_MIPS_FLAGS = 0x70000005, // 32 bits of flags.
- DT_MIPS_BASE_ADDRESS = 0x70000006, // Base address of the segment.
- DT_MIPS_MSYM = 0x70000007, // Address of .msym section.
- DT_MIPS_CONFLICT = 0x70000008, // Address of .conflict section.
- DT_MIPS_LIBLIST = 0x70000009, // Address of .liblist section.
- DT_MIPS_LOCAL_GOTNO = 0x7000000a, // Number of local global offset
- // table entries.
- DT_MIPS_CONFLICTNO = 0x7000000b, // Number of entries
- // in the .conflict section.
- DT_MIPS_LIBLISTNO = 0x70000010, // Number of entries
- // in the .liblist section.
- DT_MIPS_SYMTABNO = 0x70000011, // Number of entries
- // in the .dynsym section.
- DT_MIPS_UNREFEXTNO = 0x70000012, // Index of first external dynamic symbol
- // not referenced locally.
- DT_MIPS_GOTSYM = 0x70000013, // Index of first dynamic symbol
- // in global offset table.
- DT_MIPS_HIPAGENO = 0x70000014, // Number of page table entries
- // in global offset table.
- DT_MIPS_RLD_MAP = 0x70000016, // Address of run time loader map,
- // used for debugging.
- DT_MIPS_DELTA_CLASS = 0x70000017, // Delta C++ class definition.
- DT_MIPS_DELTA_CLASS_NO = 0x70000018, // Number of entries
- // in DT_MIPS_DELTA_CLASS.
- DT_MIPS_DELTA_INSTANCE = 0x70000019, // Delta C++ class instances.
- DT_MIPS_DELTA_INSTANCE_NO = 0x7000001A, // Number of entries
- // in DT_MIPS_DELTA_INSTANCE.
- DT_MIPS_DELTA_RELOC = 0x7000001B, // Delta relocations.
- DT_MIPS_DELTA_RELOC_NO = 0x7000001C, // Number of entries
- // in DT_MIPS_DELTA_RELOC.
- DT_MIPS_DELTA_SYM = 0x7000001D, // Delta symbols that Delta
- // relocations refer to.
- DT_MIPS_DELTA_SYM_NO = 0x7000001E, // Number of entries
- // in DT_MIPS_DELTA_SYM.
- DT_MIPS_DELTA_CLASSSYM = 0x70000020, // Delta symbols that hold
- // class declarations.
- DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, // Number of entries
- // in DT_MIPS_DELTA_CLASSSYM.
- DT_MIPS_CXX_FLAGS = 0x70000022, // Flags indicating information
- // about C++ flavor.
- DT_MIPS_PIXIE_INIT = 0x70000023, // Pixie information.
- DT_MIPS_SYMBOL_LIB = 0x70000024, // Address of .MIPS.symlib
- DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, // The GOT index of the first PTE
- // for a segment
- DT_MIPS_LOCAL_GOTIDX = 0x70000026, // The GOT index of the first PTE
- // for a local symbol
- DT_MIPS_HIDDEN_GOTIDX = 0x70000027, // The GOT index of the first PTE
- // for a hidden symbol
- DT_MIPS_PROTECTED_GOTIDX = 0x70000028, // The GOT index of the first PTE
- // for a protected symbol
- DT_MIPS_OPTIONS = 0x70000029, // Address of `.MIPS.options'.
- DT_MIPS_INTERFACE = 0x7000002A, // Address of `.interface'.
- DT_MIPS_DYNSTR_ALIGN = 0x7000002B, // Unknown.
- DT_MIPS_INTERFACE_SIZE = 0x7000002C, // Size of the .interface section.
- DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002D, // Size of rld_text_resolve
- // function stored in the GOT.
- DT_MIPS_PERF_SUFFIX = 0x7000002E, // Default suffix of DSO to be added
- // by rld on dlopen() calls.
- DT_MIPS_COMPACT_SIZE = 0x7000002F, // Size of compact relocation
- // section (O32).
- DT_MIPS_GP_VALUE = 0x70000030, // GP value for auxiliary GOTs.
- DT_MIPS_AUX_DYNAMIC = 0x70000031, // Address of auxiliary .dynamic.
- DT_MIPS_PLTGOT = 0x70000032, // Address of the base of the PLTGOT.
- DT_MIPS_RWPLT = 0x70000034, // Points to the base
- // of a writable PLT.
- DT_MIPS_RLD_MAP_REL = 0x70000035, // Relative offset of run time loader
- // map, used for debugging.
-
- // Sun machine-independent extensions.
- DT_AUXILIARY = 0x7FFFFFFD, // Shared object to load before self
- DT_FILTER = 0x7FFFFFFF // Shared object to get values from
+#define DYNAMIC_TAG(name, value) DT_##name = value,
+#include "DynamicTags.def"
+#undef DYNAMIC_TAG
};
// DT_FLAGS values.
@@ -1380,6 +1303,20 @@ enum {
NT_GNU_HWCAP = 2,
NT_GNU_BUILD_ID = 3,
NT_GNU_GOLD_VERSION = 4,
+ NT_GNU_PROPERTY_TYPE_0 = 5,
+};
+
+// Property types used in GNU_PROPERTY_TYPE_0 notes.
+enum : unsigned {
+ GNU_PROPERTY_STACK_SIZE = 1,
+ GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2,
+ GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002
+};
+
+// CET properties
+enum {
+ GNU_PROPERTY_X86_FEATURE_1_IBT = 1 << 0,
+ GNU_PROPERTY_X86_FEATURE_1_SHSTK = 1 << 1
};
// AMDGPU specific notes.
@@ -1423,6 +1360,20 @@ struct Elf64_Chdr {
Elf64_Xword ch_addralign;
};
+// Node header for ELF32.
+struct Elf32_Nhdr {
+ Elf32_Word n_namesz;
+ Elf32_Word n_descsz;
+ Elf32_Word n_type;
+};
+
+// Node header for ELF64.
+struct Elf64_Nhdr {
+ Elf64_Word n_namesz;
+ Elf64_Word n_descsz;
+ Elf64_Word n_type;
+};
+
// Legal values for ch_type field of compressed section header.
enum {
ELFCOMPRESS_ZLIB = 1, // ZLIB/DEFLATE algorithm.
diff --git a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def b/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
index 3a47c5a07574..8c5b482f0511 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
+++ b/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
@@ -89,6 +89,13 @@
#undef R_PPC64_DTPREL16_HIGHESTA
#undef R_PPC64_TLSGD
#undef R_PPC64_TLSLD
+#undef R_PPC64_ADDR16_HIGH
+#undef R_PPC64_ADDR16_HIGHA
+#undef R_PPC64_TPREL16_HIGH
+#undef R_PPC64_TPREL16_HIGHA
+#undef R_PPC64_DTPREL16_HIGH
+#undef R_PPC64_DTPREL16_HIGHA
+#undef R_PPC64_IRELATIVE
#undef R_PPC64_REL16
#undef R_PPC64_REL16_LO
#undef R_PPC64_REL16_HI
@@ -175,6 +182,13 @@ 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_ADDR16_HIGH, 110)
+ELF_RELOC(R_PPC64_ADDR16_HIGHA, 111)
+ELF_RELOC(R_PPC64_TPREL16_HIGH, 112)
+ELF_RELOC(R_PPC64_TPREL16_HIGHA, 113)
+ELF_RELOC(R_PPC64_DTPREL16_HIGH, 114)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHA, 115)
+ELF_RELOC(R_PPC64_IRELATIVE, 248)
ELF_RELOC(R_PPC64_REL16, 249)
ELF_RELOC(R_PPC64_REL16_LO, 250)
ELF_RELOC(R_PPC64_REL16_HI, 251)
diff --git a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/WebAssembly.def b/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/WebAssembly.def
deleted file mode 100644
index 9a34349efb96..000000000000
--- a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/WebAssembly.def
+++ /dev/null
@@ -1,8 +0,0 @@
-
-#ifndef ELF_RELOC
-#error "ELF_RELOC must be defined"
-#endif
-
-ELF_RELOC(R_WEBASSEMBLY_NONE, 0)
-ELF_RELOC(R_WEBASSEMBLY_DATA, 1)
-ELF_RELOC(R_WEBASSEMBLY_FUNCTION, 2)
diff --git a/contrib/llvm/include/llvm/BinaryFormat/MachO.h b/contrib/llvm/include/llvm/BinaryFormat/MachO.h
index 060fbe162ad2..c5294c76ebf7 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/MachO.h
+++ b/contrib/llvm/include/llvm/BinaryFormat/MachO.h
@@ -1973,9 +1973,11 @@ const uint32_t PPC_THREAD_STATE_COUNT =
// Define a union of all load command structs
#define LOAD_COMMAND_STRUCT(LCStruct) LCStruct LCStruct##_data;
-union macho_load_command {
+LLVM_PACKED_START
+union alignas(4) macho_load_command {
#include "llvm/BinaryFormat/MachO.def"
};
+LLVM_PACKED_END
} // end namespace MachO
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/BinaryFormat/Magic.h b/contrib/llvm/include/llvm/BinaryFormat/Magic.h
index c0e23db5e1ae..04801f810be3 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/Magic.h
+++ b/contrib/llvm/include/llvm/BinaryFormat/Magic.h
@@ -45,7 +45,8 @@ struct file_magic {
coff_import_library, ///< COFF import library
pecoff_executable, ///< PECOFF executable file
windows_resource, ///< Windows compiled resource file (.res)
- wasm_object ///< WebAssembly Object file
+ wasm_object, ///< WebAssembly Object file
+ pdb, ///< Windows PDB debug info file
};
bool is_object() const { return V != unknown; }
@@ -58,10 +59,10 @@ private:
Impl V = unknown;
};
-/// @brief Identify the type of a binary file based on how magical it is.
+/// Identify the type of a binary file based on how magical it is.
file_magic identify_magic(StringRef magic);
-/// @brief Get and identify \a path's type based on its content.
+/// Get and identify \a path's type based on its content.
///
/// @param path Input path.
/// @param result Set to the type of file, or file_magic::unknown.
diff --git a/contrib/llvm/include/llvm/BinaryFormat/Wasm.h b/contrib/llvm/include/llvm/BinaryFormat/Wasm.h
index 57a0b441821b..fa5448dacec4 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/contrib/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -24,6 +24,8 @@ namespace wasm {
const char WasmMagic[] = {'\0', 'a', 's', 'm'};
// Wasm binary format version
const uint32_t WasmVersion = 0x1;
+// Wasm linking metadata version
+const uint32_t WasmMetadataVersion = 0x1;
// Wasm uses a 64k page size
const uint32_t WasmPageSize = 65536;
@@ -33,24 +35,24 @@ struct WasmObjectHeader {
};
struct WasmSignature {
- std::vector<int32_t> ParamTypes;
- int32_t ReturnType;
+ std::vector<uint8_t> ParamTypes;
+ uint8_t ReturnType;
};
struct WasmExport {
StringRef Name;
- uint32_t Kind;
+ uint8_t Kind;
uint32_t Index;
};
struct WasmLimits {
- uint32_t Flags;
+ uint8_t Flags;
uint32_t Initial;
uint32_t Maximum;
};
struct WasmTable {
- int32_t ElemType;
+ uint8_t ElemType;
WasmLimits Limits;
};
@@ -65,43 +67,55 @@ struct WasmInitExpr {
} Value;
};
-struct WasmGlobal {
- int32_t Type;
+struct WasmGlobalType {
+ uint8_t Type;
bool Mutable;
+};
+
+struct WasmGlobal {
+ uint32_t Index;
+ WasmGlobalType Type;
WasmInitExpr InitExpr;
+ StringRef SymbolName; // from the "linking" section
};
struct WasmImport {
StringRef Module;
StringRef Field;
- uint32_t Kind;
+ uint8_t Kind;
union {
uint32_t SigIndex;
- WasmGlobal Global;
+ WasmGlobalType Global;
WasmTable Table;
WasmLimits Memory;
};
};
struct WasmLocalDecl {
- int32_t Type;
+ uint8_t Type;
uint32_t Count;
};
struct WasmFunction {
+ uint32_t Index;
std::vector<WasmLocalDecl> Locals;
ArrayRef<uint8_t> Body;
uint32_t CodeSectionOffset;
uint32_t Size;
+ uint32_t CodeOffset; // start of Locals and Body
+ StringRef SymbolName; // from the "linking" section
+ StringRef DebugName; // from the "name" section
+ uint32_t Comdat; // from the "comdat info" section
};
struct WasmDataSegment {
uint32_t MemoryIndex;
WasmInitExpr Offset;
ArrayRef<uint8_t> Content;
- StringRef Name;
+ StringRef Name; // from the "segment info" section
uint32_t Alignment;
uint32_t Flags;
+ uint32_t Comdat; // from the "comdat info" section
};
struct WasmElemSegment {
@@ -110,21 +124,50 @@ struct WasmElemSegment {
std::vector<uint32_t> Functions;
};
+// Represents the location of a Wasm data symbol within a WasmDataSegment, as
+// the index of the segment, and the offset and size within the segment.
+struct WasmDataReference {
+ uint32_t Segment;
+ uint32_t Offset;
+ uint32_t Size;
+};
+
struct WasmRelocation {
- uint32_t Type; // The type of the relocation.
- uint32_t Index; // Index into function to global index space.
+ uint8_t Type; // The type of the relocation.
+ uint32_t Index; // Index into either symbol or type index space.
uint64_t Offset; // Offset from the start of the section.
int64_t Addend; // A value to add to the symbol.
};
struct WasmInitFunc {
uint32_t Priority;
- uint32_t FunctionIndex;
+ uint32_t Symbol;
+};
+
+struct WasmSymbolInfo {
+ StringRef Name;
+ uint8_t Kind;
+ uint32_t Flags;
+ StringRef Module; // For undefined symbols the module name of the import
+ union {
+ // For function or global symbols, the index in function or global index
+ // space.
+ uint32_t ElementIndex;
+ // For a data symbols, the address of the data relative to segment.
+ WasmDataReference DataRef;
+ };
+};
+
+struct WasmFunctionName {
+ uint32_t Index;
+ StringRef Name;
};
struct WasmLinkingData {
- uint32_t DataSize;
+ uint32_t Version;
std::vector<WasmInitFunc> InitFunctions;
+ std::vector<StringRef> Comdats;
+ std::vector<WasmSymbolInfo> SymbolTable;
};
enum : unsigned {
@@ -143,14 +186,15 @@ enum : unsigned {
};
// Type immediate encodings used in various contexts.
-enum {
- WASM_TYPE_I32 = -0x01,
- WASM_TYPE_I64 = -0x02,
- WASM_TYPE_F32 = -0x03,
- WASM_TYPE_F64 = -0x04,
- WASM_TYPE_ANYFUNC = -0x10,
- WASM_TYPE_FUNC = -0x20,
- WASM_TYPE_NORESULT = -0x40, // for blocks with no result values
+enum : unsigned {
+ WASM_TYPE_I32 = 0x7F,
+ WASM_TYPE_I64 = 0x7E,
+ WASM_TYPE_F32 = 0x7D,
+ WASM_TYPE_F64 = 0x7C,
+ WASM_TYPE_ANYFUNC = 0x70,
+ WASM_TYPE_EXCEPT_REF = 0x68,
+ WASM_TYPE_FUNC = 0x60,
+ WASM_TYPE_NORESULT = 0x40, // for blocks with no result values
};
// Kinds of externals (for imports and exports).
@@ -172,11 +216,6 @@ enum : unsigned {
};
enum : unsigned {
- WASM_NAMES_FUNCTION = 0x1,
- WASM_NAMES_LOCAL = 0x2,
-};
-
-enum : unsigned {
WASM_LIMITS_FLAG_HAS_MAX = 0x1,
};
@@ -186,24 +225,46 @@ enum class ValType {
I64 = WASM_TYPE_I64,
F32 = WASM_TYPE_F32,
F64 = WASM_TYPE_F64,
+ EXCEPT_REF = WASM_TYPE_EXCEPT_REF,
+};
+
+// Kind codes used in the custom "name" section
+enum : unsigned {
+ WASM_NAMES_FUNCTION = 0x1,
+ WASM_NAMES_LOCAL = 0x2,
};
-// Linking metadata kinds.
+// Kind codes used in the custom "linking" section
enum : unsigned {
- WASM_SYMBOL_INFO = 0x2,
- WASM_DATA_SIZE = 0x3,
WASM_SEGMENT_INFO = 0x5,
WASM_INIT_FUNCS = 0x6,
+ WASM_COMDAT_INFO = 0x7,
+ WASM_SYMBOL_TABLE = 0x8,
+};
+
+// Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
+enum : unsigned {
+ WASM_COMDAT_DATA = 0x0,
+ WASM_COMDAT_FUNCTION = 0x1,
+};
+
+// Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE
+enum WasmSymbolType : unsigned {
+ WASM_SYMBOL_TYPE_FUNCTION = 0x0,
+ WASM_SYMBOL_TYPE_DATA = 0x1,
+ WASM_SYMBOL_TYPE_GLOBAL = 0x2,
+ WASM_SYMBOL_TYPE_SECTION = 0x3,
};
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
-const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0x4;
+const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
+const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
#define WASM_RELOC(name, value) name = value,
@@ -213,18 +274,25 @@ enum : unsigned {
#undef WASM_RELOC
-struct Global {
- ValType Type;
- bool Mutable;
+// Useful comparison operators
+inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) {
+ return LHS.ReturnType == RHS.ReturnType && LHS.ParamTypes == RHS.ParamTypes;
+}
- // The initial value for this global is either the value of an imported
- // global, in which case InitialModule and InitialName specify the global
- // import, or a value, in which case InitialModule is empty and InitialValue
- // holds the value.
- StringRef InitialModule;
- StringRef InitialName;
- uint64_t InitialValue;
-};
+inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) {
+ return !(LHS == RHS);
+}
+
+inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) {
+ return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable;
+}
+
+inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) {
+ return !(LHS == RHS);
+}
+
+std::string toString(wasm::WasmSymbolType type);
+std::string relocTypetoString(uint32_t type);
} // end namespace wasm
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def b/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def
index d6f0e42b33bf..8ffd51e483f3 100644
--- a/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def
+++ b/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def
@@ -11,3 +11,5 @@ WASM_RELOC(R_WEBASSEMBLY_MEMORY_ADDR_SLEB, 4)
WASM_RELOC(R_WEBASSEMBLY_MEMORY_ADDR_I32, 5)
WASM_RELOC(R_WEBASSEMBLY_TYPE_INDEX_LEB, 6)
WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB, 7)
+WASM_RELOC(R_WEBASSEMBLY_FUNCTION_OFFSET_I32, 8)
+WASM_RELOC(R_WEBASSEMBLY_SECTION_OFFSET_I32, 9)
diff --git a/contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h b/contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h
index c78077525c8b..0010cf6c0544 100644
--- a/contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h
+++ b/contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h
@@ -86,7 +86,7 @@ class raw_ostream;
/// Can be used to produce the same module hash for a minimized bitcode
/// used just for the thin link as in the regular full bitcode that will
/// be used in the backend.
- void writeModule(const Module *M, bool ShouldPreserveUseListOrder = false,
+ void writeModule(const Module &M, bool ShouldPreserveUseListOrder = false,
const ModuleSummaryIndex *Index = nullptr,
bool GenerateHash = false, ModuleHash *ModHash = nullptr);
@@ -97,7 +97,7 @@ class raw_ostream;
///
/// ModHash is for use in ThinLTO incremental build, generated while the
/// IR bitcode file writing.
- void writeThinLinkBitcode(const Module *M, const ModuleSummaryIndex &Index,
+ void writeThinLinkBitcode(const Module &M, const ModuleSummaryIndex &Index,
const ModuleHash &ModHash);
void writeIndex(
@@ -105,7 +105,7 @@ class raw_ostream;
const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex);
};
- /// \brief Write the specified module to the specified raw output stream.
+ /// Write the specified module to the specified raw output stream.
///
/// For streams where it matters, the given stream should be in "binary"
/// mode.
@@ -126,7 +126,7 @@ class raw_ostream;
/// Can be used to produce the same module hash for a minimized bitcode
/// used just for the thin link as in the regular full bitcode that will
/// be used in the backend.
- void WriteBitcodeToFile(const Module *M, raw_ostream &Out,
+ void WriteBitcodeToFile(const Module &M, raw_ostream &Out,
bool ShouldPreserveUseListOrder = false,
const ModuleSummaryIndex *Index = nullptr,
bool GenerateHash = false,
@@ -139,7 +139,7 @@ class raw_ostream;
///
/// ModHash is for use in ThinLTO incremental build, generated while the IR
/// bitcode file writing.
- void WriteThinLinkBitcodeToFile(const Module *M, raw_ostream &Out,
+ void WriteThinLinkBitcodeToFile(const Module &M, raw_ostream &Out,
const ModuleSummaryIndex &Index,
const ModuleHash &ModHash);
diff --git a/contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h b/contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h
index 9ac6fba16b96..05044c9ae11c 100644
--- a/contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h
+++ b/contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h
@@ -21,9 +21,10 @@
namespace llvm {
class Module;
class ModulePass;
+class Pass;
class raw_ostream;
-/// \brief Create and return a pass that writes the module to the specified
+/// Create and return a pass that writes the module to the specified
/// ostream. Note that this pass is designed for use with the legacy pass
/// manager.
///
@@ -40,7 +41,10 @@ ModulePass *createBitcodeWriterPass(raw_ostream &Str,
bool EmitSummaryIndex = false,
bool EmitModuleHash = false);
-/// \brief Pass for writing a module of IR out to a bitcode file.
+/// Check whether a pass is a BitcodeWriterPass.
+bool isBitcodeWriterPass(Pass *P);
+
+/// Pass for writing a module of IR out to a bitcode file.
///
/// Note that this is intended for use with the new pass manager. To construct
/// a pass for the legacy pass manager, use the function above.
@@ -51,7 +55,7 @@ class BitcodeWriterPass : public PassInfoMixin<BitcodeWriterPass> {
bool EmitModuleHash;
public:
- /// \brief Construct a bitcode writer pass around a particular output stream.
+ /// Construct a bitcode writer pass around a particular output stream.
///
/// If \c ShouldPreserveUseListOrder, encode use-list order so it can be
/// reproduced when deserialized.
@@ -65,7 +69,7 @@ public:
: OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
EmitSummaryIndex(EmitSummaryIndex), EmitModuleHash(EmitModuleHash) {}
- /// \brief Run the bitcode writer pass, and output the module to the selected
+ /// Run the bitcode writer pass, and output the module to the selected
/// output stream.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
};
diff --git a/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h b/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h
index b484fa2efbfb..72e7619d9e1c 100644
--- a/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h
+++ b/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h
@@ -429,7 +429,7 @@ public:
// don't care what code widths are used inside of it.
ReadVBR(bitc::CodeLenWidth);
SkipToFourByteBoundary();
- unsigned NumFourBytes = Read(bitc::BlockSizeWidth);
+ size_t NumFourBytes = Read(bitc::BlockSizeWidth);
// Check that the block wasn't partially defined, and that the offset isn't
// bogus.
diff --git a/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h b/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h
index e276db5f92f6..c854769e0622 100644
--- a/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h
+++ b/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h
@@ -90,10 +90,10 @@ public:
assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
}
- /// \brief Retrieve the current position in the stream, in bits.
+ /// Retrieve the current position in the stream, in bits.
uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
- /// \brief Retrieve the number of bits currently used to encode an abbrev ID.
+ /// Retrieve the number of bits currently used to encode an abbrev ID.
unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
//===--------------------------------------------------------------------===//
diff --git a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 01419d7ae2bf..6723cf42dd2c 100644
--- a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -256,6 +256,18 @@ enum GlobalValueSummarySymtabCodes {
// strings in strtab.
// [n * name]
FS_CFI_FUNCTION_DECLS = 18,
+ // Per-module summary that also adds relative block frequency to callee info.
+ // PERMODULE_RELBF: [valueid, flags, instcount, numrefs,
+ // numrefs x valueid,
+ // n x (valueid, relblockfreq)]
+ FS_PERMODULE_RELBF = 19,
+ // Index-wide flags
+ FS_FLAGS = 20,
+ // Maps type identifier to summary information for that type identifier.
+ // TYPE_ID: [typeid, kind, bitwidth, align, size, bitmask, inlinebits,
+ // n x (typeid, kind, name, numrba,
+ // numrba x (numarg, numarg x arg, kind, info, byte, bit))]
+ FS_TYPE_ID = 21,
};
enum MetadataCodes {
@@ -272,7 +284,7 @@ enum MetadataCodes {
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_ENUMERATOR = 14, // [isUnsigned|distinct, value, name]
METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc]
METADATA_FILE = 16, // [distinct, filename, directory, checksumkind, checksum]
METADATA_DERIVED_TYPE = 17, // [distinct, ...]
@@ -298,6 +310,7 @@ enum MetadataCodes {
METADATA_GLOBAL_VAR_EXPR = 37, // [distinct, var, expr]
METADATA_INDEX_OFFSET = 38, // [offset]
METADATA_INDEX = 39, // [bitpos]
+ METADATA_LABEL = 40, // [distinct, scope, name, file, line]
};
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
@@ -575,6 +588,9 @@ enum AttributeKindCodes {
ATTR_KIND_SPECULATABLE = 53,
ATTR_KIND_STRICT_FP = 54,
ATTR_KIND_SANITIZE_HWADDRESS = 55,
+ ATTR_KIND_NOCF_CHECK = 56,
+ ATTR_KIND_OPT_FOR_FUZZING = 57,
+ ATTR_KIND_SHADOWCALLSTACK = 58,
};
enum ComdatSelectionKindCodes {
diff --git a/contrib/llvm/include/llvm/CodeGen/AccelTable.h b/contrib/llvm/include/llvm/CodeGen/AccelTable.h
new file mode 100644
index 000000000000..13928582f2dd
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/AccelTable.h
@@ -0,0 +1,434 @@
+//==- include/llvm/CodeGen/AccelTable.h - Accelerator Tables -----*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing accelerator tables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_DWARFACCELTABLE_H
+#define LLVM_CODEGEN_DWARFACCELTABLE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/CodeGen/DwarfStringPoolEntry.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DJB.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+/// The DWARF and Apple accelerator tables are an indirect hash table optimized
+/// for null lookup rather than access to known data. The Apple accelerator
+/// tables are a precursor of the newer DWARF v5 accelerator tables. Both
+/// formats share common design ideas.
+///
+/// The Apple accelerator table are output into an on-disk format that looks
+/// like this:
+///
+/// .------------------.
+/// | HEADER |
+/// |------------------|
+/// | BUCKETS |
+/// |------------------|
+/// | HASHES |
+/// |------------------|
+/// | OFFSETS |
+/// |------------------|
+/// | DATA |
+/// `------------------'
+///
+/// The header contains a magic number, version, type of hash function,
+/// the number of buckets, total number of hashes, and room for a special struct
+/// of data and the length of that struct.
+///
+/// The buckets contain an index (e.g. 6) into the hashes array. The hashes
+/// section contains all of the 32-bit hash values in contiguous memory, and the
+/// offsets contain the offset into the data area for the particular hash.
+///
+/// For a lookup example, we could hash a function name and take it modulo the
+/// number of buckets giving us our bucket. From there we take the bucket value
+/// as an index into the hashes table and look at each successive hash as long
+/// as the hash value is still the same modulo result (bucket value) as earlier.
+/// If we have a match we look at that same entry in the offsets table and grab
+/// the offset in the data for our final match.
+///
+/// The DWARF v5 accelerator table consists of zero or more name indices that
+/// are output into an on-disk format that looks like this:
+///
+/// .------------------.
+/// | HEADER |
+/// |------------------|
+/// | CU LIST |
+/// |------------------|
+/// | LOCAL TU LIST |
+/// |------------------|
+/// | FOREIGN TU LIST |
+/// |------------------|
+/// | HASH TABLE |
+/// |------------------|
+/// | NAME TABLE |
+/// |------------------|
+/// | ABBREV TABLE |
+/// |------------------|
+/// | ENTRY POOL |
+/// `------------------'
+///
+/// For the full documentation please refer to the DWARF 5 standard.
+///
+///
+/// This file defines the class template AccelTable, which is represents an
+/// abstract view of an Accelerator table, without any notion of an on-disk
+/// layout. This class is parameterized by an entry type, which should derive
+/// from AccelTableData. This is the type of individual entries in the table,
+/// and it should store the data necessary to emit them. AppleAccelTableData is
+/// the base class for Apple Accelerator Table entries, which have a uniform
+/// structure based on a sequence of Atoms. There are different sub-classes
+/// derived from AppleAccelTable, which differ in the set of Atoms and how they
+/// obtain their values.
+///
+/// An Apple Accelerator Table can be serialized by calling emitAppleAccelTable
+/// function.
+///
+/// TODO: Add DWARF v5 emission code.
+
+namespace llvm {
+
+class AsmPrinter;
+class DwarfCompileUnit;
+class DwarfDebug;
+
+/// Interface which the different types of accelerator table data have to
+/// conform. It serves as a base class for different values of the template
+/// argument of the AccelTable class template.
+class AccelTableData {
+public:
+ virtual ~AccelTableData() = default;
+
+ bool operator<(const AccelTableData &Other) const {
+ return order() < Other.order();
+ }
+
+ // Subclasses should implement:
+ // static uint32_t hash(StringRef Name);
+
+#ifndef NDEBUG
+ virtual void print(raw_ostream &OS) const = 0;
+#endif
+protected:
+ virtual uint64_t order() const = 0;
+};
+
+/// A base class holding non-template-dependant functionality of the AccelTable
+/// class. Clients should not use this class directly but rather instantiate
+/// AccelTable with a type derived from AccelTableData.
+class AccelTableBase {
+public:
+ using HashFn = uint32_t(StringRef);
+
+ /// Represents a group of entries with identical name (and hence, hash value).
+ struct HashData {
+ DwarfStringPoolEntryRef Name;
+ uint32_t HashValue;
+ std::vector<AccelTableData *> Values;
+ MCSymbol *Sym;
+
+ HashData(DwarfStringPoolEntryRef Name, HashFn *Hash)
+ : Name(Name), HashValue(Hash(Name.getString())) {}
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const;
+ void dump() const { print(dbgs()); }
+#endif
+ };
+ using HashList = std::vector<HashData *>;
+ using BucketList = std::vector<HashList>;
+
+protected:
+ /// Allocator for HashData and Values.
+ BumpPtrAllocator Allocator;
+
+ using StringEntries = StringMap<HashData, BumpPtrAllocator &>;
+ StringEntries Entries;
+
+ HashFn *Hash;
+ uint32_t BucketCount;
+ uint32_t UniqueHashCount;
+
+ HashList Hashes;
+ BucketList Buckets;
+
+ void computeBucketCount();
+
+ AccelTableBase(HashFn *Hash) : Entries(Allocator), Hash(Hash) {}
+
+public:
+ void finalize(AsmPrinter *Asm, StringRef Prefix);
+ ArrayRef<HashList> getBuckets() const { return Buckets; }
+ uint32_t getBucketCount() const { return BucketCount; }
+ uint32_t getUniqueHashCount() const { return UniqueHashCount; }
+ uint32_t getUniqueNameCount() const { return Entries.size(); }
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const;
+ void dump() const { print(dbgs()); }
+#endif
+
+ AccelTableBase(const AccelTableBase &) = delete;
+ void operator=(const AccelTableBase &) = delete;
+};
+
+/// This class holds an abstract representation of an Accelerator Table,
+/// consisting of a sequence of buckets, each bucket containint a sequence of
+/// HashData entries. The class is parameterized by the type of entries it
+/// holds. The type template parameter also defines the hash function to use for
+/// hashing names.
+template <typename DataT> class AccelTable : public AccelTableBase {
+public:
+ AccelTable() : AccelTableBase(DataT::hash) {}
+
+ template <typename... Types>
+ void addName(DwarfStringPoolEntryRef Name, Types &&... Args);
+};
+
+template <typename AccelTableDataT>
+template <typename... Types>
+void AccelTable<AccelTableDataT>::addName(DwarfStringPoolEntryRef Name,
+ Types &&... Args) {
+ assert(Buckets.empty() && "Already finalized!");
+ // If the string is in the list already then add this die to the list
+ // otherwise add a new one.
+ auto Iter = Entries.try_emplace(Name.getString(), Name, Hash).first;
+ assert(Iter->second.Name == Name);
+ Iter->second.Values.push_back(
+ new (Allocator) AccelTableDataT(std::forward<Types>(Args)...));
+}
+
+/// A base class for different implementations of Data classes for Apple
+/// Accelerator Tables. The columns in the table are defined by the static Atoms
+/// variable defined on the subclasses.
+class AppleAccelTableData : public AccelTableData {
+public:
+ /// An Atom defines the form of the data in an Apple accelerator table.
+ /// Conceptually it is a column in the accelerator consisting of a type and a
+ /// specification of the form of its data.
+ struct Atom {
+ /// Atom Type.
+ const uint16_t Type;
+ /// DWARF Form.
+ const uint16_t Form;
+
+ constexpr Atom(uint16_t Type, uint16_t Form) : Type(Type), Form(Form) {}
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const;
+ void dump() const { print(dbgs()); }
+#endif
+ };
+ // Subclasses should define:
+ // static constexpr Atom Atoms[];
+
+ virtual void emit(AsmPrinter *Asm) const = 0;
+
+ static uint32_t hash(StringRef Buffer) { return djbHash(Buffer); }
+};
+
+/// The Data class implementation for DWARF v5 accelerator table. Unlike the
+/// Apple Data classes, this class is just a DIE wrapper, and does not know to
+/// serialize itself. The complete serialization logic is in the
+/// emitDWARF5AccelTable function.
+class DWARF5AccelTableData : public AccelTableData {
+public:
+ static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); }
+
+ DWARF5AccelTableData(const DIE &Die) : Die(Die) {}
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const override;
+#endif
+
+ const DIE &getDie() const { return Die; }
+ uint64_t getDieOffset() const { return Die.getOffset(); }
+ unsigned getDieTag() const { return Die.getTag(); }
+
+protected:
+ const DIE &Die;
+
+ uint64_t order() const override { return Die.getOffset(); }
+};
+
+class DWARF5AccelTableStaticData : public AccelTableData {
+public:
+ static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); }
+
+ DWARF5AccelTableStaticData(uint64_t DieOffset, unsigned DieTag,
+ unsigned CUIndex)
+ : DieOffset(DieOffset), DieTag(DieTag), CUIndex(CUIndex) {}
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const override;
+#endif
+
+ uint64_t getDieOffset() const { return DieOffset; }
+ unsigned getDieTag() const { return DieTag; }
+ unsigned getCUIndex() const { return CUIndex; }
+
+protected:
+ uint64_t DieOffset;
+ unsigned DieTag;
+ unsigned CUIndex;
+
+ uint64_t order() const override { return DieOffset; }
+};
+
+void emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
+ StringRef Prefix, const MCSymbol *SecBegin,
+ ArrayRef<AppleAccelTableData::Atom> Atoms);
+
+/// Emit an Apple Accelerator Table consisting of entries in the specified
+/// AccelTable. The DataT template parameter should be derived from
+/// AppleAccelTableData.
+template <typename DataT>
+void emitAppleAccelTable(AsmPrinter *Asm, AccelTable<DataT> &Contents,
+ StringRef Prefix, const MCSymbol *SecBegin) {
+ static_assert(std::is_convertible<DataT *, AppleAccelTableData *>::value, "");
+ emitAppleAccelTableImpl(Asm, Contents, Prefix, SecBegin, DataT::Atoms);
+}
+
+void emitDWARF5AccelTable(AsmPrinter *Asm,
+ AccelTable<DWARF5AccelTableData> &Contents,
+ const DwarfDebug &DD,
+ ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs);
+
+void emitDWARF5AccelTable(
+ AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
+ ArrayRef<MCSymbol *> CUs,
+ llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
+ getCUIndexForEntry);
+
+/// Accelerator table data implementation for simple Apple accelerator tables
+/// with just a DIE reference.
+class AppleAccelTableOffsetData : public AppleAccelTableData {
+public:
+ AppleAccelTableOffsetData(const DIE &D) : Die(D) {}
+
+ void emit(AsmPrinter *Asm) const override;
+
+#ifndef _MSC_VER
+ // The line below is rejected by older versions (TBD) of MSVC.
+ static constexpr Atom Atoms[] = {
+ Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
+#else
+ // FIXME: Erase this path once the minimum MSCV version has been bumped.
+ static const SmallVector<Atom, 4> Atoms;
+#endif
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const override;
+#endif
+protected:
+ uint64_t order() const override { return Die.getOffset(); }
+
+ const DIE &Die;
+};
+
+/// Accelerator table data implementation for Apple type accelerator tables.
+class AppleAccelTableTypeData : public AppleAccelTableOffsetData {
+public:
+ AppleAccelTableTypeData(const DIE &D) : AppleAccelTableOffsetData(D) {}
+
+ void emit(AsmPrinter *Asm) const override;
+
+#ifndef _MSC_VER
+ // The line below is rejected by older versions (TBD) of MSVC.
+ static constexpr Atom Atoms[] = {
+ Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
+ Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
+ Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)};
+#else
+ // FIXME: Erase this path once the minimum MSCV version has been bumped.
+ static const SmallVector<Atom, 4> Atoms;
+#endif
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const override;
+#endif
+};
+
+/// Accelerator table data implementation for simple Apple accelerator tables
+/// with a DIE offset but no actual DIE pointer.
+class AppleAccelTableStaticOffsetData : public AppleAccelTableData {
+public:
+ AppleAccelTableStaticOffsetData(uint32_t Offset) : Offset(Offset) {}
+
+ void emit(AsmPrinter *Asm) const override;
+
+#ifndef _MSC_VER
+ // The line below is rejected by older versions (TBD) of MSVC.
+ static constexpr Atom Atoms[] = {
+ Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
+#else
+ // FIXME: Erase this path once the minimum MSCV version has been bumped.
+ static const SmallVector<Atom, 4> Atoms;
+#endif
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const override;
+#endif
+protected:
+ uint64_t order() const override { return Offset; }
+
+ uint32_t Offset;
+};
+
+/// Accelerator table data implementation for type accelerator tables with
+/// a DIE offset but no actual DIE pointer.
+class AppleAccelTableStaticTypeData : public AppleAccelTableStaticOffsetData {
+public:
+ AppleAccelTableStaticTypeData(uint32_t Offset, uint16_t Tag,
+ bool ObjCClassIsImplementation,
+ uint32_t QualifiedNameHash)
+ : AppleAccelTableStaticOffsetData(Offset),
+ QualifiedNameHash(QualifiedNameHash), Tag(Tag),
+ ObjCClassIsImplementation(ObjCClassIsImplementation) {}
+
+ void emit(AsmPrinter *Asm) const override;
+
+#ifndef _MSC_VER
+ // The line below is rejected by older versions (TBD) of MSVC.
+ static constexpr Atom Atoms[] = {
+ Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
+ Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
+ Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)};
+#else
+ // FIXME: Erase this path once the minimum MSCV version has been bumped.
+ static const SmallVector<Atom, 4> Atoms;
+#endif
+
+#ifndef NDEBUG
+ void print(raw_ostream &OS) const override;
+#endif
+protected:
+ uint64_t order() const override { return Offset; }
+
+ uint32_t QualifiedNameHash;
+ uint16_t Tag;
+ bool ObjCClassIsImplementation;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_DWARFACCELTABLE_H
diff --git a/contrib/llvm/include/llvm/CodeGen/Analysis.h b/contrib/llvm/include/llvm/CodeGen/Analysis.h
index ba88f1f78fb8..d77aee66ed76 100644
--- a/contrib/llvm/include/llvm/CodeGen/Analysis.h
+++ b/contrib/llvm/include/llvm/CodeGen/Analysis.h
@@ -36,7 +36,7 @@ class SDValue;
class SelectionDAG;
struct EVT;
-/// \brief Compute the linearized index of a member in a nested
+/// 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
@@ -124,7 +124,7 @@ bool returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I,
const TargetLoweringBase &TLI);
DenseMap<const MachineBasicBlock *, int>
-getFuncletMembership(const MachineFunction &MF);
+getEHScopeMembership(const MachineFunction &MF);
} // End llvm namespace
diff --git a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h
index b8944a668000..b6056380916c 100644
--- a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -50,6 +50,7 @@ class GlobalValue;
class GlobalVariable;
class MachineBasicBlock;
class MachineConstantPoolValue;
+class MachineDominatorTree;
class MachineFunction;
class MachineInstr;
class MachineJumpTableInfo;
@@ -92,11 +93,17 @@ public:
std::unique_ptr<MCStreamer> OutStreamer;
/// The current machine function.
- const MachineFunction *MF = nullptr;
+ MachineFunction *MF = nullptr;
/// This is a pointer to the current MachineModuleInfo.
MachineModuleInfo *MMI = nullptr;
+ /// This is a pointer to the current MachineLoopInfo.
+ MachineDominatorTree *MDT = nullptr;
+
+ /// This is a pointer to the current MachineLoopInfo.
+ MachineLoopInfo *MLI = nullptr;
+
/// Optimization remark emitter.
MachineOptimizationRemarkEmitter *ORE;
@@ -130,9 +137,6 @@ private:
static char ID;
- /// If VerboseAsm is set, a pointer to the loop info for this function.
- MachineLoopInfo *LI = nullptr;
-
struct HandlerInfo {
AsmPrinterHandler *Handler;
const char *TimerName;
@@ -161,6 +165,12 @@ public:
};
private:
+ /// If generated on the fly this own the instance.
+ std::unique_ptr<MachineDominatorTree> OwnedMDT;
+
+ /// If generated on the fly this own the instance.
+ std::unique_ptr<MachineLoopInfo> OwnedMLI;
+
/// Structure for generating diagnostics for inline assembly. Only initialised
/// when necessary.
mutable std::unique_ptr<SrcMgrDiagInfo> DiagInfo;
@@ -191,6 +201,10 @@ public:
/// Return a unique ID for the current function.
unsigned getFunctionNumber() const;
+ /// Return symbol for the function pseudo stack if the stack frame is not a
+ /// register based.
+ virtual const MCSymbol *getFunctionFrameSymbol() const { return nullptr; }
+
MCSymbol *getFunctionBegin() const { return CurrentFnBegin; }
MCSymbol *getFunctionEnd() const { return CurrentFnEnd; }
MCSymbol *getCurExceptionSym();
@@ -228,6 +242,7 @@ public:
TAIL_CALL = 2,
LOG_ARGS_ENTER = 3,
CUSTOM_EVENT = 4,
+ TYPED_EVENT = 5,
};
// The table will contain these structs that point to the sled, the function
@@ -327,15 +342,15 @@ public:
/// global value is specified, and if that global has an explicit alignment
/// requested, it will override the alignment request if required for
/// correctness.
- void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const;
+ void EmitAlignment(unsigned NumBits, const GlobalObject *GV = nullptr) const;
/// Lower the specified LLVM Constant to an MCExpr.
virtual const MCExpr *lowerConstant(const Constant *CV);
- /// \brief Print a general LLVM constant to the .s file.
+ /// Print a general LLVM constant to the .s file.
void EmitGlobalConstant(const DataLayout &DL, const Constant *CV);
- /// \brief Unnamed constant global variables solely contaning a pointer to
+ /// 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
@@ -345,7 +360,7 @@ public:
/// accesses to GOT entries.
void computeGlobalGOTEquivs(Module &M);
- /// \brief Constant expressions using GOT equivalent globals may not be
+ /// 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();
@@ -444,13 +459,16 @@ public:
void printOffset(int64_t Offset, raw_ostream &OS) const;
/// Emit a byte directive and value.
- void EmitInt8(int Value) const;
+ void emitInt8(int Value) const;
/// Emit a short directive and value.
- void EmitInt16(int Value) const;
+ void emitInt16(int Value) const;
/// Emit a long directive and value.
- void EmitInt32(int Value) const;
+ void emitInt32(int Value) const;
+
+ /// Emit a long long directive and value.
+ void emitInt64(uint64_t Value) const;
/// Emit something like ".long Hi-Lo" where the size in bytes of the directive
/// is specified by Size and Hi/Lo specify the labels. This implicitly uses
@@ -458,6 +476,10 @@ public:
void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
unsigned Size) const;
+ /// Emit something like ".uleb128 Hi-Lo".
+ void EmitLabelDifferenceAsULEB128(const MCSymbol *Hi,
+ const MCSymbol *Lo) const;
+
/// Emit something like ".long Label+Offset" where the size in bytes of the
/// directive is specified by Size and Label specifies the label. This
/// implicitly uses .set if it is available.
@@ -471,6 +493,9 @@ public:
EmitLabelPlusOffset(Label, 0, Size, IsSectionRelative);
}
+ /// Emit something like ".long Label + Offset".
+ void EmitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const;
+
//===------------------------------------------------------------------===//
// Dwarf Emission Helper Routines
//===------------------------------------------------------------------===//
@@ -481,11 +506,6 @@ public:
/// Emit the specified unsigned leb128 value.
void EmitULEB128(uint64_t Value, const char *Desc = nullptr) const;
- /// Emit the specified unsigned leb128 value padded to a specific number
- /// bytes
- void EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
- const char *Desc = nullptr) const;
-
/// Emit a .byte 42 directive that corresponds to an encoding. If verbose
/// assembly output is enabled, we output comments describing the encoding.
/// Desc is a string saying what the encoding is specifying (e.g. "LSDA").
@@ -508,7 +528,12 @@ public:
/// When possible, emit a DwarfStringPool section offset without any
/// relocations, and without using the symbol. Otherwise, defers to \a
/// emitDwarfSymbolReference().
- void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const;
+ void emitDwarfStringOffset(DwarfStringPoolEntry S) const;
+
+ /// Emit the 4-byte offset of a string from the start of its section.
+ void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const {
+ emitDwarfStringOffset(S.getEntry());
+ }
/// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified.
virtual unsigned getISAEncoding() { return 0; }
@@ -523,10 +548,10 @@ public:
// Dwarf Lowering Routines
//===------------------------------------------------------------------===//
- /// \brief Emit frame instruction to describe the layout of the frame.
+ /// Emit frame instruction to describe the layout of the frame.
void emitCFIInstruction(const MCCFIInstruction &Inst) const;
- /// \brief Emit Dwarf abbreviation table.
+ /// Emit Dwarf abbreviation table.
template <typename T> void emitDwarfAbbrevs(const T &Abbrevs) const {
// For each abbreviation.
for (const auto &Abbrev : Abbrevs)
@@ -538,7 +563,7 @@ public:
void emitDwarfAbbrev(const DIEAbbrev &Abbrev) const;
- /// \brief Recursively emit Dwarf DIE tree.
+ /// Recursively emit Dwarf DIE tree.
void emitDwarfDIE(const DIE &Die) const;
//===------------------------------------------------------------------===//
@@ -625,10 +650,9 @@ private:
void EmitXXStructorList(const DataLayout &DL, const Constant *List,
bool isCtor);
- GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &C);
+ GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &S);
/// Emit GlobalAlias or GlobalIFunc.
- void emitGlobalIndirectSymbol(Module &M,
- const GlobalIndirectSymbol& GIS);
+ void emitGlobalIndirectSymbol(Module &M, const GlobalIndirectSymbol &GIS);
void setupCodePaddingContext(const MachineBasicBlock &MBB,
MCCodePaddingContext &Context) const;
};
diff --git a/contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h b/contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h
index 1f9c96b18e1b..b1adf66e7ff4 100644
--- a/contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h
+++ b/contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h
@@ -26,7 +26,7 @@ using CreateCmpXchgInstFun =
function_ref<void(IRBuilder<> &, Value *, Value *, Value *, AtomicOrdering,
Value *&, Value *&)>;
-/// \brief Expand an atomic RMW instruction into a loop utilizing
+/// Expand an atomic RMW instruction into a loop utilizing
/// cmpxchg. You'll want to make sure your target machine likes cmpxchg
/// instructions in the first place and that there isn't another, better,
/// transformation available (for example AArch32/AArch64 have linked loads).
@@ -58,7 +58,7 @@ using CreateCmpXchgInstFun =
/// [...]
///
/// Returns true if the containing function was modified.
-bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun Factory);
+bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg);
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 526ddb1b9706..f76a2426377a 100644
--- a/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -26,7 +26,6 @@
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/TargetTransformInfoImpl.h"
#include "llvm/CodeGen/ISDOpcodes.h"
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
@@ -47,6 +46,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
@@ -65,7 +65,7 @@ class TargetMachine;
extern cl::opt<unsigned> PartialUnrollingThreshold;
-/// \brief Base class which can be used to help build a TTI implementation.
+/// 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.
@@ -101,16 +101,32 @@ private:
return Cost;
}
- /// \brief Local query method delegates up to T which *must* implement this!
+ /// 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!
+ /// Local query method delegates up to T which *must* implement this!
const TargetLoweringBase *getTLI() const {
return static_cast<const T *>(this)->getTLI();
}
+ static ISD::MemIndexedMode getISDIndexedMode(TTI::MemIndexedMode M) {
+ switch (M) {
+ case TTI::MIM_Unindexed:
+ return ISD::UNINDEXED;
+ case TTI::MIM_PreInc:
+ return ISD::PRE_INC;
+ case TTI::MIM_PreDec:
+ return ISD::PRE_DEC;
+ case TTI::MIM_PostInc:
+ return ISD::POST_INC;
+ case TTI::MIM_PostDec:
+ return ISD::POST_DEC;
+ }
+ llvm_unreachable("Unexpected MemIndexedMode");
+ }
+
protected:
explicit BasicTTIImplBase(const TargetMachine *TM, const DataLayout &DL)
: BaseT(DL) {}
@@ -157,6 +173,18 @@ public:
return getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace, I);
}
+ bool isIndexedLoadLegal(TTI::MemIndexedMode M, Type *Ty,
+ const DataLayout &DL) const {
+ EVT VT = getTLI()->getValueType(DL, Ty);
+ return getTLI()->isIndexedLoadLegal(getISDIndexedMode(M), VT);
+ }
+
+ bool isIndexedStoreLegal(TTI::MemIndexedMode M, Type *Ty,
+ const DataLayout &DL) const {
+ EVT VT = getTLI()->getValueType(DL, Ty);
+ return getTLI()->isIndexedStoreLegal(getISDIndexedMode(M), VT);
+ }
+
bool isLSRCostLess(TTI::LSRCost C1, TTI::LSRCost C2) {
return TargetTransformInfoImplBase::isLSRCostLess(C1, C2);
}
@@ -179,6 +207,8 @@ public:
return getTLI()->isProfitableToHoist(I);
}
+ bool useAA() const { return getST()->useAA(); }
+
bool isTypeLegal(Type *Ty) {
EVT VT = getTLI()->getValueType(DL, Ty);
return getTLI()->isTypeLegal(VT);
@@ -240,7 +270,7 @@ public:
bool IsJTAllowed = TLI->areJTsAllowed(SI.getParent()->getParent());
// Early exit if both a jump table and bit test are not allowed.
- if (N < 1 || (!IsJTAllowed && DL.getPointerSizeInBits() < N))
+ if (N < 1 || (!IsJTAllowed && DL.getIndexSizeInBits(0u) < N))
return N;
APInt MaxCaseVal = SI.case_begin()->getCaseValue()->getValue();
@@ -254,7 +284,7 @@ public:
}
// Check if suitable for a bit test
- if (N <= DL.getPointerSizeInBits()) {
+ if (N <= DL.getIndexSizeInBits(0u)) {
SmallPtrSet<const BasicBlock *, 4> Dests;
for (auto I : SI.cases())
Dests.insert(I.getCaseSuccessor());
@@ -523,11 +553,15 @@ public:
unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index,
Type *SubTp) {
- if (Kind == TTI::SK_Alternate || Kind == TTI::SK_PermuteTwoSrc ||
- Kind == TTI::SK_PermuteSingleSrc) {
+ switch (Kind) {
+ case TTI::SK_Select:
+ case TTI::SK_Transpose:
+ case TTI::SK_PermuteSingleSrc:
+ case TTI::SK_PermuteTwoSrc:
return getPermuteShuffleOverhead(Tp);
+ default:
+ return 1;
}
- return 1;
}
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
@@ -614,7 +648,7 @@ public:
}
// If we are legalizing by splitting, query the concrete TTI for the cost
- // of casting the original vector twice. We also need to factor int the
+ // of casting the original vector twice. We also need to factor in the
// cost of the split itself. Count that as 1, to be consistent with
// TLI->getTypeLegalizationCost().
if ((TLI->getTypeAction(Src->getContext(), TLI->getValueType(DL, Src)) ==
@@ -916,6 +950,20 @@ public:
RetTy, Args[0], VarMask,
Alignment);
}
+ case Intrinsic::experimental_vector_reduce_add:
+ case Intrinsic::experimental_vector_reduce_mul:
+ case Intrinsic::experimental_vector_reduce_and:
+ case Intrinsic::experimental_vector_reduce_or:
+ case Intrinsic::experimental_vector_reduce_xor:
+ case Intrinsic::experimental_vector_reduce_fadd:
+ case Intrinsic::experimental_vector_reduce_fmul:
+ case Intrinsic::experimental_vector_reduce_smax:
+ case Intrinsic::experimental_vector_reduce_smin:
+ case Intrinsic::experimental_vector_reduce_fmax:
+ case Intrinsic::experimental_vector_reduce_fmin:
+ case Intrinsic::experimental_vector_reduce_umax:
+ case Intrinsic::experimental_vector_reduce_umin:
+ return getIntrinsicInstrCost(IID, RetTy, Args[0]->getType(), FMF);
}
}
@@ -1039,6 +1087,39 @@ public:
case Intrinsic::masked_load:
return static_cast<T *>(this)
->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0);
+ case Intrinsic::experimental_vector_reduce_add:
+ return static_cast<T *>(this)->getArithmeticReductionCost(
+ Instruction::Add, Tys[0], /*IsPairwiseForm=*/false);
+ case Intrinsic::experimental_vector_reduce_mul:
+ return static_cast<T *>(this)->getArithmeticReductionCost(
+ Instruction::Mul, Tys[0], /*IsPairwiseForm=*/false);
+ case Intrinsic::experimental_vector_reduce_and:
+ return static_cast<T *>(this)->getArithmeticReductionCost(
+ Instruction::And, Tys[0], /*IsPairwiseForm=*/false);
+ case Intrinsic::experimental_vector_reduce_or:
+ return static_cast<T *>(this)->getArithmeticReductionCost(
+ Instruction::Or, Tys[0], /*IsPairwiseForm=*/false);
+ case Intrinsic::experimental_vector_reduce_xor:
+ return static_cast<T *>(this)->getArithmeticReductionCost(
+ Instruction::Xor, Tys[0], /*IsPairwiseForm=*/false);
+ case Intrinsic::experimental_vector_reduce_fadd:
+ return static_cast<T *>(this)->getArithmeticReductionCost(
+ Instruction::FAdd, Tys[0], /*IsPairwiseForm=*/false);
+ case Intrinsic::experimental_vector_reduce_fmul:
+ return static_cast<T *>(this)->getArithmeticReductionCost(
+ Instruction::FMul, Tys[0], /*IsPairwiseForm=*/false);
+ case Intrinsic::experimental_vector_reduce_smax:
+ case Intrinsic::experimental_vector_reduce_smin:
+ case Intrinsic::experimental_vector_reduce_fmax:
+ case Intrinsic::experimental_vector_reduce_fmin:
+ return static_cast<T *>(this)->getMinMaxReductionCost(
+ Tys[0], CmpInst::makeCmpResultType(Tys[0]), /*IsPairwiseForm=*/false,
+ /*IsSigned=*/true);
+ case Intrinsic::experimental_vector_reduce_umax:
+ case Intrinsic::experimental_vector_reduce_umin:
+ return static_cast<T *>(this)->getMinMaxReductionCost(
+ Tys[0], CmpInst::makeCmpResultType(Tys[0]), /*IsPairwiseForm=*/false,
+ /*IsSigned=*/false);
case Intrinsic::ctpop:
ISDs.push_back(ISD::CTPOP);
// In case of legalization use TCC_Expensive. This is cheaper than a
@@ -1123,7 +1204,7 @@ public:
return SingleCallCost;
}
- /// \brief Compute a cost of the given call instruction.
+ /// Compute a cost of the given call instruction.
///
/// Compute the cost of calling function F with return type RetTy and
/// argument types Tys. F might be nullptr, in this case the cost of an
@@ -1284,7 +1365,7 @@ public:
/// @}
};
-/// \brief Concrete BasicTTIImpl that can be used if no further customization
+/// Concrete BasicTTIImpl that can be used if no further customization
/// is needed.
class BasicTTIImpl : public BasicTTIImplBase<BasicTTIImpl> {
using BaseT = BasicTTIImplBase<BasicTTIImpl>;
@@ -1298,7 +1379,7 @@ class BasicTTIImpl : public BasicTTIImplBase<BasicTTIImpl> {
const TargetLoweringBase *getTLI() const { return TLI; }
public:
- explicit BasicTTIImpl(const TargetMachine *ST, const Function &F);
+ explicit BasicTTIImpl(const TargetMachine *TM, const Function &F);
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h
index d9e8206408a7..f85767f1fc11 100644
--- a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h
+++ b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h
@@ -22,7 +22,7 @@ class MachineFunction;
class MachineLoopInfo;
class VirtRegMap;
- /// \brief Normalize the spill weight of a live interval
+ /// Normalize the spill weight of a live interval
///
/// The spill weight of a live interval is computed as:
///
@@ -42,7 +42,7 @@ class VirtRegMap;
return UseDefFreq / (Size + 25*SlotIndex::InstrDist);
}
- /// \brief Calculate auxiliary information for a virtual register such as its
+ /// Calculate auxiliary information for a virtual register such as its
/// spill weight and allocation hint.
class VirtRegAuxInfo {
public:
@@ -64,10 +64,10 @@ class VirtRegMap;
NormalizingFn norm = normalizeSpillWeight)
: MF(mf), LIS(lis), VRM(vrm), Loops(loops), MBFI(mbfi), normalize(norm) {}
- /// \brief (re)compute li's spill weight and allocation hint.
+ /// (re)compute li's spill weight and allocation hint.
void calculateSpillWeightAndHint(LiveInterval &li);
- /// \brief Compute future expected spill weight of a split artifact of li
+ /// Compute future expected spill weight of a split artifact of li
/// that will span between start and end slot indexes.
/// \param li The live interval to be split.
/// \param start The expected begining of the split artifact. Instructions
@@ -78,7 +78,7 @@ class VirtRegMap;
/// negative weight for unspillable li.
float futureWeight(LiveInterval &li, SlotIndex start, SlotIndex end);
- /// \brief Helper function for weight calculations.
+ /// Helper function for weight calculations.
/// (Re)compute li's spill weight and allocation hint, or, for non null
/// start and end - compute future expected spill weight of a split
/// artifact of li that will span between start and end slot indexes.
@@ -94,7 +94,7 @@ class VirtRegMap;
SlotIndex *end = nullptr);
};
- /// \brief Compute spill weights and allocation hints for all virtual register
+ /// Compute spill weights and allocation hints for all virtual register
/// live intervals.
void calculateSpillWeightsAndHints(LiveIntervals &LIS, MachineFunction &MF,
VirtRegMap *VRM,
diff --git a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h
index d30a27328c01..efcf80ba0b4e 100644
--- a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h
+++ b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h
@@ -304,7 +304,7 @@ public:
/// CheckReturn - Analyze the return values of a function, returning
/// true if the return can be performed without sret-demotion, and
/// false otherwise.
- bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
+ bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
CCAssignFn Fn);
/// AnalyzeCallOperands - Analyze the outgoing arguments to a call,
diff --git a/contrib/llvm/include/llvm/CodeGen/CommandFlags.def b/contrib/llvm/include/llvm/CodeGen/CommandFlags.inc
index fe96033a9c61..7d2d167289e0 100644
--- a/contrib/llvm/include/llvm/CodeGen/CommandFlags.def
+++ b/contrib/llvm/include/llvm/CodeGen/CommandFlags.inc
@@ -17,7 +17,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
-#include "llvm/MC/MCTargetOptionsCommandFlags.def"
+#include "llvm/MC/MCTargetOptionsCommandFlags.inc"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
@@ -98,7 +98,9 @@ static cl::opt<llvm::ExceptionHandling> ExceptionModel(
clEnumValN(ExceptionHandling::SjLj, "sjlj", "SjLj exception handling"),
clEnumValN(ExceptionHandling::ARM, "arm", "ARM EHABI exceptions"),
clEnumValN(ExceptionHandling::WinEH, "wineh",
- "Windows exception model")));
+ "Windows exception model"),
+ clEnumValN(ExceptionHandling::Wasm, "wasm",
+ "WebAssembly exception handling")));
static cl::opt<TargetMachine::CodeGenFileType> FileType(
"filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
@@ -259,6 +261,10 @@ static cl::opt<bool> EnableStackSizeSection(
"stack-size-section",
cl::desc("Emit a section containing stack size metadata"), cl::init(false));
+static cl::opt<bool>
+ EnableAddrsig("addrsig", cl::desc("Emit an address-significance table"),
+ cl::init(false));
+
// Common utility function tightly tied to the options listed here. Initializes
// a TargetOptions object with CodeGen flags and returns it.
static TargetOptions InitTargetOptionsFromCodeGenFlags() {
@@ -284,8 +290,10 @@ static TargetOptions InitTargetOptionsFromCodeGenFlags() {
Options.FunctionSections = FunctionSections;
Options.UniqueSectionNames = UniqueSectionNames;
Options.EmulatedTLS = EmulatedTLS;
+ Options.ExplicitEmulatedTLS = EmulatedTLS.getNumOccurrences() > 0;
Options.ExceptionModel = ExceptionModel;
Options.EmitStackSizeSection = EnableStackSizeSection;
+ Options.EmitAddrsig = EnableAddrsig;
Options.MCOptions = InitMCTargetOptionsFromFlags();
@@ -326,7 +334,27 @@ LLVM_ATTRIBUTE_UNUSED static std::string getFeaturesStr() {
return Features.getString();
}
-/// \brief Set function attributes of functions in Module M based on CPU,
+LLVM_ATTRIBUTE_UNUSED static std::vector<std::string> getFeatureList() {
+ SubtargetFeatures Features;
+
+ // If user asked for the 'native' CPU, we need to autodetect features.
+ // This is necessary for x86 where the CPU might not support all the
+ // features the autodetected CPU name lists in the target. For example,
+ // not all Sandybridge processors support AVX.
+ if (MCPU == "native") {
+ StringMap<bool> HostFeatures;
+ if (sys::getHostCPUFeatures(HostFeatures))
+ for (auto &F : HostFeatures)
+ Features.AddFeature(F.first(), F.second);
+ }
+
+ for (unsigned i = 0; i != MAttrs.size(); ++i)
+ Features.AddFeature(MAttrs[i]);
+
+ return Features.getFeatures();
+}
+
+/// Set function attributes of functions in Module M based on CPU,
/// Features, and command line flags.
LLVM_ATTRIBUTE_UNUSED static void
setFunctionAttributes(StringRef CPU, StringRef Features, Module &M) {
diff --git a/contrib/llvm/include/llvm/CodeGen/CostTable.h b/contrib/llvm/include/llvm/CodeGen/CostTable.h
index 5a6368c5a0f8..48ad76971520 100644
--- a/contrib/llvm/include/llvm/CodeGen/CostTable.h
+++ b/contrib/llvm/include/llvm/CodeGen/CostTable.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Cost tables and simple lookup functions
+/// Cost tables and simple lookup functions
///
//===----------------------------------------------------------------------===//
@@ -17,7 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/Support/MachineValueType.h"
namespace llvm {
diff --git a/contrib/llvm/include/llvm/CodeGen/DIE.h b/contrib/llvm/include/llvm/CodeGen/DIE.h
index f809fc97fe59..7d486b1df56d 100644
--- a/contrib/llvm/include/llvm/CodeGen/DIE.h
+++ b/contrib/llvm/include/llvm/CodeGen/DIE.h
@@ -136,7 +136,7 @@ class DIEAbbrevSet {
/// The bump allocator to use when creating DIEAbbrev objects in the uniqued
/// storage container.
BumpPtrAllocator &Alloc;
- /// \brief FoldingSet that uniques the abbreviations.
+ /// FoldingSet that uniques the abbreviations.
FoldingSet<DIEAbbrev> AbbreviationsSet;
/// A list of all the unique abbreviations in use.
std::vector<DIEAbbrev *> Abbreviations;
@@ -190,7 +190,7 @@ public:
uint64_t getValue() const { return Integer; }
void setValue(uint64_t Val) { Integer = Val; }
- void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
+ void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const;
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
void print(raw_ostream &O) const;
@@ -868,7 +868,7 @@ public:
return dwarf::DW_FORM_block;
}
- void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
+ void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const;
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
void print(raw_ostream &O) const;
@@ -899,7 +899,7 @@ public:
return dwarf::DW_FORM_block;
}
- void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
+ void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const;
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
void print(raw_ostream &O) const;
diff --git a/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h b/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h
index fc2b5ddd2d2c..e6c0483cfc35 100644
--- a/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h
+++ b/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h
@@ -41,6 +41,8 @@ public:
unsigned getOffset() const { return I->second.Offset; }
unsigned getIndex() const { return I->second.Index; }
StringRef getString() const { return I->first(); }
+ /// Return the entire string pool entry for convenience.
+ DwarfStringPoolEntry getEntry() const { return I->getValue(); }
bool operator==(const DwarfStringPoolEntryRef &X) const { return I == X.I; }
bool operator!=(const DwarfStringPoolEntryRef &X) const { return I != X.I; }
diff --git a/contrib/llvm/include/llvm/CodeGen/ExecutionDepsFix.h b/contrib/llvm/include/llvm/CodeGen/ExecutionDepsFix.h
deleted file mode 100644
index f4db8b7322da..000000000000
--- a/contrib/llvm/include/llvm/CodeGen/ExecutionDepsFix.h
+++ /dev/null
@@ -1,230 +0,0 @@
-//==- llvm/CodeGen/ExecutionDepsFix.h - Execution Dependency Fix -*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file Execution Dependency Fix pass.
-///
-/// Some X86 SSE instructions like mov, and, or, xor are available in different
-/// variants for different operand types. These variant instructions are
-/// equivalent, but on Nehalem and newer cpus there is extra latency
-/// transferring data between integer and floating point domains. ARM cores
-/// have similar issues when they are configured with both VFP and NEON
-/// pipelines.
-///
-/// This pass changes the variant instructions to minimize domain crossings.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_EXECUTIONDEPSFIX_H
-#define LLVM_CODEGEN_EXECUTIONDEPSFIX_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/CodeGen/LivePhysRegs.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/RegisterClassInfo.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/MathExtras.h"
-#include <cassert>
-#include <limits>
-#include <utility>
-#include <vector>
-
-namespace llvm {
-
-class MachineBasicBlock;
-class MachineInstr;
-class TargetInstrInfo;
-
-/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track
-/// of execution domains.
-///
-/// An open DomainValue represents a set of instructions that can still switch
-/// execution domain. Multiple registers may refer to the same open
-/// DomainValue - they will eventually be collapsed to the same execution
-/// domain.
-///
-/// A collapsed DomainValue represents a single register that has been forced
-/// into one of more execution domains. There is a separate collapsed
-/// DomainValue for each register, but it may contain multiple execution
-/// domains. A register value is initially created in a single execution
-/// domain, but if we were forced to pay the penalty of a domain crossing, we
-/// keep track of the fact that the register is now available in multiple
-/// domains.
-struct DomainValue {
- // Basic reference counting.
- unsigned Refs = 0;
-
- // Bitmask of available domains. For an open DomainValue, it is the still
- // possible domains for collapsing. For a collapsed DomainValue it is the
- // domains where the register is available for free.
- unsigned AvailableDomains;
-
- // Pointer to the next DomainValue in a chain. When two DomainValues are
- // merged, Victim.Next is set to point to Victor, so old DomainValue
- // references can be updated by following the chain.
- DomainValue *Next;
-
- // Twiddleable instructions using or defining these registers.
- SmallVector<MachineInstr*, 8> Instrs;
-
- DomainValue() { clear(); }
-
- // A collapsed DomainValue has no instructions to twiddle - it simply keeps
- // track of the domains where the registers are already available.
- bool isCollapsed() const { return Instrs.empty(); }
-
- // Is domain available?
- bool hasDomain(unsigned domain) const {
- assert(domain <
- static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
- "undefined behavior");
- return AvailableDomains & (1u << domain);
- }
-
- // Mark domain as available.
- void addDomain(unsigned domain) {
- AvailableDomains |= 1u << domain;
- }
-
- // Restrict to a single domain available.
- void setSingleDomain(unsigned domain) {
- AvailableDomains = 1u << domain;
- }
-
- // Return bitmask of domains that are available and in mask.
- unsigned getCommonDomains(unsigned mask) const {
- return AvailableDomains & mask;
- }
-
- // First domain available.
- unsigned getFirstDomain() const {
- return countTrailingZeros(AvailableDomains);
- }
-
- // Clear this DomainValue and point to next which has all its data.
- void clear() {
- AvailableDomains = 0;
- Next = nullptr;
- Instrs.clear();
- }
-};
-
-/// Information about a live register.
-struct LiveReg {
- /// Value currently in this register, or NULL when no value is being tracked.
- /// This counts as a DomainValue reference.
- DomainValue *Value;
-
- /// Instruction that defined this register, relative to the beginning of the
- /// current basic block. When a LiveReg is used to represent a live-out
- /// register, this value is relative to the end of the basic block, so it
- /// will be a negative number.
- int Def;
-};
-
-class ExecutionDepsFix : public MachineFunctionPass {
- SpecificBumpPtrAllocator<DomainValue> Allocator;
- SmallVector<DomainValue*,16> Avail;
-
- const TargetRegisterClass *const RC;
- MachineFunction *MF;
- const TargetInstrInfo *TII;
- const TargetRegisterInfo *TRI;
- RegisterClassInfo RegClassInfo;
- std::vector<SmallVector<int, 1>> AliasMap;
- const unsigned NumRegs;
- LiveReg *LiveRegs;
- struct MBBInfo {
- // Keeps clearance and domain information for all registers. Note that this
- // is different from the usual definition notion of liveness. The CPU
- // doesn't care whether or not we consider a register killed.
- LiveReg *OutRegs = nullptr;
-
- // Whether we have gotten to this block in primary processing yet.
- bool PrimaryCompleted = false;
-
- // The number of predecessors for which primary processing has completed
- unsigned IncomingProcessed = 0;
-
- // The value of `IncomingProcessed` at the start of primary processing
- unsigned PrimaryIncoming = 0;
-
- // The number of predecessors for which all processing steps are done.
- unsigned IncomingCompleted = 0;
-
- MBBInfo() = default;
- };
- using MBBInfoMap = DenseMap<MachineBasicBlock *, MBBInfo>;
- MBBInfoMap MBBInfos;
-
- /// List of undefined register reads in this block in forward order.
- std::vector<std::pair<MachineInstr *, unsigned>> UndefReads;
-
- /// Storage for register unit liveness.
- LivePhysRegs LiveRegSet;
-
- /// Current instruction number.
- /// The first instruction in each basic block is 0.
- int CurInstr;
-
-public:
- ExecutionDepsFix(char &PassID, const TargetRegisterClass &RC)
- : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {}
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
-
- bool runOnMachineFunction(MachineFunction &MF) override;
-
- MachineFunctionProperties getRequiredProperties() const override {
- return MachineFunctionProperties().set(
- MachineFunctionProperties::Property::NoVRegs);
- }
-
-private:
- iterator_range<SmallVectorImpl<int>::const_iterator>
- regIndices(unsigned Reg) const;
- // DomainValue allocation.
- DomainValue *alloc(int domain = -1);
- DomainValue *retain(DomainValue *DV) {
- if (DV) ++DV->Refs;
- return DV;
- }
- void release(DomainValue*);
- DomainValue *resolve(DomainValue*&);
-
- // LiveRegs manipulations.
- void setLiveReg(int rx, DomainValue *DV);
- void kill(int rx);
- void force(int rx, unsigned domain);
- void collapse(DomainValue *dv, unsigned domain);
- bool merge(DomainValue *A, DomainValue *B);
-
- void enterBasicBlock(MachineBasicBlock*);
- void leaveBasicBlock(MachineBasicBlock*);
- bool isBlockDone(MachineBasicBlock *);
- void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass);
- bool visitInstr(MachineInstr *);
- void processDefs(MachineInstr *, bool breakDependency, bool Kill);
- void visitSoftInstr(MachineInstr*, unsigned mask);
- void visitHardInstr(MachineInstr*, unsigned domain);
- bool pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx,
- unsigned Pref);
- bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref);
- void processUndefReads(MachineBasicBlock*);
-};
-
-} // end namepsace llvm
-
-#endif // LLVM_CODEGEN_EXECUTIONDEPSFIX_H
diff --git a/contrib/llvm/include/llvm/CodeGen/ExecutionDomainFix.h b/contrib/llvm/include/llvm/CodeGen/ExecutionDomainFix.h
new file mode 100644
index 000000000000..338c214dd073
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/ExecutionDomainFix.h
@@ -0,0 +1,213 @@
+//==-- llvm/CodeGen/ExecutionDomainFix.h - Execution Domain Fix -*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file Execution Domain Fix pass.
+///
+/// Some X86 SSE instructions like mov, and, or, xor are available in different
+/// variants for different operand types. These variant instructions are
+/// equivalent, but on Nehalem and newer cpus there is extra latency
+/// transferring data between integer and floating point domains. ARM cores
+/// have similar issues when they are configured with both VFP and NEON
+/// pipelines.
+///
+/// This pass changes the variant instructions to minimize domain crossings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_EXECUTIONDOMAINFIX_H
+#define LLVM_CODEGEN_EXECUTIONDOMAINFIX_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/LoopTraversal.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/ReachingDefAnalysis.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+
+namespace llvm {
+
+class MachineBasicBlock;
+class MachineInstr;
+class TargetInstrInfo;
+
+/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track
+/// of execution domains.
+///
+/// An open DomainValue represents a set of instructions that can still switch
+/// execution domain. Multiple registers may refer to the same open
+/// DomainValue - they will eventually be collapsed to the same execution
+/// domain.
+///
+/// A collapsed DomainValue represents a single register that has been forced
+/// into one of more execution domains. There is a separate collapsed
+/// DomainValue for each register, but it may contain multiple execution
+/// domains. A register value is initially created in a single execution
+/// domain, but if we were forced to pay the penalty of a domain crossing, we
+/// keep track of the fact that the register is now available in multiple
+/// domains.
+struct DomainValue {
+ /// Basic reference counting.
+ unsigned Refs = 0;
+
+ /// Bitmask of available domains. For an open DomainValue, it is the still
+ /// possible domains for collapsing. For a collapsed DomainValue it is the
+ /// domains where the register is available for free.
+ unsigned AvailableDomains;
+
+ /// Pointer to the next DomainValue in a chain. When two DomainValues are
+ /// merged, Victim.Next is set to point to Victor, so old DomainValue
+ /// references can be updated by following the chain.
+ DomainValue *Next;
+
+ /// Twiddleable instructions using or defining these registers.
+ SmallVector<MachineInstr *, 8> Instrs;
+
+ DomainValue() { clear(); }
+
+ /// A collapsed DomainValue has no instructions to twiddle - it simply keeps
+ /// track of the domains where the registers are already available.
+ bool isCollapsed() const { return Instrs.empty(); }
+
+ /// Is domain available?
+ bool hasDomain(unsigned domain) const {
+ assert(domain <
+ static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
+ "undefined behavior");
+ return AvailableDomains & (1u << domain);
+ }
+
+ /// Mark domain as available.
+ void addDomain(unsigned domain) { AvailableDomains |= 1u << domain; }
+
+ // Restrict to a single domain available.
+ void setSingleDomain(unsigned domain) { AvailableDomains = 1u << domain; }
+
+ /// Return bitmask of domains that are available and in mask.
+ unsigned getCommonDomains(unsigned mask) const {
+ return AvailableDomains & mask;
+ }
+
+ /// First domain available.
+ unsigned getFirstDomain() const {
+ return countTrailingZeros(AvailableDomains);
+ }
+
+ /// Clear this DomainValue and point to next which has all its data.
+ void clear() {
+ AvailableDomains = 0;
+ Next = nullptr;
+ Instrs.clear();
+ }
+};
+
+class ExecutionDomainFix : public MachineFunctionPass {
+ SpecificBumpPtrAllocator<DomainValue> Allocator;
+ SmallVector<DomainValue *, 16> Avail;
+
+ const TargetRegisterClass *const RC;
+ MachineFunction *MF;
+ const TargetInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+ std::vector<SmallVector<int, 1>> AliasMap;
+ const unsigned NumRegs;
+ /// Value currently in each register, or NULL when no value is being tracked.
+ /// This counts as a DomainValue reference.
+ using LiveRegsDVInfo = std::vector<DomainValue *>;
+ LiveRegsDVInfo LiveRegs;
+ /// Keeps domain information for all registers. Note that this
+ /// is different from the usual definition notion of liveness. The CPU
+ /// doesn't care whether or not we consider a register killed.
+ using OutRegsInfoMap = SmallVector<LiveRegsDVInfo, 4>;
+ OutRegsInfoMap MBBOutRegsInfos;
+
+ ReachingDefAnalysis *RDA;
+
+public:
+ ExecutionDomainFix(char &PassID, const TargetRegisterClass &RC)
+ : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ AU.addRequired<ReachingDefAnalysis>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::NoVRegs);
+ }
+
+private:
+ /// Translate TRI register number to a list of indices into our smaller tables
+ /// of interesting registers.
+ iterator_range<SmallVectorImpl<int>::const_iterator>
+ regIndices(unsigned Reg) const;
+
+ /// DomainValue allocation.
+ DomainValue *alloc(int domain = -1);
+
+ /// Add reference to DV.
+ DomainValue *retain(DomainValue *DV) {
+ if (DV)
+ ++DV->Refs;
+ return DV;
+ }
+
+ /// Release a reference to DV. When the last reference is released,
+ /// collapse if needed.
+ void release(DomainValue *);
+
+ /// Follow the chain of dead DomainValues until a live DomainValue is reached.
+ /// Update the referenced pointer when necessary.
+ DomainValue *resolve(DomainValue *&);
+
+ /// Set LiveRegs[rx] = dv, updating reference counts.
+ void setLiveReg(int rx, DomainValue *DV);
+
+ /// Kill register rx, recycle or collapse any DomainValue.
+ void kill(int rx);
+
+ /// Force register rx into domain.
+ void force(int rx, unsigned domain);
+
+ /// Collapse open DomainValue into given domain. If there are multiple
+ /// registers using dv, they each get a unique collapsed DomainValue.
+ void collapse(DomainValue *dv, unsigned domain);
+
+ /// All instructions and registers in B are moved to A, and B is released.
+ bool merge(DomainValue *A, DomainValue *B);
+
+ /// Set up LiveRegs by merging predecessor live-out values.
+ void enterBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
+
+ /// Update live-out values.
+ void leaveBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
+
+ /// Process he given basic block.
+ void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
+
+ /// Visit given insturcion.
+ bool visitInstr(MachineInstr *);
+
+ /// Update def-ages for registers defined by MI.
+ /// If Kill is set, also kill off DomainValues clobbered by the defs.
+ void processDefs(MachineInstr *, bool Kill);
+
+ /// A soft instruction can be changed to work in other domains given by mask.
+ void visitSoftInstr(MachineInstr *, unsigned mask);
+
+ /// A hard instruction only works in one domain. All input registers will be
+ /// forced into that domain.
+ void visitHardInstr(MachineInstr *, unsigned domain);
+};
+
+} // namespace llvm
+
+#endif // LLVM_CODEGEN_EXECUTIONDOMAINFIX_H
diff --git a/contrib/llvm/include/llvm/CodeGen/FastISel.h b/contrib/llvm/include/llvm/CodeGen/FastISel.h
index 85bb826dcb8c..865d8a88b8cc 100644
--- a/contrib/llvm/include/llvm/CodeGen/FastISel.h
+++ b/contrib/llvm/include/llvm/CodeGen/FastISel.h
@@ -19,7 +19,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallSite.h"
@@ -28,6 +27,7 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/Support/MachineValueType.h"
#include <algorithm>
#include <cstdint>
#include <utility>
@@ -61,7 +61,7 @@ class Type;
class User;
class Value;
-/// \brief This is a fast-path instruction selection class that generates poor
+/// This is a fast-path instruction selection class that generates poor
/// code and doesn't support illegal types or non-trivial lowering, but runs
/// quickly.
class FastISel {
@@ -78,7 +78,7 @@ public:
bool IsReturnValueUsed : 1;
bool IsPatchPoint : 1;
- // \brief IsTailCall Should be modified by implementations of FastLowerCall
+ // IsTailCall Should be modified by implementations of FastLowerCall
// that perform tail call conversions.
bool IsTailCall = false;
@@ -215,67 +215,74 @@ protected:
const TargetLibraryInfo *LibInfo;
bool SkipTargetIndependentISel;
- /// \brief The position of the last instruction for materializing constants
+ /// The position of the last instruction for materializing constants
/// for use in the current block. It resets to EmitStartPt when it makes sense
/// (for example, it's usually profitable to avoid function calls between the
/// definition and the use)
MachineInstr *LastLocalValue;
- /// \brief The top most instruction in the current block that is allowed for
+ /// The top most instruction in the current block that is allowed for
/// emitting local variables. LastLocalValue resets to EmitStartPt when it
/// makes sense (for example, on function calls)
MachineInstr *EmitStartPt;
+ /// Last local value flush point. On a subsequent flush, no local value will
+ /// sink past this point.
+ MachineBasicBlock::iterator LastFlushPoint;
+
public:
virtual ~FastISel();
- /// \brief Return the position of the last instruction emitted for
+ /// Return the position of the last instruction emitted for
/// materializing constants for use in the current block.
MachineInstr *getLastLocalValue() { return LastLocalValue; }
- /// \brief Update the position of the last instruction emitted for
+ /// Update the position of the last instruction emitted for
/// materializing constants for use in the current block.
void setLastLocalValue(MachineInstr *I) {
EmitStartPt = I;
LastLocalValue = I;
}
- /// \brief Set the current block to which generated machine instructions will
- /// be appended, and clear the local CSE map.
+ /// Set the current block to which generated machine instructions will
+ /// be appended.
void startNewBlock();
- /// \brief Return current debug location information.
+ /// Flush the local value map and sink local values if possible.
+ void finishBasicBlock();
+
+ /// Return current debug location information.
DebugLoc getCurDebugLoc() const { return DbgLoc; }
- /// \brief Do "fast" instruction selection for function arguments and append
+ /// Do "fast" instruction selection for function arguments and append
/// the machine instructions to the current block. Returns true when
/// successful.
bool lowerArguments();
- /// \brief Do "fast" instruction selection for the given LLVM IR instruction
+ /// Do "fast" instruction selection for the given LLVM IR instruction
/// and append the generated machine instructions to the current block.
/// Returns true if selection was successful.
bool selectInstruction(const Instruction *I);
- /// \brief Do "fast" instruction selection for the given LLVM IR operator
+ /// Do "fast" instruction selection for the given LLVM IR operator
/// (Instruction or ConstantExpr), and append generated machine instructions
/// to the current block. Return true if selection was successful.
bool selectOperator(const User *I, unsigned Opcode);
- /// \brief Create a virtual register and arrange for it to be assigned the
+ /// Create a virtual register and arrange for it to be assigned the
/// value for the given LLVM value.
unsigned getRegForValue(const Value *V);
- /// \brief Look up the value to see if its value is already cached in a
+ /// Look up the value to see if its value is already cached in a
/// register. It may be defined by instructions across blocks or defined
/// locally.
unsigned lookUpRegForValue(const Value *V);
- /// \brief This is a wrapper around getRegForValue that also takes care of
+ /// This is a wrapper around getRegForValue that also takes care of
/// truncating or sign-extending the given getelementptr index value.
- std::pair<unsigned, bool> getRegForGEPIndex(const Value *V);
+ std::pair<unsigned, bool> getRegForGEPIndex(const Value *Idx);
- /// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note
+ /// We're checking to see if we can fold \p LI into \p FoldInst. Note
/// that we could have a sequence where multiple LLVM IR instructions are
/// folded into the same machineinstr. For example we could have:
///
@@ -289,7 +296,7 @@ public:
/// If we succeed folding, return true.
bool tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst);
- /// \brief The specified machine instr operand is a vreg, and that vreg is
+ /// The specified machine instr operand is a vreg, and that vreg is
/// being provided by the specified load instruction. If possible, try to
/// fold the load as an operand to the instruction, returning true if
/// possible.
@@ -300,11 +307,11 @@ public:
return false;
}
- /// \brief Reset InsertPt to prepare for inserting instructions into the
+ /// Reset InsertPt to prepare for inserting instructions into the
/// current block.
void recomputeInsertPt();
- /// \brief Remove all dead instructions between the I and E.
+ /// Remove all dead instructions between the I and E.
void removeDeadCode(MachineBasicBlock::iterator I,
MachineBasicBlock::iterator E);
@@ -313,11 +320,11 @@ public:
DebugLoc DL;
};
- /// \brief Prepare InsertPt to begin inserting instructions into the local
+ /// Prepare InsertPt to begin inserting instructions into the local
/// value area and return the old insert position.
SavePoint enterLocalValueArea();
- /// \brief Reset InsertPt to the given old insert position.
+ /// Reset InsertPt to the given old insert position.
void leaveLocalValueArea(SavePoint Old);
protected:
@@ -325,45 +332,45 @@ protected:
const TargetLibraryInfo *LibInfo,
bool SkipTargetIndependentISel = false);
- /// \brief This method is called by target-independent code when the normal
+ /// This method is called by target-independent code when the normal
/// FastISel process fails to select an instruction. This gives targets a
/// chance to emit code for anything that doesn't fit into FastISel's
/// framework. It returns true if it was successful.
virtual bool fastSelectInstruction(const Instruction *I) = 0;
- /// \brief This method is called by target-independent code to do target-
+ /// This method is called by target-independent code to do target-
/// specific argument lowering. It returns true if it was successful.
virtual bool fastLowerArguments();
- /// \brief This method is called by target-independent code to do target-
+ /// This method is called by target-independent code to do target-
/// specific call lowering. It returns true if it was successful.
virtual bool fastLowerCall(CallLoweringInfo &CLI);
- /// \brief This method is called by target-independent code to do target-
+ /// This method is called by target-independent code to do target-
/// specific intrinsic lowering. It returns true if it was successful.
virtual bool fastLowerIntrinsicCall(const IntrinsicInst *II);
- /// \brief This method is called by target-independent code to request that an
+ /// This method is called by target-independent code to request that an
/// instruction with the given type and opcode be emitted.
virtual unsigned fastEmit_(MVT VT, MVT RetVT, unsigned Opcode);
- /// \brief This method is called by target-independent code to request that an
+ /// This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register operand be emitted.
virtual unsigned fastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
bool Op0IsKill);
- /// \brief This method is called by target-independent code to request that an
+ /// This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register operands be emitted.
virtual unsigned fastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
bool Op0IsKill, unsigned Op1, bool Op1IsKill);
- /// \brief This method is called by target-independent code to request that an
+ /// This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register and immediate
/// operands be emitted.
virtual unsigned fastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
bool Op0IsKill, uint64_t Imm);
- /// \brief This method is a wrapper of fastEmit_ri.
+ /// This method is a wrapper of fastEmit_ri.
///
/// It first tries to emit an instruction with an immediate operand using
/// fastEmit_ri. If that fails, it materializes the immediate into a register
@@ -371,89 +378,89 @@ protected:
unsigned fastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill,
uint64_t Imm, MVT ImmType);
- /// \brief This method is called by target-independent code to request that an
+ /// This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and immediate operand be emitted.
virtual unsigned fastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm);
- /// \brief This method is called by target-independent code to request that an
+ /// This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and floating-point immediate
/// operand be emitted.
virtual unsigned fastEmit_f(MVT VT, MVT RetVT, unsigned Opcode,
const ConstantFP *FPImm);
- /// \brief Emit a MachineInstr with no operands and a result register in the
+ /// Emit a MachineInstr with no operands and a result register in the
/// given register class.
unsigned fastEmitInst_(unsigned MachineInstOpcode,
const TargetRegisterClass *RC);
- /// \brief Emit a MachineInstr with one register operand and a result register
+ /// Emit a MachineInstr with one register operand and a result register
/// in the given register class.
unsigned fastEmitInst_r(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, unsigned Op0,
bool Op0IsKill);
- /// \brief Emit a MachineInstr with two register operands and a result
+ /// Emit a MachineInstr with two register operands and a result
/// register in the given register class.
unsigned fastEmitInst_rr(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, unsigned Op0,
bool Op0IsKill, unsigned Op1, bool Op1IsKill);
- /// \brief Emit a MachineInstr with three register operands and a result
+ /// Emit a MachineInstr with three register operands and a result
/// register in the given register class.
unsigned fastEmitInst_rrr(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, unsigned Op0,
bool Op0IsKill, unsigned Op1, bool Op1IsKill,
unsigned Op2, bool Op2IsKill);
- /// \brief Emit a MachineInstr with a register operand, an immediate, and a
+ /// Emit a MachineInstr with a register operand, an immediate, and a
/// result register in the given register class.
unsigned fastEmitInst_ri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, unsigned Op0,
bool Op0IsKill, uint64_t Imm);
- /// \brief Emit a MachineInstr with one register operand and two immediate
+ /// Emit a MachineInstr with one register operand and two immediate
/// operands.
unsigned fastEmitInst_rii(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, unsigned Op0,
bool Op0IsKill, uint64_t Imm1, uint64_t Imm2);
- /// \brief Emit a MachineInstr with a floating point immediate, and a result
+ /// Emit a MachineInstr with a floating point immediate, and a result
/// register in the given register class.
unsigned fastEmitInst_f(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
const ConstantFP *FPImm);
- /// \brief Emit a MachineInstr with two register operands, an immediate, and a
+ /// Emit a MachineInstr with two register operands, an immediate, and a
/// result register in the given register class.
unsigned fastEmitInst_rri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, unsigned Op0,
bool Op0IsKill, unsigned Op1, bool Op1IsKill,
uint64_t Imm);
- /// \brief Emit a MachineInstr with a single immediate operand, and a result
+ /// Emit a MachineInstr with a single immediate operand, and a result
/// register in the given register class.
- unsigned fastEmitInst_i(unsigned MachineInstrOpcode,
+ unsigned fastEmitInst_i(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, uint64_t Imm);
- /// \brief Emit a MachineInstr for an extract_subreg from a specified index of
+ /// Emit a MachineInstr for an extract_subreg from a specified index of
/// a superregister to a specified type.
unsigned fastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill,
uint32_t Idx);
- /// \brief Emit MachineInstrs to compute the value of Op with all but the
+ /// Emit MachineInstrs to compute the value of Op with all but the
/// least significant bit set to zero.
unsigned fastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill);
- /// \brief Emit an unconditional branch to the given block, unless it is the
+ /// Emit an unconditional branch to the given block, unless it is the
/// immediate (fall-through) successor, and update the CFG.
- void fastEmitBranch(MachineBasicBlock *MBB, const DebugLoc &DL);
+ void fastEmitBranch(MachineBasicBlock *MSucc, const DebugLoc &DbgLoc);
/// Emit an unconditional branch to \p FalseMBB, obtains the branch weight
/// and adds TrueMBB and FalseMBB to the successor list.
void finishCondBranch(const BasicBlock *BranchBB, MachineBasicBlock *TrueMBB,
MachineBasicBlock *FalseMBB);
- /// \brief Update the value map to include the new mapping for this
+ /// Update the value map to include the new mapping for this
/// instruction, or insert an extra copy to get the result in a previous
/// determined register.
///
@@ -464,26 +471,26 @@ protected:
unsigned createResultReg(const TargetRegisterClass *RC);
- /// \brief Try to constrain Op so that it is usable by argument OpNum of the
+ /// Try to constrain Op so that it is usable by argument OpNum of the
/// provided MCInstrDesc. If this fails, create a new virtual register in the
/// correct class and COPY the value there.
unsigned constrainOperandRegClass(const MCInstrDesc &II, unsigned Op,
unsigned OpNum);
- /// \brief Emit a constant in a register using target-specific logic, such as
+ /// Emit a constant in a register using target-specific logic, such as
/// constant pool loads.
virtual unsigned fastMaterializeConstant(const Constant *C) { return 0; }
- /// \brief Emit an alloca address in a register using target-specific logic.
+ /// Emit an alloca address in a register using target-specific logic.
virtual unsigned fastMaterializeAlloca(const AllocaInst *C) { return 0; }
- /// \brief Emit the floating-point constant +0.0 in a register using target-
+ /// Emit the floating-point constant +0.0 in a register using target-
/// specific logic.
virtual unsigned fastMaterializeFloatZero(const ConstantFP *CF) {
return 0;
}
- /// \brief Check if \c Add is an add that can be safely folded into \c GEP.
+ /// Check if \c Add is an add that can be safely folded into \c GEP.
///
/// \c Add can be folded into \c GEP if:
/// - \c Add is an add,
@@ -492,16 +499,16 @@ protected:
/// - \c Add has a constant operand.
bool canFoldAddIntoGEP(const User *GEP, const Value *Add);
- /// \brief Test whether the given value has exactly one use.
+ /// Test whether the given value has exactly one use.
bool hasTrivialKill(const Value *V);
- /// \brief Create a machine mem operand from the given instruction.
+ /// Create a machine mem operand from the given instruction.
MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const;
CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) const;
bool lowerCallTo(const CallInst *CI, MCSymbol *Symbol, unsigned NumArgs);
- bool lowerCallTo(const CallInst *CI, const char *SymbolName,
+ bool lowerCallTo(const CallInst *CI, const char *SymName,
unsigned NumArgs);
bool lowerCallTo(CallLoweringInfo &CLI);
@@ -518,23 +525,24 @@ protected:
}
bool lowerCall(const CallInst *I);
- /// \brief Select and emit code for a binary operator instruction, which has
+ /// Select and emit code for a binary operator instruction, which has
/// an opcode which directly corresponds to the given ISD opcode.
bool selectBinaryOp(const User *I, unsigned ISDOpcode);
bool selectFNeg(const User *I);
bool selectGetElementPtr(const User *I);
bool selectStackmap(const CallInst *I);
bool selectPatchpoint(const CallInst *I);
- bool selectCall(const User *Call);
+ bool selectCall(const User *I);
bool selectIntrinsicCall(const IntrinsicInst *II);
bool selectBitCast(const User *I);
bool selectCast(const User *I, unsigned Opcode);
- bool selectExtractValue(const User *I);
+ bool selectExtractValue(const User *U);
bool selectInsertValue(const User *I);
bool selectXRayCustomEvent(const CallInst *II);
+ bool selectXRayTypedEvent(const CallInst *II);
private:
- /// \brief Handle PHI nodes in successor blocks.
+ /// Handle PHI nodes in successor blocks.
///
/// Emit code to ensure constants are copied into registers when needed.
/// Remember the virtual registers that need to be added to the Machine PHI
@@ -543,27 +551,41 @@ private:
/// correspond to a different MBB than the end.
bool handlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
- /// \brief Helper for materializeRegForValue to materialize a constant in a
+ /// Helper for materializeRegForValue to materialize a constant in a
/// target-independent way.
unsigned materializeConstant(const Value *V, MVT VT);
- /// \brief Helper for getRegForVale. This function is called when the value
+ /// Helper for getRegForVale. This function is called when the value
/// isn't already available in a register and must be materialized with new
/// instructions.
unsigned materializeRegForValue(const Value *V, MVT VT);
- /// \brief Clears LocalValueMap and moves the area for the new local variables
+ /// Clears LocalValueMap and moves the area for the new local variables
/// to the beginning of the block. It helps to avoid spilling cached variables
/// across heavy instructions like calls.
void flushLocalValueMap();
- /// \brief Removes dead local value instructions after SavedLastLocalvalue.
+ /// Removes dead local value instructions after SavedLastLocalvalue.
void removeDeadLocalValueCode(MachineInstr *SavedLastLocalValue);
- /// \brief Insertion point before trying to select the current instruction.
+ struct InstOrderMap {
+ DenseMap<MachineInstr *, unsigned> Orders;
+ MachineInstr *FirstTerminator = nullptr;
+ unsigned FirstTerminatorOrder = std::numeric_limits<unsigned>::max();
+
+ void initialize(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator LastFlushPoint);
+ };
+
+ /// Sinks the local value materialization instruction LocalMI to its first use
+ /// in the basic block, or deletes it if it is not used.
+ void sinkLocalValueMaterialization(MachineInstr &LocalMI, unsigned DefReg,
+ InstOrderMap &OrderMap);
+
+ /// Insertion point before trying to select the current instruction.
MachineBasicBlock::iterator SavedInsertPt;
- /// \brief Add a stackmap or patchpoint intrinsic call's live variable
+ /// Add a stackmap or patchpoint intrinsic call's live variable
/// operands to a stackmap or patchpoint machine instruction.
bool addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops,
const CallInst *CI, unsigned StartIdx);
diff --git a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
index 3b39d87ffb4a..2da00b7d61ab 100644
--- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
@@ -118,6 +118,17 @@ public:
/// cross-basic-block values.
DenseMap<const Value *, unsigned> ValueMap;
+ /// VirtReg2Value map is needed by the Divergence Analysis driven
+ /// instruction selection. It is reverted ValueMap. It is computed
+ /// in lazy style - on demand. It is used to get the Value corresponding
+ /// to the live in virtual register and is called from the
+ /// TargetLowerinInfo::isSDNodeSourceOfDivergence.
+ DenseMap<unsigned, const Value*> VirtReg2Value;
+
+ /// This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence
+ /// to get the Value corresponding to the live-in virtual register.
+ const Value * getValueFromVirtualReg(unsigned Vreg);
+
/// Track virtual registers created for exception pointers.
DenseMap<const Value *, unsigned> CatchPadExceptionPointers;
@@ -167,6 +178,8 @@ public:
/// RegFixups - Registers which need to be replaced after isel is done.
DenseMap<unsigned, unsigned> RegFixups;
+ DenseSet<unsigned> RegsWithFixups;
+
/// 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
diff --git a/contrib/llvm/include/llvm/CodeGen/GCStrategy.h b/contrib/llvm/include/llvm/CodeGen/GCStrategy.h
index 16168e785f81..91604fd2df87 100644
--- a/contrib/llvm/include/llvm/CodeGen/GCStrategy.h
+++ b/contrib/llvm/include/llvm/CodeGen/GCStrategy.h
@@ -105,12 +105,12 @@ public:
/// By default, write barriers are replaced with simple store
/// instructions. If true, you must provide a custom pass to lower
- /// calls to @llvm.gcwrite.
+ /// 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.
+ /// calls to \@llvm.gcread.
bool customReadBarrier() const { return CustomReadBarriers; }
/// Returns true if this strategy is expecting the use of gc.statepoints,
@@ -147,7 +147,7 @@ public:
/// 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.
+ /// calls to \@llvm.gcroot.
bool customRoots() const { return CustomRoots; }
/// If set, gcroot intrinsics should initialize their allocas to null
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
index ba84d76de164..58eb412d8c24 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
@@ -17,11 +17,11 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/CallingConvLower.h"
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/TargetCallingConv.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MachineValueType.h"
#include <cstdint>
#include <functional>
@@ -123,7 +123,7 @@ protected:
}
template <typename FuncInfoTy>
- void setArgFlags(ArgInfo &Arg, unsigned OpNum, const DataLayout &DL,
+ void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL,
const FuncInfoTy &FuncInfo) const;
/// Invoke Handler::assignArg on each of the given \p Args and then use
@@ -131,7 +131,7 @@ protected:
///
/// \return True if everything has succeeded, false otherwise.
bool handleAssignments(MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args,
- ValueHandler &Callback) const;
+ ValueHandler &Handler) const;
public:
CallLowering(const TargetLowering *TLI) : TLI(TLI) {}
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
new file mode 100644
index 000000000000..36a33deb4a64
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
@@ -0,0 +1,43 @@
+//== ----- llvm/CodeGen/GlobalISel/Combiner.h --------------------- == //
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// This contains common code to drive combines. Combiner Passes will need to
+/// setup a CombinerInfo and call combineMachineFunction.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_H
+#define LLVM_CODEGEN_GLOBALISEL_COMBINER_H
+
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+class MachineRegisterInfo;
+class CombinerInfo;
+class TargetPassConfig;
+class MachineFunction;
+
+class Combiner {
+public:
+ Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC);
+
+ bool combineMachineInstrs(MachineFunction &MF);
+
+protected:
+ CombinerInfo &CInfo;
+
+ MachineRegisterInfo *MRI = nullptr;
+ const TargetPassConfig *TPC;
+ MachineIRBuilder Builder;
+};
+
+} // End namespace llvm.
+
+#endif // LLVM_CODEGEN_GLOBALISEL_GICOMBINER_H
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
new file mode 100644
index 000000000000..5d5b8398452c
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -0,0 +1,44 @@
+//== llvm/CodeGen/GlobalISel/CombinerHelper.h -------------- -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+//
+/// This contains common combine transformations that may be used in a combine
+/// pass,or by the target elsewhere.
+/// Targets can pick individual opcode transformations from the helper or use
+/// tryCombine which invokes all transformations. All of the transformations
+/// return true if the MachineInstruction changed and false otherwise.
+//
+//===--------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H
+#define LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H
+
+namespace llvm {
+
+class MachineIRBuilder;
+class MachineRegisterInfo;
+class MachineInstr;
+
+class CombinerHelper {
+ MachineIRBuilder &Builder;
+ MachineRegisterInfo &MRI;
+
+public:
+ CombinerHelper(MachineIRBuilder &B);
+
+ /// If \p MI is COPY, try to combine it.
+ /// Returns true if MI changed.
+ bool tryCombineCopy(MachineInstr &MI);
+
+ /// Try to transform \p MI by using all of the above
+ /// combine functions. Returns true if changed.
+ bool tryCombine(MachineInstr &MI);
+};
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h
new file mode 100644
index 000000000000..1d248547adbf
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h
@@ -0,0 +1,48 @@
+//===- llvm/CodeGen/GlobalISel/CombinerInfo.h ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// Interface for Targets to specify which operations are combined how and when.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_INFO_H
+#define LLVM_CODEGEN_GLOBALISEL_COMBINER_INFO_H
+
+#include <cassert>
+namespace llvm {
+
+class LegalizerInfo;
+class MachineInstr;
+class MachineIRBuilder;
+class MachineRegisterInfo;
+// Contains information relevant to enabling/disabling various combines for a
+// pass.
+class CombinerInfo {
+public:
+ CombinerInfo(bool AllowIllegalOps, bool ShouldLegalizeIllegal,
+ LegalizerInfo *LInfo)
+ : IllegalOpsAllowed(AllowIllegalOps),
+ LegalizeIllegalOps(ShouldLegalizeIllegal), LInfo(LInfo) {
+ assert(((AllowIllegalOps || !LegalizeIllegalOps) || LInfo) &&
+ "Expecting legalizerInfo when illegalops not allowed");
+ }
+ virtual ~CombinerInfo() = default;
+ /// If \p IllegalOpsAllowed is false, the CombinerHelper will make use of
+ /// the legalizerInfo to check for legality before each transformation.
+ bool IllegalOpsAllowed; // TODO: Make use of this.
+
+ /// If \p LegalizeIllegalOps is true, the Combiner will also legalize the
+ /// illegal ops that are created.
+ bool LegalizeIllegalOps; // TODO: Make use of this.
+ const LegalizerInfo *LInfo;
+ virtual bool combine(MachineInstr &MI, MachineIRBuilder &B) const = 0;
+};
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h
new file mode 100644
index 000000000000..8d61f9a68279
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h
@@ -0,0 +1,134 @@
+//===-- llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.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 implements a version of MachineIRBuilder which does trivial
+/// constant folding.
+//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
+
+namespace llvm {
+
+static Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const unsigned Op1,
+ const unsigned Op2,
+ const MachineRegisterInfo &MRI) {
+ auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI);
+ auto MaybeOp2Cst = getConstantVRegVal(Op2, MRI);
+ if (MaybeOp1Cst && MaybeOp2Cst) {
+ LLT Ty = MRI.getType(Op1);
+ APInt C1(Ty.getSizeInBits(), *MaybeOp1Cst, true);
+ APInt C2(Ty.getSizeInBits(), *MaybeOp2Cst, true);
+ switch (Opcode) {
+ default:
+ break;
+ case TargetOpcode::G_ADD:
+ return C1 + C2;
+ case TargetOpcode::G_AND:
+ return C1 & C2;
+ case TargetOpcode::G_ASHR:
+ return C1.ashr(C2);
+ case TargetOpcode::G_LSHR:
+ return C1.lshr(C2);
+ case TargetOpcode::G_MUL:
+ return C1 * C2;
+ case TargetOpcode::G_OR:
+ return C1 | C2;
+ case TargetOpcode::G_SHL:
+ return C1 << C2;
+ case TargetOpcode::G_SUB:
+ return C1 - C2;
+ case TargetOpcode::G_XOR:
+ return C1 ^ C2;
+ case TargetOpcode::G_UDIV:
+ if (!C2.getBoolValue())
+ break;
+ return C1.udiv(C2);
+ case TargetOpcode::G_SDIV:
+ if (!C2.getBoolValue())
+ break;
+ return C1.sdiv(C2);
+ case TargetOpcode::G_UREM:
+ if (!C2.getBoolValue())
+ break;
+ return C1.urem(C2);
+ case TargetOpcode::G_SREM:
+ if (!C2.getBoolValue())
+ break;
+ return C1.srem(C2);
+ }
+ }
+ return None;
+}
+
+/// An MIRBuilder which does trivial constant folding of binary ops.
+/// Calls to buildInstr will also try to constant fold binary ops.
+class ConstantFoldingMIRBuilder
+ : public FoldableInstructionsBuilder<ConstantFoldingMIRBuilder> {
+public:
+ // Pull in base class constructors.
+ using FoldableInstructionsBuilder<
+ ConstantFoldingMIRBuilder>::FoldableInstructionsBuilder;
+ // Unhide buildInstr
+ using FoldableInstructionsBuilder<ConstantFoldingMIRBuilder>::buildInstr;
+
+ // Implement buildBinaryOp required by FoldableInstructionsBuilder which
+ // tries to constant fold.
+ MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst,
+ unsigned Src0, unsigned Src1) {
+ validateBinaryOp(Dst, Src0, Src1);
+ auto MaybeCst = ConstantFoldBinOp(Opcode, Src0, Src1, getMF().getRegInfo());
+ if (MaybeCst)
+ return buildConstant(Dst, MaybeCst->getSExtValue());
+ return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1);
+ }
+
+ template <typename DstTy, typename UseArg1Ty, typename UseArg2Ty>
+ MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, UseArg1Ty &&Arg1,
+ UseArg2Ty &&Arg2) {
+ unsigned Dst = getDestFromArg(Ty);
+ return buildInstr(Opc, Dst, getRegFromArg(std::forward<UseArg1Ty>(Arg1)),
+ getRegFromArg(std::forward<UseArg2Ty>(Arg2)));
+ }
+
+ // Try to provide an overload for buildInstr for binary ops in order to
+ // constant fold.
+ MachineInstrBuilder buildInstr(unsigned Opc, unsigned Dst, unsigned Src0,
+ unsigned Src1) {
+ switch (Opc) {
+ default:
+ break;
+ case TargetOpcode::G_ADD:
+ case TargetOpcode::G_AND:
+ case TargetOpcode::G_ASHR:
+ case TargetOpcode::G_LSHR:
+ case TargetOpcode::G_MUL:
+ case TargetOpcode::G_OR:
+ case TargetOpcode::G_SHL:
+ case TargetOpcode::G_SUB:
+ case TargetOpcode::G_XOR:
+ case TargetOpcode::G_UDIV:
+ case TargetOpcode::G_SDIV:
+ case TargetOpcode::G_UREM:
+ case TargetOpcode::G_SREM: {
+ return buildBinaryOp(Opc, Dst, Src0, Src1);
+ }
+ }
+ return buildInstr(Opc).addDef(Dst).addUse(Src0).addUse(Src1);
+ }
+
+ // Fallback implementation of buildInstr.
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
+ UseArgsTy &&... Args) {
+ auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
+ addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
+ return MIB;
+ }
+};
+} // namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 7061c014d9b7..f3553966fcdf 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Types.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/IR/Intrinsics.h"
#include <memory>
#include <utility>
@@ -63,9 +64,83 @@ private:
/// Interface used to lower the everything related to calls.
const CallLowering *CLI;
- /// Mapping of the values of the current LLVM IR function
- /// to the related virtual registers.
- ValueToVReg ValToVReg;
+ /// This class contains the mapping between the Values to vreg related data.
+ class ValueToVRegInfo {
+ public:
+ ValueToVRegInfo() = default;
+
+ using VRegListT = SmallVector<unsigned, 1>;
+ using OffsetListT = SmallVector<uint64_t, 1>;
+
+ using const_vreg_iterator =
+ DenseMap<const Value *, VRegListT *>::const_iterator;
+ using const_offset_iterator =
+ DenseMap<const Value *, OffsetListT *>::const_iterator;
+
+ inline const_vreg_iterator vregs_end() const { return ValToVRegs.end(); }
+
+ VRegListT *getVRegs(const Value &V) {
+ auto It = ValToVRegs.find(&V);
+ if (It != ValToVRegs.end())
+ return It->second;
+
+ return insertVRegs(V);
+ }
+
+ OffsetListT *getOffsets(const Value &V) {
+ auto It = TypeToOffsets.find(V.getType());
+ if (It != TypeToOffsets.end())
+ return It->second;
+
+ return insertOffsets(V);
+ }
+
+ const_vreg_iterator findVRegs(const Value &V) const {
+ return ValToVRegs.find(&V);
+ }
+
+ bool contains(const Value &V) const {
+ return ValToVRegs.find(&V) != ValToVRegs.end();
+ }
+
+ void reset() {
+ ValToVRegs.clear();
+ TypeToOffsets.clear();
+ VRegAlloc.DestroyAll();
+ OffsetAlloc.DestroyAll();
+ }
+
+ private:
+ VRegListT *insertVRegs(const Value &V) {
+ assert(ValToVRegs.find(&V) == ValToVRegs.end() && "Value already exists");
+
+ // We placement new using our fast allocator since we never try to free
+ // the vectors until translation is finished.
+ auto *VRegList = new (VRegAlloc.Allocate()) VRegListT();
+ ValToVRegs[&V] = VRegList;
+ return VRegList;
+ }
+
+ OffsetListT *insertOffsets(const Value &V) {
+ assert(TypeToOffsets.find(V.getType()) == TypeToOffsets.end() &&
+ "Type already exists");
+
+ auto *OffsetList = new (OffsetAlloc.Allocate()) OffsetListT();
+ TypeToOffsets[V.getType()] = OffsetList;
+ return OffsetList;
+ }
+ SpecificBumpPtrAllocator<VRegListT> VRegAlloc;
+ SpecificBumpPtrAllocator<OffsetListT> OffsetAlloc;
+
+ // We store pointers to vectors here since references may be invalidated
+ // while we hold them if we stored the vectors directly.
+ DenseMap<const Value *, VRegListT*> ValToVRegs;
+ DenseMap<const Type *, OffsetListT*> TypeToOffsets;
+ };
+
+ /// Mapping of the values of the current LLVM IR function to the related
+ /// virtual registers and offsets.
+ ValueToVRegInfo VMap;
// N.b. it's not completely obvious that this will be sufficient for every
// LLVM IR construct (with "invoke" being the obvious candidate to mess up our
@@ -82,7 +157,8 @@ private:
// List of stubbed PHI instructions, for values and basic blocks to be filled
// in once all MachineBasicBlocks have been created.
- SmallVector<std::pair<const PHINode *, MachineInstr *>, 4> PendingPHIs;
+ SmallVector<std::pair<const PHINode *, SmallVector<MachineInstr *, 1>>, 4>
+ PendingPHIs;
/// Record of what frame index has been allocated to specified allocas for
/// this function.
@@ -99,7 +175,7 @@ private:
/// The general algorithm is:
/// 1. Look for a virtual register for each operand or
/// create one.
- /// 2 Update the ValToVReg accordingly.
+ /// 2 Update the VMap accordingly.
/// 2.alt. For constant arguments, if they are compile time constants,
/// produce an immediate in the right operand and do not touch
/// ValToReg. Actually we will go with a virtual register for each
@@ -134,7 +210,7 @@ private:
/// Translate an LLVM string intrinsic (memcpy, memset, ...).
bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder,
- unsigned Intrinsic);
+ unsigned ID);
void getStackGuard(unsigned DstReg, MachineIRBuilder &MIRBuilder);
@@ -146,6 +222,19 @@ private:
bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder);
+ // FIXME: temporary function to expose previous interface to call lowering
+ // until it is refactored.
+ /// Combines all component registers of \p V into a single scalar with size
+ /// "max(Offsets) + last size".
+ unsigned packRegs(const Value &V, MachineIRBuilder &MIRBuilder);
+
+ void unpackRegs(const Value &V, unsigned Src, MachineIRBuilder &MIRBuilder);
+
+ /// Returns true if the value should be split into multiple LLTs.
+ /// If \p Offsets is given then the split type's offsets will be stored in it.
+ bool valueIsSplit(const Value &V,
+ SmallVectorImpl<uint64_t> *Offsets = nullptr);
+
/// Translate call instruction.
/// \pre \p U is a call instruction.
bool translateCall(const User &U, MachineIRBuilder &MIRBuilder);
@@ -310,6 +399,9 @@ private:
bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder);
+
// Stubs to keep the compiler happy while we implement the rest of the
// translation.
bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) {
@@ -327,14 +419,8 @@ private:
bool translateFence(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
- bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
- }
- bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
- }
bool translateAddrSpaceCast(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
+ return translateCast(TargetOpcode::G_ADDRSPACE_CAST, U, MIRBuilder);
}
bool translateCleanupPad(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
@@ -381,9 +467,24 @@ private:
// * Clear the different maps.
void finalizeFunction();
- /// Get the VReg that represents \p Val.
- /// If such VReg does not exist, it is created.
- unsigned getOrCreateVReg(const Value &Val);
+ /// Get the VRegs that represent \p Val.
+ /// Non-aggregate types have just one corresponding VReg and the list can be
+ /// used as a single "unsigned". Aggregates get flattened. If such VRegs do
+ /// not exist, they are created.
+ ArrayRef<unsigned> getOrCreateVRegs(const Value &Val);
+
+ unsigned getOrCreateVReg(const Value &Val) {
+ auto Regs = getOrCreateVRegs(Val);
+ if (Regs.empty())
+ return 0;
+ assert(Regs.size() == 1 &&
+ "attempt to get single VReg for aggregate or void");
+ return Regs[0];
+ }
+
+ /// Allocate some vregs and offsets in the VMap. Then populate just the
+ /// offsets while leaving the vregs empty.
+ ValueToVRegInfo::VRegListT &allocateVRegs(const Value &Val);
/// Get the frame index that represents \p Val.
/// If such VReg does not exist, it is created.
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
index 4264a866b6c0..471def7f45a3 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CodeGenCoverage.h"
+#include "llvm/Support/LowLevelTypeImpl.h"
#include <bitset>
#include <cstddef>
#include <cstdint>
@@ -31,7 +32,6 @@ namespace llvm {
class APInt;
class APFloat;
-class LLT;
class MachineInstr;
class MachineInstrBuilder;
class MachineFunction;
@@ -81,6 +81,23 @@ enum {
/// failed match.
GIM_Try,
+ /// Switch over the opcode on the specified instruction
+ /// - InsnID - Instruction ID
+ /// - LowerBound - numerically minimum opcode supported
+ /// - UpperBound - numerically maximum + 1 opcode supported
+ /// - Default - failure jump target
+ /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets
+ GIM_SwitchOpcode,
+
+ /// Switch over the LLT on the specified instruction operand
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ /// - LowerBound - numerically minimum Type ID supported
+ /// - UpperBound - numerically maximum + 1 Type ID supported
+ /// - Default - failure jump target
+ /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets
+ GIM_SwitchType,
+
/// Record the specified instruction
/// - NewInsnID - Instruction ID to define
/// - InsnID - Instruction ID
@@ -117,6 +134,23 @@ enum {
GIM_CheckAtomicOrdering,
GIM_CheckAtomicOrderingOrStrongerThan,
GIM_CheckAtomicOrderingWeakerThan,
+ /// Check the size of the memory access for the given machine memory operand.
+ /// - InsnID - Instruction ID
+ /// - MMOIdx - MMO index
+ /// - Size - The size in bytes of the memory access
+ GIM_CheckMemorySizeEqualTo,
+ /// Check the size of the memory access for the given machine memory operand
+ /// against the size of an operand.
+ /// - InsnID - Instruction ID
+ /// - MMOIdx - MMO index
+ /// - OpIdx - The operand index to compare the MMO against
+ GIM_CheckMemorySizeEqualToLLT,
+ GIM_CheckMemorySizeLessThanLLT,
+ GIM_CheckMemorySizeGreaterThanLLT,
+ /// Check a generic C++ instruction predicate
+ /// - InsnID - Instruction ID
+ /// - PredicateID - The ID of the predicate function to call
+ GIM_CheckCxxInsnPredicate,
/// Check the type for the specified operand
/// - InsnID - Instruction ID
@@ -133,12 +167,14 @@ enum {
/// - OpIdx - Operand index
/// - Expected register bank (specified as a register class)
GIM_CheckRegBankForClass,
+
/// Check the operand matches a complex predicate
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
/// - RendererID - The renderer to hold the result
/// - Complex predicate ID
GIM_CheckComplexPattern,
+
/// Check the operand is a specific integer
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
@@ -155,6 +191,7 @@ enum {
/// - OpIdx - Operand index
/// - Expected Intrinsic ID
GIM_CheckIntrinsicID,
+
/// Check the specified operand is an MBB
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
@@ -183,6 +220,7 @@ enum {
/// - OldInsnID - Instruction ID to mutate
/// - NewOpcode - The new opcode to use
GIR_MutateOpcode,
+
/// Build a new instruction
/// - InsnID - Instruction ID to define
/// - Opcode - The new opcode to use
@@ -193,6 +231,7 @@ enum {
/// - OldInsnID - Instruction ID to copy from
/// - OpIdx - The operand to copy
GIR_Copy,
+
/// Copy an operand to the specified instruction or add a zero register if the
/// operand is a zero immediate.
/// - NewInsnID - Instruction ID to modify
@@ -206,6 +245,7 @@ enum {
/// - OpIdx - The operand to copy
/// - SubRegIdx - The subregister to copy
GIR_CopySubReg,
+
/// Add an implicit register def to the specified instruction
/// - InsnID - Instruction ID to modify
/// - RegNum - The register to add
@@ -218,10 +258,13 @@ enum {
/// - InsnID - Instruction ID to modify
/// - RegNum - The register to add
GIR_AddRegister,
- /// Add a a temporary register to the specified instruction
+
+ /// Add a temporary register to the specified instruction
/// - InsnID - Instruction ID to modify
/// - TempRegID - The temporary register ID to add
+ /// - TempRegFlags - The register flags to set
GIR_AddTempRegister,
+
/// Add an immediate to the specified instruction
/// - InsnID - Instruction ID to modify
/// - Imm - The immediate to add
@@ -230,11 +273,17 @@ enum {
/// - InsnID - Instruction ID to modify
/// - RendererID - The renderer to call
GIR_ComplexRenderer,
+
/// Render sub-operands of complex operands to the specified instruction
/// - InsnID - Instruction ID to modify
/// - RendererID - The renderer to call
/// - RenderOpID - The suboperand to render.
GIR_ComplexSubOperandRenderer,
+ /// Render operands to the specified instruction using a custom function
+ /// - InsnID - Instruction ID to modify
+ /// - OldInsnID - Instruction ID to get the matched operand from
+ /// - RendererFnID - Custom renderer function to call
+ GIR_CustomRenderer,
/// Render a G_CONSTANT operator as a sign-extended immediate.
/// - NewInsnID - Instruction ID to modify
@@ -242,24 +291,34 @@ enum {
/// The operand index is implicitly 1.
GIR_CopyConstantAsSImm,
+ /// Render a G_FCONSTANT operator as a sign-extended immediate.
+ /// - NewInsnID - Instruction ID to modify
+ /// - OldInsnID - Instruction ID to copy from
+ /// The operand index is implicitly 1.
+ GIR_CopyFConstantAsFPImm,
+
/// Constrain an instruction operand to a register class.
/// - InsnID - Instruction ID to modify
/// - OpIdx - Operand index
/// - RCEnum - Register class enumeration value
GIR_ConstrainOperandRC,
+
/// Constrain an instructions operands according to the instruction
/// description.
/// - InsnID - Instruction ID to modify
GIR_ConstrainSelectedInstOperands,
+
/// Merge all memory operands into instruction.
/// - InsnID - Instruction ID to modify
/// - MergeInsnID... - One or more Instruction ID to merge into the result.
/// - GIU_MergeMemOperands_EndOfList - Terminates the list of instructions to
/// merge.
GIR_MergeMemOperands,
+
/// Erase from parent.
/// - InsnID - Instruction ID to erase
GIR_EraseFromParent,
+
/// Create a new temporary register that's not constrained.
/// - TempRegID - The temporary register ID to initialize.
/// - Expected type
@@ -271,6 +330,9 @@ enum {
/// Increment the rule coverage counter.
/// - RuleID - The ID of the rule that was covered.
GIR_Coverage,
+
+ /// Keeping track of the number of the GI opcodes. Must be the last entry.
+ GIU_NumOpcodes,
};
enum {
@@ -311,11 +373,27 @@ protected:
};
public:
- template <class PredicateBitset, class ComplexMatcherMemFn>
- struct MatcherInfoTy {
+ template <class PredicateBitset, class ComplexMatcherMemFn,
+ class CustomRendererFn>
+ struct ISelInfoTy {
+ ISelInfoTy(const LLT *TypeObjects, size_t NumTypeObjects,
+ const PredicateBitset *FeatureBitsets,
+ const ComplexMatcherMemFn *ComplexPredicates,
+ const CustomRendererFn *CustomRenderers)
+ : TypeObjects(TypeObjects),
+ FeatureBitsets(FeatureBitsets),
+ ComplexPredicates(ComplexPredicates),
+ CustomRenderers(CustomRenderers) {
+
+ for (size_t I = 0; I < NumTypeObjects; ++I)
+ TypeIDMap[TypeObjects[I]] = I;
+ }
const LLT *TypeObjects;
const PredicateBitset *FeatureBitsets;
const ComplexMatcherMemFn *ComplexPredicates;
+ const CustomRendererFn *CustomRenderers;
+
+ SmallDenseMap<LLT, unsigned, 64> TypeIDMap;
};
protected:
@@ -324,23 +402,35 @@ protected:
/// Execute a given matcher table and return true if the match was successful
/// and false otherwise.
template <class TgtInstructionSelector, class PredicateBitset,
- class ComplexMatcherMemFn>
+ class ComplexMatcherMemFn, class CustomRendererFn>
bool executeMatchTable(
TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
- const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
+ const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn>
+ &ISelInfo,
const int64_t *MatchTable, const TargetInstrInfo &TII,
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures,
CodeGenCoverage &CoverageInfo) const;
+ virtual const int64_t *getMatchTable() const {
+ llvm_unreachable("Should have been overridden by tablegen if used");
+ }
+
virtual bool testImmPredicate_I64(unsigned, int64_t) const {
- llvm_unreachable("Subclasses must override this to use tablegen");
+ llvm_unreachable(
+ "Subclasses must override this with a tablegen-erated function");
}
virtual bool testImmPredicate_APInt(unsigned, const APInt &) const {
- llvm_unreachable("Subclasses must override this to use tablegen");
+ llvm_unreachable(
+ "Subclasses must override this with a tablegen-erated function");
}
virtual bool testImmPredicate_APFloat(unsigned, const APFloat &) const {
- llvm_unreachable("Subclasses must override this to use tablegen");
+ llvm_unreachable(
+ "Subclasses must override this with a tablegen-erated function");
+ }
+ virtual bool testMIPredicate_MI(unsigned, const MachineInstr &) const {
+ llvm_unreachable(
+ "Subclasses must override this with a tablegen-erated function");
}
/// Constrain a register operand of an instruction \p I to a specified
@@ -353,20 +443,6 @@ protected:
const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI) const;
- /// Mutate the newly-selected instruction \p I to constrain its (possibly
- /// generic) virtual register operands to the instruction's register class.
- /// This could involve inserting COPYs before (for uses) or after (for defs).
- /// This requires the number of operands to match the instruction description.
- /// \returns whether operand regclass constraining succeeded.
- ///
- // FIXME: Not all instructions have the same number of operands. We should
- // probably expose a constrain helper per operand and let the target selector
- // constrain individual registers, like fast-isel.
- bool constrainSelectedInstRegOperands(MachineInstr &I,
- const TargetInstrInfo &TII,
- const TargetRegisterInfo &TRI,
- const RegisterBankInfo &RBI) const;
-
bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
const MachineRegisterInfo &MRI) const;
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
index bf834cf8f5e3..2003a79f6b20 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -40,19 +41,22 @@ enum {
GIPFP_I64_Invalid = 0,
GIPFP_APInt_Invalid = 0,
GIPFP_APFloat_Invalid = 0,
+ GIPFP_MI_Invalid = 0,
};
template <class TgtInstructionSelector, class PredicateBitset,
- class ComplexMatcherMemFn>
+ class ComplexMatcherMemFn, class CustomRendererFn>
bool InstructionSelector::executeMatchTable(
TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
- const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
+ const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn>
+ &ISelInfo,
const int64_t *MatchTable, const TargetInstrInfo &TII,
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures,
CodeGenCoverage &CoverageInfo) const {
+
uint64_t CurrentIdx = 0;
- SmallVector<uint64_t, 8> OnFailResumeAt;
+ SmallVector<uint64_t, 4> OnFailResumeAt;
enum RejectAction { RejectAndGiveUp, RejectAndResume };
auto handleReject = [&]() -> RejectAction {
@@ -60,8 +64,7 @@ bool InstructionSelector::executeMatchTable(
dbgs() << CurrentIdx << ": Rejected\n");
if (OnFailResumeAt.empty())
return RejectAndGiveUp;
- CurrentIdx = OnFailResumeAt.back();
- OnFailResumeAt.pop_back();
+ CurrentIdx = OnFailResumeAt.pop_back_val();
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " ("
<< OnFailResumeAt.size() << " try-blocks remain)\n");
@@ -70,7 +73,8 @@ bool InstructionSelector::executeMatchTable(
while (true) {
assert(CurrentIdx != ~0u && "Invalid MatchTable index");
- switch (MatchTable[CurrentIdx++]) {
+ int64_t MatcherOpcode = MatchTable[CurrentIdx++];
+ switch (MatcherOpcode) {
case GIM_Try: {
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
dbgs() << CurrentIdx << ": Begin try-block\n");
@@ -124,8 +128,8 @@ bool InstructionSelector::executeMatchTable(
dbgs() << CurrentIdx
<< ": GIM_CheckFeatures(ExpectedBitsetID="
<< ExpectedBitsetID << ")\n");
- if ((AvailableFeatures & MatcherInfo.FeatureBitsets[ExpectedBitsetID]) !=
- MatcherInfo.FeatureBitsets[ExpectedBitsetID]) {
+ if ((AvailableFeatures & ISelInfo.FeatureBitsets[ExpectedBitsetID]) !=
+ ISelInfo.FeatureBitsets[ExpectedBitsetID]) {
if (handleReject() == RejectAndGiveUp)
return false;
}
@@ -136,12 +140,13 @@ bool InstructionSelector::executeMatchTable(
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t Expected = MatchTable[CurrentIdx++];
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
unsigned Opcode = State.MIs[InsnID]->getOpcode();
+
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID
<< "], ExpectedOpcode=" << Expected
<< ") // Got=" << Opcode << "\n");
- assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (Opcode != Expected) {
if (handleReject() == RejectAndGiveUp)
return false;
@@ -149,6 +154,77 @@ bool InstructionSelector::executeMatchTable(
break;
}
+ case GIM_SwitchOpcode: {
+ int64_t InsnID = MatchTable[CurrentIdx++];
+ int64_t LowerBound = MatchTable[CurrentIdx++];
+ int64_t UpperBound = MatchTable[CurrentIdx++];
+ int64_t Default = MatchTable[CurrentIdx++];
+
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ const int64_t Opcode = State.MIs[InsnID]->getOpcode();
+
+ DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), {
+ dbgs() << CurrentIdx << ": GIM_SwitchOpcode(MIs[" << InsnID << "], ["
+ << LowerBound << ", " << UpperBound << "), Default=" << Default
+ << ", JumpTable...) // Got=" << Opcode << "\n";
+ });
+ if (Opcode < LowerBound || UpperBound <= Opcode) {
+ CurrentIdx = Default;
+ break;
+ }
+ CurrentIdx = MatchTable[CurrentIdx + (Opcode - LowerBound)];
+ if (!CurrentIdx) {
+ CurrentIdx = Default;
+ break;
+ }
+ OnFailResumeAt.push_back(Default);
+ break;
+ }
+
+ case GIM_SwitchType: {
+ int64_t InsnID = MatchTable[CurrentIdx++];
+ int64_t OpIdx = MatchTable[CurrentIdx++];
+ int64_t LowerBound = MatchTable[CurrentIdx++];
+ int64_t UpperBound = MatchTable[CurrentIdx++];
+ int64_t Default = MatchTable[CurrentIdx++];
+
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
+
+ DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), {
+ dbgs() << CurrentIdx << ": GIM_SwitchType(MIs[" << InsnID
+ << "]->getOperand(" << OpIdx << "), [" << LowerBound << ", "
+ << UpperBound << "), Default=" << Default
+ << ", JumpTable...) // Got=";
+ if (!MO.isReg())
+ dbgs() << "Not a VReg\n";
+ else
+ dbgs() << MRI.getType(MO.getReg()) << "\n";
+ });
+ if (!MO.isReg()) {
+ CurrentIdx = Default;
+ break;
+ }
+ const LLT Ty = MRI.getType(MO.getReg());
+ const auto TyI = ISelInfo.TypeIDMap.find(Ty);
+ if (TyI == ISelInfo.TypeIDMap.end()) {
+ CurrentIdx = Default;
+ break;
+ }
+ const int64_t TypeID = TyI->second;
+ if (TypeID < LowerBound || UpperBound <= TypeID) {
+ CurrentIdx = Default;
+ break;
+ }
+ CurrentIdx = MatchTable[CurrentIdx + (TypeID - LowerBound)];
+ if (!CurrentIdx) {
+ CurrentIdx = Default;
+ break;
+ }
+ OnFailResumeAt.push_back(Default);
+ break;
+ }
+
case GIM_CheckNumOperands: {
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t Expected = MatchTable[CurrentIdx++];
@@ -194,7 +270,8 @@ bool InstructionSelector::executeMatchTable(
<< CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs["
<< InsnID << "], Predicate=" << Predicate << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
- assert(State.MIs[InsnID]->getOpcode() && "Expected G_CONSTANT");
+ assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
+ "Expected G_CONSTANT");
assert(Predicate > GIPFP_APInt_Invalid && "Expected a valid predicate");
APInt Value;
if (State.MIs[InsnID]->getOperand(1).isCImm())
@@ -226,6 +303,21 @@ bool InstructionSelector::executeMatchTable(
return false;
break;
}
+ case GIM_CheckCxxInsnPredicate: {
+ int64_t InsnID = MatchTable[CurrentIdx++];
+ int64_t Predicate = MatchTable[CurrentIdx++];
+ DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+ dbgs()
+ << CurrentIdx << ": GIM_CheckCxxPredicate(MIs["
+ << InsnID << "], Predicate=" << Predicate << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ assert(Predicate > GIPFP_MI_Invalid && "Expected a valid predicate");
+
+ if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID]))
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ break;
+ }
case GIM_CheckAtomicOrdering: {
int64_t InsnID = MatchTable[CurrentIdx++];
AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
@@ -233,7 +325,6 @@ bool InstructionSelector::executeMatchTable(
dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs["
<< InsnID << "], " << (uint64_t)Ordering << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
-
if (!State.MIs[InsnID]->hasOneMemOperand())
if (handleReject() == RejectAndGiveUp)
return false;
@@ -252,7 +343,6 @@ bool InstructionSelector::executeMatchTable(
<< ": GIM_CheckAtomicOrderingOrStrongerThan(MIs["
<< InsnID << "], " << (uint64_t)Ordering << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
-
if (!State.MIs[InsnID]->hasOneMemOperand())
if (handleReject() == RejectAndGiveUp)
return false;
@@ -271,7 +361,6 @@ bool InstructionSelector::executeMatchTable(
<< ": GIM_CheckAtomicOrderingWeakerThan(MIs["
<< InsnID << "], " << (uint64_t)Ordering << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
-
if (!State.MIs[InsnID]->hasOneMemOperand())
if (handleReject() == RejectAndGiveUp)
return false;
@@ -282,6 +371,87 @@ bool InstructionSelector::executeMatchTable(
return false;
break;
}
+ case GIM_CheckMemorySizeEqualTo: {
+ int64_t InsnID = MatchTable[CurrentIdx++];
+ int64_t MMOIdx = MatchTable[CurrentIdx++];
+ uint64_t Size = MatchTable[CurrentIdx++];
+
+ DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+ dbgs() << CurrentIdx
+ << ": GIM_CheckMemorySizeEqual(MIs[" << InsnID
+ << "]->memoperands() + " << MMOIdx
+ << ", Size=" << Size << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+
+ if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ break;
+ }
+
+ MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
+
+ DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+ dbgs() << MMO->getSize() << " bytes vs " << Size
+ << " bytes\n");
+ if (MMO->getSize() != Size)
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+
+ break;
+ }
+ case GIM_CheckMemorySizeEqualToLLT:
+ case GIM_CheckMemorySizeLessThanLLT:
+ case GIM_CheckMemorySizeGreaterThanLLT: {
+ int64_t InsnID = MatchTable[CurrentIdx++];
+ int64_t MMOIdx = MatchTable[CurrentIdx++];
+ int64_t OpIdx = MatchTable[CurrentIdx++];
+
+ DEBUG_WITH_TYPE(
+ TgtInstructionSelector::getName(),
+ dbgs() << CurrentIdx << ": GIM_CheckMemorySize"
+ << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT
+ ? "EqualTo"
+ : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT
+ ? "GreaterThan"
+ : "LessThan")
+ << "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx
+ << ", OpIdx=" << OpIdx << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+
+ MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
+ if (!MO.isReg()) {
+ DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+ dbgs() << CurrentIdx << ": Not a register\n");
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ break;
+ }
+
+ if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ break;
+ }
+
+ MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
+
+ unsigned Size = MRI.getType(MO.getReg()).getSizeInBits();
+ if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT &&
+ MMO->getSize() * 8 != Size) {
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT &&
+ MMO->getSize() * 8 >= Size) {
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT &&
+ MMO->getSize() * 8 <= Size)
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+
+ break;
+ }
case GIM_CheckType: {
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t OpIdx = MatchTable[CurrentIdx++];
@@ -291,8 +461,9 @@ bool InstructionSelector::executeMatchTable(
<< "]->getOperand(" << OpIdx
<< "), TypeID=" << TypeID << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
- if (MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg()) !=
- MatcherInfo.TypeObjects[TypeID]) {
+ MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
+ if (!MO.isReg() ||
+ MRI.getType(MO.getReg()) != ISelInfo.TypeObjects[TypeID]) {
if (handleReject() == RejectAndGiveUp)
return false;
}
@@ -308,7 +479,6 @@ bool InstructionSelector::executeMatchTable(
<< InsnID << "]->getOperand(" << OpIdx
<< "), SizeInBits=" << SizeInBits << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
-
// iPTR must be looked up in the target.
if (SizeInBits == 0) {
MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent();
@@ -317,11 +487,15 @@ bool InstructionSelector::executeMatchTable(
assert(SizeInBits != 0 && "Pointer size must be known");
- const LLT &Ty = MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg());
- if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) {
- if (handleReject() == RejectAndGiveUp)
- return false;
- }
+ MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
+ if (MO.isReg()) {
+ const LLT &Ty = MRI.getType(MO.getReg());
+ if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits)
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ } else if (handleReject() == RejectAndGiveUp)
+ return false;
+
break;
}
case GIM_CheckRegBankForClass: {
@@ -333,9 +507,10 @@ bool InstructionSelector::executeMatchTable(
<< InsnID << "]->getOperand(" << OpIdx
<< "), RCEnum=" << RCEnum << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
- if (&RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum)) !=
- RBI.getRegBank(State.MIs[InsnID]->getOperand(OpIdx).getReg(), MRI,
- TRI)) {
+ MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
+ if (!MO.isReg() ||
+ &RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum)) !=
+ RBI.getRegBank(MO.getReg(), MRI, TRI)) {
if (handleReject() == RejectAndGiveUp)
return false;
}
@@ -356,7 +531,7 @@ bool InstructionSelector::executeMatchTable(
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
// FIXME: Use std::invoke() when it's available.
ComplexRendererFns Renderer =
- (ISel.*MatcherInfo.ComplexPredicates[ComplexPredicateID])(
+ (ISel.*ISelInfo.ComplexPredicates[ComplexPredicateID])(
State.MIs[InsnID]->getOperand(OpIdx));
if (Renderer.hasValue())
State.Renderers[RendererID] = Renderer.getValue();
@@ -375,16 +550,19 @@ bool InstructionSelector::executeMatchTable(
<< InsnID << "]->getOperand(" << OpIdx
<< "), Value=" << Value << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
+ if (MO.isReg()) {
+ // isOperandImmEqual() will sign-extend to 64-bits, so should we.
+ LLT Ty = MRI.getType(MO.getReg());
+ Value = SignExtend64(Value, Ty.getSizeInBits());
- // isOperandImmEqual() will sign-extend to 64-bits, so should we.
- LLT Ty = MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg());
- Value = SignExtend64(Value, Ty.getSizeInBits());
+ if (!isOperandImmEqual(MO, Value, MRI)) {
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ }
+ } else if (handleReject() == RejectAndGiveUp)
+ return false;
- if (!isOperandImmEqual(State.MIs[InsnID]->getOperand(OpIdx), Value,
- MRI)) {
- if (handleReject() == RejectAndGiveUp)
- return false;
- }
break;
}
@@ -467,7 +645,7 @@ bool InstructionSelector::executeMatchTable(
}
case GIM_Reject:
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
- dbgs() << CurrentIdx << ": GIM_Reject");
+ dbgs() << CurrentIdx << ": GIM_Reject\n");
if (handleReject() == RejectAndGiveUp)
return false;
break;
@@ -649,6 +827,36 @@ bool InstructionSelector::executeMatchTable(
break;
}
+ // TODO: Needs a test case once we have a pattern that uses this.
+ case GIR_CopyFConstantAsFPImm: {
+ int64_t NewInsnID = MatchTable[CurrentIdx++];
+ int64_t OldInsnID = MatchTable[CurrentIdx++];
+ assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
+ assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT && "Expected G_FCONSTANT");
+ if (State.MIs[OldInsnID]->getOperand(1).isFPImm())
+ OutMIs[NewInsnID].addFPImm(
+ State.MIs[OldInsnID]->getOperand(1).getFPImm());
+ else
+ llvm_unreachable("Expected FPImm operand");
+ DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+ dbgs() << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs["
+ << NewInsnID << "], MIs[" << OldInsnID << "])\n");
+ break;
+ }
+
+ case GIR_CustomRenderer: {
+ int64_t InsnID = MatchTable[CurrentIdx++];
+ int64_t OldInsnID = MatchTable[CurrentIdx++];
+ int64_t RendererFnID = MatchTable[CurrentIdx++];
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+ dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs["
+ << InsnID << "], MIs[" << OldInsnID << "], "
+ << RendererFnID << ")\n");
+ (ISel.*ISelInfo.CustomRenderers[RendererFnID])(OutMIs[InsnID],
+ *State.MIs[OldInsnID]);
+ break;
+ }
case GIR_ConstrainOperandRC: {
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t OpIdx = MatchTable[CurrentIdx++];
@@ -710,7 +918,7 @@ bool InstructionSelector::executeMatchTable(
int64_t TypeID = MatchTable[CurrentIdx++];
State.TempRegisters[TempRegID] =
- MRI.createGenericVirtualRegister(MatcherInfo.TypeObjects[TypeID]);
+ MRI.createGenericVirtualRegister(ISelInfo.TypeObjects[TypeID]);
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
dbgs() << CurrentIdx << ": TempRegs[" << TempRegID
<< "] = GIR_MakeTempReg(" << TypeID << ")\n");
@@ -729,7 +937,7 @@ bool InstructionSelector::executeMatchTable(
case GIR_Done:
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
- dbgs() << CurrentIdx << ": GIR_Done");
+ dbgs() << CurrentIdx << ": GIR_Done\n");
return true;
default:
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
index e7945ff5bf4f..873587651efd 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
@@ -38,7 +38,7 @@ public:
return false;
if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_TRUNC,
MI.getOperand(1).getReg(), MRI)) {
- DEBUG(dbgs() << ".. Combine MI: " << MI;);
+ LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
unsigned DstReg = MI.getOperand(0).getReg();
unsigned SrcReg = DefMI->getOperand(1).getReg();
Builder.setInstr(MI);
@@ -59,10 +59,10 @@ public:
MI.getOperand(1).getReg(), MRI)) {
unsigned DstReg = MI.getOperand(0).getReg();
LLT DstTy = MRI.getType(DstReg);
- if (isInstUnsupported(TargetOpcode::G_AND, DstTy) ||
- isInstUnsupported(TargetOpcode::G_CONSTANT, DstTy))
+ if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
+ isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
return false;
- DEBUG(dbgs() << ".. Combine MI: " << MI;);
+ LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
Builder.setInstr(MI);
unsigned ZExtSrc = MI.getOperand(1).getReg();
LLT ZExtSrcTy = MRI.getType(ZExtSrc);
@@ -87,11 +87,11 @@ public:
MI.getOperand(1).getReg(), MRI)) {
unsigned DstReg = MI.getOperand(0).getReg();
LLT DstTy = MRI.getType(DstReg);
- if (isInstUnsupported(TargetOpcode::G_SHL, DstTy) ||
- isInstUnsupported(TargetOpcode::G_ASHR, DstTy) ||
- isInstUnsupported(TargetOpcode::G_CONSTANT, DstTy))
+ if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) ||
+ isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) ||
+ isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
return false;
- DEBUG(dbgs() << ".. Combine MI: " << MI;);
+ LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
Builder.setInstr(MI);
unsigned SExtSrc = MI.getOperand(1).getReg();
LLT SExtSrcTy = MRI.getType(SExtSrc);
@@ -121,9 +121,9 @@ public:
MI.getOperand(1).getReg(), MRI)) {
unsigned DstReg = MI.getOperand(0).getReg();
LLT DstTy = MRI.getType(DstReg);
- if (isInstUnsupported(TargetOpcode::G_IMPLICIT_DEF, DstTy))
+ if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
return false;
- DEBUG(dbgs() << ".. Combine EXT(IMPLICIT_DEF) " << MI;);
+ LLVM_DEBUG(dbgs() << ".. Combine EXT(IMPLICIT_DEF) " << MI;);
Builder.setInstr(MI);
Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, DstReg);
markInstAndDefDead(MI, *DefMI, DeadInsts);
@@ -139,9 +139,9 @@ public:
return false;
unsigned NumDefs = MI.getNumOperands() - 1;
- unsigned SrcReg = MI.getOperand(NumDefs).getReg();
- MachineInstr *MergeI = MRI.getVRegDef(SrcReg);
- if (!MergeI || (MergeI->getOpcode() != TargetOpcode::G_MERGE_VALUES))
+ MachineInstr *MergeI = getOpcodeDef(TargetOpcode::G_MERGE_VALUES,
+ MI.getOperand(NumDefs).getReg(), MRI);
+ if (!MergeI)
return false;
const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
@@ -253,11 +253,8 @@ private:
// and as a result, %3, %2, %1 are dead.
MachineInstr *PrevMI = &MI;
while (PrevMI != &DefMI) {
- // If we're dealing with G_UNMERGE_VALUES, tryCombineMerges doesn't really try
- // to fold copies in between and we can ignore them here.
- if (PrevMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
- break;
- unsigned PrevRegSrc = PrevMI->getOperand(1).getReg();
+ unsigned PrevRegSrc =
+ PrevMI->getOperand(PrevMI->getNumOperands() - 1).getReg();
MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
if (MRI.hasOneUse(PrevRegSrc)) {
if (TmpDef != &DefMI) {
@@ -269,18 +266,16 @@ private:
break;
PrevMI = TmpDef;
}
- if ((PrevMI == &DefMI ||
- DefMI.getOpcode() == TargetOpcode::G_MERGE_VALUES) &&
- MRI.hasOneUse(DefMI.getOperand(0).getReg()))
+ if (PrevMI == &DefMI && MRI.hasOneUse(DefMI.getOperand(0).getReg()))
DeadInsts.push_back(&DefMI);
}
/// Checks if the target legalizer info has specified anything about the
/// instruction, or if unsupported.
- bool isInstUnsupported(unsigned Opcode, const LLT &DstTy) const {
- auto Action = LI.getAction({Opcode, 0, DstTy});
- return Action.first == LegalizerInfo::LegalizeAction::Unsupported ||
- Action.first == LegalizerInfo::LegalizeAction::NotFound;
+ bool isInstUnsupported(const LegalityQuery &Query) const {
+ using namespace LegalizeActions;
+ auto Step = LI.getAction(Query);
+ return Step.Action == Unsupported || Step.Action == NotFound;
}
};
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 8bd8a9dcd0e2..d122e67b87b8 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -93,12 +93,24 @@ public:
const LegalizerInfo &getLegalizerInfo() const { return LI; }
private:
+ /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
+ /// Use by extending the operand's type to \p WideTy using the specified \p
+ /// ExtOpcode for the extension instruction, and replacing the vreg of the
+ /// operand in place.
+ void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx,
+ unsigned ExtOpcode);
+
+ /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
+ /// Def by extending the operand's type to \p WideTy and truncating it back
+ /// with the \p TruncOpcode, and replacing the vreg of the operand in place.
+ void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx = 0,
+ unsigned TruncOpcode = TargetOpcode::G_TRUNC);
/// Helper function to split a wide generic register into bitwise blocks with
/// the given Type (which implies the number of blocks needed). The generic
/// registers created are appended to Ops, starting at bit 0 of Reg.
void extractParts(unsigned Reg, LLT Ty, int NumParts,
- SmallVectorImpl<unsigned> &Ops);
+ SmallVectorImpl<unsigned> &VRegs);
MachineRegisterInfo &MRI;
const LegalizerInfo &LI;
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index b6735d538b37..713d72eb4c9b 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -19,8 +19,11 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/LowLevelTypeImpl.h"
#include <cassert>
#include <cstdint>
@@ -30,9 +33,67 @@
namespace llvm {
+extern cl::opt<bool> DisableGISelLegalityCheck;
+
class MachineInstr;
class MachineIRBuilder;
class MachineRegisterInfo;
+class MCInstrInfo;
+
+namespace LegalizeActions {
+enum LegalizeAction : std::uint8_t {
+ /// The operation is expected to be selectable directly by the target, and
+ /// no transformation is necessary.
+ Legal,
+
+ /// The operation should be synthesized from multiple instructions acting on
+ /// a narrower scalar base-type. For example a 64-bit add might be
+ /// implemented in terms of 32-bit add-with-carry.
+ NarrowScalar,
+
+ /// The operation should be implemented in terms of a wider scalar
+ /// base-type. For example a <2 x s8> add could be implemented as a <2
+ /// x s32> add (ignoring the high bits).
+ WidenScalar,
+
+ /// The (vector) operation should be implemented by splitting it into
+ /// sub-vectors where the operation is legal. For example a <8 x s64> add
+ /// might be implemented as 4 separate <2 x s64> adds.
+ FewerElements,
+
+ /// The (vector) operation should be implemented by widening the input
+ /// vector and ignoring the lanes added by doing so. For example <2 x i8> is
+ /// rarely legal, but you might perform an <8 x i8> and then only look at
+ /// the first two results.
+ MoreElements,
+
+ /// The operation itself must be expressed in terms of simpler actions on
+ /// this target. E.g. a SREM replaced by an SDIV and subtraction.
+ Lower,
+
+ /// The operation should be implemented as a call to some kind of runtime
+ /// support library. For example this usually happens on machines that don't
+ /// support floating-point operations natively.
+ Libcall,
+
+ /// The target wants to do something special with this combination of
+ /// operand and type. A callback will be issued when it is needed.
+ Custom,
+
+ /// This operation is completely unsupported on the target. A programming
+ /// error has occurred.
+ Unsupported,
+
+ /// Sentinel value for when no action was found in the specified table.
+ NotFound,
+
+ /// Fall back onto the old rules.
+ /// TODO: Remove this once we've migrated
+ UseLegacyRules,
+};
+} // end namespace LegalizeActions
+
+using LegalizeActions::LegalizeAction;
/// Legalization is decided based on an instruction's opcode, which type slot
/// we're considering, and what the existing type is. These aspects are gathered
@@ -51,64 +112,642 @@ struct InstrAspect {
}
};
-class LegalizerInfo {
-public:
- enum LegalizeAction : std::uint8_t {
- /// The operation is expected to be selectable directly by the target, and
- /// no transformation is necessary.
- Legal,
+/// The LegalityQuery object bundles together all the information that's needed
+/// to decide whether a given operation is legal or not.
+/// For efficiency, it doesn't make a copy of Types so care must be taken not
+/// to free it before using the query.
+struct LegalityQuery {
+ unsigned Opcode;
+ ArrayRef<LLT> Types;
+
+ struct MemDesc {
+ uint64_t Size;
+ AtomicOrdering Ordering;
+ };
- /// The operation should be synthesized from multiple instructions acting on
- /// a narrower scalar base-type. For example a 64-bit add might be
- /// implemented in terms of 32-bit add-with-carry.
- NarrowScalar,
+ /// Operations which require memory can use this to place requirements on the
+ /// memory type for each MMO.
+ ArrayRef<MemDesc> MMODescrs;
- /// The operation should be implemented in terms of a wider scalar
- /// base-type. For example a <2 x s8> add could be implemented as a <2
- /// x s32> add (ignoring the high bits).
- WidenScalar,
+ constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types,
+ const ArrayRef<MemDesc> MMODescrs)
+ : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {}
+ constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types)
+ : LegalityQuery(Opcode, Types, {}) {}
- /// The (vector) operation should be implemented by splitting it into
- /// sub-vectors where the operation is legal. For example a <8 x s64> add
- /// might be implemented as 4 separate <2 x s64> adds.
- FewerElements,
+ raw_ostream &print(raw_ostream &OS) const;
+};
- /// The (vector) operation should be implemented by widening the input
- /// vector and ignoring the lanes added by doing so. For example <2 x i8> is
- /// rarely legal, but you might perform an <8 x i8> and then only look at
- /// the first two results.
- MoreElements,
+/// The result of a query. It either indicates a final answer of Legal or
+/// Unsupported or describes an action that must be taken to make an operation
+/// more legal.
+struct LegalizeActionStep {
+ /// The action to take or the final answer.
+ LegalizeAction Action;
+ /// If describing an action, the type index to change. Otherwise zero.
+ unsigned TypeIdx;
+ /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
+ LLT NewType;
- /// The operation itself must be expressed in terms of simpler actions on
- /// this target. E.g. a SREM replaced by an SDIV and subtraction.
- Lower,
+ LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx,
+ const LLT &NewType)
+ : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
- /// The operation should be implemented as a call to some kind of runtime
- /// support library. For example this usually happens on machines that don't
- /// support floating-point operations natively.
- Libcall,
+ bool operator==(const LegalizeActionStep &RHS) const {
+ return std::tie(Action, TypeIdx, NewType) ==
+ std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
+ }
+};
- /// The target wants to do something special with this combination of
- /// operand and type. A callback will be issued when it is needed.
- Custom,
+using LegalityPredicate = std::function<bool (const LegalityQuery &)>;
+using LegalizeMutation =
+ std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>;
- /// This operation is completely unsupported on the target. A programming
- /// error has occurred.
- Unsupported,
+namespace LegalityPredicates {
+struct TypePairAndMemSize {
+ LLT Type0;
+ LLT Type1;
+ uint64_t MemSize;
+
+ bool operator==(const TypePairAndMemSize &Other) const {
+ return Type0 == Other.Type0 && Type1 == Other.Type1 &&
+ MemSize == Other.MemSize;
+ }
+};
- /// Sentinel value for when no action was found in the specified table.
- NotFound,
+/// True iff P0 and P1 are true.
+template<typename Predicate>
+Predicate all(Predicate P0, Predicate P1) {
+ return [=](const LegalityQuery &Query) {
+ return P0(Query) && P1(Query);
};
+}
+/// True iff all given predicates are true.
+template<typename Predicate, typename... Args>
+Predicate all(Predicate P0, Predicate P1, Args... args) {
+ return all(all(P0, P1), args...);
+}
+/// True iff the given type index is the specified types.
+LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit);
+/// True iff the given type index is one of the specified types.
+LegalityPredicate typeInSet(unsigned TypeIdx,
+ std::initializer_list<LLT> TypesInit);
+/// True iff the given types for the given pair of type indexes is one of the
+/// specified type pairs.
+LegalityPredicate
+typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1,
+ std::initializer_list<std::pair<LLT, LLT>> TypesInit);
+/// True iff the given types for the given pair of type indexes is one of the
+/// specified type pairs.
+LegalityPredicate typePairAndMemSizeInSet(
+ unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx,
+ std::initializer_list<TypePairAndMemSize> TypesAndMemSizeInit);
+/// True iff the specified type index is a scalar.
+LegalityPredicate isScalar(unsigned TypeIdx);
+/// True iff the specified type index is a scalar that's narrower than the given
+/// size.
+LegalityPredicate narrowerThan(unsigned TypeIdx, unsigned Size);
+/// True iff the specified type index is a scalar that's wider than the given
+/// size.
+LegalityPredicate widerThan(unsigned TypeIdx, unsigned Size);
+/// True iff the specified type index is a scalar whose size is not a power of
+/// 2.
+LegalityPredicate sizeNotPow2(unsigned TypeIdx);
+/// True iff the specified MMO index has a size that is not a power of 2
+LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx);
+/// True iff the specified type index is a vector whose element count is not a
+/// power of 2.
+LegalityPredicate numElementsNotPow2(unsigned TypeIdx);
+/// True iff the specified MMO index has at an atomic ordering of at Ordering or
+/// stronger.
+LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx,
+ AtomicOrdering Ordering);
+} // end namespace LegalityPredicates
+
+namespace LegalizeMutations {
+/// Select this specific type for the given type index.
+LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty);
+/// Keep the same type as the given type index.
+LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx);
+/// Widen the type for the given type index to the next power of 2.
+LegalizeMutation widenScalarToNextPow2(unsigned TypeIdx, unsigned Min = 0);
+/// Add more elements to the type for the given type index to the next power of
+/// 2.
+LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0);
+} // end namespace LegalizeMutations
+
+/// A single rule in a legalizer info ruleset.
+/// The specified action is chosen when the predicate is true. Where appropriate
+/// for the action (e.g. for WidenScalar) the new type is selected using the
+/// given mutator.
+class LegalizeRule {
+ LegalityPredicate Predicate;
+ LegalizeAction Action;
+ LegalizeMutation Mutation;
+
+public:
+ LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action,
+ LegalizeMutation Mutation = nullptr)
+ : Predicate(Predicate), Action(Action), Mutation(Mutation) {}
+
+ /// Test whether the LegalityQuery matches.
+ bool match(const LegalityQuery &Query) const {
+ return Predicate(Query);
+ }
+
+ LegalizeAction getAction() const { return Action; }
+
+ /// Determine the change to make.
+ std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const {
+ if (Mutation)
+ return Mutation(Query);
+ return std::make_pair(0, LLT{});
+ }
+};
+
+class LegalizeRuleSet {
+ /// When non-zero, the opcode we are an alias of
+ unsigned AliasOf;
+ /// If true, there is another opcode that aliases this one
+ bool IsAliasedByAnother;
+ SmallVector<LegalizeRule, 2> Rules;
+
+#ifndef NDEBUG
+ /// If bit I is set, this rule set contains a rule that may handle (predicate
+ /// or perform an action upon (or both)) the type index I. The uncertainty
+ /// comes from free-form rules executing user-provided lambda functions. We
+ /// conservatively assume such rules do the right thing and cover all type
+ /// indices. The bitset is intentionally 1 bit wider than it absolutely needs
+ /// to be to distinguish such cases from the cases where all type indices are
+ /// individually handled.
+ SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC -
+ MCOI::OPERAND_FIRST_GENERIC + 2};
+#endif
+
+ unsigned typeIdx(unsigned TypeIdx) {
+ assert(TypeIdx <=
+ (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) &&
+ "Type Index is out of bounds");
+#ifndef NDEBUG
+ TypeIdxsCovered.set(TypeIdx);
+#endif
+ return TypeIdx;
+ }
+ void markAllTypeIdxsAsCovered() {
+#ifndef NDEBUG
+ TypeIdxsCovered.set();
+#endif
+ }
+
+ void add(const LegalizeRule &Rule) {
+ assert(AliasOf == 0 &&
+ "RuleSet is aliased, change the representative opcode instead");
+ Rules.push_back(Rule);
+ }
+
+ static bool always(const LegalityQuery &) { return true; }
+
+ /// Use the given action when the predicate is true.
+ /// Action should not be an action that requires mutation.
+ LegalizeRuleSet &actionIf(LegalizeAction Action,
+ LegalityPredicate Predicate) {
+ add({Predicate, Action});
+ return *this;
+ }
+ /// Use the given action when the predicate is true.
+ /// Action should be an action that requires mutation.
+ LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate,
+ LegalizeMutation Mutation) {
+ add({Predicate, Action, Mutation});
+ return *this;
+ }
+ /// Use the given action when type index 0 is any type in the given list.
+ /// Action should not be an action that requires mutation.
+ LegalizeRuleSet &actionFor(LegalizeAction Action,
+ std::initializer_list<LLT> Types) {
+ using namespace LegalityPredicates;
+ return actionIf(Action, typeInSet(typeIdx(0), Types));
+ }
+ /// Use the given action when type index 0 is any type in the given list.
+ /// Action should be an action that requires mutation.
+ LegalizeRuleSet &actionFor(LegalizeAction Action,
+ std::initializer_list<LLT> Types,
+ LegalizeMutation Mutation) {
+ using namespace LegalityPredicates;
+ return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation);
+ }
+ /// Use the given action when type indexes 0 and 1 is any type pair in the
+ /// given list.
+ /// Action should not be an action that requires mutation.
+ LegalizeRuleSet &actionFor(LegalizeAction Action,
+ std::initializer_list<std::pair<LLT, LLT>> Types) {
+ using namespace LegalityPredicates;
+ return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
+ }
+ /// Use the given action when type indexes 0 and 1 is any type pair in the
+ /// given list.
+ /// Action should be an action that requires mutation.
+ LegalizeRuleSet &actionFor(LegalizeAction Action,
+ std::initializer_list<std::pair<LLT, LLT>> Types,
+ LegalizeMutation Mutation) {
+ using namespace LegalityPredicates;
+ return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types),
+ Mutation);
+ }
+ /// Use the given action when type indexes 0 and 1 are both in the given list.
+ /// That is, the type pair is in the cartesian product of the list.
+ /// Action should not be an action that requires mutation.
+ LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action,
+ std::initializer_list<LLT> Types) {
+ using namespace LegalityPredicates;
+ return actionIf(Action, all(typeInSet(typeIdx(0), Types),
+ typeInSet(typeIdx(1), Types)));
+ }
+ /// Use the given action when type indexes 0 and 1 are both in their
+ /// respective lists.
+ /// That is, the type pair is in the cartesian product of the lists
+ /// Action should not be an action that requires mutation.
+ LegalizeRuleSet &
+ actionForCartesianProduct(LegalizeAction Action,
+ std::initializer_list<LLT> Types0,
+ std::initializer_list<LLT> Types1) {
+ using namespace LegalityPredicates;
+ return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
+ typeInSet(typeIdx(1), Types1)));
+ }
+ /// Use the given action when type indexes 0, 1, and 2 are all in their
+ /// respective lists.
+ /// That is, the type triple is in the cartesian product of the lists
+ /// Action should not be an action that requires mutation.
+ LegalizeRuleSet &actionForCartesianProduct(
+ LegalizeAction Action, std::initializer_list<LLT> Types0,
+ std::initializer_list<LLT> Types1, std::initializer_list<LLT> Types2) {
+ using namespace LegalityPredicates;
+ return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
+ all(typeInSet(typeIdx(1), Types1),
+ typeInSet(typeIdx(2), Types2))));
+ }
+
+public:
+ LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {}
+
+ bool isAliasedByAnother() { return IsAliasedByAnother; }
+ void setIsAliasedByAnother() { IsAliasedByAnother = true; }
+ void aliasTo(unsigned Opcode) {
+ assert((AliasOf == 0 || AliasOf == Opcode) &&
+ "Opcode is already aliased to another opcode");
+ assert(Rules.empty() && "Aliasing will discard rules");
+ AliasOf = Opcode;
+ }
+ unsigned getAlias() const { return AliasOf; }
+
+ /// The instruction is legal if predicate is true.
+ LegalizeRuleSet &legalIf(LegalityPredicate Predicate) {
+ // We have no choice but conservatively assume that the free-form
+ // user-provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::Legal, Predicate);
+ }
+ /// The instruction is legal when type index 0 is any type in the given list.
+ LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) {
+ return actionFor(LegalizeAction::Legal, Types);
+ }
+ /// The instruction is legal when type indexes 0 and 1 is any type pair in the
+ /// given list.
+ LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
+ return actionFor(LegalizeAction::Legal, Types);
+ }
+ /// The instruction is legal when type indexes 0 and 1 along with the memory
+ /// size is any type and size tuple in the given list.
+ LegalizeRuleSet &legalForTypesWithMemSize(
+ std::initializer_list<LegalityPredicates::TypePairAndMemSize>
+ TypesAndMemSize) {
+ return actionIf(LegalizeAction::Legal,
+ LegalityPredicates::typePairAndMemSizeInSet(
+ typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemSize));
+ }
+ /// The instruction is legal when type indexes 0 and 1 are both in the given
+ /// list. That is, the type pair is in the cartesian product of the list.
+ LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) {
+ return actionForCartesianProduct(LegalizeAction::Legal, Types);
+ }
+ /// The instruction is legal when type indexes 0 and 1 are both their
+ /// respective lists.
+ LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
+ std::initializer_list<LLT> Types1) {
+ return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1);
+ }
+
+ /// The instruction is lowered.
+ LegalizeRuleSet &lower() {
+ using namespace LegalizeMutations;
+ // We have no choice but conservatively assume that predicate-less lowering
+ // properly handles all type indices by design:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::Lower, always);
+ }
+ /// The instruction is lowered if predicate is true. Keep type index 0 as the
+ /// same type.
+ LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) {
+ using namespace LegalizeMutations;
+ // We have no choice but conservatively assume that lowering with a
+ // free-form user provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::Lower, Predicate);
+ }
+ /// The instruction is lowered if predicate is true.
+ LegalizeRuleSet &lowerIf(LegalityPredicate Predicate,
+ LegalizeMutation Mutation) {
+ // We have no choice but conservatively assume that lowering with a
+ // free-form user provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::Lower, Predicate, Mutation);
+ }
+ /// The instruction is lowered when type index 0 is any type in the given
+ /// list. Keep type index 0 as the same type.
+ LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) {
+ return actionFor(LegalizeAction::Lower, Types,
+ LegalizeMutations::changeTo(0, 0));
+ }
+ /// The instruction is lowered when type index 0 is any type in the given
+ /// list.
+ LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types,
+ LegalizeMutation Mutation) {
+ return actionFor(LegalizeAction::Lower, Types, Mutation);
+ }
+ /// The instruction is lowered when type indexes 0 and 1 is any type pair in
+ /// the given list. Keep type index 0 as the same type.
+ LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
+ return actionFor(LegalizeAction::Lower, Types,
+ LegalizeMutations::changeTo(0, 0));
+ }
+ /// The instruction is lowered when type indexes 0 and 1 is any type pair in
+ /// the given list.
+ LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types,
+ LegalizeMutation Mutation) {
+ return actionFor(LegalizeAction::Lower, Types, Mutation);
+ }
+ /// The instruction is lowered when type indexes 0 and 1 are both in their
+ /// respective lists.
+ LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
+ std::initializer_list<LLT> Types1) {
+ using namespace LegalityPredicates;
+ return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1);
+ }
+ /// The instruction is lowered when when type indexes 0, 1, and 2 are all in
+ /// their respective lists.
+ LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
+ std::initializer_list<LLT> Types1,
+ std::initializer_list<LLT> Types2) {
+ using namespace LegalityPredicates;
+ return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1,
+ Types2);
+ }
+
+ /// Like legalIf, but for the Libcall action.
+ LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) {
+ // We have no choice but conservatively assume that a libcall with a
+ // free-form user provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::Libcall, Predicate);
+ }
+ LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) {
+ return actionFor(LegalizeAction::Libcall, Types);
+ }
+ LegalizeRuleSet &
+ libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
+ return actionFor(LegalizeAction::Libcall, Types);
+ }
+ LegalizeRuleSet &
+ libcallForCartesianProduct(std::initializer_list<LLT> Types) {
+ return actionForCartesianProduct(LegalizeAction::Libcall, Types);
+ }
+ LegalizeRuleSet &
+ libcallForCartesianProduct(std::initializer_list<LLT> Types0,
+ std::initializer_list<LLT> Types1) {
+ return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1);
+ }
+
+ /// Widen the scalar to the one selected by the mutation if the predicate is
+ /// true.
+ LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate,
+ LegalizeMutation Mutation) {
+ // We have no choice but conservatively assume that an action with a
+ // free-form user provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation);
+ }
+ /// Narrow the scalar to the one selected by the mutation if the predicate is
+ /// true.
+ LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate,
+ LegalizeMutation Mutation) {
+ // We have no choice but conservatively assume that an action with a
+ // free-form user provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation);
+ }
+
+ /// Add more elements to reach the type selected by the mutation if the
+ /// predicate is true.
+ LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate,
+ LegalizeMutation Mutation) {
+ // We have no choice but conservatively assume that an action with a
+ // free-form user provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::MoreElements, Predicate, Mutation);
+ }
+ /// Remove elements to reach the type selected by the mutation if the
+ /// predicate is true.
+ LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate,
+ LegalizeMutation Mutation) {
+ // We have no choice but conservatively assume that an action with a
+ // free-form user provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::FewerElements, Predicate, Mutation);
+ }
+
+ /// The instruction is unsupported.
+ LegalizeRuleSet &unsupported() {
+ return actionIf(LegalizeAction::Unsupported, always);
+ }
+ LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) {
+ return actionIf(LegalizeAction::Unsupported, Predicate);
+ }
+ LegalizeRuleSet &unsupportedIfMemSizeNotPow2() {
+ return actionIf(LegalizeAction::Unsupported,
+ LegalityPredicates::memSizeInBytesNotPow2(0));
+ }
+
+ LegalizeRuleSet &customIf(LegalityPredicate Predicate) {
+ // We have no choice but conservatively assume that a custom action with a
+ // free-form user provided Predicate properly handles all type indices:
+ markAllTypeIdxsAsCovered();
+ return actionIf(LegalizeAction::Custom, Predicate);
+ }
+ LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) {
+ return actionFor(LegalizeAction::Custom, Types);
+ }
+ LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) {
+ return actionForCartesianProduct(LegalizeAction::Custom, Types);
+ }
+ LegalizeRuleSet &
+ customForCartesianProduct(std::initializer_list<LLT> Types0,
+ std::initializer_list<LLT> Types1) {
+ return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1);
+ }
+
+ /// Widen the scalar to the next power of two that is at least MinSize.
+ /// No effect if the type is not a scalar or is a power of two.
+ LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx,
+ unsigned MinSize = 0) {
+ using namespace LegalityPredicates;
+ return actionIf(LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)),
+ LegalizeMutations::widenScalarToNextPow2(TypeIdx, MinSize));
+ }
+
+ LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) {
+ using namespace LegalityPredicates;
+ return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)),
+ Mutation);
+ }
+
+ /// Ensure the scalar is at least as wide as Ty.
+ LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT &Ty) {
+ using namespace LegalityPredicates;
+ using namespace LegalizeMutations;
+ return actionIf(LegalizeAction::WidenScalar,
+ narrowerThan(TypeIdx, Ty.getSizeInBits()),
+ changeTo(typeIdx(TypeIdx), Ty));
+ }
+
+ /// Ensure the scalar is at most as wide as Ty.
+ LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT &Ty) {
+ using namespace LegalityPredicates;
+ using namespace LegalizeMutations;
+ return actionIf(LegalizeAction::NarrowScalar,
+ widerThan(TypeIdx, Ty.getSizeInBits()),
+ changeTo(typeIdx(TypeIdx), Ty));
+ }
+
+ /// Conditionally limit the maximum size of the scalar.
+ /// For example, when the maximum size of one type depends on the size of
+ /// another such as extracting N bits from an M bit container.
+ LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
+ const LLT &Ty) {
+ using namespace LegalityPredicates;
+ using namespace LegalizeMutations;
+ return actionIf(LegalizeAction::NarrowScalar,
+ [=](const LegalityQuery &Query) {
+ return widerThan(TypeIdx, Ty.getSizeInBits()) &&
+ Predicate(Query);
+ },
+ changeTo(typeIdx(TypeIdx), Ty));
+ }
+
+ /// Limit the range of scalar sizes to MinTy and MaxTy.
+ LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT &MinTy,
+ const LLT &MaxTy) {
+ assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types");
+ return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy);
+ }
+
+ /// Add more elements to the vector to reach the next power of two.
+ /// No effect if the type is not a vector or the element count is a power of
+ /// two.
+ LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) {
+ using namespace LegalityPredicates;
+ return actionIf(LegalizeAction::MoreElements,
+ numElementsNotPow2(typeIdx(TypeIdx)),
+ LegalizeMutations::moreElementsToNextPow2(TypeIdx));
+ }
+
+ /// Limit the number of elements in EltTy vectors to at least MinElements.
+ LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT &EltTy,
+ unsigned MinElements) {
+ // Mark the type index as covered:
+ typeIdx(TypeIdx);
+ return actionIf(
+ LegalizeAction::MoreElements,
+ [=](const LegalityQuery &Query) {
+ LLT VecTy = Query.Types[TypeIdx];
+ return VecTy.isVector() && VecTy.getElementType() == EltTy &&
+ VecTy.getNumElements() < MinElements;
+ },
+ [=](const LegalityQuery &Query) {
+ LLT VecTy = Query.Types[TypeIdx];
+ return std::make_pair(
+ TypeIdx, LLT::vector(MinElements, VecTy.getScalarSizeInBits()));
+ });
+ }
+ /// Limit the number of elements in EltTy vectors to at most MaxElements.
+ LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT &EltTy,
+ unsigned MaxElements) {
+ // Mark the type index as covered:
+ typeIdx(TypeIdx);
+ return actionIf(
+ LegalizeAction::FewerElements,
+ [=](const LegalityQuery &Query) {
+ LLT VecTy = Query.Types[TypeIdx];
+ return VecTy.isVector() && VecTy.getElementType() == EltTy &&
+ VecTy.getNumElements() > MaxElements;
+ },
+ [=](const LegalityQuery &Query) {
+ LLT VecTy = Query.Types[TypeIdx];
+ return std::make_pair(
+ TypeIdx, LLT::vector(MaxElements, VecTy.getScalarSizeInBits()));
+ });
+ }
+ /// Limit the number of elements for the given vectors to at least MinTy's
+ /// number of elements and at most MaxTy's number of elements.
+ ///
+ /// No effect if the type is not a vector or does not have the same element
+ /// type as the constraints.
+ /// The element type of MinTy and MaxTy must match.
+ LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT &MinTy,
+ const LLT &MaxTy) {
+ assert(MinTy.getElementType() == MaxTy.getElementType() &&
+ "Expected element types to agree");
+
+ const LLT &EltTy = MinTy.getElementType();
+ return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements())
+ .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements());
+ }
+
+ /// Fallback on the previous implementation. This should only be used while
+ /// porting a rule.
+ LegalizeRuleSet &fallback() {
+ add({always, LegalizeAction::UseLegacyRules});
+ return *this;
+ }
+
+ /// Check if there is no type index which is obviously not handled by the
+ /// LegalizeRuleSet in any way at all.
+ /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
+ bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const;
+ /// Apply the ruleset to the given LegalityQuery.
+ LegalizeActionStep apply(const LegalityQuery &Query) const;
+};
+
+class LegalizerInfo {
+public:
LegalizerInfo();
virtual ~LegalizerInfo() = default;
+ unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
+ unsigned getActionDefinitionsIdx(unsigned Opcode) const;
+
/// Compute any ancillary tables needed to quickly decide how an operation
/// should be handled. This must be called after all "set*Action"methods but
/// before any query is made or incorrect results may be returned.
void computeTables();
+ /// Perform simple self-diagnostic and assert if there is anything obviously
+ /// wrong with the actions set up.
+ void verify(const MCInstrInfo &MII) const;
+
static bool needsLegalizingToDifferentSize(const LegalizeAction Action) {
+ using namespace LegalizeActions;
switch (Action) {
case NarrowScalar:
case WidenScalar:
@@ -121,8 +760,8 @@ public:
}
}
- typedef std::pair<uint16_t, LegalizeAction> SizeAndAction;
- typedef std::vector<SizeAndAction> SizeAndActionsVec;
+ using SizeAndAction = std::pair<uint16_t, LegalizeAction>;
+ using SizeAndActionsVec = std::vector<SizeAndAction>;
using SizeChangeStrategy =
std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
@@ -186,8 +825,9 @@ public:
/// and Unsupported for all other scalar types T.
static SizeAndActionsVec
unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
+ using namespace LegalizeActions;
return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
- Unsupported);
+ Unsupported);
}
/// A SizeChangeStrategy for the common case where legalization for a
@@ -196,32 +836,36 @@ public:
/// largest legal type.
static SizeAndActionsVec
widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
+ using namespace LegalizeActions;
assert(v.size() > 0 &&
"At least one size that can be legalized towards is needed"
" for this SizeChangeStrategy");
return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
- NarrowScalar);
+ NarrowScalar);
}
static SizeAndActionsVec
widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
+ using namespace LegalizeActions;
return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
- Unsupported);
+ Unsupported);
}
static SizeAndActionsVec
narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
+ using namespace LegalizeActions;
return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
- Unsupported);
+ Unsupported);
}
static SizeAndActionsVec
narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
+ using namespace LegalizeActions;
assert(v.size() > 0 &&
"At least one size that can be legalized towards is needed"
" for this SizeChangeStrategy");
return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
- WidenScalar);
+ WidenScalar);
}
/// A SizeChangeStrategy for the common case where legalization for a
@@ -244,8 +888,9 @@ public:
/// (FewerElements, vector(4,32)).
static SizeAndActionsVec
moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
+ using namespace LegalizeActions;
return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
- FewerElements);
+ FewerElements);
}
/// Helper function to implement many typical SizeChangeStrategy functions.
@@ -259,22 +904,46 @@ public:
LegalizeAction DecreaseAction,
LegalizeAction IncreaseAction);
- /// Determine what action should be taken to legalize the given generic
- /// instruction opcode, type-index and type. Requires computeTables to have
- /// been called.
+ /// Get the action definitions for the given opcode. Use this to run a
+ /// LegalityQuery through the definitions.
+ const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
+
+ /// Get the action definition builder for the given opcode. Use this to define
+ /// the action definitions.
///
- /// \returns a pair consisting of the kind of legalization that should be
- /// performed and the destination type.
- std::pair<LegalizeAction, LLT> getAction(const InstrAspect &Aspect) const;
+ /// It is an error to request an opcode that has already been requested by the
+ /// multiple-opcode variant.
+ LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode);
+
+ /// Get the action definition builder for the given set of opcodes. Use this
+ /// to define the action definitions for multiple opcodes at once. The first
+ /// opcode given will be considered the representative opcode and will hold
+ /// the definitions whereas the other opcodes will be configured to refer to
+ /// the representative opcode. This lowers memory requirements and very
+ /// slightly improves performance.
+ ///
+ /// It would be very easy to introduce unexpected side-effects as a result of
+ /// this aliasing if it were permitted to request different but intersecting
+ /// sets of opcodes but that is difficult to keep track of. It is therefore an
+ /// error to request the same opcode twice using this API, to request an
+ /// opcode that already has definitions, or to use the single-opcode API on an
+ /// opcode that has already been requested by this API.
+ LegalizeRuleSet &
+ getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes);
+ void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom);
+
+ /// Determine what action should be taken to legalize the described
+ /// instruction. Requires computeTables to have been called.
+ ///
+ /// \returns a description of the next legalization step to perform.
+ LegalizeActionStep getAction(const LegalityQuery &Query) const;
/// Determine what action should be taken to legalize the given generic
/// instruction.
///
- /// \returns a tuple consisting of the LegalizeAction that should be
- /// performed, the type-index it should be performed on and the destination
- /// type.
- std::tuple<LegalizeAction, unsigned, LLT>
- getAction(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
+ /// \returns a description of the next legalization step to perform.
+ LegalizeActionStep getAction(const MachineInstr &MI,
+ const MachineRegisterInfo &MRI) const;
bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
@@ -283,6 +952,15 @@ public:
MachineIRBuilder &MIRBuilder) const;
private:
+ /// Determine what action should be taken to legalize the given generic
+ /// instruction opcode, type-index and type. Requires computeTables to have
+ /// been called.
+ ///
+ /// \returns a pair consisting of the kind of legalization that should be
+ /// performed and the destination type.
+ std::pair<LegalizeAction, LLT>
+ getAspectAction(const InstrAspect &Aspect) const;
+
/// The SizeAndActionsVec is a representation mapping between all natural
/// numbers and an Action. The natural number represents the bit size of
/// the InstrAspect. For example, for a target with native support for 32-bit
@@ -350,6 +1028,7 @@ private:
/// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
/// i.e. it's OK if it doesn't start from size 1.
static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
+ using namespace LegalizeActions;
#ifndef NDEBUG
// The sizes should be in increasing order
int prev_size = -1;
@@ -441,7 +1120,7 @@ private:
static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
// Data structures used temporarily during construction of legality data:
- typedef DenseMap<LLT, LegalizeAction> TypeMap;
+ using TypeMap = DenseMap<LLT, LegalizeAction>;
SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
SmallVector<SizeChangeStrategy, 1>
ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
@@ -456,8 +1135,16 @@ private:
AddrSpace2PointerActions[LastOp - FirstOp + 1];
std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
NumElements2Actions[LastOp - FirstOp + 1];
+
+ LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
};
+#ifndef NDEBUG
+/// Checks that MIR is fully legal, returns an illegal instruction if it's not,
+/// nullptr otherwise
+const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF);
+#endif
+
} // end namespace llvm.
#endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h
index 0a46eb9e7840..1e2d4763e5e1 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h
@@ -70,6 +70,8 @@ public:
.set(MachineFunctionProperties::Property::RegBankSelected);
}
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
bool runOnMachineFunction(MachineFunction &MF) override;
};
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
new file mode 100644
index 000000000000..f77f9a8df7ee
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
@@ -0,0 +1,338 @@
+//== ----- llvm/CodeGen/GlobalISel/MIPatternMatch.h --------------------- == //
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// Contains matchers for matching SSA Machine Instructions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_GMIR_PATTERNMATCH_H
+#define LLVM_GMIR_PATTERNMATCH_H
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+
+namespace llvm {
+namespace MIPatternMatch {
+
+template <typename Reg, typename Pattern>
+bool mi_match(Reg R, MachineRegisterInfo &MRI, Pattern &&P) {
+ return P.match(MRI, R);
+}
+
+// TODO: Extend for N use.
+template <typename SubPatternT> struct OneUse_match {
+ SubPatternT SubPat;
+ OneUse_match(const SubPatternT &SP) : SubPat(SP) {}
+
+ template <typename OpTy>
+ bool match(const MachineRegisterInfo &MRI, unsigned Reg) {
+ return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg);
+ }
+};
+
+template <typename SubPat>
+inline OneUse_match<SubPat> m_OneUse(const SubPat &SP) {
+ return SP;
+}
+
+struct ConstantMatch {
+ int64_t &CR;
+ ConstantMatch(int64_t &C) : CR(C) {}
+ bool match(const MachineRegisterInfo &MRI, unsigned Reg) {
+ if (auto MaybeCst = getConstantVRegVal(Reg, MRI)) {
+ CR = *MaybeCst;
+ return true;
+ }
+ return false;
+ }
+};
+
+inline ConstantMatch m_ICst(int64_t &Cst) { return ConstantMatch(Cst); }
+
+// TODO: Rework this for different kinds of MachineOperand.
+// Currently assumes the Src for a match is a register.
+// We might want to support taking in some MachineOperands and call getReg on
+// that.
+
+struct operand_type_match {
+ bool match(const MachineRegisterInfo &MRI, unsigned Reg) { return true; }
+ bool match(const MachineRegisterInfo &MRI, MachineOperand *MO) {
+ return MO->isReg();
+ }
+};
+
+inline operand_type_match m_Reg() { return operand_type_match(); }
+
+/// Matching combinators.
+template <typename... Preds> struct And {
+ template <typename MatchSrc>
+ bool match(MachineRegisterInfo &MRI, MatchSrc &&src) {
+ return true;
+ }
+};
+
+template <typename Pred, typename... Preds>
+struct And<Pred, Preds...> : And<Preds...> {
+ Pred P;
+ And(Pred &&p, Preds &&... preds)
+ : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
+ }
+ template <typename MatchSrc>
+ bool match(MachineRegisterInfo &MRI, MatchSrc &&src) {
+ return P.match(MRI, src) && And<Preds...>::match(MRI, src);
+ }
+};
+
+template <typename... Preds> struct Or {
+ template <typename MatchSrc>
+ bool match(MachineRegisterInfo &MRI, MatchSrc &&src) {
+ return false;
+ }
+};
+
+template <typename Pred, typename... Preds>
+struct Or<Pred, Preds...> : Or<Preds...> {
+ Pred P;
+ Or(Pred &&p, Preds &&... preds)
+ : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
+ template <typename MatchSrc>
+ bool match(MachineRegisterInfo &MRI, MatchSrc &&src) {
+ return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
+ }
+};
+
+template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
+ return And<Preds...>(std::forward<Preds>(preds)...);
+}
+
+template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
+ return Or<Preds...>(std::forward<Preds>(preds)...);
+}
+
+template <typename BindTy> struct bind_helper {
+ static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
+ VR = V;
+ return true;
+ }
+};
+
+template <> struct bind_helper<MachineInstr *> {
+ static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
+ unsigned Reg) {
+ MI = MRI.getVRegDef(Reg);
+ if (MI)
+ return true;
+ return false;
+ }
+};
+
+template <> struct bind_helper<LLT> {
+ static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, unsigned Reg) {
+ Ty = MRI.getType(Reg);
+ if (Ty.isValid())
+ return true;
+ return false;
+ }
+};
+
+template <> struct bind_helper<const ConstantFP *> {
+ static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
+ unsigned Reg) {
+ F = getConstantFPVRegVal(Reg, MRI);
+ if (F)
+ return true;
+ return false;
+ }
+};
+
+template <typename Class> struct bind_ty {
+ Class &VR;
+
+ bind_ty(Class &V) : VR(V) {}
+
+ template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
+ return bind_helper<Class>::bind(MRI, VR, V);
+ }
+};
+
+inline bind_ty<unsigned> m_Reg(unsigned &R) { return R; }
+inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; }
+inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
+
+// Helper for matching G_FCONSTANT
+inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
+
+// General helper for all the binary generic MI such as G_ADD/G_SUB etc
+template <typename LHS_P, typename RHS_P, unsigned Opcode,
+ bool Commutable = false>
+struct BinaryOp_match {
+ LHS_P L;
+ RHS_P R;
+
+ BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
+ template <typename OpTy> bool match(MachineRegisterInfo &MRI, OpTy &&Op) {
+ MachineInstr *TmpMI;
+ if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
+ if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
+ return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
+ R.match(MRI, TmpMI->getOperand(2).getReg())) ||
+ (Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) &&
+ L.match(MRI, TmpMI->getOperand(2).getReg())));
+ }
+ }
+ return false;
+ }
+};
+
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>
+m_GAdd(const LHS &L, const RHS &R) {
+ return BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>(L, R);
+}
+
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB> m_GSub(const LHS &L,
+ const RHS &R) {
+ return BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB>(L, R);
+}
+
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>
+m_GMul(const LHS &L, const RHS &R) {
+ return BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>(L, R);
+}
+
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>
+m_GFAdd(const LHS &L, const RHS &R) {
+ return BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>(L, R);
+}
+
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>
+m_GFMul(const LHS &L, const RHS &R) {
+ return BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>(L, R);
+}
+
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>
+m_GFSub(const LHS &L, const RHS &R) {
+ return BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>(L, R);
+}
+
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>
+m_GAnd(const LHS &L, const RHS &R) {
+ return BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>(L, R);
+}
+
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true> m_GOr(const LHS &L,
+ const RHS &R) {
+ return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true>(L, R);
+}
+
+// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
+template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
+ SrcTy L;
+
+ UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
+ template <typename OpTy> bool match(MachineRegisterInfo &MRI, OpTy &&Op) {
+ MachineInstr *TmpMI;
+ if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
+ if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
+ return L.match(MRI, TmpMI->getOperand(1).getReg());
+ }
+ }
+ return false;
+ }
+};
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>
+m_GAnyExt(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_SEXT> m_GSExt(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_SEXT>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT> m_GZExt(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT> m_GFPExt(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC> m_GTrunc(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>
+m_GBitcast(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>
+m_GPtrToInt(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>
+m_GIntToPtr(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>
+m_GFPTrunc(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_FABS> m_GFabs(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_FABS>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::G_FNEG> m_GFNeg(const SrcTy &Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::G_FNEG>(Src);
+}
+
+template <typename SrcTy>
+inline UnaryOp_match<SrcTy, TargetOpcode::COPY> m_Copy(SrcTy &&Src) {
+ return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
+}
+
+// Helper for checking if a Reg is of specific type.
+struct CheckType {
+ LLT Ty;
+ CheckType(const LLT &Ty) : Ty(Ty) {}
+
+ bool match(MachineRegisterInfo &MRI, unsigned Reg) {
+ return MRI.getType(Reg) == Ty;
+ }
+};
+
+inline CheckType m_SpecificType(LLT Ty) { return Ty; }
+
+} // namespace GMIPatternMatch
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index aa875c11d86f..983a4e680d5c 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -23,7 +23,6 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
-#include <queue>
namespace llvm {
@@ -32,11 +31,10 @@ class MachineFunction;
class MachineInstr;
class TargetInstrInfo;
-/// Helper class to build MachineInstr.
-/// It keeps internally the insertion point and debug location for all
-/// the new instructions we want to create.
-/// This information can be modify via the related setters.
-class MachineIRBuilder {
+/// Class which stores all the state required in a MachineIRBuilder.
+/// Since MachineIRBuilders will only store state in this object, it allows
+/// to transfer BuilderState between different kinds of MachineIRBuilders.
+struct MachineIRBuilderState {
/// MachineFunction under construction.
MachineFunction *MF;
/// Information used to access the description of the opcodes.
@@ -53,15 +51,23 @@ class MachineIRBuilder {
/// @}
std::function<void(MachineInstr *)> InsertedInstr;
+};
+
+/// Helper class to build MachineInstr.
+/// It keeps internally the insertion point and debug location for all
+/// the new instructions we want to create.
+/// This information can be modify via the related setters.
+class MachineIRBuilderBase {
+ MachineIRBuilderState State;
const TargetInstrInfo &getTII() {
- assert(TII && "TargetInstrInfo is not set");
- return *TII;
+ assert(State.TII && "TargetInstrInfo is not set");
+ return *State.TII;
}
void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend);
- MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Res, unsigned Op0, unsigned Op1);
+protected:
unsigned getDestFromArg(unsigned Reg) { return Reg; }
unsigned getDestFromArg(LLT Ty) {
return getMF().getRegInfo().createGenericVirtualRegister(Ty);
@@ -89,30 +95,41 @@ class MachineIRBuilder {
return MIB->getOperand(0).getReg();
}
+ void validateBinaryOp(unsigned Res, unsigned Op0, unsigned Op1);
+
public:
/// Some constructors for easy use.
- MachineIRBuilder() = default;
- MachineIRBuilder(MachineFunction &MF) { setMF(MF); }
- MachineIRBuilder(MachineInstr &MI) : MachineIRBuilder(*MI.getMF()) {
+ MachineIRBuilderBase() = default;
+ MachineIRBuilderBase(MachineFunction &MF) { setMF(MF); }
+ MachineIRBuilderBase(MachineInstr &MI) : MachineIRBuilderBase(*MI.getMF()) {
setInstr(MI);
}
+ MachineIRBuilderBase(const MachineIRBuilderState &BState) : State(BState) {}
+
/// Getter for the function we currently build.
MachineFunction &getMF() {
- assert(MF && "MachineFunction is not set");
- return *MF;
+ assert(State.MF && "MachineFunction is not set");
+ return *State.MF;
}
+ /// Getter for DebugLoc
+ const DebugLoc &getDL() { return State.DL; }
+
+ /// Getter for MRI
+ MachineRegisterInfo *getMRI() { return State.MRI; }
+
+ /// Getter for the State
+ MachineIRBuilderState &getState() { return State; }
+
/// Getter for the basic block we currently build.
MachineBasicBlock &getMBB() {
- assert(MBB && "MachineBasicBlock is not set");
- return *MBB;
+ assert(State.MBB && "MachineBasicBlock is not set");
+ return *State.MBB;
}
/// Current insertion point for new instructions.
- MachineBasicBlock::iterator getInsertPt() {
- return II;
- }
+ MachineBasicBlock::iterator getInsertPt() { return State.II; }
/// Set the insertion point before the specified position.
/// \pre MBB must be in getMF().
@@ -137,15 +154,16 @@ public:
/// \name Control where instructions we create are recorded (typically for
/// visiting again later during legalization).
/// @{
+ void recordInsertion(MachineInstr *InsertedInstr) const;
void recordInsertions(std::function<void(MachineInstr *)> InsertedInstr);
void stopRecordingInsertions();
/// @}
/// Set the debug location to \p DL for all the next build instructions.
- void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
+ void setDebugLoc(const DebugLoc &DL) { this->State.DL = DL; }
/// Get the current instruction's debug location.
- DebugLoc getDebugLoc() { return DL; }
+ DebugLoc getDebugLoc() { return State.DL; }
/// Build and insert <empty> = \p Opcode <empty>.
/// The insertion point is the one set by the last call of either
@@ -156,20 +174,6 @@ public:
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildInstr(unsigned Opcode);
- /// DAG like Generic method for building arbitrary instructions as above.
- /// \Opc opcode for the instruction.
- /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst
- /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder)
- /// Uses of type MachineInstrBuilder will perform
- /// getOperand(0).getReg() to convert to register.
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
- UseArgsTy &&... Args) {
- auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
- addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
- return MIB;
- }
-
/// Build but don't insert <empty> = \p Opcode <empty>.
///
/// \pre setMF, setBasicBlock or setMI must have been called.
@@ -227,49 +231,6 @@ public:
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildGlobalValue(unsigned Res, const GlobalValue *GV);
- /// Build and insert \p Res = G_ADD \p Op0, \p Op1
- ///
- /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
- /// truncated to their width.
- ///
- /// \pre setBasicBlock or setMI must have been called.
- /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
- /// with the same (scalar or vector) type).
- ///
- /// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildAdd(unsigned Res, unsigned Op0,
- unsigned Op1);
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
- unsigned Res = getDestFromArg(Ty);
- return buildAdd(Res, (getRegFromArg(UseArgs))...);
- }
-
- /// Build and insert \p Res = G_SUB \p Op0, \p Op1
- ///
- /// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
- /// truncated to their width.
- ///
- /// \pre setBasicBlock or setMI must have been called.
- /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
- /// with the same (scalar or vector) type).
- ///
- /// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildSub(unsigned Res, unsigned Op0,
- unsigned Op1);
-
- /// Build and insert \p Res = G_MUL \p Op0, \p Op1
- ///
- /// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
- /// truncated to their width.
- ///
- /// \pre setBasicBlock or setMI must have been called.
- /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
- /// with the same (scalar or vector) type).
- ///
- /// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildMul(unsigned Res, unsigned Op0,
- unsigned Op1);
/// Build and insert \p Res = G_GEP \p Op0, \p Op1
///
@@ -338,34 +299,6 @@ public:
MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0,
unsigned Op1, unsigned CarryIn);
- /// Build and insert \p Res = G_AND \p Op0, \p Op1
- ///
- /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p
- /// Op1.
- ///
- /// \pre setBasicBlock or setMI must have been called.
- /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
- /// with the same (scalar or vector) type).
- ///
- /// \return a MachineInstrBuilder for the newly created instruction.
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildAnd(DstTy &&Dst, UseArgsTy &&... UseArgs) {
- return buildAnd(getDestFromArg(Dst), getRegFromArg(UseArgs)...);
- }
- MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0,
- unsigned Op1);
-
- /// Build and insert \p Res = G_OR \p Op0, \p Op1
- ///
- /// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p
- /// Op1.
- ///
- /// \pre setBasicBlock or setMI must have been called.
- /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
- /// with the same (scalar or vector) type).
- ///
- /// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildOr(unsigned Res, unsigned Op0, unsigned Op1);
/// Build and insert \p Res = G_ANYEXT \p Op0
///
@@ -399,6 +332,10 @@ public:
/// \pre \p Op must be smaller than \p Res
///
/// \return The newly created instruction.
+ template <typename DstType, typename ArgType>
+ MachineInstrBuilder buildSExt(DstType &&Res, ArgType &&Arg) {
+ return buildSExt(getDestFromArg(Res), getRegFromArg(Arg));
+ }
MachineInstrBuilder buildSExt(unsigned Res, unsigned Op);
/// Build and insert \p Res = G_ZEXT \p Op
@@ -413,6 +350,10 @@ public:
/// \pre \p Op must be smaller than \p Res
///
/// \return The newly created instruction.
+ template <typename DstType, typename ArgType>
+ MachineInstrBuilder buildZExt(DstType &&Res, ArgType &&Arg) {
+ return buildZExt(getDestFromArg(Res), getRegFromArg(Arg));
+ }
MachineInstrBuilder buildZExt(unsigned Res, unsigned Op);
/// Build and insert \p Res = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or
@@ -423,6 +364,10 @@ public:
/// \pre \p Op must be a generic virtual register with scalar or vector type.
///
/// \return The newly created instruction.
+ template <typename DstTy, typename UseArgTy>
+ MachineInstrBuilder buildSExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) {
+ return buildSExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use));
+ }
MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op);
/// Build and insert \p Res = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or
@@ -433,6 +378,10 @@ public:
/// \pre \p Op must be a generic virtual register with scalar or vector type.
///
/// \return The newly created instruction.
+ template <typename DstTy, typename UseArgTy>
+ MachineInstrBuilder buildZExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) {
+ return buildZExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use));
+ }
MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op);
// Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or
@@ -462,6 +411,10 @@ public:
unsigned Op);
/// Build and insert an appropriate cast between two registers of equal size.
+ template <typename DstType, typename ArgType>
+ MachineInstrBuilder buildCast(DstType &&Res, ArgType &&Arg) {
+ return buildCast(getDestFromArg(Res), getRegFromArg(Arg));
+ }
MachineInstrBuilder buildCast(unsigned Dst, unsigned Src);
/// Build and insert G_BR \p Dest
@@ -471,7 +424,7 @@ public:
/// \pre setBasicBlock or setMI must have been called.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildBr(MachineBasicBlock &BB);
+ MachineInstrBuilder buildBr(MachineBasicBlock &Dest);
/// Build and insert G_BRCOND \p Tst, \p Dest
///
@@ -485,7 +438,7 @@ public:
/// depend on bit 0 (for now).
///
/// \return The newly created instruction.
- MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB);
+ MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &Dest);
/// Build and insert G_BRINDIRECT \p Tgt
///
@@ -532,8 +485,18 @@ public:
/// \pre \p Res must be a generic virtual register with scalar type.
///
/// \return The newly created instruction.
+ template <typename DstType>
+ MachineInstrBuilder buildFConstant(DstType &&Res, const ConstantFP &Val) {
+ return buildFConstant(getDestFromArg(Res), Val);
+ }
MachineInstrBuilder buildFConstant(unsigned Res, const ConstantFP &Val);
+ template <typename DstType>
+ MachineInstrBuilder buildFConstant(DstType &&Res, double Val) {
+ return buildFConstant(getDestFromArg(Res), Val);
+ }
+ MachineInstrBuilder buildFConstant(unsigned Res, double Val);
+
/// Build and insert \p Res = COPY Op
///
/// Register-to-register COPY sets \p Res to \p Op.
@@ -559,6 +522,18 @@ public:
MachineInstrBuilder buildLoad(unsigned Res, unsigned Addr,
MachineMemOperand &MMO);
+ /// Build and insert `Res = <opcode> Addr, MMO`.
+ ///
+ /// Loads the value stored at \p Addr. Puts the result in \p Res.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildLoadInstr(unsigned Opcode, unsigned Res,
+ unsigned Addr, MachineMemOperand &MMO);
+
/// Build and insert `G_STORE Val, Addr, MMO`.
///
/// Stores the value \p Val to \p Addr.
@@ -580,7 +555,10 @@ public:
MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index);
/// Build and insert \p Res = IMPLICIT_DEF.
- MachineInstrBuilder buildUndef(unsigned Dst);
+ template <typename DstType> MachineInstrBuilder buildUndef(DstType &&Res) {
+ return buildUndef(getDestFromArg(Res));
+ }
+ MachineInstrBuilder buildUndef(unsigned Res);
/// Build and insert instructions to put \p Ops together at the specified p
/// Indices to form a larger register.
@@ -649,6 +627,10 @@ public:
/// \pre \p Res must be smaller than \p Op
///
/// \return The newly created instruction.
+ template <typename DstType, typename SrcType>
+ MachineInstrBuilder buildFPTrunc(DstType &&Res, SrcType &&Src) {
+ return buildFPTrunc(getDestFromArg(Res), getRegFromArg(Src));
+ }
MachineInstrBuilder buildFPTrunc(unsigned Res, unsigned Op);
/// Build and insert \p Res = G_TRUNC \p Op
@@ -735,7 +717,28 @@ public:
MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val,
unsigned Idx);
- /// Build and insert `OldValRes = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal,
+ /// Build and insert `OldValRes<def>, SuccessRes<def> =
+ /// G_ATOMIC_CMPXCHG_WITH_SUCCESS Addr, CmpVal, NewVal, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with \p NewVal if it is currently
+ /// \p CmpVal otherwise leaves it unchanged. Puts the original value from \p
+ /// Addr in \p Res, along with an s1 indicating whether it was replaced.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register of scalar type.
+ /// \pre \p SuccessRes must be a generic virtual register of scalar type. It
+ /// will be assigned 0 on failure and 1 on success.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, \p CmpVal, and \p NewVal must be generic virtual
+ /// registers of the same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder
+ buildAtomicCmpXchgWithSuccess(unsigned OldValRes, unsigned SuccessRes,
+ unsigned Addr, unsigned CmpVal, unsigned NewVal,
+ MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal,
/// MMO`.
///
/// Atomically replace the value at \p Addr with \p NewVal if it is currently
@@ -752,6 +755,328 @@ public:
MachineInstrBuilder buildAtomicCmpXchg(unsigned OldValRes, unsigned Addr,
unsigned CmpVal, unsigned NewVal,
MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_<Opcode> Addr, Val, MMO`.
+ ///
+ /// Atomically read-modify-update the value at \p Addr with \p Val. Puts the
+ /// original value from \p Addr in \p OldValRes. The modification is
+ /// determined by the opcode.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMW(unsigned Opcode, unsigned OldValRes,
+ unsigned Addr, unsigned Val,
+ MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_XCHG Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with \p Val. Puts the original
+ /// value from \p Addr in \p OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWXchg(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_ADD Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the addition of \p Val and
+ /// the original value. Puts the original value from \p Addr in \p OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWAdd(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_SUB Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the subtraction of \p Val and
+ /// the original value. Puts the original value from \p Addr in \p OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWSub(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_AND Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the bitwise and of \p Val and
+ /// the original value. Puts the original value from \p Addr in \p OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWAnd(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_NAND Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the bitwise nand of \p Val
+ /// and the original value. Puts the original value from \p Addr in \p
+ /// OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWNand(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_OR Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the bitwise or of \p Val and
+ /// the original value. Puts the original value from \p Addr in \p OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWOr(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_XOR Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the bitwise xor of \p Val and
+ /// the original value. Puts the original value from \p Addr in \p OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWXor(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_MAX Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the signed maximum of \p
+ /// Val and the original value. Puts the original value from \p Addr in \p
+ /// OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWMax(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_MIN Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the signed minimum of \p
+ /// Val and the original value. Puts the original value from \p Addr in \p
+ /// OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWMin(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_UMAX Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the unsigned maximum of \p
+ /// Val and the original value. Puts the original value from \p Addr in \p
+ /// OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWUmax(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+
+ /// Build and insert `OldValRes<def> = G_ATOMICRMW_UMIN Addr, Val, MMO`.
+ ///
+ /// Atomically replace the value at \p Addr with the unsigned minimum of \p
+ /// Val and the original value. Puts the original value from \p Addr in \p
+ /// OldValRes.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p OldValRes must be a generic virtual register.
+ /// \pre \p Addr must be a generic virtual register with pointer type.
+ /// \pre \p OldValRes, and \p Val must be generic virtual registers of the
+ /// same type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAtomicRMWUmin(unsigned OldValRes, unsigned Addr,
+ unsigned Val, MachineMemOperand &MMO);
+};
+
+/// A CRTP class that contains methods for building instructions that can
+/// be constant folded. MachineIRBuilders that want to inherit from this will
+/// need to implement buildBinaryOp (for constant folding binary ops).
+/// Alternatively, they can implement buildInstr(Opc, Dst, Uses...) to perform
+/// additional folding for Opc.
+template <typename Base>
+class FoldableInstructionsBuilder : public MachineIRBuilderBase {
+ Base &base() { return static_cast<Base &>(*this); }
+
+public:
+ using MachineIRBuilderBase::MachineIRBuilderBase;
+ /// Build and insert \p Res = G_ADD \p Op0, \p Op1
+ ///
+ /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+ /// truncated to their width.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+ /// with the same (scalar or vector) type).
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+
+ MachineInstrBuilder buildAdd(unsigned Dst, unsigned Src0, unsigned Src1) {
+ return base().buildBinaryOp(TargetOpcode::G_ADD, Dst, Src0, Src1);
+ }
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+ unsigned Res = base().getDestFromArg(Ty);
+ return base().buildAdd(Res, (base().getRegFromArg(UseArgs))...);
+ }
+
+ /// Build and insert \p Res = G_SUB \p Op0, \p Op1
+ ///
+ /// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+ /// truncated to their width.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+ /// with the same (scalar or vector) type).
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+
+ MachineInstrBuilder buildSub(unsigned Dst, unsigned Src0, unsigned Src1) {
+ return base().buildBinaryOp(TargetOpcode::G_SUB, Dst, Src0, Src1);
+ }
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildSub(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+ unsigned Res = base().getDestFromArg(Ty);
+ return base().buildSub(Res, (base().getRegFromArg(UseArgs))...);
+ }
+
+ /// Build and insert \p Res = G_MUL \p Op0, \p Op1
+ ///
+ /// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+ /// truncated to their width.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+ /// with the same (scalar or vector) type).
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildMul(unsigned Dst, unsigned Src0, unsigned Src1) {
+ return base().buildBinaryOp(TargetOpcode::G_MUL, Dst, Src0, Src1);
+ }
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildMul(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+ unsigned Res = base().getDestFromArg(Ty);
+ return base().buildMul(Res, (base().getRegFromArg(UseArgs))...);
+ }
+
+ /// Build and insert \p Res = G_AND \p Op0, \p Op1
+ ///
+ /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p
+ /// Op1.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+ /// with the same (scalar or vector) type).
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+
+ MachineInstrBuilder buildAnd(unsigned Dst, unsigned Src0, unsigned Src1) {
+ return base().buildBinaryOp(TargetOpcode::G_AND, Dst, Src0, Src1);
+ }
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildAnd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+ unsigned Res = base().getDestFromArg(Ty);
+ return base().buildAnd(Res, (base().getRegFromArg(UseArgs))...);
+ }
+
+ /// Build and insert \p Res = G_OR \p Op0, \p Op1
+ ///
+ /// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p
+ /// Op1.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+ /// with the same (scalar or vector) type).
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildOr(unsigned Dst, unsigned Src0, unsigned Src1) {
+ return base().buildBinaryOp(TargetOpcode::G_OR, Dst, Src0, Src1);
+ }
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildOr(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+ unsigned Res = base().getDestFromArg(Ty);
+ return base().buildOr(Res, (base().getRegFromArg(UseArgs))...);
+ }
+};
+
+class MachineIRBuilder : public FoldableInstructionsBuilder<MachineIRBuilder> {
+public:
+ using FoldableInstructionsBuilder<
+ MachineIRBuilder>::FoldableInstructionsBuilder;
+ MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst,
+ unsigned Src0, unsigned Src1) {
+ validateBinaryOp(Dst, Src0, Src1);
+ return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1);
+ }
+ using FoldableInstructionsBuilder<MachineIRBuilder>::buildInstr;
+ /// DAG like Generic method for building arbitrary instructions as above.
+ /// \Opc opcode for the instruction.
+ /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst
+ /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder)
+ /// Uses of type MachineInstrBuilder will perform
+ /// getOperand(0).getReg() to convert to register.
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
+ UseArgsTy &&... Args) {
+ auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
+ addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
+ return MIB;
+ }
};
} // End namespace llvm.
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
index 676955c33fe9..c53ae416e60b 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
@@ -22,7 +22,7 @@
/// of an instruction should live. It asks the target which banks may be
/// used for each operand of the instruction and what is the cost. Then,
/// it chooses the solution which minimize the cost of the instruction plus
-/// the cost of any move that may be needed to to the values into the right
+/// the cost of any move that may be needed to the values into the right
/// register bank.
/// In other words, the cost for an instruction on a register bank RegBank
/// is: Cost of I on RegBank plus the sum of the cost for bringing the
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h
index 5d758423f4e7..d5612e17393c 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h
@@ -42,7 +42,7 @@ private:
public:
RegisterBank(unsigned ID, const char *Name, unsigned Size,
- const uint32_t *ContainedRegClasses, unsigned NumRegClasses);
+ const uint32_t *CoveredClasses, unsigned NumRegClasses);
/// Get the identifier of this register bank.
unsigned getID() const { return ID; }
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
index 02868b220984..82fd7eddb68a 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
@@ -622,6 +622,8 @@ public:
/// \pre \p Reg is a virtual register that either has a bank or a class.
/// \returns The constrained register class, or nullptr if there is none.
/// \note This is a generic variant of MachineRegisterInfo::constrainRegClass
+ /// \note Use MachineRegisterInfo::constrainRegAttrs instead for any non-isel
+ /// purpose, including non-select passes of GlobalISel
static const TargetRegisterClass *
constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC,
MachineRegisterInfo &MRI);
diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
index 5864c15cc8eb..51e3a2732972 100644
--- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -19,8 +19,10 @@
namespace llvm {
+class AnalysisUsage;
class MachineFunction;
class MachineInstr;
+class MachineOperand;
class MachineOptimizationRemarkEmitter;
class MachineOptimizationRemarkMissed;
class MachineRegisterInfo;
@@ -32,6 +34,7 @@ class TargetRegisterInfo;
class TargetRegisterClass;
class Twine;
class ConstantFP;
+class APFloat;
/// Try to constrain Reg to the specified register class. If this fails,
/// create a new virtual register in the correct class and insert a COPY before
@@ -57,8 +60,21 @@ unsigned constrainOperandRegClass(const MachineFunction &MF,
const TargetInstrInfo &TII,
const RegisterBankInfo &RBI,
MachineInstr &InsertPt, const MCInstrDesc &II,
- unsigned Reg, unsigned OpIdx);
+ const MachineOperand &RegMO, unsigned OpIdx);
+/// Mutate the newly-selected instruction \p I to constrain its (possibly
+/// generic) virtual register operands to the instruction's register class.
+/// This could involve inserting COPYs before (for uses) or after (for defs).
+/// This requires the number of operands to match the instruction description.
+/// \returns whether operand regclass constraining succeeded.
+///
+// FIXME: Not all instructions have the same number of operands. We should
+// probably expose a constrain helper per operand and let the target selector
+// constrain individual registers, like fast-isel.
+bool constrainSelectedInstRegOperands(MachineInstr &I,
+ const TargetInstrInfo &TII,
+ const TargetRegisterInfo &TRI,
+ const RegisterBankInfo &RBI);
/// Check whether an instruction \p MI is dead: it only defines dead virtual
/// registers, and doesn't have other side effects.
bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI);
@@ -85,5 +101,12 @@ const ConstantFP* getConstantFPVRegVal(unsigned VReg,
MachineInstr *getOpcodeDef(unsigned Opcode, unsigned Reg,
const MachineRegisterInfo &MRI);
+/// Returns an APFloat from Val converted to the appropriate size.
+APFloat getAPFloatFromSize(double Val, unsigned Size);
+
+/// Modify analysis usage so it preserves passes required for the SelectionDAG
+/// fallback.
+void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU);
+
} // End namespace llvm.
#endif
diff --git a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h
index d256849be9af..80bd796d5374 100644
--- a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -377,6 +377,8 @@ namespace ISD {
/// When the 1st operand is a vector, the shift amount must be in the same
/// type. (TLI.getShiftAmountTy() will return the same type when the input
/// type is a vector.)
+ /// For rotates, the shift amount is treated as an unsigned amount modulo
+ /// the element size of the first operand.
SHL, SRA, SRL, ROTL, ROTR,
/// Byte Swap and Counting operators.
@@ -412,19 +414,11 @@ namespace ISD {
/// then the result type must also be a vector type.
SETCC,
- /// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, and
- /// op #2 is a *carry value*. This operator checks the result of
- /// "LHS - RHS - Carry", and can be used to compare two wide integers:
- /// (setcce lhshi rhshi (subc lhslo rhslo) cc). Only valid for integers.
- /// FIXME: This node is deprecated in favor of SETCCCARRY.
- /// It is kept around for now to provide a smooth transition path
- /// toward the use of SETCCCARRY and will eventually be removed.
- SETCCE,
-
/// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but
/// op #2 is a boolean indicating if there is an incoming carry. This
/// operator checks the result of "LHS - RHS - Carry", and can be used to
- /// compare two wide integers: (setcce lhshi rhshi (subc lhslo rhslo) cc).
+ /// compare two wide integers:
+ /// (setcccarry lhshi rhshi (subcarry lhslo rhslo) cc).
/// Only valid for integers.
SETCCCARRY,
@@ -495,7 +489,8 @@ namespace ISD {
ZERO_EXTEND_VECTOR_INREG,
/// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned
- /// integer.
+ /// integer. These have the same semantics as fptosi and fptoui in IR. If
+ /// the FP value cannot fit in the integer type, the results are undefined.
FP_TO_SINT,
FP_TO_UINT,
@@ -779,6 +774,7 @@ namespace ISD {
ATOMIC_LOAD_ADD,
ATOMIC_LOAD_SUB,
ATOMIC_LOAD_AND,
+ ATOMIC_LOAD_CLR,
ATOMIC_LOAD_OR,
ATOMIC_LOAD_XOR,
ATOMIC_LOAD_NAND,
diff --git a/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h b/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h
index 988e6d6cb3a3..9b8d83ce77ca 100644
--- a/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h
+++ b/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h
@@ -17,6 +17,7 @@
#define LLVM_CODEGEN_LATENCYPRIORITYQUEUE_H
#include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/Config/llvm-config.h"
namespace llvm {
class LatencyPriorityQueue;
@@ -26,7 +27,7 @@ namespace llvm {
LatencyPriorityQueue *PQ;
explicit latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {}
- bool operator()(const SUnit* left, const SUnit* right) const;
+ bool operator()(const SUnit* LHS, const SUnit* RHS) const;
};
class LatencyPriorityQueue : public SchedulingPriorityQueue {
@@ -83,11 +84,15 @@ namespace llvm {
void remove(SUnit *SU) override;
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump(ScheduleDAG *DAG) const override;
+#endif
+
// scheduledNode - As nodes are scheduled, we look to see if there are any
// successor nodes that have a single unscheduled predecessor. If so, that
// single predecessor has a higher priority, since scheduling it will make
// the node available.
- void scheduledNode(SUnit *Node) override;
+ void scheduledNode(SUnit *SU) override;
private:
void AdjustPriorityOfUnscheduledPreds(SUnit *SU);
diff --git a/contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h b/contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h
index 848ee1dc0dc6..221f16a03f16 100644
--- a/contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h
@@ -23,7 +23,7 @@
#include "llvm/CodeGen/MachineLoopInfo.h"
namespace llvm {
-/// \brief This is an alternative analysis pass to MachineBlockFrequencyInfo.
+/// This is an alternative analysis pass to MachineBlockFrequencyInfo.
/// The difference is that with this pass, the block frequencies are not
/// computed when the analysis pass is executed but rather when the BFI result
/// is explicitly requested by the analysis client.
@@ -49,7 +49,7 @@ private:
/// The function.
MachineFunction *MF = nullptr;
- /// \brief Calculate MBFI and all other analyses that's not available and
+ /// Calculate MBFI and all other analyses that's not available and
/// required by BFI.
MachineBlockFrequencyInfo &calculateIfNotAvailable() const;
@@ -58,10 +58,10 @@ public:
LazyMachineBlockFrequencyInfoPass();
- /// \brief Compute and return the block frequencies.
+ /// Compute and return the block frequencies.
MachineBlockFrequencyInfo &getBFI() { return calculateIfNotAvailable(); }
- /// \brief Compute and return the block frequencies.
+ /// Compute and return the block frequencies.
const MachineBlockFrequencyInfo &getBFI() const {
return calculateIfNotAvailable();
}
diff --git a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h
index f4fa872c7f5b..cdf9ad2588cf 100644
--- a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h
+++ b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h
@@ -326,7 +326,7 @@ namespace llvm {
/// createDeadDef - Make sure the range has a value defined at Def.
/// If one already exists, return it. Otherwise allocate a new value and
/// add liveness for a dead def.
- VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator);
+ VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNIAlloc);
/// Create a def of value @p VNI. Return @p VNI. If there already exists
/// a definition at VNI->def, the value defined there must be @p VNI.
@@ -454,7 +454,7 @@ namespace llvm {
/// overlapsFrom - Return true if the intersection of the two live ranges
/// is not empty. The specified iterator is a hint that we can begin
/// scanning the Other range starting at I.
- bool overlapsFrom(const LiveRange &Other, const_iterator I) const;
+ bool overlapsFrom(const LiveRange &Other, const_iterator StartPos) const;
/// Returns true if all segments of the @p Other live range are completely
/// covered by this live range.
@@ -482,7 +482,7 @@ namespace llvm {
/// @p Use, return {nullptr, false}. If there is an "undef" before @p Use,
/// return {nullptr, true}.
std::pair<VNInfo*,bool> extendInBlock(ArrayRef<SlotIndex> Undefs,
- SlotIndex StartIdx, SlotIndex Use);
+ SlotIndex StartIdx, SlotIndex Kill);
/// Simplified version of the above "extendInBlock", which assumes that
/// no register lanes are undefined by <def,read-undef> operands.
@@ -609,7 +609,7 @@ namespace llvm {
void print(raw_ostream &OS) const;
void dump() const;
- /// \brief Walk the range and assert if any invariants fail to hold.
+ /// Walk the range and assert if any invariants fail to hold.
///
/// Note that this is a no-op when asserts are disabled.
#ifdef NDEBUG
@@ -791,7 +791,7 @@ namespace llvm {
/// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod
/// function will be applied to the L0010 and L0008 subranges.
void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask,
- std::function<void(LiveInterval::SubRange&)> Mod);
+ std::function<void(LiveInterval::SubRange&)> Apply);
bool operator<(const LiveInterval& other) const {
const SlotIndex &thisIndex = beginIndex();
@@ -802,7 +802,7 @@ namespace llvm {
void print(raw_ostream &OS) const;
void dump() const;
- /// \brief Walks the interval and assert if any invariants fail to hold.
+ /// Walks the interval and assert if any invariants fail to hold.
///
/// Note that this is a no-op when asserts are disabled.
#ifdef NDEBUG
diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h
index b922e543c856..9e2799bd4414 100644
--- a/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h
+++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h
@@ -154,7 +154,7 @@ public:
unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max());
// Was this virtual register visited during collectInterferingVRegs?
- bool isSeenInterference(LiveInterval *VReg) const;
+ bool isSeenInterference(LiveInterval *VirtReg) const;
// Did collectInterferingVRegs collect all interferences?
bool seenAllInterferences() const { return SeenAllInterferences; }
diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h
index 1150f3c1c47b..291a07a712cb 100644
--- a/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h
+++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h
@@ -105,7 +105,7 @@ class VirtRegMap;
/// Calculate the spill weight to assign to a single instruction.
static float getSpillWeight(bool isDef, bool isUse,
const MachineBlockFrequencyInfo *MBFI,
- const MachineInstr &Instr);
+ const MachineInstr &MI);
/// Calculate the spill weight to assign to a single instruction.
static float getSpillWeight(bool isDef, bool isUse,
@@ -462,6 +462,10 @@ class VirtRegMap;
void computeRegUnitRange(LiveRange&, unsigned Unit);
void computeVirtRegInterval(LiveInterval&);
+ using ShrinkToUsesWorkList = SmallVector<std::pair<SlotIndex, VNInfo*>, 16>;
+ void extendSegmentsToUses(LiveRange &Segments,
+ ShrinkToUsesWorkList &WorkList, unsigned Reg,
+ LaneBitmask LaneMask);
/// Helper function for repairIntervalsInRange(), walks backwards and
/// creates/modifies live segments in \p LR to match the operands found.
diff --git a/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h b/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h
index f9aab0d09e1f..301a45066b4c 100644
--- a/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h
+++ b/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h
@@ -44,7 +44,7 @@ class MachineOperand;
class MachineRegisterInfo;
class raw_ostream;
-/// \brief A set of physical registers with utility functions to track liveness
+/// A set of physical registers with utility functions to track liveness
/// when walking backward/forward through a basic block.
class LivePhysRegs {
const TargetRegisterInfo *TRI = nullptr;
@@ -84,7 +84,7 @@ public:
LiveRegs.insert(*SubRegs);
}
- /// \brief Removes a physical register, all its sub-registers, and all its
+ /// Removes a physical register, all its sub-registers, and all its
/// super-registers from the set.
void removeReg(unsigned Reg) {
assert(TRI && "LivePhysRegs is not initialized.");
@@ -98,7 +98,7 @@ public:
SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers =
nullptr);
- /// \brief Returns true if register \p Reg is contained in the set. This also
+ /// Returns true if register \p Reg is contained in the set. This also
/// works if only the super register of \p Reg has been defined, because
/// addReg() always adds all sub-registers to the set as well.
/// Note: Returns false if just some sub registers are live, use available()
@@ -155,7 +155,7 @@ public:
void dump() const;
private:
- /// \brief Adds live-in registers from basic block \p MBB, taking associated
+ /// Adds live-in registers from basic block \p MBB, taking associated
/// lane masks into consideration.
void addBlockLiveIns(const MachineBasicBlock &MBB);
@@ -169,7 +169,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const LivePhysRegs& LR) {
return OS;
}
-/// \brief Computes registers live-in to \p MBB assuming all of its successors
+/// Computes registers live-in to \p MBB assuming all of its successors
/// live-in lists are up-to-date. Puts the result into the given LivePhysReg
/// instance \p LiveRegs.
void computeLiveIns(LivePhysRegs &LiveRegs, const MachineBasicBlock &MBB);
@@ -185,6 +185,13 @@ void addLiveIns(MachineBasicBlock &MBB, const LivePhysRegs &LiveRegs);
void computeAndAddLiveIns(LivePhysRegs &LiveRegs,
MachineBasicBlock &MBB);
+/// Convenience function for recomputing live-in's for \p MBB.
+static inline void recomputeLiveIns(MachineBasicBlock &MBB) {
+ LivePhysRegs LPR;
+ MBB.clearLiveIns();
+ computeAndAddLiveIns(LPR, MBB);
+}
+
} // end namespace llvm
#endif // LLVM_CODEGEN_LIVEPHYSREGS_H
diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h b/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h
index 84bccde0caa2..53830297c525 100644
--- a/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h
+++ b/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h
@@ -117,10 +117,13 @@ private:
/// registers are created.
void MRI_NoteNewVirtualRegister(unsigned VReg) override;
- /// \brief Check if MachineOperand \p MO is a last use/kill either in the
+ /// Check if MachineOperand \p MO is a last use/kill either in the
/// main live range of \p LI or in one of the matching subregister ranges.
bool useIsKill(const LiveInterval &LI, const MachineOperand &MO) const;
+ /// Create a new empty interval based on OldReg.
+ LiveInterval &createEmptyIntervalFrom(unsigned OldReg, bool createSubRanges);
+
public:
/// Create a LiveRangeEdit for breaking down parent into smaller pieces.
/// @param parent The register being spilled or split.
@@ -174,16 +177,13 @@ public:
return makeArrayRef(NewRegs).slice(FirstNew);
}
- /// createEmptyIntervalFrom - Create a new empty interval based on OldReg.
- LiveInterval &createEmptyIntervalFrom(unsigned OldReg);
-
/// createFrom - Create a new virtual register based on OldReg.
unsigned createFrom(unsigned OldReg);
/// create - Create a new register with the same class and original slot as
/// parent.
LiveInterval &createEmptyInterval() {
- return createEmptyIntervalFrom(getReg());
+ return createEmptyIntervalFrom(getReg(), true);
}
unsigned create() { return createFrom(getReg()); }
@@ -233,12 +233,6 @@ public:
return Rematted.count(ParentVNI);
}
- void markDeadRemat(MachineInstr *inst) {
- // DeadRemats is an optional field.
- if (DeadRemats)
- DeadRemats->insert(inst);
- }
-
/// eraseVirtReg - Notify the delegate that Reg is no longer in use, and try
/// to erase it from LIS.
void eraseVirtReg(unsigned Reg);
diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h b/contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h
index fa6827f6b1f9..f62a55c73085 100644
--- a/contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h
+++ b/contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h
@@ -107,6 +107,13 @@ public:
/// with the highest enum value is returned.
InterferenceKind checkInterference(LiveInterval &VirtReg, unsigned PhysReg);
+ /// Check for interference in the segment [Start, End) that may prevent
+ /// assignment to PhysReg. If this function returns true, there is
+ /// interference in the segment [Start, End) of some other interval already
+ /// assigned to PhysReg. If this function returns false, PhysReg is free at
+ /// the segment [Start, End).
+ bool checkInterference(SlotIndex Start, SlotIndex End, unsigned PhysReg);
+
/// Assign VirtReg to PhysReg.
/// This will mark VirtReg's live range as occupied in the LiveRegMatrix and
/// update VirtRegMap. The live range is expected to be available in PhysReg.
diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h b/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h
index dc4956da9637..249545906e01 100644
--- a/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h
+++ b/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h
@@ -16,6 +16,7 @@
#define LLVM_CODEGEN_LIVEREGUNITS_H
#include "llvm/ADT/BitVector.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -40,6 +41,36 @@ public:
init(TRI);
}
+ /// For a machine instruction \p MI, adds all register units used in
+ /// \p UsedRegUnits and defined or clobbered in \p ModifiedRegUnits. This is
+ /// useful when walking over a range of instructions to track registers
+ /// used or defined seperately.
+ static void accumulateUsedDefed(const MachineInstr &MI,
+ LiveRegUnits &ModifiedRegUnits,
+ LiveRegUnits &UsedRegUnits,
+ const TargetRegisterInfo *TRI) {
+ for (ConstMIBundleOperands O(MI); O.isValid(); ++O) {
+ if (O->isRegMask())
+ ModifiedRegUnits.addRegsInMask(O->getRegMask());
+ if (!O->isReg())
+ continue;
+ unsigned Reg = O->getReg();
+ if (!TargetRegisterInfo::isPhysicalRegister(Reg))
+ continue;
+ if (O->isDef()) {
+ // Some architectures (e.g. AArch64 XZR/WZR) have registers that are
+ // constant and may be used as destinations to indicate the generated
+ // value is discarded. No need to track such case as a def.
+ if (!TRI->isConstantPhysReg(Reg))
+ ModifiedRegUnits.addReg(Reg);
+ } else {
+ assert(O->isUse() && "Reg operand not a def and not a use");
+ UsedRegUnits.addReg(Reg);
+ }
+ }
+ return;
+ }
+
/// Initialize and clear the set.
void init(const TargetRegisterInfo &TRI) {
this->TRI = &TRI;
@@ -59,7 +90,7 @@ public:
Units.set(*Unit);
}
- /// \brief Adds register units covered by physical register \p Reg that are
+ /// Adds register units covered by physical register \p Reg that are
/// part of the lanemask \p Mask.
void addRegMasked(unsigned Reg, LaneBitmask Mask) {
for (MCRegUnitMaskIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) {
diff --git a/contrib/llvm/include/llvm/CodeGen/LoopTraversal.h b/contrib/llvm/include/llvm/CodeGen/LoopTraversal.h
new file mode 100644
index 000000000000..750da0143c0d
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/LoopTraversal.h
@@ -0,0 +1,116 @@
+//==------ llvm/CodeGen/LoopTraversal.h - Loop Traversal -*- C++ -*---------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file Loop Traversal logic.
+///
+/// This class provides the basic blocks traversal order used by passes like
+/// ReachingDefAnalysis and ExecutionDomainFix.
+/// It identifies basic blocks that are part of loops and should to be visited
+/// twice and returns efficient traversal order for all the blocks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_LOOPTRAVERSAL_H
+#define LLVM_CODEGEN_LOOPTRAVERSAL_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+class MachineBasicBlock;
+class MachineFunction;
+
+/// This class provides the basic blocks traversal order used by passes like
+/// ReachingDefAnalysis and ExecutionDomainFix.
+/// It identifies basic blocks that are part of loops and should to be visited
+/// twice and returns efficient traversal order for all the blocks.
+///
+/// We want to visit every instruction in every basic block in order to update
+/// it's execution domain or collect clearance information. However, for the
+/// clearance calculation, we need to know clearances from all predecessors
+/// (including any backedges), therfore we need to visit some blocks twice.
+/// As an example, consider the following loop.
+///
+///
+/// PH -> A -> B (xmm<Undef> -> xmm<Def>) -> C -> D -> EXIT
+/// ^ |
+/// +----------------------------------+
+///
+/// The iteration order this pass will return is as follows:
+/// Optimized: PH A B C A' B' C' D
+///
+/// The basic block order is constructed as follows:
+/// Once we finish processing some block, we update the counters in MBBInfos
+/// and re-process any successors that are now 'done'.
+/// We call a block that is ready for its final round of processing `done`
+/// (isBlockDone), e.g. when all predecessor information is known.
+///
+/// Note that a naive traversal order would be to do two complete passes over
+/// all basic blocks/instructions, the first for recording clearances, the
+/// second for updating clearance based on backedges.
+/// However, for functions without backedges, or functions with a lot of
+/// straight-line code, and a small loop, that would be a lot of unnecessary
+/// work (since only the BBs that are part of the loop require two passes).
+///
+/// E.g., the naive iteration order for the above exmple is as follows:
+/// Naive: PH A B C D A' B' C' D'
+///
+/// In the optimized approach we avoid processing D twice, because we
+/// can entirely process the predecessors before getting to D.
+class LoopTraversal {
+private:
+ struct MBBInfo {
+ /// Whether we have gotten to this block in primary processing yet.
+ bool PrimaryCompleted = false;
+
+ /// The number of predecessors for which primary processing has completed
+ unsigned IncomingProcessed = 0;
+
+ /// The value of `IncomingProcessed` at the start of primary processing
+ unsigned PrimaryIncoming = 0;
+
+ /// The number of predecessors for which all processing steps are done.
+ unsigned IncomingCompleted = 0;
+
+ MBBInfo() = default;
+ };
+ using MBBInfoMap = SmallVector<MBBInfo, 4>;
+ /// Helps keep track if we proccessed this block and all its predecessors.
+ MBBInfoMap MBBInfos;
+
+public:
+ struct TraversedMBBInfo {
+ /// The basic block.
+ MachineBasicBlock *MBB = nullptr;
+
+ /// True if this is the first time we process the basic block.
+ bool PrimaryPass = true;
+
+ /// True if the block that is ready for its final round of processing.
+ bool IsDone = true;
+
+ TraversedMBBInfo(MachineBasicBlock *BB = nullptr, bool Primary = true,
+ bool Done = true)
+ : MBB(BB), PrimaryPass(Primary), IsDone(Done) {}
+ };
+ LoopTraversal() {}
+
+ /// Identifies basic blocks that are part of loops and should to be
+ /// visited twice and returns efficient traversal order for all the blocks.
+ typedef SmallVector<TraversedMBBInfo, 4> TraversalOrder;
+ TraversalOrder traverse(MachineFunction &MF);
+
+private:
+ /// Returens true if the block is ready for its final round of processing.
+ bool isBlockDone(MachineBasicBlock *MBB);
+};
+
+} // namespace llvm
+
+#endif // LLVM_CODEGEN_LOOPTRAVERSAL_H
diff --git a/contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h b/contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h
index b631a8c0122a..e199a1f69ad7 100644
--- a/contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h
+++ b/contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h
@@ -45,7 +45,7 @@ public:
/// \returns nullptr if a parsing error occurred.
std::unique_ptr<Module> parseIRModule();
- /// \brief Parses MachineFunctions in the MIR file and add them to the given
+ /// Parses MachineFunctions in the MIR file and add them to the given
/// MachineModuleInfo \p MMI.
///
/// \returns true if an error occurred.
diff --git a/contrib/llvm/include/llvm/CodeGen/MIRPrinter.h b/contrib/llvm/include/llvm/CodeGen/MIRPrinter.h
index c73adc3f2b11..078c4b2f6072 100644
--- a/contrib/llvm/include/llvm/CodeGen/MIRPrinter.h
+++ b/contrib/llvm/include/llvm/CodeGen/MIRPrinter.h
@@ -38,7 +38,7 @@ void printMIR(raw_ostream &OS, const MachineFunction &MF);
/// this funciton and the parser will use this function to construct a list if
/// it is missing.
void guessSuccessors(const MachineBasicBlock &MBB,
- SmallVectorImpl<MachineBasicBlock*> &Successors,
+ SmallVectorImpl<MachineBasicBlock*> &Result,
bool &IsFallthrough);
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index ba40e522e261..7f46406c4789 100644
--- a/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -258,11 +258,11 @@ template <> struct MappingTraits<MachineStackObject> {
YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
true);
YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional<int64_t>());
- YamlIO.mapOptional("di-variable", Object.DebugVar,
+ YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
StringValue()); // Don't print it out when it's empty.
- YamlIO.mapOptional("di-expression", Object.DebugExpr,
+ YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
StringValue()); // Don't print it out when it's empty.
- YamlIO.mapOptional("di-location", Object.DebugLoc,
+ YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
StringValue()); // Don't print it out when it's empty.
}
@@ -283,6 +283,9 @@ struct FixedMachineStackObject {
bool IsAliased = false;
StringValue CalleeSavedRegister;
bool CalleeSavedRestored = true;
+ StringValue DebugVar;
+ StringValue DebugExpr;
+ StringValue DebugLoc;
bool operator==(const FixedMachineStackObject &Other) const {
return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
@@ -290,7 +293,9 @@ struct FixedMachineStackObject {
StackID == Other.StackID &&
IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
CalleeSavedRegister == Other.CalleeSavedRegister &&
- CalleeSavedRestored == Other.CalleeSavedRestored;
+ CalleeSavedRestored == Other.CalleeSavedRestored &&
+ DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
+ && DebugLoc == Other.DebugLoc;
}
};
@@ -321,6 +326,12 @@ template <> struct MappingTraits<FixedMachineStackObject> {
StringValue()); // Don't print it out when it's empty.
YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
true);
+ YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
+ StringValue()); // Don't print it out when it's empty.
+ YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
+ StringValue()); // Don't print it out when it's empty.
+ YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
+ StringValue()); // Don't print it out when it's empty.
}
static const bool flow = true;
@@ -417,6 +428,7 @@ struct MachineFrameInfo {
bool HasOpaqueSPAdjustment = false;
bool HasVAStart = false;
bool HasMustTailInVarArgFunc = false;
+ unsigned LocalFrameSize = 0;
StringValue SavePoint;
StringValue RestorePoint;
@@ -434,6 +446,7 @@ struct MachineFrameInfo {
HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
HasVAStart == Other.HasVAStart &&
HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
+ LocalFrameSize == Other.LocalFrameSize &&
SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
}
};
@@ -457,6 +470,7 @@ template <> struct MappingTraits<MachineFrameInfo> {
YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
false);
+ YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
YamlIO.mapOptional("savePoint", MFI.SavePoint,
StringValue()); // Don't print it out when it's empty.
YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
@@ -472,6 +486,7 @@ struct MachineFunction {
bool Legalized = false;
bool RegBankSelected = false;
bool Selected = false;
+ bool FailedISel = false;
// Register information
bool TracksRegLiveness = false;
std::vector<VirtualRegisterDefinition> VirtualRegisters;
@@ -495,6 +510,7 @@ template <> struct MappingTraits<MachineFunction> {
YamlIO.mapOptional("legalized", MF.Legalized, false);
YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
YamlIO.mapOptional("selected", MF.Selected, false);
+ YamlIO.mapOptional("failedISel", MF.FailedISel, false);
YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
YamlIO.mapOptional("registers", MF.VirtualRegisters,
std::vector<VirtualRegisterDefinition>());
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index 89210e16629e..ace33efd8713 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -58,7 +58,7 @@ private:
public:
void addNodeToList(MachineInstr *N);
void removeNodeFromList(MachineInstr *N);
- void transferNodesFromList(ilist_traits &OldList, instr_iterator First,
+ void transferNodesFromList(ilist_traits &FromList, instr_iterator First,
instr_iterator Last);
void deleteNode(MachineInstr *MI);
};
@@ -115,13 +115,18 @@ private:
/// branch.
bool AddressTaken = false;
+ /// Indicate that this basic block is the entry block of an EH scope, i.e.,
+ /// the block that used to have a catchpad or cleanuppad instruction in the
+ /// LLVM IR.
+ bool IsEHScopeEntry = false;
+
/// Indicate that this basic block is the entry block of an EH funclet.
bool IsEHFuncletEntry = false;
/// Indicate that this basic block is the entry block of a cleanup funclet.
bool IsCleanupFuncletEntry = false;
- /// \brief since getSymbol is a relatively heavy-weight operation, the symbol
+ /// since getSymbol is a relatively heavy-weight operation, the symbol
/// is only computed once and is cached.
mutable MCSymbol *CachedMCSymbol = nullptr;
@@ -225,6 +230,14 @@ public:
return make_range(getFirstTerminator(), end());
}
+ /// Returns a range that iterates over the phis in the basic block.
+ inline iterator_range<iterator> phis() {
+ return make_range(begin(), getFirstNonPHI());
+ }
+ inline iterator_range<const_iterator> phis() const {
+ return const_cast<MachineBasicBlock *>(this)->phis();
+ }
+
// Machine-CFG iterators
using pred_iterator = std::vector<MachineBasicBlock *>::iterator;
using const_pred_iterator = std::vector<MachineBasicBlock *>::const_iterator;
@@ -367,6 +380,14 @@ public:
bool hasEHPadSuccessor() const;
+ /// Returns true if this is the entry block of an EH scope, i.e., the block
+ /// that used to have a catchpad or cleanuppad instruction in the LLVM IR.
+ bool isEHScopeEntry() const { return IsEHScopeEntry; }
+
+ /// Indicates if this is the entry block of an EH scope, i.e., the block that
+ /// that used to have a catchpad or cleanuppad instruction in the LLVM IR.
+ void setIsEHScopeEntry(bool V = true) { IsEHScopeEntry = V; }
+
/// Returns true if this is the entry block of an EH funclet.
bool isEHFuncletEntry() const { return IsEHFuncletEntry; }
@@ -456,6 +477,11 @@ public:
/// probabilities may need to be normalized.
void copySuccessor(MachineBasicBlock *Orig, succ_iterator I);
+ /// Split the old successor into old plus new and updates the probability
+ /// info.
+ void splitSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New,
+ bool NormalizeSuccProbs = false);
+
/// Transfers all the successors from MBB to this machine basic block (i.e.,
/// copies all the successors FromMBB and remove all the successors from
/// FromMBB).
@@ -553,7 +579,7 @@ public:
/// Check if the edge between this block and the given successor \p
/// Succ, can be split. If this returns true a subsequent call to
/// SplitCriticalEdge is guaranteed to return a valid basic block if
- /// no changes occured in the meantime.
+ /// no changes occurred in the meantime.
bool canSplitCriticalEdge(const MachineBasicBlock *Succ) const;
void pop_front() { Insts.pop_front(); }
@@ -692,12 +718,19 @@ public:
bool IsCond);
/// Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE
- /// instructions. Return UnknownLoc if there is none.
+ /// and DBG_LABEL instructions. Return UnknownLoc if there is none.
DebugLoc findDebugLoc(instr_iterator MBBI);
DebugLoc findDebugLoc(iterator MBBI) {
return findDebugLoc(MBBI.getInstrIterator());
}
+ /// Find the previous valid DebugLoc preceding MBBI, skipping and DBG_VALUE
+ /// instructions. Return UnknownLoc if there is none.
+ DebugLoc findPrevDebugLoc(instr_iterator MBBI);
+ DebugLoc findPrevDebugLoc(iterator MBBI) {
+ return findPrevDebugLoc(MBBI.getInstrIterator());
+ }
+
/// Find and return the merged DebugLoc of the branch instructions of the
/// block. Return UnknownLoc if there is none.
DebugLoc findBranchDebugLoc();
@@ -724,9 +757,10 @@ public:
// Debugging methods.
void dump() const;
- void print(raw_ostream &OS, const SlotIndexes* = nullptr) const;
+ void print(raw_ostream &OS, const SlotIndexes * = nullptr,
+ bool IsStandalone = true) const;
void print(raw_ostream &OS, ModuleSlotTracker &MST,
- const SlotIndexes* = nullptr) const;
+ const SlotIndexes * = nullptr, bool IsStandalone = true) const;
// Printing method used by LoopInfo.
void printAsOperand(raw_ostream &OS, bool PrintType = true) const;
@@ -881,7 +915,7 @@ public:
/// const_instr_iterator} and the respective reverse iterators.
template<typename IterT>
inline IterT skipDebugInstructionsForward(IterT It, IterT End) {
- while (It != End && It->isDebugValue())
+ while (It != End && It->isDebugInstr())
It++;
return It;
}
@@ -892,7 +926,7 @@ inline IterT skipDebugInstructionsForward(IterT It, IterT End) {
/// const_instr_iterator} and the respective reverse iterators.
template<class IterT>
inline IterT skipDebugInstructionsBackward(IterT It, IterT Begin) {
- while (It != Begin && It->isDebugValue())
+ while (It != Begin && It->isDebugInstr())
It--;
return It;
}
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h
index 1705a0f7e59b..b0b5420a884b 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h
@@ -63,7 +63,7 @@ inline raw_ostream &operator<<(raw_ostream &OS,
/// This class is a data container for one entry in a MachineConstantPool.
/// It contains a pointer to the value and an offset from the start of
/// the constant pool.
-/// @brief An entry in a MachineConstantPool
+/// An entry in a MachineConstantPool
class MachineConstantPoolEntry {
public:
/// The constant itself.
@@ -117,7 +117,7 @@ public:
/// the use of MO_ConstantPoolIndex values. When emitting assembly or machine
/// code, these virtual address references are converted to refer to the
/// address of the function constant pool values.
-/// @brief The machine constant pool.
+/// The machine constant pool.
class MachineConstantPool {
unsigned PoolAlignment; ///< The alignment for the pool.
std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants.
@@ -128,7 +128,7 @@ class MachineConstantPool {
const DataLayout &getDataLayout() const { return DL; }
public:
- /// @brief The only constructor.
+ /// The only constructor.
explicit MachineConstantPool(const DataLayout &DL)
: PoolAlignment(1), DL(DL) {}
~MachineConstantPool();
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h b/contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h
index ffbcc62bfa36..75d75bc3669a 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h
@@ -37,9 +37,9 @@ public:
MachineDominanceFrontier();
- DominanceFrontierBase<MachineBasicBlock, false> &getBase() { return Base; }
+ ForwardDominanceFrontierBase<MachineBasicBlock> &getBase() { return Base; }
- const SmallVectorImpl<MachineBasicBlock *> &getRoots() const {
+ const SmallVectorImpl<MachineBasicBlock *> &getRoots() const {
return Base.getRoots();
}
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineDominators.h b/contrib/llvm/include/llvm/CodeGen/MachineDominators.h
index 98fdb51aae2f..e3d3d169db97 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineDominators.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineDominators.h
@@ -45,7 +45,7 @@ using MachineDomTreeNode = DomTreeNodeBase<MachineBasicBlock>;
/// compute a normal dominator tree.
///
class MachineDominatorTree : public MachineFunctionPass {
- /// \brief Helper structure used to hold all the basic blocks
+ /// Helper structure used to hold all the basic blocks
/// involved in the split of a critical edge.
struct CriticalEdge {
MachineBasicBlock *FromBB;
@@ -53,12 +53,12 @@ class MachineDominatorTree : public MachineFunctionPass {
MachineBasicBlock *NewBB;
};
- /// \brief Pile up all the critical edges to be split.
+ /// Pile up all the critical edges to be split.
/// The splitting of a critical edge is local and thus, it is possible
/// to apply several of those changes at the same time.
mutable SmallVector<CriticalEdge, 32> CriticalEdgesToSplit;
- /// \brief Remember all the basic blocks that are inserted during
+ /// Remember all the basic blocks that are inserted during
/// edge splitting.
/// Invariant: NewBBs == all the basic blocks contained in the NewBB
/// field of all the elements of CriticalEdgesToSplit.
@@ -69,7 +69,7 @@ class MachineDominatorTree : public MachineFunctionPass {
/// The DominatorTreeBase that is used to compute a normal dominator tree
std::unique_ptr<DomTreeBase<MachineBasicBlock>> DT;
- /// \brief Apply all the recorded critical edges to the DT.
+ /// Apply all the recorded critical edges to the DT.
/// This updates the underlying DT information in a way that uses
/// the fast query path of DT as much as possible.
///
@@ -228,7 +228,7 @@ public:
void print(raw_ostream &OS, const Module*) const override;
- /// \brief Record that the critical edge (FromBB, ToBB) has been
+ /// Record that the critical edge (FromBB, ToBB) has been
/// split with NewBB.
/// This is best to use this method instead of directly update the
/// underlying information, because this helps mitigating the
@@ -249,12 +249,6 @@ public:
"A basic block inserted via edge splitting cannot appear twice");
CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB});
}
-
- /// \brief Verify the correctness of the domtree by re-computing it.
- ///
- /// This should only be used for debugging as it aborts the program if the
- /// verification fails.
- void verifyDomTree() const;
};
//===-------------------------------------
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h
index f887517217e1..2d6081f3577d 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -85,9 +85,23 @@ public:
/// stack offsets of the object, eliminating all MO_FrameIndex operands from
/// the program.
///
-/// @brief Abstract Stack Frame Information
+/// Abstract Stack Frame Information
class MachineFrameInfo {
+public:
+ /// Stack Smashing Protection (SSP) rules require that vulnerable stack
+ /// allocations are located close the stack protector.
+ enum SSPLayoutKind {
+ SSPLK_None, ///< Did not trigger a stack protector. No effect on data
+ ///< layout.
+ SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest
+ ///< to the stack protector.
+ SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest
+ ///< to the stack protector.
+ SSPLK_AddrOf ///< The address of this allocation is exposed and
+ ///< triggered protection. 3rd closest to the protector.
+ };
+private:
// Represent a single object allocated on the stack.
struct StackObject {
// The offset of this object from the stack pointer on entry to
@@ -123,6 +137,9 @@ class MachineFrameInfo {
/// necessarily reside in the same contiguous memory block as other stack
/// objects. Objects with differing stack IDs should not be merged or
/// replaced substituted for each other.
+ //
+ /// It is assumed a target uses consecutive, increasing stack IDs starting
+ /// from 1.
uint8_t StackID;
/// If this stack object is originated from an Alloca instruction
@@ -145,12 +162,15 @@ class MachineFrameInfo {
/// If true, the object has been zero-extended.
bool isSExt = false;
+ uint8_t SSPLayout;
+
StackObject(uint64_t Size, unsigned Alignment, int64_t SPOffset,
bool IsImmutable, bool IsSpillSlot, const AllocaInst *Alloca,
bool IsAliased, uint8_t StackID = 0)
: SPOffset(SPOffset), Size(Size), Alignment(Alignment),
isImmutable(IsImmutable), isSpillSlot(IsSpillSlot),
- StackID(StackID), Alloca(Alloca), isAliased(IsAliased) {}
+ StackID(StackID), Alloca(Alloca), isAliased(IsAliased),
+ SSPLayout(SSPLK_None) {}
};
/// The alignment of the stack.
@@ -485,6 +505,20 @@ public:
Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset;
}
+ SSPLayoutKind getObjectSSPLayout(int ObjectIdx) const {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ return (SSPLayoutKind)Objects[ObjectIdx+NumFixedObjects].SSPLayout;
+ }
+
+ void setObjectSSPLayout(int ObjectIdx, SSPLayoutKind Kind) {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ assert(!isDeadObjectIndex(ObjectIdx) &&
+ "Setting SSP layout for a dead object?");
+ Objects[ObjectIdx+NumFixedObjects].SSPLayout = Kind;
+ }
+
/// Return the number of bytes that must be allocated to hold
/// all of the fixed size frame objects. This is only valid after
/// Prolog/Epilog code insertion has finalized the stack frame layout.
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h
index 7d8b7ebe8d62..e8a4d529faac 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -73,6 +73,7 @@ class SlotIndexes;
class TargetMachine;
class TargetRegisterClass;
class TargetSubtargetInfo;
+struct WasmEHFuncInfo;
struct WinEHFuncInfo;
template <> struct ilist_alloc_traits<MachineBasicBlock> {
@@ -80,8 +81,8 @@ template <> struct ilist_alloc_traits<MachineBasicBlock> {
};
template <> struct ilist_callback_traits<MachineBasicBlock> {
- void addNodeToList(MachineBasicBlock* MBB);
- void removeNodeFromList(MachineBasicBlock* MBB);
+ void addNodeToList(MachineBasicBlock* N);
+ void removeNodeFromList(MachineBasicBlock* N);
template <class Iterator>
void transferNodesFromList(ilist_callback_traits &OldList, Iterator, Iterator) {
@@ -96,7 +97,7 @@ template <> struct ilist_callback_traits<MachineBasicBlock> {
struct MachineFunctionInfo {
virtual ~MachineFunctionInfo();
- /// \brief Factory function: default behavior is to call new using the
+ /// Factory function: default behavior is to call new using the
/// supplied allocator.
///
/// This function can be overridden in a derive class.
@@ -245,6 +246,10 @@ class MachineFunction {
// Keep track of jump tables for switch instructions
MachineJumpTableInfo *JumpTableInfo;
+ // Keeps track of Wasm exception handling related data. This will be null for
+ // functions that aren't using a wasm EH personality.
+ WasmEHFuncInfo *WasmEHInfo = nullptr;
+
// Keeps track of Windows exception handling related data. This will be null
// for functions that aren't using a funclet-based EH personality.
WinEHFuncInfo *WinEHInfo = nullptr;
@@ -319,6 +324,7 @@ class MachineFunction {
bool CallsEHReturn = false;
bool CallsUnwindInit = false;
+ bool HasEHScopes = false;
bool HasEHFunclets = false;
/// List of C++ TypeInfo used.
@@ -349,17 +355,18 @@ public:
struct VariableDbgInfo {
const DILocalVariable *Var;
const DIExpression *Expr;
- unsigned Slot;
+ // The Slot can be negative for fixed stack objects.
+ int Slot;
const DILocation *Loc;
VariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr,
- unsigned Slot, const DILocation *Loc)
+ int Slot, const DILocation *Loc)
: Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {}
};
using VariableDbgInfoMapTy = SmallVector<VariableDbgInfo, 4>;
VariableDbgInfoMapTy VariableDbgInfos;
- MachineFunction(const Function &F, const TargetMachine &TM,
+ MachineFunction(const Function &F, const TargetMachine &Target,
const TargetSubtargetInfo &STI, unsigned FunctionNum,
MachineModuleInfo &MMI);
MachineFunction(const MachineFunction &) = delete;
@@ -430,6 +437,12 @@ public:
MachineConstantPool *getConstantPool() { return ConstantPool; }
const MachineConstantPool *getConstantPool() const { return ConstantPool; }
+ /// getWasmEHFuncInfo - Return information about how the current function uses
+ /// Wasm exception handling. Returns null for functions that don't use wasm
+ /// exception handling.
+ const WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; }
+ WasmEHFuncInfo *getWasmEHFuncInfo() { return WasmEHInfo; }
+
/// getWinEHFuncInfo - Return information about how the current function uses
/// Windows exception handling. Returns null for functions that don't use
/// funclets for exception handling.
@@ -609,7 +622,7 @@ public:
//===--------------------------------------------------------------------===//
// Internal functions used to automatically number MachineBasicBlocks
- /// \brief Adds the MBB to the internal numbering. Returns the unique number
+ /// Adds the MBB to the internal numbering. Returns the unique number
/// assigned to the MBB.
unsigned addToMBBNumbering(MachineBasicBlock *MBB) {
MBBNumbering.push_back(MBB);
@@ -695,14 +708,8 @@ public:
OperandRecycler.deallocate(Cap, Array);
}
- /// \brief Allocate and initialize a register mask with @p NumRegister bits.
- uint32_t *allocateRegisterMask(unsigned NumRegister) {
- unsigned Size = (NumRegister + 31) / 32;
- uint32_t *Mask = Allocator.Allocate<uint32_t>(Size);
- for (unsigned i = 0; i != Size; ++i)
- Mask[i] = 0;
- return Mask;
- }
+ /// Allocate and initialize a register mask with @p NumRegister bits.
+ uint32_t *allocateRegMask();
/// allocateMemRefsArray - Allocate an array to hold MachineMemOperand
/// pointers. This array is owned by the MachineFunction.
@@ -759,6 +766,9 @@ public:
bool callsUnwindInit() const { return CallsUnwindInit; }
void setCallsUnwindInit(bool b) { CallsUnwindInit = b; }
+ bool hasEHScopes() const { return HasEHScopes; }
+ void setHasEHScopes(bool V) { HasEHScopes = V; }
+
bool hasEHFunclets() const { return HasEHFunclets; }
void setHasEHFunclets(bool V) { HasEHFunclets = V; }
@@ -793,7 +803,7 @@ public:
void addCleanup(MachineBasicBlock *LandingPad);
void addSEHCatchHandler(MachineBasicBlock *LandingPad, const Function *Filter,
- const BlockAddress *RecoverLabel);
+ const BlockAddress *RecoverBA);
void addSEHCleanupHandler(MachineBasicBlock *LandingPad,
const Function *Cleanup);
@@ -860,7 +870,7 @@ public:
/// Collect information used to emit debugging information of a variable.
void setVariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr,
- unsigned Slot, const DILocation *Loc) {
+ int Slot, const DILocation *Loc) {
VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc);
}
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h
index 3c1c1bb14f42..88e13cdf4138 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -80,7 +80,21 @@ public:
FrameDestroy = 1 << 1, // Instruction is used as a part of
// function frame destruction code.
BundledPred = 1 << 2, // Instruction has bundled predecessors.
- BundledSucc = 1 << 3 // Instruction has bundled successors.
+ BundledSucc = 1 << 3, // Instruction has bundled successors.
+ FmNoNans = 1 << 4, // Instruction does not support Fast
+ // math nan values.
+ FmNoInfs = 1 << 5, // Instruction does not support Fast
+ // math infinity values.
+ FmNsz = 1 << 6, // Instruction is not required to retain
+ // signed zero values.
+ FmArcp = 1 << 7, // Instruction supports Fast math
+ // reciprocal approximations.
+ FmContract = 1 << 8, // Instruction supports Fast math
+ // contraction operations like fma.
+ FmAfn = 1 << 9, // Instruction may map to Fast math
+ // instrinsic approximation.
+ FmReassoc = 1 << 10 // Instruction supports Fast math
+ // reassociation of operand order.
};
private:
@@ -93,7 +107,7 @@ private:
using OperandCapacity = ArrayRecycler<MachineOperand>::Capacity;
OperandCapacity CapOperands; // Capacity of the Operands array.
- uint8_t Flags = 0; // Various bits of additional
+ uint16_t Flags = 0; // Various bits of additional
// information about machine
// instruction.
@@ -127,7 +141,7 @@ private:
/// 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, DebugLoc dl,
+ MachineInstr(MachineFunction &, const MCInstrDesc &tid, DebugLoc dl,
bool NoImp = false);
// MachineInstrs are pool-allocated and owned by MachineFunction.
@@ -175,7 +189,7 @@ public:
}
/// Return the MI flags bitvector.
- uint8_t getFlags() const {
+ uint16_t getFlags() const {
return Flags;
}
@@ -186,7 +200,7 @@ public:
/// Set a MI flag.
void setFlag(MIFlag Flag) {
- Flags |= (uint8_t)Flag;
+ Flags |= (uint16_t)Flag;
}
void setFlags(unsigned flags) {
@@ -197,7 +211,7 @@ public:
/// clearFlag - Clear a MI flag.
void clearFlag(MIFlag Flag) {
- Flags &= ~((uint8_t)Flag);
+ Flags &= ~((uint16_t)Flag);
}
/// Return true if MI is in a bundle (but not the first MI in a bundle).
@@ -278,6 +292,10 @@ public:
/// this DBG_VALUE instruction.
const DIExpression *getDebugExpression() const;
+ /// Return the debug label referenced by
+ /// this DBG_LABEL instruction.
+ const DILabel *getDebugLabel() const;
+
/// Emit an error referring to the source location of this instruction.
/// This should only be used for inline assembly that is somehow
/// impossible to compile. Other errors should have been handled much
@@ -304,6 +322,11 @@ public:
return Operands[i];
}
+ /// Returns the total number of definitions.
+ unsigned getNumDefs() const {
+ return getNumExplicitDefs() + MCID->getNumImplicitDefs();
+ }
+
/// Return true if operand \p OpIdx is a subregister index.
bool isOperandSubregIdx(unsigned OpIdx) const {
assert(getOperand(OpIdx).getType() == MachineOperand::MO_Immediate &&
@@ -322,6 +345,9 @@ public:
/// Returns the number of non-implicit operands.
unsigned getNumExplicitOperands() const;
+ /// Returns the number of non-implicit definitions.
+ unsigned getNumExplicitDefs() const;
+
/// iterator/begin/end - Iterate over all operands of a machine instruction.
using mop_iterator = MachineOperand *;
using const_mop_iterator = const MachineOperand *;
@@ -356,31 +382,29 @@ public:
/// Implicit definition are not included!
iterator_range<mop_iterator> defs() {
return make_range(operands_begin(),
- operands_begin() + getDesc().getNumDefs());
+ operands_begin() + getNumExplicitDefs());
}
/// \copydoc defs()
iterator_range<const_mop_iterator> defs() const {
return make_range(operands_begin(),
- operands_begin() + getDesc().getNumDefs());
+ operands_begin() + getNumExplicitDefs());
}
/// Returns a range that includes all operands that are register uses.
/// This may include unrelated operands which are not register uses.
iterator_range<mop_iterator> uses() {
- return make_range(operands_begin() + getDesc().getNumDefs(),
- operands_end());
+ return make_range(operands_begin() + getNumExplicitDefs(), operands_end());
}
/// \copydoc uses()
iterator_range<const_mop_iterator> uses() const {
- return make_range(operands_begin() + getDesc().getNumDefs(),
- operands_end());
+ return make_range(operands_begin() + getNumExplicitDefs(), operands_end());
}
iterator_range<mop_iterator> explicit_uses() {
- return make_range(operands_begin() + getDesc().getNumDefs(),
- operands_begin() + getNumExplicitOperands() );
+ return make_range(operands_begin() + getNumExplicitDefs(),
+ operands_begin() + getNumExplicitOperands());
}
iterator_range<const_mop_iterator> explicit_uses() const {
- return make_range(operands_begin() + getDesc().getNumDefs(),
- operands_begin() + getNumExplicitOperands() );
+ return make_range(operands_begin() + getNumExplicitDefs(),
+ operands_begin() + getNumExplicitOperands());
}
/// Returns the number of the operand iterator \p I points to.
@@ -391,7 +415,7 @@ public:
/// Access to memory operands of the instruction
mmo_iterator memoperands_begin() const { return MemRefs; }
mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; }
- /// Return true if we don't have any memory operands which described the the
+ /// Return true if we don't have any memory operands which described the
/// memory access done by this instruction. If this is true, calling code
/// must be conservative.
bool memoperands_empty() const { return NumMemRefs == 0; }
@@ -529,6 +553,12 @@ public:
return hasProperty(MCID::MoveImm, Type);
}
+ /// Return true if this instruction is a register move.
+ /// (including moving values from subreg to reg)
+ bool isMoveReg(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::MoveReg, Type);
+ }
+
/// Return true if this instruction is a bitcast instruction.
bool isBitcast(QueryType Type = IgnoreBundle) const {
return hasProperty(MCID::Bitcast, Type);
@@ -576,7 +606,7 @@ public:
return hasProperty(MCID::FoldableAsLoad, Type);
}
- /// \brief Return true if this instruction behaves
+ /// Return true if this instruction behaves
/// the same way as the generic REG_SEQUENCE instructions.
/// E.g., on ARM,
/// dX VMOVDRR rY, rZ
@@ -590,7 +620,7 @@ public:
return hasProperty(MCID::RegSequence, Type);
}
- /// \brief Return true if this instruction behaves
+ /// Return true if this instruction behaves
/// the same way as the generic EXTRACT_SUBREG instructions.
/// E.g., on ARM,
/// rX, rY VMOVRRD dZ
@@ -605,7 +635,7 @@ public:
return hasProperty(MCID::ExtractSubreg, Type);
}
- /// \brief Return true if this instruction behaves
+ /// Return true if this instruction behaves
/// the same way as the generic INSERT_SUBREG instructions.
/// E.g., on ARM,
/// dX = VSETLNi32 dY, rZ, Imm
@@ -817,6 +847,8 @@ public:
bool isPosition() const { return isLabel() || isCFIInstruction(); }
bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; }
+ bool isDebugLabel() const { return getOpcode() == TargetOpcode::DBG_LABEL; }
+ bool isDebugInstr() const { return isDebugValue() || isDebugLabel(); }
/// A DBG_VALUE is indirect iff the first operand is a register and
/// the second operand is an immediate.
@@ -893,6 +925,9 @@ public:
case TargetOpcode::EH_LABEL:
case TargetOpcode::GC_LABEL:
case TargetOpcode::DBG_VALUE:
+ case TargetOpcode::DBG_LABEL:
+ case TargetOpcode::LIFETIME_START:
+ case TargetOpcode::LIFETIME_END:
return true;
}
}
@@ -1047,7 +1082,7 @@ public:
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI) const;
- /// \brief Applies the constraints (def/use) implied by this MI on \p Reg to
+ /// Applies the constraints (def/use) implied by this MI on \p Reg to
/// the given \p CurRC.
/// If \p ExploreBundle is set and MI is part of a bundle, all the
/// instructions inside the bundle will be taken into account. In other words,
@@ -1064,7 +1099,7 @@ public:
const TargetInstrInfo *TII, const TargetRegisterInfo *TRI,
bool ExploreBundle = false) const;
- /// \brief Applies the constraints (def/use) implied by the \p OpIdx operand
+ /// Applies the constraints (def/use) implied by the \p OpIdx operand
/// to the given \p CurRC.
///
/// Returns the register class that satisfies both \p CurRC and the
@@ -1233,15 +1268,20 @@ public:
bool hasComplexRegisterTies() const;
/// Print this MI to \p OS.
+ /// Don't print information that can be inferred from other instructions if
+ /// \p IsStandalone is false. It is usually true when only a fragment of the
+ /// function is printed.
/// Only print the defs and the opcode if \p SkipOpers is true.
/// Otherwise, also print operands if \p SkipDebugLoc is true.
/// Otherwise, also print the debug loc, with a terminating newline.
/// \p TII is used to print the opcode name. If it's not present, but the
/// MI is in a function, the opcode will be printed using the function's TII.
- void print(raw_ostream &OS, bool SkipOpers = false, bool SkipDebugLoc = false,
+ void print(raw_ostream &OS, bool IsStandalone = true, bool SkipOpers = false,
+ bool SkipDebugLoc = false, bool AddNewLine = true,
const TargetInstrInfo *TII = nullptr) const;
- void print(raw_ostream &OS, ModuleSlotTracker &MST, bool SkipOpers = false,
- bool SkipDebugLoc = false,
+ void print(raw_ostream &OS, ModuleSlotTracker &MST, bool IsStandalone = true,
+ bool SkipOpers = false, bool SkipDebugLoc = false,
+ bool AddNewLine = true,
const TargetInstrInfo *TII = nullptr) const;
void dump() const;
/// @}
@@ -1281,7 +1321,7 @@ public:
/// Erase an operand from an instruction, leaving it with one
/// fewer operand than it started with.
- void RemoveOperand(unsigned i);
+ void RemoveOperand(unsigned OpNo);
/// Add a MachineMemOperand to the machine instruction.
/// This function should be used only occasionally. The setMemRefs function
@@ -1311,6 +1351,11 @@ public:
/// modify the memrefs of the this MachineInstr.
std::pair<mmo_iterator, unsigned> mergeMemRefsWith(const MachineInstr& Other);
+ /// Return the MIFlags which represent both MachineInstrs. This
+ /// should be used when merging two MachineInstrs into one. This routine does
+ /// not modify the MIFlags of this MachineInstr.
+ uint16_t mergeFlagsWith(const MachineInstr& Other) const;
+
/// Clear this MachineInstr's memory reference descriptor list. This resets
/// the memrefs to their most conservative state. This should be used only
/// as a last resort since it greatly pessimizes our knowledge of the memory
@@ -1351,7 +1396,7 @@ private:
/// Slow path for hasProperty when we're dealing with a bundle.
bool hasPropertyInBundle(unsigned Mask, QueryType Type) const;
- /// \brief Implements the logic of getRegClassConstraintEffectForVReg for the
+ /// Implements the logic of getRegClassConstraintEffectForVReg for the
/// this MI and the given operand index \p OpIdx.
/// If the related operand does not constrained Reg, this returns CurRC.
const TargetRegisterClass *getRegClassConstraintEffectForVRegImpl(
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
index e4f3976ec950..665608755741 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -20,6 +20,7 @@
#define LLVM_CODEGEN_MACHINEINSTRBUILDER_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
@@ -219,6 +220,9 @@ public:
assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable())
: true) &&
"first MDNode argument of a DBG_VALUE not a variable");
+ assert((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel())
+ : true) &&
+ "first MDNode argument of a DBG_LABEL not a label");
return *this;
}
@@ -283,6 +287,12 @@ public:
MI->copyImplicitOps(*MF, OtherMI);
return *this;
}
+
+ bool constrainAllUses(const TargetInstrInfo &TII,
+ const TargetRegisterInfo &TRI,
+ const RegisterBankInfo &RBI) const {
+ return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
+ }
};
/// Builder interface. Specify how to create the initial instruction itself.
@@ -408,6 +418,13 @@ MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MDNode *Expr);
/// This version of the builder builds a DBG_VALUE intrinsic
+/// for a MachineOperand.
+MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ MachineOperand &MO, const MDNode *Variable,
+ const MDNode *Expr);
+
+/// This version of the builder builds a DBG_VALUE intrinsic
/// for either a value in a register or a register-indirect
/// address and inserts it at position I.
MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
@@ -416,6 +433,14 @@ MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
unsigned Reg, const MDNode *Variable,
const MDNode *Expr);
+/// This version of the builder builds a DBG_VALUE intrinsic
+/// for a machine operand and inserts it at position I.
+MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
+ MachineBasicBlock::iterator I, const DebugLoc &DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ MachineOperand &MO, const MDNode *Variable,
+ const MDNode *Expr);
+
/// Clone a DBG_VALUE whose value has been spilled to FrameIndex.
MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h
index 104655e45524..917fb90380f5 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h
@@ -54,7 +54,7 @@ public:
/// that contains the header.
MachineBasicBlock *getBottomBlock();
- /// \brief Find the block that contains the loop control variable and the
+ /// Find the block that contains the loop control variable and the
/// loop test. This will return the latch block if it's one of the exiting
/// blocks. Otherwise, return the exiting block. Return 'null' when
/// multiple exiting blocks are present.
@@ -97,7 +97,7 @@ public:
LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; }
- /// \brief Find the block that either is the loop preheader, or could
+ /// Find the block that either is the loop preheader, or could
/// speculatively be used as the preheader. This is e.g. useful to place
/// loop setup code. Code that cannot be speculated should not be placed
/// here. SpeculativePreheader is controlling whether it also tries to
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h b/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h
index c5b204a79f04..078ef7ca510c 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h
@@ -184,7 +184,7 @@ public:
/// atomic operations the atomic ordering requirements when store does not
/// occur must also be specified.
MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, uint64_t s,
- unsigned base_alignment,
+ uint64_t a,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr,
SyncScope::ID SSID = SyncScope::System,
@@ -295,6 +295,9 @@ public:
/// @{
void print(raw_ostream &OS) const;
void print(raw_ostream &OS, ModuleSlotTracker &MST) const;
+ void print(raw_ostream &OS, ModuleSlotTracker &MST,
+ SmallVectorImpl<StringRef> &SSNs, const LLVMContext &Context,
+ const MachineFrameInfo *MFI, const TargetInstrInfo *TII) const;
/// @}
friend bool operator==(const MachineMemOperand &LHS,
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h
index 4be7942c2c64..53e8889d118a 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h
@@ -74,7 +74,7 @@ public:
private:
/// OpKind - Specify what kind of operand this is. This discriminates the
/// union.
- MachineOperandType OpKind : 8;
+ unsigned OpKind : 8;
/// Subregister number for MO_Register. A value of 0 indicates the
/// MO_Register has no subReg.
@@ -85,17 +85,17 @@ private:
/// TiedTo - Non-zero when this register operand is tied to another register
/// operand. The encoding of this field is described in the block comment
/// before MachineInstr::tieOperands().
- unsigned char TiedTo : 4;
+ unsigned TiedTo : 4;
/// IsDef - True if this is a def, false if this is a use of the register.
/// This is only valid on register operands.
///
- bool IsDef : 1;
+ unsigned IsDef : 1;
/// IsImp - True if this is an implicit def or use, false if it is explicit.
/// This is only valid on register opderands.
///
- bool IsImp : 1;
+ unsigned IsImp : 1;
/// IsDeadOrKill
/// For uses: IsKill - True if this instruction is the last use of the
@@ -103,14 +103,10 @@ private:
/// For defs: IsDead - True if this register is never used by a subsequent
/// instruction.
/// This is only valid on register operands.
- bool IsDeadOrKill : 1;
+ unsigned IsDeadOrKill : 1;
- /// IsRenamable - True if this register may be renamed, i.e. it does not
- /// generate a value that is somehow read in a way that is not represented by
- /// the Machine IR (e.g. to meet an ABI or ISA requirement). This is only
- /// valid on physical register operands. Virtual registers are assumed to
- /// always be renamable regardless of the value of this field.
- bool IsRenamable : 1;
+ /// See isRenamable().
+ unsigned IsRenamable : 1;
/// IsUndef - True if this register operand reads an "undef" value, i.e. the
/// read value doesn't matter. This flag can be set on both use and def
@@ -129,7 +125,7 @@ private:
/// Any register can be used for %2, and its value doesn't matter, but
/// the two operands must be the same register.
///
- bool IsUndef : 1;
+ unsigned IsUndef : 1;
/// IsInternalRead - True if this operand reads a value that was defined
/// inside the same instruction or bundle. This flag can be set on both use
@@ -140,16 +136,16 @@ private:
/// When this flag is set, the instruction bundle must contain at least one
/// other def of the register. If multiple instructions in the bundle define
/// the register, the meaning is target-defined.
- bool IsInternalRead : 1;
+ unsigned IsInternalRead : 1;
/// IsEarlyClobber - True if this MO_Register 'def' operand is written to
/// by the MachineInstr before all input registers are read. This is used to
/// model the GCC inline asm '&' constraint modifier.
- bool IsEarlyClobber : 1;
+ unsigned IsEarlyClobber : 1;
/// IsDebug - True if this MO_Register 'use' operand is in a debug pseudo,
/// not a real instruction. Such uses should be ignored during codegen.
- bool IsDebug : 1;
+ unsigned IsDebug : 1;
/// SmallContents - This really should be part of the Contents union, but
/// lives out here so we can get a better packed struct.
@@ -198,7 +194,19 @@ private:
} Contents;
explicit MachineOperand(MachineOperandType K)
- : OpKind(K), SubReg_TargetFlags(0), ParentMI(nullptr) {}
+ : OpKind(K), SubReg_TargetFlags(0), ParentMI(nullptr) {
+ // Assert that the layout is what we expect. It's easy to grow this object.
+ static_assert(alignof(MachineOperand) <= alignof(int64_t),
+ "MachineOperand shouldn't be more than 8 byte aligned");
+ static_assert(sizeof(Contents) <= 2 * sizeof(void *),
+ "Contents should be at most two pointers");
+ static_assert(sizeof(MachineOperand) <=
+ alignTo<alignof(int64_t)>(2 * sizeof(unsigned) +
+ 3 * sizeof(void *)),
+ "MachineOperand too big. Should be Kind, SmallContents, "
+ "ParentMI, and Contents");
+ }
+
public:
/// getType - Returns the MachineOperandType for this operand.
///
@@ -238,7 +246,7 @@ public:
/// MO_Immediate operands can also be subreg idices. If it's the case, the
/// subreg index name will be printed. MachineInstr::isOperandSubregIdx can be
/// called to check this.
- static void printSubregIdx(raw_ostream &OS, uint64_t Index,
+ static void printSubRegIdx(raw_ostream &OS, uint64_t Index,
const TargetRegisterInfo *TRI);
/// Print operand target flags.
@@ -270,6 +278,9 @@ public:
/// \param PrintDef - whether we want to print `def` on an operand which
/// isDef. Sometimes, if the operand is printed before '=', we don't print
/// `def`.
+ /// \param IsStandalone - whether we want a verbose output of the MO. This
+ /// prints extra information that can be easily inferred when printing the
+ /// whole function, but not when printing only a fragment of it.
/// \param ShouldPrintRegisterTies - whether we want to print register ties.
/// Sometimes they are easily determined by the instruction's descriptor
/// (MachineInstr::hasComplexRegiterTies can determine if it's needed).
@@ -280,10 +291,16 @@ public:
/// information from it's parent.
/// \param IntrinsicInfo - same as \p TRI.
void print(raw_ostream &os, ModuleSlotTracker &MST, LLT TypeToPrint,
- bool PrintDef, bool ShouldPrintRegisterTies,
+ bool PrintDef, bool IsStandalone, bool ShouldPrintRegisterTies,
unsigned TiedOperandIdx, const TargetRegisterInfo *TRI,
const TargetIntrinsicInfo *IntrinsicInfo) const;
+ /// Same as print(os, TRI, IntrinsicInfo), but allows to specify the low-level
+ /// type to be printed the same way the full version of print(...) does it.
+ void print(raw_ostream &os, LLT TypeToPrint,
+ const TargetRegisterInfo *TRI = nullptr,
+ const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const;
+
void dump() const;
//===--------------------------------------------------------------------===//
@@ -369,6 +386,35 @@ public:
return IsUndef;
}
+ /// isRenamable - Returns true if this register may be renamed, i.e. it does
+ /// not generate a value that is somehow read in a way that is not represented
+ /// by the Machine IR (e.g. to meet an ABI or ISA requirement). This is only
+ /// valid on physical register operands. Virtual registers are assumed to
+ /// always be renamable regardless of the value of this field.
+ ///
+ /// Operands that are renamable can freely be changed to any other register
+ /// that is a member of the register class returned by
+ /// MI->getRegClassConstraint().
+ ///
+ /// isRenamable can return false for several different reasons:
+ ///
+ /// - ABI constraints (since liveness is not always precisely modeled). We
+ /// conservatively handle these cases by setting all physical register
+ /// operands that didn’t start out as virtual regs to not be renamable.
+ /// Also any physical register operands created after register allocation or
+ /// whose register is changed after register allocation will not be
+ /// renamable. This state is tracked in the MachineOperand::IsRenamable
+ /// bit.
+ ///
+ /// - Opcode/target constraints: for opcodes that have complex register class
+ /// requirements (e.g. that depend on other operands/instructions), we set
+ /// hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq in the machine opcode
+ /// description. Operands belonging to instructions with opcodes that are
+ /// marked hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq return false from
+ /// isRenamable(). Additionally, the AllowRegisterRenaming target property
+ /// prevents any operands from being marked renamable for targets that don't
+ /// have detailed opcode hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq
+ /// values.
bool isRenamable() const;
bool isInternalRead() const {
@@ -458,10 +504,6 @@ public:
void setIsRenamable(bool Val = true);
- /// Set IsRenamable to true if there are no extra register allocation
- /// requirements placed on this operand by the parent instruction's opcode.
- void setIsRenamableIfNoExtraRegAllocReq();
-
void setIsInternalRead(bool Val = true) {
assert(isReg() && "Wrong MachineOperand mutator");
IsInternalRead = Val;
@@ -574,6 +616,11 @@ public:
return Contents.RegMask;
}
+ /// Returns number of elements needed for a regmask array.
+ static unsigned getRegMaskSize(unsigned NumRegs) {
+ return (NumRegs + 31) / 32;
+ }
+
/// getRegLiveOut - Returns a bit mask of live-out registers.
const uint32_t *getRegLiveOut() const {
assert(isRegLiveOut() && "Wrong MachineOperand accessor");
@@ -594,6 +641,11 @@ public:
Contents.ImmVal = immVal;
}
+ void setCImm(const ConstantInt *CI) {
+ assert(isCImm() && "Wrong MachineOperand mutator");
+ Contents.CI = CI;
+ }
+
void setFPImm(const ConstantFP *CFP) {
assert(isFPImm() && "Wrong MachineOperand mutator");
Contents.CFP = CFP;
@@ -641,7 +693,7 @@ public:
/// should stay in sync with the hash_value overload below.
bool isIdenticalTo(const MachineOperand &Other) const;
- /// \brief MachineOperand hash_value overload.
+ /// MachineOperand hash_value overload.
///
/// Note that this includes the same information in the hash that
/// isIdenticalTo uses for comparison. It is thus suited for use in hash
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h b/contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h
index 2fdefbed37ce..a7ce870400c2 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h
@@ -24,7 +24,7 @@ class MachineBasicBlock;
class MachineBlockFrequencyInfo;
class MachineInstr;
-/// \brief Common features for diagnostics dealing with optimization remarks
+/// Common features for diagnostics dealing with optimization remarks
/// that are used by machine passes.
class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase {
public:
@@ -151,7 +151,7 @@ public:
/// Emit an optimization remark.
void emit(DiagnosticInfoOptimizationBase &OptDiag);
- /// \brief Whether we allow for extra compile-time budget to perform more
+ /// Whether we allow for extra compile-time budget to perform more
/// analysis to be more informative.
///
/// This is useful to enable additional missed optimizations to be reported
@@ -164,7 +164,7 @@ public:
.getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
}
- /// \brief Take a lambda that returns a remark which will be emitted. Second
+ /// Take a lambda that returns a remark which will be emitted. Second
/// argument is only used to restrict this to functions.
template <typename T>
void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
@@ -192,7 +192,7 @@ private:
/// Similar but use value from \p OptDiag and update hotness there.
void computeHotness(DiagnosticInfoMIROptimization &Remark);
- /// \brief Only allow verbose messages if we know we're filtering by hotness
+ /// Only allow verbose messages if we know we're filtering by hotness
/// (BFI is only set in this case).
bool shouldEmitVerbose() { return MBFI != nullptr; }
};
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h b/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h
new file mode 100644
index 000000000000..4249a99a891b
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h
@@ -0,0 +1,226 @@
+//===---- MachineOutliner.h - Outliner data structures ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Contains all data structures shared between the outliner implemented in
+/// MachineOutliner.cpp and target implementations of the outliner.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MACHINEOUTLINER_H
+#define LLVM_MACHINEOUTLINER_H
+
+#include "llvm/CodeGen/LiveRegUnits.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+
+namespace llvm {
+namespace outliner {
+
+/// Represents how an instruction should be mapped by the outliner.
+/// \p Legal instructions are those which are safe to outline.
+/// \p LegalTerminator instructions are safe to outline, but only as the
+/// last instruction in a sequence.
+/// \p Illegal instructions are those which cannot be outlined.
+/// \p Invisible instructions are instructions which can be outlined, but
+/// shouldn't actually impact the outlining result.
+enum InstrType { Legal, LegalTerminator, Illegal, Invisible };
+
+/// An individual sequence of instructions to be replaced with a call to
+/// an outlined function.
+struct Candidate {
+private:
+ /// The start index of this \p Candidate in the instruction list.
+ unsigned StartIdx;
+
+ /// The number of instructions in this \p Candidate.
+ unsigned Len;
+
+ // The first instruction in this \p Candidate.
+ MachineBasicBlock::iterator FirstInst;
+
+ // The last instruction in this \p Candidate.
+ MachineBasicBlock::iterator LastInst;
+
+ // The basic block that contains this Candidate.
+ MachineBasicBlock *MBB;
+
+ /// Cost of calling an outlined function from this point as defined by the
+ /// target.
+ unsigned CallOverhead;
+
+public:
+ /// The index of this \p Candidate's \p OutlinedFunction in the list of
+ /// \p OutlinedFunctions.
+ unsigned FunctionIdx;
+
+ /// Set to false if the candidate overlapped with another candidate.
+ bool InCandidateList = true;
+
+ /// Identifier denoting the instructions to emit to call an outlined function
+ /// from this point. Defined by the target.
+ unsigned CallConstructionID;
+
+ /// Contains physical register liveness information for the MBB containing
+ /// this \p Candidate.
+ ///
+ /// This is optionally used by the target to calculate more fine-grained
+ /// cost model information.
+ LiveRegUnits LRU;
+
+ /// Return the number of instructions in this Candidate.
+ unsigned getLength() const { return Len; }
+
+ /// Return the start index of this candidate.
+ unsigned getStartIdx() const { return StartIdx; }
+
+ /// Return the end index of this candidate.
+ unsigned getEndIdx() const { return StartIdx + Len - 1; }
+
+ /// Set the CallConstructionID and CallOverhead of this candidate to CID and
+ /// CO respectively.
+ void setCallInfo(unsigned CID, unsigned CO) {
+ CallConstructionID = CID;
+ CallOverhead = CO;
+ }
+
+ /// Returns the call overhead of this candidate if it is in the list.
+ unsigned getCallOverhead() const {
+ return InCandidateList ? CallOverhead : 0;
+ }
+
+ MachineBasicBlock::iterator &front() { return FirstInst; }
+ MachineBasicBlock::iterator &back() { return LastInst; }
+ MachineFunction *getMF() const { return MBB->getParent(); }
+ MachineBasicBlock *getMBB() const { return MBB; }
+
+ /// The number of instructions that would be saved by outlining every
+ /// candidate of this type.
+ ///
+ /// This is a fixed value which is not updated during the candidate pruning
+ /// process. It is only used for deciding which candidate to keep if two
+ /// candidates overlap. The true benefit is stored in the OutlinedFunction
+ /// for some given candidate.
+ unsigned Benefit = 0;
+
+ Candidate(unsigned StartIdx, unsigned Len,
+ MachineBasicBlock::iterator &FirstInst,
+ MachineBasicBlock::iterator &LastInst, MachineBasicBlock *MBB,
+ unsigned FunctionIdx)
+ : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst),
+ MBB(MBB), FunctionIdx(FunctionIdx) {}
+ Candidate() {}
+
+ /// Used to ensure that \p Candidates are outlined in an order that
+ /// preserves the start and end indices of other \p Candidates.
+ bool operator<(const Candidate &RHS) const {
+ return getStartIdx() > RHS.getStartIdx();
+ }
+
+ /// Compute the registers that are live across this Candidate.
+ /// Used by targets that need this information for cost model calculation.
+ /// If a target does not need this information, then this should not be
+ /// called.
+ void initLRU(const TargetRegisterInfo &TRI) {
+ assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
+ "Candidate's Machine Function must track liveness");
+ LRU.init(TRI);
+ LRU.addLiveOuts(*MBB);
+
+ // Compute liveness from the end of the block up to the beginning of the
+ // outlining candidate.
+ std::for_each(MBB->rbegin(), (MachineBasicBlock::reverse_iterator)front(),
+ [this](MachineInstr &MI) { LRU.stepBackward(MI); });
+ }
+};
+
+/// The information necessary to create an outlined function for some
+/// class of candidate.
+struct OutlinedFunction {
+
+private:
+ /// The number of candidates for this \p OutlinedFunction.
+ unsigned OccurrenceCount = 0;
+
+public:
+ std::vector<std::shared_ptr<Candidate>> Candidates;
+
+ /// The actual outlined function created.
+ /// This is initialized after we go through and create the actual function.
+ MachineFunction *MF = nullptr;
+
+ /// A number assigned to this function which appears at the end of its name.
+ unsigned Name;
+
+ /// The sequence of integers corresponding to the instructions in this
+ /// function.
+ std::vector<unsigned> Sequence;
+
+ /// Represents the size of a sequence in bytes. (Some instructions vary
+ /// widely in size, so just counting the instructions isn't very useful.)
+ unsigned SequenceSize;
+
+ /// Target-defined overhead of constructing a frame for this function.
+ unsigned FrameOverhead;
+
+ /// Target-defined identifier for constructing a frame for this function.
+ unsigned FrameConstructionID;
+
+ /// Return the number of candidates for this \p OutlinedFunction.
+ unsigned getOccurrenceCount() { return OccurrenceCount; }
+
+ /// Decrement the occurrence count of this OutlinedFunction and return the
+ /// new count.
+ unsigned decrement() {
+ assert(OccurrenceCount > 0 && "Can't decrement an empty function!");
+ OccurrenceCount--;
+ return getOccurrenceCount();
+ }
+
+ /// Return the number of bytes it would take to outline this
+ /// function.
+ unsigned getOutliningCost() {
+ unsigned CallOverhead = 0;
+ for (std::shared_ptr<Candidate> &C : Candidates)
+ CallOverhead += C->getCallOverhead();
+ return CallOverhead + SequenceSize + FrameOverhead;
+ }
+
+ /// Return the size in bytes of the unoutlined sequences.
+ unsigned getNotOutlinedCost() { return OccurrenceCount * SequenceSize; }
+
+ /// Return the number of instructions that would be saved by outlining
+ /// this function.
+ unsigned getBenefit() {
+ unsigned NotOutlinedCost = getNotOutlinedCost();
+ unsigned OutlinedCost = getOutliningCost();
+ return (NotOutlinedCost < OutlinedCost) ? 0
+ : NotOutlinedCost - OutlinedCost;
+ }
+
+ OutlinedFunction(std::vector<Candidate> &Cands,
+ unsigned SequenceSize, unsigned FrameOverhead,
+ unsigned FrameConstructionID)
+ : SequenceSize(SequenceSize), FrameOverhead(FrameOverhead),
+ FrameConstructionID(FrameConstructionID) {
+ OccurrenceCount = Cands.size();
+ for (Candidate &C : Cands)
+ Candidates.push_back(std::make_shared<outliner::Candidate>(C));
+
+ unsigned B = getBenefit();
+ for (std::shared_ptr<Candidate> &C : Candidates)
+ C->Benefit = B;
+ }
+
+ OutlinedFunction() {}
+};
+} // namespace outliner
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index 3be94f802170..5bf4a49c8b3b 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/LowLevelType.h"
@@ -75,6 +76,13 @@ private:
VirtReg2IndexFunctor>
VRegInfo;
+ /// Map for recovering vreg name from vreg number.
+ /// This map is used by the MIR Printer.
+ IndexedMap<std::string, VirtReg2IndexFunctor> VReg2Name;
+
+ /// StringSet that is used to unique vreg names.
+ StringSet<> VRegNames;
+
/// The flag is true upon \p UpdatedCSRs initialization
/// and false otherwise.
bool IsUpdatedCSRsInitialized;
@@ -128,9 +136,9 @@ private:
/// started.
BitVector ReservedRegs;
- using VRegToTypeMap = DenseMap<unsigned, LLT>;
- /// Map generic virtual registers to their actual size.
- mutable std::unique_ptr<VRegToTypeMap> VRegToType;
+ using VRegToTypeMap = IndexedMap<LLT, VirtReg2IndexFunctor>;
+ /// Map generic virtual registers to their low-level type.
+ VRegToTypeMap VRegToType;
/// Keep track of the physical registers that are live in to the function.
/// Live in values are typically arguments in registers. LiveIn values are
@@ -418,6 +426,20 @@ public:
/// specified register (it may be live-in).
bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); }
+ StringRef getVRegName(unsigned Reg) const {
+ return VReg2Name.inBounds(Reg) ? StringRef(VReg2Name[Reg]) : "";
+ }
+
+ void insertVRegByName(StringRef Name, unsigned Reg) {
+ assert((Name.empty() || VRegNames.find(Name) == VRegNames.end()) &&
+ "Named VRegs Must be Unique.");
+ if (!Name.empty()) {
+ VRegNames.insert(Name);
+ VReg2Name.grow(Reg);
+ VReg2Name[Reg] = Name.str();
+ }
+ }
+
/// Return true if there is exactly one operand defining the specified
/// register.
bool hasOneDef(unsigned RegNo) const {
@@ -548,12 +570,16 @@ public:
/// except that it also changes any definitions of the register as well.
///
/// Note that it is usually necessary to first constrain ToReg's register
- /// class to match the FromReg constraints using:
+ /// class and register bank to match the FromReg constraints using one of the
+ /// methods:
///
/// constrainRegClass(ToReg, getRegClass(FromReg))
+ /// constrainRegAttrs(ToReg, FromReg)
+ /// RegisterBankInfo::constrainGenericRegister(ToReg,
+ /// *MRI.getRegClass(FromReg), MRI)
///
- /// That function will return NULL if the virtual registers have incompatible
- /// constraints.
+ /// These functions will return a falsy result if the virtual registers have
+ /// incompatible constraints.
///
/// Note that if ToReg is a physical register the function will replace and
/// apply sub registers to ToReg in order to obtain a final/proper physical
@@ -653,10 +679,30 @@ public:
/// new register class, or NULL if no such class exists.
/// This should only be used when the constraint is known to be trivial, like
/// GR32 -> GR32_NOSP. Beware of increasing register pressure.
+ ///
+ /// \note Assumes that the register has a register class assigned.
+ /// Use RegisterBankInfo::constrainGenericRegister in GlobalISel's
+ /// InstructionSelect pass and constrainRegAttrs in every other pass,
+ /// including non-select passes of GlobalISel, instead.
const TargetRegisterClass *constrainRegClass(unsigned Reg,
const TargetRegisterClass *RC,
unsigned MinNumRegs = 0);
+ /// Constrain the register class or the register bank of the virtual register
+ /// \p Reg to be a common subclass and a common bank of both registers
+ /// provided respectively. Do nothing if any of the attributes (classes,
+ /// banks, or low-level types) of the registers are deemed incompatible, or if
+ /// the resulting register will have a class smaller than before and of size
+ /// less than \p MinNumRegs. Return true if such register attributes exist,
+ /// false otherwise.
+ ///
+ /// \note Assumes that each register has either a low-level type or a class
+ /// assigned, but not both. Use this method instead of constrainRegClass and
+ /// RegisterBankInfo::constrainGenericRegister everywhere but SelectionDAG
+ /// ISel / FastISel and GlobalISel's InstructionSelect pass respectively.
+ bool constrainRegAttrs(unsigned Reg, unsigned ConstrainingReg,
+ unsigned MinNumRegs = 0);
+
/// recomputeRegClass - Try to find a legal super-class of Reg's register
/// class that still satisfies the constraints from the instructions using
/// Reg. Returns true if Reg was upgraded.
@@ -668,26 +714,23 @@ public:
/// createVirtualRegister - Create and return a new virtual register in the
/// function with the specified register class.
- unsigned createVirtualRegister(const TargetRegisterClass *RegClass);
+ unsigned createVirtualRegister(const TargetRegisterClass *RegClass,
+ StringRef Name = "");
- /// Accessor for VRegToType. This accessor should only be used
- /// by global-isel related work.
- VRegToTypeMap &getVRegToType() const {
- if (!VRegToType)
- VRegToType.reset(new VRegToTypeMap);
- return *VRegToType.get();
- }
-
- /// Get the low-level type of \p VReg or LLT{} if VReg is not a generic
+ /// Get the low-level type of \p Reg or LLT{} if Reg is not a generic
/// (target independent) virtual register.
- LLT getType(unsigned VReg) const;
+ LLT getType(unsigned Reg) const {
+ if (TargetRegisterInfo::isVirtualRegister(Reg) && VRegToType.inBounds(Reg))
+ return VRegToType[Reg];
+ return LLT{};
+ }
/// Set the low-level type of \p VReg to \p Ty.
void setType(unsigned VReg, LLT Ty);
/// Create and return a new generic virtual register with low-level
/// type \p Ty.
- unsigned createGenericVirtualRegister(LLT Ty);
+ unsigned createGenericVirtualRegister(LLT Ty, StringRef Name = "");
/// Remove all types associated to virtual registers (after instruction
/// selection and constraining of all generic virtual registers).
@@ -698,7 +741,7 @@ public:
/// temporarily while constructing machine instructions. Most operations are
/// undefined on an incomplete register until one of setRegClass(),
/// setRegBank() or setSize() has been called on it.
- unsigned createIncompleteVirtualRegister();
+ unsigned createIncompleteVirtualRegister(StringRef Name = "");
/// getNumVirtRegs - Return the number of virtual registers created.
unsigned getNumVirtRegs() const { return VRegInfo.size(); }
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h b/contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h
index b5ea2080444d..5e91246b402c 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h
@@ -56,7 +56,7 @@ public:
/// MachineSSAUpdater constructor. If InsertedPHIs is specified, it will be
/// filled in with all PHI Nodes created by rewriting.
explicit MachineSSAUpdater(MachineFunction &MF,
- SmallVectorImpl<MachineInstr*> *InsertedPHIs = nullptr);
+ SmallVectorImpl<MachineInstr*> *NewPHI = nullptr);
MachineSSAUpdater(const MachineSSAUpdater &) = delete;
MachineSSAUpdater &operator=(const MachineSSAUpdater &) = delete;
~MachineSSAUpdater();
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h
index e327881de13a..85ffa4eda2b8 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h
+++ b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h
@@ -237,7 +237,7 @@ public:
/// be scheduled at the bottom.
virtual SUnit *pickNode(bool &IsTopNode) = 0;
- /// \brief Scheduler callback to notify that a new subtree is scheduled.
+ /// Scheduler callback to notify that a new subtree is scheduled.
virtual void scheduleTree(unsigned SubtreeID) {}
/// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an
@@ -318,11 +318,11 @@ public:
Mutations.push_back(std::move(Mutation));
}
- /// \brief True if an edge can be added from PredSU to SuccSU without creating
+ /// True if an edge can be added from PredSU to SuccSU without creating
/// a cycle.
bool canAddEdge(SUnit *SuccSU, SUnit *PredSU);
- /// \brief Add a DAG edge to the given SU with the given predecessor
+ /// Add a DAG edge to the given SU with the given predecessor
/// dependence data.
///
/// \returns true if the edge may be added without creating a cycle OR if an
@@ -374,7 +374,7 @@ protected:
/// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
void placeDebugValues();
- /// \brief dump the scheduled Sequence.
+ /// dump the scheduled Sequence.
void dumpSchedule() const;
// Lesser helpers...
@@ -445,7 +445,7 @@ public:
/// Return true if this DAG supports VReg liveness and RegPressure.
bool hasVRegLiveness() const override { return true; }
- /// \brief Return true if register pressure tracking is enabled.
+ /// Return true if register pressure tracking is enabled.
bool isTrackingPressure() const { return ShouldTrackPressure; }
/// Get current register pressure for the top scheduled instructions.
@@ -897,6 +897,28 @@ protected:
#endif
};
+// Utility functions used by heuristics in tryCandidate().
+bool tryLess(int TryVal, int CandVal,
+ GenericSchedulerBase::SchedCandidate &TryCand,
+ GenericSchedulerBase::SchedCandidate &Cand,
+ GenericSchedulerBase::CandReason Reason);
+bool tryGreater(int TryVal, int CandVal,
+ GenericSchedulerBase::SchedCandidate &TryCand,
+ GenericSchedulerBase::SchedCandidate &Cand,
+ GenericSchedulerBase::CandReason Reason);
+bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand,
+ GenericSchedulerBase::SchedCandidate &Cand,
+ SchedBoundary &Zone);
+bool tryPressure(const PressureChange &TryP,
+ const PressureChange &CandP,
+ GenericSchedulerBase::SchedCandidate &TryCand,
+ GenericSchedulerBase::SchedCandidate &Cand,
+ GenericSchedulerBase::CandReason Reason,
+ const TargetRegisterInfo *TRI,
+ const MachineFunction &MF);
+unsigned getWeakLeft(const SUnit *SU, bool isTop);
+int biasPhysRegCopy(const SUnit *SU, bool isTop);
+
/// GenericScheduler shrinks the unscheduled zone using heuristics to balance
/// the schedule.
class GenericScheduler : public GenericSchedulerBase {
@@ -963,9 +985,8 @@ protected:
const RegPressureTracker &RPTracker,
RegPressureTracker &TempTracker);
- void tryCandidate(SchedCandidate &Cand,
- SchedCandidate &TryCand,
- SchedBoundary *Zone);
+ virtual void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
+ SchedBoundary *Zone) const;
SUnit *pickNodeBidirectional(bool &IsTopNode);
diff --git a/contrib/llvm/include/llvm/CodeGen/MacroFusion.h b/contrib/llvm/include/llvm/CodeGen/MacroFusion.h
index dc105fdc68fd..a77226ddaf33 100644
--- a/contrib/llvm/include/llvm/CodeGen/MacroFusion.h
+++ b/contrib/llvm/include/llvm/CodeGen/MacroFusion.h
@@ -25,7 +25,7 @@ class ScheduleDAGMutation;
class TargetInstrInfo;
class TargetSubtargetInfo;
-/// \brief Check if the instr pair, FirstMI and SecondMI, should be fused
+/// Check if the instr pair, FirstMI and SecondMI, should be fused
/// together. Given SecondMI, when FirstMI is unspecified, then check if
/// SecondMI may be part of a fused pair at all.
using ShouldSchedulePredTy = std::function<bool(const TargetInstrInfo &TII,
@@ -33,13 +33,13 @@ using ShouldSchedulePredTy = std::function<bool(const TargetInstrInfo &TII,
const MachineInstr *FirstMI,
const MachineInstr &SecondMI)>;
-/// \brief Create a DAG scheduling mutation to pair instructions back to back
+/// Create a DAG scheduling mutation to pair instructions back to back
/// for instructions that benefit according to the target-specific
/// shouldScheduleAdjacent predicate function.
std::unique_ptr<ScheduleDAGMutation>
createMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent);
-/// \brief Create a DAG scheduling mutation to pair branch instructions with one
+/// Create a DAG scheduling mutation to pair branch instructions with one
/// of their predecessors back to back for instructions that benefit according
/// to the target-specific shouldScheduleAdjacent predicate function.
std::unique_ptr<ScheduleDAGMutation>
diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h
index e94878ced10d..a6d88b057dcb 100644
--- a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h
+++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h
@@ -29,12 +29,12 @@ namespace PBQP {
using NodeId = unsigned;
using EdgeId = unsigned;
- /// @brief Returns a value representing an invalid (non-existent) node.
+ /// Returns a value representing an invalid (non-existent) node.
static NodeId invalidNodeId() {
return std::numeric_limits<NodeId>::max();
}
- /// @brief Returns a value representing an invalid (non-existent) edge.
+ /// Returns a value representing an invalid (non-existent) edge.
static EdgeId invalidEdgeId() {
return std::numeric_limits<EdgeId>::max();
}
@@ -338,19 +338,19 @@ namespace PBQP {
const NodeEntry &NE;
};
- /// @brief Construct an empty PBQP graph.
+ /// Construct an empty PBQP graph.
Graph() = default;
- /// @brief Construct an empty PBQP graph with the given graph metadata.
+ /// Construct an empty PBQP graph with the given graph metadata.
Graph(GraphMetadata Metadata) : Metadata(std::move(Metadata)) {}
- /// @brief Get a reference to the graph metadata.
+ /// Get a reference to the graph metadata.
GraphMetadata& getMetadata() { return Metadata; }
- /// @brief Get a const-reference to the graph metadata.
+ /// Get a const-reference to the graph metadata.
const GraphMetadata& getMetadata() const { return Metadata; }
- /// @brief Lock this graph to the given solver instance in preparation
+ /// Lock this graph to the given solver instance in preparation
/// for running the solver. This method will call solver.handleAddNode for
/// each node in the graph, and handleAddEdge for each edge, to give the
/// solver an opportunity to set up any requried metadata.
@@ -363,13 +363,13 @@ namespace PBQP {
Solver->handleAddEdge(EId);
}
- /// @brief Release from solver instance.
+ /// Release from solver instance.
void unsetSolver() {
assert(Solver && "Solver not set.");
Solver = nullptr;
}
- /// @brief Add a node with the given costs.
+ /// Add a node with the given costs.
/// @param Costs Cost vector for the new node.
/// @return Node iterator for the added node.
template <typename OtherVectorT>
@@ -382,7 +382,7 @@ namespace PBQP {
return NId;
}
- /// @brief Add a node bypassing the cost allocator.
+ /// Add a node bypassing the cost allocator.
/// @param Costs Cost vector ptr for the new node (must be convertible to
/// VectorPtr).
/// @return Node iterator for the added node.
@@ -401,7 +401,7 @@ namespace PBQP {
return NId;
}
- /// @brief Add an edge between the given nodes with the given costs.
+ /// Add an edge between the given nodes with the given costs.
/// @param N1Id First node.
/// @param N2Id Second node.
/// @param Costs Cost matrix for new edge.
@@ -419,7 +419,7 @@ namespace PBQP {
return EId;
}
- /// @brief Add an edge bypassing the cost allocator.
+ /// Add an edge bypassing the cost allocator.
/// @param N1Id First node.
/// @param N2Id Second node.
/// @param Costs Cost matrix for new edge.
@@ -444,7 +444,7 @@ namespace PBQP {
return EId;
}
- /// @brief Returns true if the graph is empty.
+ /// Returns true if the graph is empty.
bool empty() const { return NodeIdSet(*this).empty(); }
NodeIdSet nodeIds() const { return NodeIdSet(*this); }
@@ -452,15 +452,15 @@ namespace PBQP {
AdjEdgeIdSet adjEdgeIds(NodeId NId) { return AdjEdgeIdSet(getNode(NId)); }
- /// @brief Get the number of nodes in the graph.
+ /// Get the number of nodes in the graph.
/// @return Number of nodes in the graph.
unsigned getNumNodes() const { return NodeIdSet(*this).size(); }
- /// @brief Get the number of edges in the graph.
+ /// Get the number of edges in the graph.
/// @return Number of edges in the graph.
unsigned getNumEdges() const { return EdgeIdSet(*this).size(); }
- /// @brief Set a node's cost vector.
+ /// Set a node's cost vector.
/// @param NId Node to update.
/// @param Costs New costs to set.
template <typename OtherVectorT>
@@ -471,7 +471,7 @@ namespace PBQP {
getNode(NId).Costs = AllocatedCosts;
}
- /// @brief Get a VectorPtr to a node's cost vector. Rarely useful - use
+ /// Get a VectorPtr to a node's cost vector. Rarely useful - use
/// getNodeCosts where possible.
/// @param NId Node id.
/// @return VectorPtr to node cost vector.
@@ -483,7 +483,7 @@ namespace PBQP {
return getNode(NId).Costs;
}
- /// @brief Get a node's cost vector.
+ /// Get a node's cost vector.
/// @param NId Node id.
/// @return Node cost vector.
const Vector& getNodeCosts(NodeId NId) const {
@@ -502,7 +502,7 @@ namespace PBQP {
return getNode(NId).getAdjEdgeIds().size();
}
- /// @brief Update an edge's cost matrix.
+ /// Update an edge's cost matrix.
/// @param EId Edge id.
/// @param Costs New cost matrix.
template <typename OtherMatrixT>
@@ -513,7 +513,7 @@ namespace PBQP {
getEdge(EId).Costs = AllocatedCosts;
}
- /// @brief Get a MatrixPtr to a node's cost matrix. Rarely useful - use
+ /// Get a MatrixPtr to a node's cost matrix. Rarely useful - use
/// getEdgeCosts where possible.
/// @param EId Edge id.
/// @return MatrixPtr to edge cost matrix.
@@ -525,7 +525,7 @@ namespace PBQP {
return getEdge(EId).Costs;
}
- /// @brief Get an edge's cost matrix.
+ /// Get an edge's cost matrix.
/// @param EId Edge id.
/// @return Edge cost matrix.
const Matrix& getEdgeCosts(EdgeId EId) const {
@@ -540,21 +540,21 @@ namespace PBQP {
return getEdge(EId).Metadata;
}
- /// @brief Get the first node connected to this edge.
+ /// 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) const {
return getEdge(EId).getN1Id();
}
- /// @brief Get the second node connected to this edge.
+ /// 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) const {
return getEdge(EId).getN2Id();
}
- /// @brief Get the "other" node connected to this edge.
+ /// Get the "other" node connected to this edge.
/// @param EId Edge id.
/// @param NId Node id for the "given" node.
/// @return The iterator for the "other" node connected to this edge.
@@ -566,7 +566,7 @@ namespace PBQP {
return E.getN1Id();
}
- /// @brief Get the edge connecting two nodes.
+ /// Get the edge connecting two nodes.
/// @param N1Id First node id.
/// @param N2Id Second node id.
/// @return An id for edge (N1Id, N2Id) if such an edge exists,
@@ -581,7 +581,7 @@ namespace PBQP {
return invalidEdgeId();
}
- /// @brief Remove a node from the graph.
+ /// Remove a node from the graph.
/// @param NId Node id.
void removeNode(NodeId NId) {
if (Solver)
@@ -598,7 +598,7 @@ namespace PBQP {
FreeNodeIds.push_back(NId);
}
- /// @brief Disconnect an edge from the given node.
+ /// Disconnect an edge from the given node.
///
/// Removes the given edge from the adjacency list of the given node.
/// This operation leaves the edge in an 'asymmetric' state: It will no
@@ -631,14 +631,14 @@ namespace PBQP {
E.disconnectFrom(*this, NId);
}
- /// @brief Convenience method to disconnect all neighbours from the given
+ /// Convenience method to disconnect all neighbours from the given
/// node.
void disconnectAllNeighborsFromNode(NodeId NId) {
for (auto AEId : adjEdgeIds(NId))
disconnectEdge(AEId, getEdgeOtherNodeId(AEId, NId));
}
- /// @brief Re-attach an edge to its nodes.
+ /// Re-attach an edge to its nodes.
///
/// Adds an edge that had been previously disconnected back into the
/// adjacency set of the nodes that the edge connects.
@@ -649,7 +649,7 @@ namespace PBQP {
Solver->handleReconnectEdge(EId, NId);
}
- /// @brief Remove an edge from the graph.
+ /// Remove an edge from the graph.
/// @param EId Edge id.
void removeEdge(EdgeId EId) {
if (Solver)
@@ -660,7 +660,7 @@ namespace PBQP {
Edges[EId].invalidate();
}
- /// @brief Remove all nodes and edges from the graph.
+ /// Remove all nodes and edges from the graph.
void clear() {
Nodes.clear();
FreeNodeIds.clear();
diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h
index ba405e816d10..d1432a3053c4 100644
--- a/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h
+++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h
@@ -22,34 +22,34 @@ namespace PBQP {
using PBQPNum = float;
-/// \brief PBQP Vector class.
+/// PBQP Vector class.
class Vector {
friend hash_code hash_value(const Vector &);
public:
- /// \brief Construct a PBQP vector of the given size.
+ /// Construct a PBQP vector of the given size.
explicit Vector(unsigned Length)
: Length(Length), Data(llvm::make_unique<PBQPNum []>(Length)) {}
- /// \brief Construct a PBQP vector with initializer.
+ /// Construct a PBQP vector with initializer.
Vector(unsigned Length, PBQPNum InitVal)
: Length(Length), Data(llvm::make_unique<PBQPNum []>(Length)) {
std::fill(Data.get(), Data.get() + Length, InitVal);
}
- /// \brief Copy construct a PBQP vector.
+ /// Copy construct a PBQP vector.
Vector(const Vector &V)
: Length(V.Length), Data(llvm::make_unique<PBQPNum []>(Length)) {
std::copy(V.Data.get(), V.Data.get() + Length, Data.get());
}
- /// \brief Move construct a PBQP vector.
+ /// Move construct a PBQP vector.
Vector(Vector &&V)
: Length(V.Length), Data(std::move(V.Data)) {
V.Length = 0;
}
- /// \brief Comparison operator.
+ /// Comparison operator.
bool operator==(const Vector &V) const {
assert(Length != 0 && Data && "Invalid vector");
if (Length != V.Length)
@@ -57,27 +57,27 @@ public:
return std::equal(Data.get(), Data.get() + Length, V.Data.get());
}
- /// \brief Return the length of the vector
+ /// Return the length of the vector
unsigned getLength() const {
assert(Length != 0 && Data && "Invalid vector");
return Length;
}
- /// \brief Element access.
+ /// Element access.
PBQPNum& operator[](unsigned Index) {
assert(Length != 0 && Data && "Invalid vector");
assert(Index < Length && "Vector element access out of bounds.");
return Data[Index];
}
- /// \brief Const element access.
+ /// Const element access.
const PBQPNum& operator[](unsigned Index) const {
assert(Length != 0 && Data && "Invalid vector");
assert(Index < Length && "Vector element access out of bounds.");
return Data[Index];
}
- /// \brief Add another vector to this one.
+ /// Add another vector to this one.
Vector& operator+=(const Vector &V) {
assert(Length != 0 && Data && "Invalid vector");
assert(Length == V.Length && "Vector length mismatch.");
@@ -86,7 +86,7 @@ public:
return *this;
}
- /// \brief Returns the index of the minimum value in this vector
+ /// Returns the index of the minimum value in this vector
unsigned minIndex() const {
assert(Length != 0 && Data && "Invalid vector");
return std::min_element(Data.get(), Data.get() + Length) - Data.get();
@@ -97,14 +97,14 @@ private:
std::unique_ptr<PBQPNum []> Data;
};
-/// \brief Return a hash_value for the given vector.
+/// Return a hash_value for the given vector.
inline hash_code hash_value(const Vector &V) {
unsigned *VBegin = reinterpret_cast<unsigned*>(V.Data.get());
unsigned *VEnd = reinterpret_cast<unsigned*>(V.Data.get() + V.Length);
return hash_combine(V.Length, hash_combine_range(VBegin, VEnd));
}
-/// \brief Output a textual representation of the given vector on the given
+/// Output a textual representation of the given vector on the given
/// output stream.
template <typename OStream>
OStream& operator<<(OStream &OS, const Vector &V) {
@@ -118,18 +118,18 @@ OStream& operator<<(OStream &OS, const Vector &V) {
return OS;
}
-/// \brief PBQP Matrix class
+/// PBQP Matrix class
class Matrix {
private:
friend hash_code hash_value(const Matrix &);
public:
- /// \brief Construct a PBQP Matrix with the given dimensions.
+ /// Construct a PBQP Matrix with the given dimensions.
Matrix(unsigned Rows, unsigned Cols) :
Rows(Rows), Cols(Cols), Data(llvm::make_unique<PBQPNum []>(Rows * Cols)) {
}
- /// \brief Construct a PBQP Matrix with the given dimensions and initial
+ /// Construct a PBQP Matrix with the given dimensions and initial
/// value.
Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal)
: Rows(Rows), Cols(Cols),
@@ -137,20 +137,20 @@ public:
std::fill(Data.get(), Data.get() + (Rows * Cols), InitVal);
}
- /// \brief Copy construct a PBQP matrix.
+ /// Copy construct a PBQP matrix.
Matrix(const Matrix &M)
: Rows(M.Rows), Cols(M.Cols),
Data(llvm::make_unique<PBQPNum []>(Rows * Cols)) {
std::copy(M.Data.get(), M.Data.get() + (Rows * Cols), Data.get());
}
- /// \brief Move construct a PBQP matrix.
+ /// Move construct a PBQP matrix.
Matrix(Matrix &&M)
: Rows(M.Rows), Cols(M.Cols), Data(std::move(M.Data)) {
M.Rows = M.Cols = 0;
}
- /// \brief Comparison operator.
+ /// Comparison operator.
bool operator==(const Matrix &M) const {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
if (Rows != M.Rows || Cols != M.Cols)
@@ -158,33 +158,33 @@ public:
return std::equal(Data.get(), Data.get() + (Rows * Cols), M.Data.get());
}
- /// \brief Return the number of rows in this matrix.
+ /// Return the number of rows in this matrix.
unsigned getRows() const {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
return Rows;
}
- /// \brief Return the number of cols in this matrix.
+ /// Return the number of cols in this matrix.
unsigned getCols() const {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
return Cols;
}
- /// \brief Matrix element access.
+ /// Matrix element access.
PBQPNum* operator[](unsigned R) {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
assert(R < Rows && "Row out of bounds.");
return Data.get() + (R * Cols);
}
- /// \brief Matrix element access.
+ /// Matrix element access.
const PBQPNum* operator[](unsigned R) const {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
assert(R < Rows && "Row out of bounds.");
return Data.get() + (R * Cols);
}
- /// \brief Returns the given row as a vector.
+ /// Returns the given row as a vector.
Vector getRowAsVector(unsigned R) const {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
Vector V(Cols);
@@ -193,7 +193,7 @@ public:
return V;
}
- /// \brief Returns the given column as a vector.
+ /// Returns the given column as a vector.
Vector getColAsVector(unsigned C) const {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
Vector V(Rows);
@@ -202,7 +202,7 @@ public:
return V;
}
- /// \brief Matrix transpose.
+ /// Matrix transpose.
Matrix transpose() const {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
Matrix M(Cols, Rows);
@@ -212,7 +212,7 @@ public:
return M;
}
- /// \brief Add the given matrix to this one.
+ /// Add the given matrix to this one.
Matrix& operator+=(const Matrix &M) {
assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
assert(Rows == M.Rows && Cols == M.Cols &&
@@ -234,7 +234,7 @@ private:
std::unique_ptr<PBQPNum []> Data;
};
-/// \brief Return a hash_code for the given matrix.
+/// Return a hash_code for the given matrix.
inline hash_code hash_value(const Matrix &M) {
unsigned *MBegin = reinterpret_cast<unsigned*>(M.Data.get());
unsigned *MEnd =
@@ -242,7 +242,7 @@ inline hash_code hash_value(const Matrix &M) {
return hash_combine(M.Rows, M.Cols, hash_combine_range(MBegin, MEnd));
}
-/// \brief Output a textual representation of the given matrix on the given
+/// Output a textual representation of the given matrix on the given
/// output stream.
template <typename OStream>
OStream& operator<<(OStream &OS, const Matrix &M) {
diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h b/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h
index 8aeb51936760..21b99027970d 100644
--- a/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h
+++ b/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h
@@ -23,7 +23,7 @@
namespace llvm {
namespace PBQP {
- /// \brief Reduce a node of degree one.
+ /// Reduce a node of degree one.
///
/// Propagate costs from the given node, which must be of degree one, to its
/// neighbor. Notify the problem domain.
@@ -166,7 +166,7 @@ namespace PBQP {
}
#endif
- // \brief Find a solution to a fully reduced graph by backpropagation.
+ // Find a solution to a fully reduced graph by backpropagation.
//
// Given a graph and a reduction order, pop each node from the reduction
// order and greedily compute a minimum solution based on the node costs, and
diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h
index 6a247277fdfa..4d4379fbc2c2 100644
--- a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h
+++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h
@@ -21,7 +21,7 @@
namespace llvm {
namespace PBQP {
- /// \brief Represents a solution to a PBQP problem.
+ /// Represents a solution to a PBQP problem.
///
/// To get the selection for each node in the problem use the getSelection method.
class Solution {
@@ -30,17 +30,17 @@ namespace PBQP {
SelectionsMap selections;
public:
- /// \brief Initialise an empty solution.
+ /// Initialise an empty solution.
Solution() = default;
- /// \brief Set the selection for a given node.
+ /// Set the selection for a given node.
/// @param nodeId Node id.
/// @param selection Selection for nodeId.
void setSelection(GraphBase::NodeId nodeId, unsigned selection) {
selections[nodeId] = selection;
}
- /// \brief Get a node's selection.
+ /// Get a node's selection.
/// @param nodeId Node id.
/// @return The selection for nodeId;
unsigned getSelection(GraphBase::NodeId nodeId) const {
diff --git a/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h b/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h
index 269b7a7b3a35..995467dc56d8 100644
--- a/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h
+++ b/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h
@@ -33,7 +33,7 @@ class PBQPRAGraph;
using PBQPRAGraph = PBQP::RegAlloc::PBQPRAGraph;
-/// @brief Abstract base for classes implementing PBQP register allocation
+/// Abstract base for classes implementing PBQP register allocation
/// constraints (e.g. Spill-costs, interference, coalescing).
class PBQPRAConstraint {
public:
@@ -44,7 +44,7 @@ private:
virtual void anchor();
};
-/// @brief PBQP register allocation constraint composer.
+/// PBQP register allocation constraint composer.
///
/// Constraints added to this list will be applied, in the order that they are
/// added, to the PBQP graph.
diff --git a/contrib/llvm/include/llvm/CodeGen/ParallelCG.h b/contrib/llvm/include/llvm/CodeGen/ParallelCG.h
index 14ef0ec408ba..dbf09ea31e20 100644
--- a/contrib/llvm/include/llvm/CodeGen/ParallelCG.h
+++ b/contrib/llvm/include/llvm/CodeGen/ParallelCG.h
@@ -40,7 +40,7 @@ std::unique_ptr<Module>
splitCodeGen(std::unique_ptr<Module> M, ArrayRef<raw_pwrite_stream *> OSs,
ArrayRef<llvm::raw_pwrite_stream *> BCOSs,
const std::function<std::unique_ptr<TargetMachine>()> &TMFactory,
- TargetMachine::CodeGenFileType FT = TargetMachine::CGFT_ObjectFile,
+ TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile,
bool PreserveLocals = false);
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/Passes.h b/contrib/llvm/include/llvm/CodeGen/Passes.h
index 064526b1efa7..cb12b14f4435 100644
--- a/contrib/llvm/include/llvm/CodeGen/Passes.h
+++ b/contrib/llvm/include/llvm/CodeGen/Passes.h
@@ -154,6 +154,9 @@ namespace llvm {
/// This pass adds dead/undef flags after analyzing subregister lanes.
extern char &DetectDeadLanesID;
+ /// This pass perform post-ra machine sink for COPY instructions.
+ extern char &PostRAMachineSinkingID;
+
/// FastRegisterAllocation Pass - This pass register allocates as fast as
/// possible. It is best suited for debug code where live ranges are short.
///
@@ -212,6 +215,10 @@ namespace llvm {
/// into tails of their predecessors.
extern char &TailDuplicateID;
+ /// Duplicate blocks with unconditional branches into tails of their
+ /// predecessors. Variant that works before register allocation.
+ extern char &EarlyTailDuplicateID;
+
/// MachineTraceMetrics - This pass computes critical path and CPU resource
/// usage in an ensemble of traces.
extern char &MachineTraceMetricsID;
@@ -269,9 +276,13 @@ namespace llvm {
/// memory operations.
extern char &ImplicitNullChecksID;
- /// MachineLICM - This pass performs LICM on machine instructions.
+ /// This pass performs loop invariant code motion on machine instructions.
extern char &MachineLICMID;
+ /// This pass performs loop invariant code motion on machine instructions.
+ /// This variant works before register allocation. \see MachineLICMID.
+ extern char &EarlyMachineLICMID;
+
/// MachineSinking - This pass performs sinking on machine instructions.
extern char &MachineSinkingID;
@@ -290,7 +301,7 @@ namespace llvm {
/// StackSlotColoring - This pass performs stack slot coloring.
extern char &StackSlotColoringID;
- /// \brief This pass lays out funclets contiguously.
+ /// This pass lays out funclets contiguously.
extern char &FuncletLayoutID;
/// This pass inserts the XRay instrumentation sleds if they are supported by
@@ -300,7 +311,7 @@ namespace llvm {
/// This pass inserts FEntry calls
extern char &FEntryInserterID;
- /// \brief This pass implements the "patchable-function" attribute.
+ /// This pass implements the "patchable-function" attribute.
extern char &PatchableFunctionID;
/// createStackProtectorPass - This pass adds stack protectors to functions.
@@ -318,13 +329,17 @@ namespace llvm {
/// createWinEHPass - Prepares personality functions used by MSVC on Windows,
/// in addition to the Itanium LSDA based personalities.
- FunctionPass *createWinEHPass();
+ FunctionPass *createWinEHPass(bool DemoteCatchSwitchPHIOnly = false);
/// createSjLjEHPreparePass - This pass adapts exception handling code to use
/// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow.
///
FunctionPass *createSjLjEHPreparePass();
+ /// createWasmEHPass - This pass adapts exception handling code to use
+ /// WebAssembly's exception handling scheme.
+ FunctionPass *createWasmEHPass();
+
/// LocalStackSlotAllocation - This pass assigns local frame indices to stack
/// slots relative to one another and allocates base registers to access them
/// when it is estimated by the target to be out of range of normal frame
@@ -369,7 +384,7 @@ namespace llvm {
///
ModulePass *createLowerEmuTLSPass();
- /// This pass lowers the @llvm.load.relative intrinsic to instructions.
+ /// This pass lowers the \@llvm.load.relative intrinsic to instructions.
/// This is unsafe to do earlier because a pass may combine the constant
/// initializer into the load, which may result in an overflowing evaluation.
ModulePass *createPreISelIntrinsicLoweringPass();
@@ -408,7 +423,7 @@ namespace llvm {
/// This pass performs outlining on machine instructions directly before
/// printing assembly.
- ModulePass *createMachineOutlinerPass(bool OutlineFromLinkOnceODRs = false);
+ ModulePass *createMachineOutlinerPass(bool RunOnAllFunctions = true);
/// This pass expands the experimental reduction intrinsics into sequences of
/// shuffles.
@@ -417,9 +432,15 @@ namespace llvm {
// This pass expands memcmp() to load/stores.
FunctionPass *createExpandMemCmpPass();
+ /// Creates Break False Dependencies pass. \see BreakFalseDeps.cpp
+ FunctionPass *createBreakFalseDeps();
+
// This pass expands indirectbr instructions.
FunctionPass *createIndirectBrExpandPass();
+ /// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp
+ FunctionPass *createCFIInstrInserter();
+
} // End llvm namespace
#endif
diff --git a/contrib/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h b/contrib/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h
new file mode 100644
index 000000000000..b21b745c8fd1
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h
@@ -0,0 +1,118 @@
+//==--- llvm/CodeGen/ReachingDefAnalysis.h - Reaching Def Analysis -*- C++ -*---==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file Reaching Defs Analysis pass.
+///
+/// This pass tracks for each instruction what is the “closest” reaching def of
+/// a given register. It is used by BreakFalseDeps (for clearance calculation)
+/// and ExecutionDomainFix (for arbitrating conflicting domains).
+///
+/// Note that this is different from the usual definition notion of liveness.
+/// The CPU doesn't care whether or not we consider a register killed.
+///
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_REACHINGDEFSANALYSIS_H
+#define LLVM_CODEGEN_REACHINGDEFSANALYSIS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/LoopTraversal.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+
+class MachineBasicBlock;
+class MachineInstr;
+
+/// This class provides the reaching def analysis.
+class ReachingDefAnalysis : public MachineFunctionPass {
+private:
+ MachineFunction *MF;
+ const TargetRegisterInfo *TRI;
+ unsigned NumRegUnits;
+ /// Instruction that defined each register, relative to the beginning of the
+ /// current basic block. When a LiveRegsDefInfo is used to represent a
+ /// live-out register, this value is relative to the end of the basic block,
+ /// so it will be a negative number.
+ using LiveRegsDefInfo = std::vector<int>;
+ LiveRegsDefInfo LiveRegs;
+
+ /// Keeps clearance information for all registers. Note that this
+ /// is different from the usual definition notion of liveness. The CPU
+ /// doesn't care whether or not we consider a register killed.
+ using OutRegsInfoMap = SmallVector<LiveRegsDefInfo, 4>;
+ OutRegsInfoMap MBBOutRegsInfos;
+
+ /// Current instruction number.
+ /// The first instruction in each basic block is 0.
+ int CurInstr;
+
+ /// Maps instructions to their instruction Ids, relative to the begining of
+ /// their basic blocks.
+ DenseMap<MachineInstr *, int> InstIds;
+
+ /// All reaching defs of a given RegUnit for a given MBB.
+ using MBBRegUnitDefs = SmallVector<int, 1>;
+ /// All reaching defs of all reg units for a given MBB
+ using MBBDefsInfo = std::vector<MBBRegUnitDefs>;
+ /// All reaching defs of all reg units for a all MBBs
+ using MBBReachingDefsInfo = SmallVector<MBBDefsInfo, 4>;
+ MBBReachingDefsInfo MBBReachingDefs;
+
+ /// Default values are 'nothing happened a long time ago'.
+ const int ReachingDefDefaultVal = -(1 << 20);
+
+public:
+ static char ID; // Pass identification, replacement for typeid
+
+ ReachingDefAnalysis() : MachineFunctionPass(ID) {
+ initializeReachingDefAnalysisPass(*PassRegistry::getPassRegistry());
+ }
+ void releaseMemory() override;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::NoVRegs);
+ }
+
+ /// Provides the instruction id of the closest reaching def instruction of
+ /// PhysReg that reaches MI, relative to the begining of MI's basic block.
+ int getReachingDef(MachineInstr *MI, int PhysReg);
+
+ /// Provides the clearance - the number of instructions since the closest
+ /// reaching def instuction of PhysReg that reaches MI.
+ int getClearance(MachineInstr *MI, MCPhysReg PhysReg);
+
+private:
+ /// Set up LiveRegs by merging predecessor live-out values.
+ void enterBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
+
+ /// Update live-out values.
+ void leaveBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
+
+ /// Process he given basic block.
+ void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
+
+ /// Update def-ages for registers defined by MI.
+ /// Also break dependencies on partial defs and undef uses.
+ void processDefs(MachineInstr *);
+};
+
+} // namespace llvm
+
+#endif // LLVM_CODEGEN_REACHINGDEFSANALYSIS_H
diff --git a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h
index 5b342863eb50..ba9763077d09 100644
--- a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h
+++ b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h
@@ -43,10 +43,10 @@ class raw_ostream;
namespace PBQP {
namespace RegAlloc {
-/// @brief Spill option index.
+/// Spill option index.
inline unsigned getSpillOptionIdx() { return 0; }
-/// \brief Metadata to speed allocatability test.
+/// Metadata to speed allocatability test.
///
/// Keeps track of the number of infinities in each row and column.
class MatrixMetadata {
@@ -89,7 +89,7 @@ private:
std::unique_ptr<bool[]> UnsafeCols;
};
-/// \brief Holds a vector of the allowed physical regs for a vreg.
+/// Holds a vector of the allowed physical regs for a vreg.
class AllowedRegVector {
friend hash_code hash_value(const AllowedRegVector &);
@@ -127,7 +127,7 @@ inline hash_code hash_value(const AllowedRegVector &OptRegs) {
hash_combine_range(OStart, OEnd));
}
-/// \brief Holds graph-level metadata relevant to PBQP RA problems.
+/// Holds graph-level metadata relevant to PBQP RA problems.
class GraphMetadata {
private:
using AllowedRegVecPool = ValuePool<AllowedRegVector>;
@@ -164,7 +164,7 @@ private:
AllowedRegVecPool AllowedRegVecs;
};
-/// \brief Holds solver state and other metadata relevant to each PBQP RA node.
+/// Holds solver state and other metadata relevant to each PBQP RA node.
class NodeMetadata {
public:
using AllowedRegVector = RegAlloc::AllowedRegVector;
@@ -505,14 +505,14 @@ private:
public:
PBQPRAGraph(GraphMetadata Metadata) : BaseT(std::move(Metadata)) {}
- /// @brief Dump this graph to dbgs().
+ /// Dump this graph to dbgs().
void dump() const;
- /// @brief Dump this graph to an output stream.
+ /// 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.
+ /// Print a representation of this graph in DOT format.
/// @param OS Output stream to print on.
void printDot(raw_ostream &OS) const;
};
@@ -527,7 +527,7 @@ inline Solution solve(PBQPRAGraph& G) {
} // end namespace RegAlloc
} // end namespace PBQP
-/// @brief Create a PBQP register allocator instance.
+/// Create a PBQP register allocator instance.
FunctionPass *
createPBQPRegisterAllocator(char *customPassID = nullptr);
diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h b/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h
index 2b14b78d621d..79054b9e33b7 100644
--- a/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h
+++ b/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h
@@ -171,10 +171,10 @@ class RegisterOperands {
public:
/// List of virtual registers and register units read by the instruction.
SmallVector<RegisterMaskPair, 8> Uses;
- /// \brief List of virtual registers and register units defined by the
+ /// List of virtual registers and register units defined by the
/// instruction which are not dead.
SmallVector<RegisterMaskPair, 8> Defs;
- /// \brief List of virtual registers and register units defined by the
+ /// List of virtual registers and register units defined by the
/// instruction but dead.
SmallVector<RegisterMaskPair, 8> DeadDefs;
@@ -219,7 +219,7 @@ public:
return const_cast<PressureDiffs*>(this)->operator[](Idx);
}
- /// \brief Record pressure difference induced by the given operand list to
+ /// Record pressure difference induced by the given operand list to
/// node with index \p Idx.
void addInstruction(unsigned Idx, const RegisterOperands &RegOpers,
const MachineRegisterInfo &MRI);
@@ -546,7 +546,7 @@ protected:
/// Add Reg to the live in set and increase max pressure.
void discoverLiveIn(RegisterMaskPair Pair);
- /// \brief Get the SlotIndex for the first nondebug instruction including or
+ /// Get the SlotIndex for the first nondebug instruction including or
/// after the current position.
SlotIndex getCurrSlot() const;
diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h
index 489c72b81a98..b6bd028a8cac 100644
--- a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h
+++ b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h
@@ -127,7 +127,7 @@ public:
/// Find an unused register of the specified register class.
/// Return 0 if none is found.
- unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const;
+ unsigned FindUnusedReg(const TargetRegisterClass *RC) const;
/// Add a scavenging frame index.
void addScavengingFrameIndex(int FI) {
@@ -158,7 +158,7 @@ public:
/// Returns the scavenged register.
/// This is deprecated as it depends on the quality of the kill flags being
/// present; Use scavengeRegisterBackwards() instead!
- unsigned scavengeRegister(const TargetRegisterClass *RegClass,
+ unsigned scavengeRegister(const TargetRegisterClass *RC,
MachineBasicBlock::iterator I, int SPAdj);
unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj) {
return scavengeRegister(RegClass, MBBI, SPAdj);
@@ -218,7 +218,7 @@ private:
/// Spill a register after position \p After and reload it before position
/// \p UseMI.
ScavengedInfo &spill(unsigned Reg, const TargetRegisterClass &RC, int SPAdj,
- MachineBasicBlock::iterator After,
+ MachineBasicBlock::iterator Before,
MachineBasicBlock::iterator &UseMI);
};
diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h b/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h
index eabadd8d784a..efd175eeed30 100644
--- a/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h
@@ -19,6 +19,7 @@
#ifndef LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H
#define LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
@@ -31,8 +32,6 @@ class Function;
class TargetMachine;
class PhysicalRegisterUsageInfo : public ImmutablePass {
- virtual void anchor();
-
public:
static char ID;
@@ -41,25 +40,20 @@ public:
initializePhysicalRegisterUsageInfoPass(Registry);
}
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
-
- /// To set TargetMachine *, which is used to print
- /// analysis when command line option -print-regusage is used.
- void setTargetMachine(const TargetMachine *TM_) { TM = TM_; }
+ /// Set TargetMachine which is used to print analysis.
+ void setTargetMachine(const TargetMachine &TM);
bool doInitialization(Module &M) override;
bool doFinalization(Module &M) override;
/// To store RegMask for given Function *.
- void storeUpdateRegUsageInfo(const Function *FP,
- std::vector<uint32_t> RegMask);
+ void storeUpdateRegUsageInfo(const Function &FP,
+ ArrayRef<uint32_t> RegMask);
- /// To query stored RegMask for given Function *, it will return nullptr if
- /// function is not known.
- const std::vector<uint32_t> *getRegUsageInfo(const Function *FP);
+ /// To query stored RegMask for given Function *, it will returns ane empty
+ /// array if function is not known.
+ ArrayRef<uint32_t> getRegUsageInfo(const Function &FP);
void print(raw_ostream &OS, const Module *M = nullptr) const override;
diff --git a/contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h b/contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h
index 03166ccdfe38..8d582ee298b6 100644
--- a/contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h
+++ b/contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h
@@ -32,7 +32,7 @@ namespace llvm {
ResourcePriorityQueue *PQ;
explicit resource_sort(ResourcePriorityQueue *pq) : PQ(pq) {}
- bool operator()(const SUnit* left, const SUnit* right) const;
+ bool operator()(const SUnit* LHS, const SUnit* RHS) const;
};
class ResourcePriorityQueue : public SchedulingPriorityQueue {
@@ -121,7 +121,7 @@ namespace llvm {
void remove(SUnit *SU) override;
/// scheduledNode - Main resource tracking point.
- void scheduledNode(SUnit *Node) override;
+ void scheduledNode(SUnit *SU) override;
bool isResourceAvailable(SUnit *SU);
void reserveResources(SUnit *SU);
diff --git a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h b/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h
index 016bef1702c4..28567a1ce437 100644
--- a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -29,7 +29,7 @@ namespace RTLIB {
///
enum Libcall {
#define HANDLE_LIBCALL(code, name) code,
- #include "RuntimeLibcalls.def"
+ #include "llvm/IR/RuntimeLibcalls.def"
#undef HANDLE_LIBCALL
};
diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h
index f3f2f05b877d..5e7837834ec8 100644
--- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h
+++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h
@@ -76,7 +76,7 @@ class TargetRegisterInfo;
};
private:
- /// \brief A pointer to the depending/depended-on SUnit, and an enum
+ /// A pointer to the depending/depended-on SUnit, and an enum
/// indicating the kind of the dependency.
PointerIntPair<SUnit *, 2, Kind> Dep;
@@ -137,7 +137,7 @@ class TargetRegisterInfo;
return !operator==(Other);
}
- /// \brief Returns the latency value for this edge, which roughly means the
+ /// Returns the latency value for this edge, which roughly means the
/// minimum number of cycles that must elapse between the predecessor and
/// the successor, given that they have this edge between them.
unsigned getLatency() const {
@@ -163,7 +163,7 @@ class TargetRegisterInfo;
return getKind() != Data;
}
- /// \brief Tests if this is an Order dependence between two memory accesses
+ /// Tests if this is an Order dependence between two memory accesses
/// where both sides of the dependence access memory in non-volatile and
/// fully modeled ways.
bool isNormalMemory() const {
@@ -181,7 +181,7 @@ class TargetRegisterInfo;
return (isNormalMemory() || isBarrier());
}
- /// \brief Tests if this is an Order dependence that is marked as
+ /// Tests if this is an Order dependence that is marked as
/// "must alias", meaning that the SUnits at either end of the edge have a
/// memory dependence on a known memory location.
bool isMustAlias() const {
@@ -196,13 +196,13 @@ class TargetRegisterInfo;
return getKind() == Order && Contents.OrdKind >= Weak;
}
- /// \brief Tests if this is an Order dependence that is marked as
+ /// Tests if this is an Order dependence that is marked as
/// "artificial", meaning it isn't necessary for correctness.
bool isArtificial() const {
return getKind() == Order && Contents.OrdKind == Artificial;
}
- /// \brief Tests if this is an Order dependence that is marked as "cluster",
+ /// Tests if this is an Order dependence that is marked as "cluster",
/// meaning it is artificial and wants to be adjacent.
bool isCluster() const {
return getKind() == Order && Contents.OrdKind == Cluster;
@@ -308,7 +308,7 @@ class TargetRegisterInfo;
nullptr; ///< Is a special copy node if != nullptr.
const TargetRegisterClass *CopySrcRC = nullptr;
- /// \brief Constructs an SUnit for pre-regalloc scheduling to represent an
+ /// Constructs an SUnit for pre-regalloc scheduling to represent an
/// SDNode and any nodes flagged to it.
SUnit(SDNode *node, unsigned nodenum)
: Node(node), NodeNum(nodenum), isVRegCycle(false), isCall(false),
@@ -319,7 +319,7 @@ class TargetRegisterInfo;
isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false),
isHeightCurrent(false) {}
- /// \brief Constructs an SUnit for post-regalloc scheduling to represent a
+ /// Constructs an SUnit for post-regalloc scheduling to represent a
/// MachineInstr.
SUnit(MachineInstr *instr, unsigned nodenum)
: Instr(instr), NodeNum(nodenum), isVRegCycle(false), isCall(false),
@@ -330,7 +330,7 @@ class TargetRegisterInfo;
isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false),
isHeightCurrent(false) {}
- /// \brief Constructs a placeholder SUnit.
+ /// Constructs a placeholder SUnit.
SUnit()
: isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false),
isCommutable(false), hasPhysRegUses(false), hasPhysRegDefs(false),
@@ -339,7 +339,7 @@ class TargetRegisterInfo;
isCloned(false), isUnbuffered(false), hasReservedResource(false),
isDepthCurrent(false), isHeightCurrent(false) {}
- /// \brief Boundary nodes are placeholders for the boundary of the
+ /// Boundary nodes are placeholders for the boundary of the
/// scheduling region.
///
/// BoundaryNodes can have DAG edges, including Data edges, but they do not
@@ -362,7 +362,7 @@ class TargetRegisterInfo;
return Node;
}
- /// \brief Returns true if this SUnit refers to a machine instruction as
+ /// Returns true if this SUnit refers to a machine instruction as
/// opposed to an SDNode.
bool isInstr() const { return Instr; }
@@ -384,7 +384,7 @@ class TargetRegisterInfo;
/// It also adds the current node as a successor of the specified node.
bool addPred(const SDep &D, bool Required = true);
- /// \brief Adds a barrier edge to SU by calling addPred(), with latency 0
+ /// Adds a barrier edge to SU by calling addPred(), with latency 0
/// generally or latency 1 for a store followed by a load.
bool addPredBarrier(SUnit *SU) {
SDep Dep(SU, SDep::Barrier);
@@ -406,7 +406,7 @@ class TargetRegisterInfo;
return Depth;
}
- /// \brief Returns the height of this node, which is the length of the
+ /// Returns the height of this node, which is the length of the
/// maximum path down to any node which has no successors.
unsigned getHeight() const {
if (!isHeightCurrent)
@@ -414,21 +414,21 @@ class TargetRegisterInfo;
return Height;
}
- /// \brief If NewDepth is greater than this node's depth value, sets it to
+ /// If NewDepth is greater than this node's depth value, sets it to
/// be the new depth value. This also recursively marks successor nodes
/// dirty.
void setDepthToAtLeast(unsigned NewDepth);
- /// \brief If NewDepth is greater than this node's depth value, set it to be
+ /// If NewDepth is greater than this node's depth value, set it to be
/// the new height value. This also recursively marks predecessor nodes
/// dirty.
void setHeightToAtLeast(unsigned NewHeight);
- /// \brief Sets a flag in this node to indicate that its stored Depth value
+ /// Sets a flag in this node to indicate that its stored Depth value
/// will require recomputation the next time getDepth() is called.
void setDepthDirty();
- /// \brief Sets a flag in this node to indicate that its stored Height value
+ /// Sets a flag in this node to indicate that its stored Height value
/// will require recomputation the next time getHeight() is called.
void setHeightDirty();
@@ -455,15 +455,15 @@ class TargetRegisterInfo;
return NumSuccsLeft == 0;
}
- /// \brief Orders this node's predecessor edges such that the critical path
+ /// Orders this node's predecessor edges such that the critical path
/// edge occurs first.
void biasCriticalPath();
void dump(const ScheduleDAG *G) const;
void dumpAll(const ScheduleDAG *G) const;
raw_ostream &print(raw_ostream &O,
- const SUnit *N = nullptr,
- const SUnit *X = nullptr) const;
+ const SUnit *Entry = nullptr,
+ const SUnit *Exit = nullptr) const;
raw_ostream &print(raw_ostream &O, const ScheduleDAG *G) const;
private:
@@ -497,7 +497,7 @@ class TargetRegisterInfo;
//===--------------------------------------------------------------------===//
- /// \brief This interface is used to plug different priorities computation
+ /// This interface is used to plug different priorities computation
/// algorithms into the list scheduler. It implements the interface of a
/// standard priority queue, where nodes are inserted in arbitrary order and
/// returned in priority order. The computation of the priority and the
@@ -609,7 +609,7 @@ class TargetRegisterInfo;
virtual void addCustomGraphFeatures(GraphWriter<ScheduleDAG*> &) const {}
#ifndef NDEBUG
- /// \brief Verifies that all SUnits were scheduled and that their state is
+ /// Verifies that all SUnits were scheduled and that their state is
/// consistent. Returns the number of scheduled SUnits.
unsigned VerifyScheduledDAG(bool isBottomUp);
#endif
@@ -708,7 +708,7 @@ class TargetRegisterInfo;
/// method.
void DFS(const SUnit *SU, int UpperBound, bool& HasLoop);
- /// \brief Reassigns topological indexes for the nodes in the DAG to
+ /// Reassigns topological indexes for the nodes in the DAG to
/// preserve the topological ordering.
void Shift(BitVector& Visited, int LowerBound, int UpperBound);
@@ -735,11 +735,11 @@ class TargetRegisterInfo;
/// Returns true if addPred(TargetSU, SU) creates a cycle.
bool WillCreateCycle(SUnit *TargetSU, SUnit *SU);
- /// \brief Updates the topological ordering to accommodate an edge to be
+ /// Updates the topological ordering to accommodate an edge to be
/// added from SUnit \p X to SUnit \p Y.
void AddPred(SUnit *Y, SUnit *X);
- /// \brief Updates the topological ordering to accommodate an an edge to be
+ /// Updates the topological ordering to accommodate an an edge to be
/// removed from the specified node \p N from the predecessors of the
/// current node \p M.
void RemovePred(SUnit *M, SUnit *N);
diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
index 14882205584e..520a23846f6e 100644
--- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -190,7 +190,7 @@ namespace llvm {
using SUList = std::list<SUnit *>;
protected:
- /// \brief A map from ValueType to SUList, used during DAG construction, as
+ /// A map from ValueType to SUList, used during DAG construction, as
/// a means of remembering which SUs depend on which memory locations.
class Value2SUsMap;
@@ -201,7 +201,7 @@ namespace llvm {
void reduceHugeMemNodeMaps(Value2SUsMap &stores,
Value2SUsMap &loads, unsigned N);
- /// \brief Adds a chain edge between SUa and SUb, but only if both
+ /// Adds a chain edge between SUa and SUb, but only if both
/// AliasAnalysis and Target fail to deny the dependency.
void addChainDependency(SUnit *SUa, SUnit *SUb,
unsigned Latency = 0);
@@ -286,7 +286,7 @@ namespace llvm {
/// Cleans up after scheduling in the given block.
virtual void finishBlock();
- /// \brief Initialize the DAG and common scheduler state for a new
+ /// Initialize the DAG and common scheduler state for a new
/// scheduling region. This does not actually create the DAG, only clears
/// it. The scheduling driver may call BuildSchedGraph multiple times per
/// scheduling region.
@@ -308,7 +308,7 @@ namespace llvm {
LiveIntervals *LIS = nullptr,
bool TrackLaneMasks = false);
- /// \brief Adds dependencies from instructions in the current list of
+ /// Adds dependencies from instructions in the current list of
/// instructions being scheduled to scheduling barrier. We want to make sure
/// instructions which define registers that are either used by the
/// terminator or are live-out are properly scheduled. This is especially
diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h
index d6a8c791392c..3ecc033ac35a 100644
--- a/contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h
+++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h
@@ -25,7 +25,7 @@ namespace llvm {
class raw_ostream;
-/// \brief Represent the ILP of the subDAG rooted at a DAG node.
+/// Represent the ILP of the subDAG rooted at a DAG node.
///
/// ILPValues summarize the DAG subtree rooted at each node. ILPValues are
/// valid for all nodes regardless of their subtree membership.
@@ -62,13 +62,13 @@ struct ILPValue {
void dump() const;
};
-/// \brief Compute the values of each DAG node for various metrics during DFS.
+/// Compute the values of each DAG node for various metrics during DFS.
class SchedDFSResult {
friend class SchedDFSImpl;
static const unsigned InvalidSubtreeID = ~0u;
- /// \brief Per-SUnit data computed during DFS for various metrics.
+ /// Per-SUnit data computed during DFS for various metrics.
///
/// A node's SubtreeID is set to itself when it is visited to indicate that it
/// is the root of a subtree. Later it is set to its parent to indicate an
@@ -81,7 +81,7 @@ class SchedDFSResult {
NodeData() = default;
};
- /// \brief Per-Subtree data computed during DFS.
+ /// Per-Subtree data computed during DFS.
struct TreeData {
unsigned ParentTreeID = InvalidSubtreeID;
unsigned SubInstrCount = 0;
@@ -89,7 +89,7 @@ class SchedDFSResult {
TreeData() = default;
};
- /// \brief Record a connection between subtrees and the connection level.
+ /// Record a connection between subtrees and the connection level.
struct Connection {
unsigned TreeID;
unsigned Level;
@@ -117,15 +117,15 @@ public:
SchedDFSResult(bool IsBU, unsigned lim)
: IsBottomUp(IsBU), SubtreeLimit(lim) {}
- /// \brief Get the node cutoff before subtrees are considered significant.
+ /// Get the node cutoff before subtrees are considered significant.
unsigned getSubtreeLimit() const { return SubtreeLimit; }
- /// \brief Return true if this DFSResult is uninitialized.
+ /// Return true if this DFSResult is uninitialized.
///
/// resize() initializes DFSResult, while compute() populates it.
bool empty() const { return DFSNodeData.empty(); }
- /// \brief Clear the results.
+ /// Clear the results.
void clear() {
DFSNodeData.clear();
DFSTreeData.clear();
@@ -133,37 +133,37 @@ public:
SubtreeConnectLevels.clear();
}
- /// \brief Initialize the result data with the size of the DAG.
+ /// Initialize the result data with the size of the DAG.
void resize(unsigned NumSUnits) {
DFSNodeData.resize(NumSUnits);
}
- /// \brief Compute various metrics for the DAG with given roots.
+ /// Compute various metrics for the DAG with given roots.
void compute(ArrayRef<SUnit> SUnits);
- /// \brief Get the number of instructions in the given subtree and its
+ /// Get the number of instructions in the given subtree and its
/// children.
unsigned getNumInstrs(const SUnit *SU) const {
return DFSNodeData[SU->NodeNum].InstrCount;
}
- /// \brief Get the number of instructions in the given subtree not including
+ /// Get the number of instructions in the given subtree not including
/// children.
unsigned getNumSubInstrs(unsigned SubtreeID) const {
return DFSTreeData[SubtreeID].SubInstrCount;
}
- /// \brief Get the ILP value for a DAG node.
+ /// Get the ILP value for a DAG node.
///
/// A leaf node has an ILP of 1/1.
ILPValue getILP(const SUnit *SU) const {
return ILPValue(DFSNodeData[SU->NodeNum].InstrCount, 1 + SU->getDepth());
}
- /// \brief The number of subtrees detected in this DAG.
+ /// The number of subtrees detected in this DAG.
unsigned getNumSubtrees() const { return SubtreeConnectLevels.size(); }
- /// \brief Get the ID of the subtree the given DAG node belongs to.
+ /// Get the ID of the subtree the given DAG node belongs to.
///
/// For convenience, if DFSResults have not been computed yet, give everything
/// tree ID 0.
@@ -174,7 +174,7 @@ public:
return DFSNodeData[SU->NodeNum].SubtreeID;
}
- /// \brief Get the connection level of a subtree.
+ /// Get the connection level of a subtree.
///
/// For bottom-up trees, the connection level is the latency depth (in cycles)
/// of the deepest connection to another subtree.
@@ -182,7 +182,7 @@ public:
return SubtreeConnectLevels[SubtreeID];
}
- /// \brief Scheduler callback to update SubtreeConnectLevels when a tree is
+ /// Scheduler callback to update SubtreeConnectLevels when a tree is
/// initially scheduled.
void scheduleTree(unsigned SubtreeID);
};
diff --git a/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
index 466ab532030c..3f75d108f282 100644
--- a/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
+++ b/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
@@ -106,7 +106,7 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer {
Scoreboard RequiredScoreboard;
public:
- ScoreboardHazardRecognizer(const InstrItineraryData *ItinData,
+ ScoreboardHazardRecognizer(const InstrItineraryData *II,
const ScheduleDAG *DAG,
const char *ParentDebugType = "");
diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h
index 6a5c2db34bb1..888f9425ff90 100644
--- a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -28,11 +28,12 @@
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/DivergenceAnalysis.h"
#include "llvm/CodeGen/DAGCombine.h"
+#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineMemOperand.h"
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/DebugLoc.h"
@@ -44,6 +45,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/RecyclingAllocator.h"
#include <algorithm>
#include <cassert>
@@ -71,8 +73,10 @@ class MachineConstantPoolValue;
class MCSymbol;
class OptimizationRemarkEmitter;
class SDDbgValue;
+class SDDbgLabel;
class SelectionDAG;
class SelectionDAGTargetInfo;
+class TargetLibraryInfo;
class TargetLowering;
class TargetMachine;
class TargetSubtargetInfo;
@@ -145,6 +149,7 @@ class SDDbgInfo {
BumpPtrAllocator Alloc;
SmallVector<SDDbgValue*, 32> DbgValues;
SmallVector<SDDbgValue*, 32> ByvalParmDbgValues;
+ SmallVector<SDDbgLabel*, 4> DbgLabels;
using DbgValMapType = DenseMap<const SDNode *, SmallVector<SDDbgValue *, 2>>;
DbgValMapType DbgValMap;
@@ -161,7 +166,11 @@ public:
DbgValMap[Node].push_back(V);
}
- /// \brief Invalidate all DbgValues attached to the node and remove
+ void add(SDDbgLabel *L) {
+ DbgLabels.push_back(L);
+ }
+
+ /// Invalidate all DbgValues attached to the node and remove
/// it from the Node-to-DbgValues map.
void erase(const SDNode *Node);
@@ -169,13 +178,14 @@ public:
DbgValMap.clear();
DbgValues.clear();
ByvalParmDbgValues.clear();
+ DbgLabels.clear();
Alloc.Reset();
}
BumpPtrAllocator &getAlloc() { return Alloc; }
bool empty() const {
- return DbgValues.empty() && ByvalParmDbgValues.empty();
+ return DbgValues.empty() && ByvalParmDbgValues.empty() && DbgLabels.empty();
}
ArrayRef<SDDbgValue*> getSDDbgValues(const SDNode *Node) {
@@ -186,11 +196,14 @@ public:
}
using DbgIterator = SmallVectorImpl<SDDbgValue*>::iterator;
+ using DbgLabelIterator = SmallVectorImpl<SDDbgLabel*>::iterator;
DbgIterator DbgBegin() { return DbgValues.begin(); }
DbgIterator DbgEnd() { return DbgValues.end(); }
DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); }
DbgIterator ByvalParmDbgEnd() { return ByvalParmDbgValues.end(); }
+ DbgLabelIterator DbgLabelBegin() { return DbgLabels.begin(); }
+ DbgLabelIterator DbgLabelEnd() { return DbgLabels.end(); }
};
void checkForCycles(const SelectionDAG *DAG, bool force = false);
@@ -210,11 +223,15 @@ class SelectionDAG {
const TargetMachine &TM;
const SelectionDAGTargetInfo *TSI = nullptr;
const TargetLowering *TLI = nullptr;
+ const TargetLibraryInfo *LibInfo = nullptr;
MachineFunction *MF;
Pass *SDAGISelPass = nullptr;
LLVMContext *Context;
CodeGenOpt::Level OptLevel;
+ DivergenceAnalysis * DA = nullptr;
+ FunctionLoweringInfo * FLI = nullptr;
+
/// The function-level optimization remark emitter. Used to emit remarks
/// whenever manipulating the DAG.
OptimizationRemarkEmitter *ORE;
@@ -248,7 +265,7 @@ class SelectionDAG {
/// Pool allocation for misc. objects that are created once per SelectionDAG.
BumpPtrAllocator Allocator;
- /// Tracks dbg_value information through SDISel.
+ /// Tracks dbg_value and dbg_label information through SDISel.
SDDbgInfo *DbgInfo;
uint16_t NextPersistentId = 0;
@@ -344,19 +361,7 @@ private:
.getRawSubclassData();
}
- void createOperands(SDNode *Node, ArrayRef<SDValue> Vals) {
- assert(!Node->OperandList && "Node already has operands");
- SDUse *Ops = OperandRecycler.allocate(
- ArrayRecycler<SDUse>::Capacity::get(Vals.size()), OperandAllocator);
-
- for (unsigned I = 0; I != Vals.size(); ++I) {
- Ops[I].setUser(Node);
- Ops[I].setInitial(Vals[I]);
- }
- Node->NumOperands = Vals.size();
- Node->OperandList = Ops;
- checkForCycles(Node);
- }
+ void createOperands(SDNode *Node, ArrayRef<SDValue> Vals);
void removeOperands(SDNode *Node) {
if (!Node->OperandList)
@@ -367,7 +372,7 @@ private:
Node->NumOperands = 0;
Node->OperandList = nullptr;
}
-
+ void CreateTopologicalOrder(std::vector<SDNode*>& Order);
public:
explicit SelectionDAG(const TargetMachine &TM, CodeGenOpt::Level);
SelectionDAG(const SelectionDAG &) = delete;
@@ -376,7 +381,12 @@ public:
/// Prepare this SelectionDAG to process code in the given MachineFunction.
void init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE,
- Pass *PassPtr);
+ Pass *PassPtr, const TargetLibraryInfo *LibraryInfo,
+ DivergenceAnalysis * Divergence);
+
+ void setFunctionLoweringInfo(FunctionLoweringInfo * FuncInfo) {
+ FLI = FuncInfo;
+ }
/// Clear state and free memory necessary to make this
/// SelectionDAG ready to process a new block.
@@ -389,6 +399,7 @@ public:
const TargetMachine &getTarget() const { return TM; }
const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); }
const TargetLowering &getTargetLoweringInfo() const { return *TLI; }
+ const TargetLibraryInfo &getLibInfo() const { return *LibInfo; }
const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; }
LLVMContext *getContext() const {return Context; }
OptimizationRemarkEmitter &getORE() const { return *ORE; }
@@ -460,6 +471,8 @@ public:
return Root;
}
+ void VerifyDAGDiverence();
+
/// This iterates over the nodes in the SelectionDAG, folding
/// certain types of nodes together, or eliminating superfluous nodes. The
/// Level argument controls whether Combine is allowed to produce nodes and
@@ -483,7 +496,7 @@ public:
/// the graph.
void Legalize();
- /// \brief Transforms a SelectionDAG node and any operands to it into a node
+ /// Transforms a SelectionDAG node and any operands to it into a node
/// that is compatible with the target instruction selector, as indicated by
/// the TargetLowering object.
///
@@ -534,7 +547,7 @@ public:
//===--------------------------------------------------------------------===//
// Node creation methods.
- /// \brief Create a ConstantSDNode wrapping a constant value.
+ /// Create a ConstantSDNode wrapping a constant value.
/// If VT is a vector type, the constant is splatted into a BUILD_VECTOR.
///
/// If only legal types can be produced, this does the necessary
@@ -567,9 +580,13 @@ public:
bool isOpaque = false) {
return getConstant(Val, DL, VT, true, isOpaque);
}
+
+ /// Create a true or false constant of type \p VT using the target's
+ /// BooleanContent for type \p OpVT.
+ SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT);
/// @}
- /// \brief Create a ConstantFPSDNode wrapping a constant value.
+ /// Create a ConstantFPSDNode wrapping a constant value.
/// If VT is a vector type, the constant is splatted into a BUILD_VECTOR.
///
/// If only legal types can be produced, this does the necessary
@@ -581,7 +598,7 @@ public:
bool isTarget = false);
SDValue getConstantFP(const APFloat &Val, const SDLoc &DL, EVT VT,
bool isTarget = false);
- SDValue getConstantFP(const ConstantFP &CF, const SDLoc &DL, EVT VT,
+ SDValue getConstantFP(const ConstantFP &V, const SDLoc &DL, EVT VT,
bool isTarget = false);
SDValue getTargetConstantFP(double Val, const SDLoc &DL, EVT VT) {
return getConstantFP(Val, DL, VT, true);
@@ -741,7 +758,7 @@ public:
return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);
}
- /// \brief Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to
+ /// Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to
/// the shuffle node in input but with swapped operands.
///
/// Example: shuffle A, B, <0,5,2,7> -> shuffle B, A, <4,1,6,3>
@@ -765,7 +782,7 @@ public:
/// Return the expression required to zero extend the Op
/// value assuming it was the smaller SrcTy value.
- SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT SrcTy);
+ SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT);
/// Return an operation which will any-extend the low lanes of the operand
/// into the specified vector type. For example,
@@ -793,10 +810,10 @@ public:
/// Create a bitwise NOT operation as (XOR Val, -1).
SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT);
- /// \brief Create a logical NOT operation as (XOR Val, BooleanOne).
+ /// Create a logical NOT operation as (XOR Val, BooleanOne).
SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT);
- /// \brief Create an add instruction with appropriate flags when used for
+ /// Create an add instruction with appropriate flags when used for
/// addressing some offset of an object. i.e. if a load is split into multiple
/// components, create an add nuw from the base pointer to the offset.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Op, int64_t Offset) {
@@ -862,17 +879,18 @@ public:
ArrayRef<SDValue> Ops, const SDNodeFlags Flags = SDNodeFlags());
SDValue getNode(unsigned Opcode, const SDLoc &DL, ArrayRef<EVT> ResultTys,
ArrayRef<SDValue> Ops);
- SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
ArrayRef<SDValue> Ops);
// Specialize based on number of operands.
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT);
- SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue Operand,
const SDNodeFlags Flags = SDNodeFlags());
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
SDValue N2, const SDNodeFlags Flags = SDNodeFlags());
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
- SDValue N2, SDValue N3);
+ SDValue N2, SDValue N3,
+ const SDNodeFlags Flags = SDNodeFlags());
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
SDValue N2, SDValue N3, SDValue N4);
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
@@ -880,15 +898,15 @@ public:
// Specialize again based on number of operands for nodes with a VTList
// rather than a single VT.
- SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs);
- SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N);
- SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N);
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1,
SDValue N2);
- SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1,
SDValue N2, SDValue N3);
- SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1,
SDValue N2, SDValue N3, SDValue N4);
- SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1,
+ SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1,
SDValue N2, SDValue N3, SDValue N4, SDValue N5);
/// Compute a TokenFactor to force all the incoming stack arguments to be
@@ -910,6 +928,23 @@ public:
SDValue Size, unsigned Align, bool isVol, bool isTailCall,
MachinePointerInfo DstPtrInfo);
+ SDValue getAtomicMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst,
+ unsigned DstAlign, SDValue Src, unsigned SrcAlign,
+ SDValue Size, Type *SizeTy, unsigned ElemSz,
+ bool isTailCall, MachinePointerInfo DstPtrInfo,
+ MachinePointerInfo SrcPtrInfo);
+
+ SDValue getAtomicMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst,
+ unsigned DstAlign, SDValue Src, unsigned SrcAlign,
+ SDValue Size, Type *SizeTy, unsigned ElemSz,
+ bool isTailCall, MachinePointerInfo DstPtrInfo,
+ MachinePointerInfo SrcPtrInfo);
+
+ SDValue getAtomicMemset(SDValue Chain, const SDLoc &dl, SDValue Dst,
+ unsigned DstAlign, SDValue Value, SDValue Size,
+ Type *SizeTy, unsigned ElemSz, bool isTailCall,
+ MachinePointerInfo DstPtrInfo);
+
/// Helper function to make it easier to build SetCC's if you just
/// have an ISD::CondCode instead of an SDValue.
///
@@ -1050,12 +1085,12 @@ public:
MachineMemOperand *MMO);
SDValue
getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr,
- MachinePointerInfo PtrInfo, EVT TVT, unsigned Alignment = 0,
+ MachinePointerInfo PtrInfo, EVT SVT, unsigned Alignment = 0,
MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone,
const AAMDNodes &AAInfo = AAMDNodes());
SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val,
- SDValue Ptr, EVT TVT, MachineMemOperand *MMO);
- SDValue getIndexedStore(SDValue OrigStoe, const SDLoc &dl, SDValue Base,
+ SDValue Ptr, EVT SVT, MachineMemOperand *MMO);
+ SDValue getIndexedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base,
SDValue Offset, ISD::MemIndexedMode AM);
/// Returns sum of the base pointer and offset.
@@ -1121,28 +1156,31 @@ public:
SDValue Op3, SDValue Op4, SDValue Op5);
SDNode *UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops);
+ // Propagates the change in divergence to users
+ void updateDivergence(SDNode * N);
+
/// These are used for target selectors to *mutate* the
/// specified node to have the specified return type, Target opcode, and
/// operands. Note that target opcodes are stored as
/// ~TargetOpcode in the node opcode field. The resultant node is returned.
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, SDValue Op1);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT,
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT);
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, SDValue Op1);
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT,
SDValue Op1, SDValue Op2);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT,
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT,
SDValue Op1, SDValue Op2, SDValue Op3);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT,
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT,
ArrayRef<SDValue> Ops);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1,
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, EVT VT2);
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1,
EVT VT2, ArrayRef<SDValue> Ops);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1,
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1,
EVT VT2, EVT VT3, ArrayRef<SDValue> Ops);
SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1,
EVT VT2, SDValue Op1);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1,
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1,
EVT VT2, SDValue Op1, SDValue Op2);
- SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs,
+ SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, SDVTList VTs,
ArrayRef<SDValue> Ops);
/// This *mutates* the specified node to have the specified
@@ -1197,7 +1235,7 @@ public:
SDValue Operand, SDValue Subreg);
/// Get the specified node if it's already available, or else return NULL.
- SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef<SDValue> Ops,
+ SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef<SDValue> Ops,
const SDNodeFlags Flags = SDNodeFlags());
/// Creates a SDDbgValue node.
@@ -1212,8 +1250,16 @@ public:
/// Creates a FrameIndex SDDbgValue node.
SDDbgValue *getFrameIndexDbgValue(DIVariable *Var, DIExpression *Expr,
- unsigned FI, const DebugLoc &DL,
- unsigned O);
+ unsigned FI, bool IsIndirect,
+ const DebugLoc &DL, unsigned O);
+
+ /// Creates a VReg SDDbgValue node.
+ SDDbgValue *getVRegDbgValue(DIVariable *Var, DIExpression *Expr,
+ unsigned VReg, bool IsIndirect,
+ const DebugLoc &DL, unsigned O);
+
+ /// Creates a SDDbgLabel node.
+ SDDbgLabel *getDbgLabel(DILabel *Label, const DebugLoc &DL, unsigned O);
/// Transfer debug values from one node to another, while optionally
/// generating fragment expressions for split-up values. If \p InvalidateDbg
@@ -1245,7 +1291,7 @@ public:
/// to be given new uses. These new uses of From are left in place, and
/// not automatically transferred to To.
///
- void ReplaceAllUsesWith(SDValue From, SDValue Op);
+ void ReplaceAllUsesWith(SDValue From, SDValue To);
void ReplaceAllUsesWith(SDNode *From, SDNode *To);
void ReplaceAllUsesWith(SDNode *From, const SDValue *To);
@@ -1296,6 +1342,9 @@ public:
/// value is produced by SD.
void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter);
+ /// Add a dbg_label SDNode.
+ void AddDbgLabel(SDDbgLabel *DB);
+
/// Get the debug values which reference the given SDNode.
ArrayRef<SDDbgValue*> GetDbgValues(const SDNode* SD) {
return DbgInfo->getSDDbgValues(SD);
@@ -1317,6 +1366,13 @@ public:
return DbgInfo->ByvalParmDbgEnd();
}
+ SDDbgInfo::DbgLabelIterator DbgLabelBegin() {
+ return DbgInfo->DbgLabelBegin();
+ }
+ SDDbgInfo::DbgLabelIterator DbgLabelEnd() {
+ return DbgInfo->DbgLabelEnd();
+ }
+
/// To be invoked on an SDNode that is slated to be erased. This
/// function mirrors \c llvm::salvageDebugInfo.
void salvageDebugInfo(SDNode &N);
@@ -1431,8 +1487,11 @@ public:
/// Test whether the given SDValue is known to never be NaN.
bool isKnownNeverNaN(SDValue Op) const;
- /// Test whether the given SDValue is known to never be positive or negative
- /// zero.
+ /// Test whether the given floating point SDValue is known to never be
+ /// positive or negative zero.
+ bool isKnownNeverZeroFloat(SDValue Op) const;
+
+ /// Test whether the given SDValue is known to contain non-zero value(s).
bool isKnownNeverZero(SDValue Op) const;
/// Test whether two SDValues are known to compare equal. This
diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h
index de6849a1eae1..86df0af7303f 100644
--- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h
@@ -110,6 +110,11 @@ public:
CodeGenOpt::Level OptLevel,
bool IgnoreChains = false);
+ static void InvalidateNodeId(SDNode *N);
+ static int getUninvalidatedNodeId(SDNode *N);
+
+ static void EnforceNodeIdInvariant(SDNode *N);
+
// Opcodes used by the DAG state machine:
enum BuiltinOpcodes {
OPC_Scope,
@@ -199,23 +204,28 @@ protected:
/// of the new node T.
void ReplaceUses(SDValue F, SDValue T) {
CurDAG->ReplaceAllUsesOfValueWith(F, T);
+ EnforceNodeIdInvariant(T.getNode());
}
/// ReplaceUses - replace all uses of the old nodes F with the use
/// of the new nodes T.
void ReplaceUses(const SDValue *F, const SDValue *T, unsigned Num) {
CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num);
+ for (unsigned i = 0; i < Num; ++i)
+ EnforceNodeIdInvariant(T[i].getNode());
}
/// ReplaceUses - replace all uses of the old node F with the use
/// of the new node T.
void ReplaceUses(SDNode *F, SDNode *T) {
CurDAG->ReplaceAllUsesWith(F, T);
+ EnforceNodeIdInvariant(T);
}
/// Replace all uses of \c F with \c T, then remove \c F from the DAG.
void ReplaceNode(SDNode *F, SDNode *T) {
CurDAG->ReplaceAllUsesWith(F, T);
+ EnforceNodeIdInvariant(T);
CurDAG->RemoveDeadNode(F);
}
@@ -270,7 +280,7 @@ public:
void SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
unsigned TableSize);
- /// \brief Return true if complex patterns for this target can mutate the
+ /// Return true if complex patterns for this target can mutate the
/// DAG.
virtual bool ComplexPatternFuncMutatesDAG() const {
return false;
@@ -282,14 +292,14 @@ private:
// Calls to these functions are generated by tblgen.
void Select_INLINEASM(SDNode *N);
- void Select_READ_REGISTER(SDNode *N);
- void Select_WRITE_REGISTER(SDNode *N);
+ void Select_READ_REGISTER(SDNode *Op);
+ void Select_WRITE_REGISTER(SDNode *Op);
void Select_UNDEF(SDNode *N);
void CannotYetSelect(SDNode *N);
private:
void DoInstructionSelection();
- SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs,
+ SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList,
ArrayRef<SDValue> Ops, unsigned EmitNodeInfo);
SDNode *MutateStrictFPToFP(SDNode *Node, unsigned NewOpc);
@@ -299,10 +309,10 @@ private:
/// instruction selected, false if no code should be emitted for it.
bool PrepareEHLandingPad();
- /// \brief Perform instruction selection on all basic blocks in the function.
+ /// Perform instruction selection on all basic blocks in the function.
void SelectAllBasicBlocks(const Function &Fn);
- /// \brief Perform instruction selection on a single basic block, for
+ /// Perform instruction selection on a single basic block, for
/// instructions between \p Begin and \p End. \p HadTailCall will be set
/// to true if a call in the block was translated as a tail call.
void SelectBasicBlock(BasicBlock::const_iterator Begin,
@@ -312,7 +322,7 @@ private:
void CodeGenAndEmitDAG();
- /// \brief Generate instructions for lowering the incoming arguments of the
+ /// Generate instructions for lowering the incoming arguments of the
/// given function.
void LowerArguments(const Function &F);
diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 522c2f1b2cb2..1af22185d366 100644
--- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -31,17 +31,18 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineMemOperand.h"
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Operator.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MachineValueType.h"
#include <algorithm>
#include <cassert>
#include <climits>
@@ -189,8 +190,10 @@ public:
inline bool isUndef() const;
inline unsigned getMachineOpcode() const;
inline const DebugLoc &getDebugLoc() const;
- inline void dump(const SelectionDAG *G = nullptr) const;
- inline void dumpr(const SelectionDAG *G = nullptr) const;
+ inline void dump() const;
+ inline void dump(const SelectionDAG *G) const;
+ inline void dumpr() const;
+ inline void dumpr(const SelectionDAG *G) const;
/// Return true if this operand (which must be a chain) reaches the
/// specified operand without crossing any side-effecting instructions.
@@ -357,21 +360,34 @@ private:
bool NoUnsignedWrap : 1;
bool NoSignedWrap : 1;
bool Exact : 1;
- bool UnsafeAlgebra : 1;
bool NoNaNs : 1;
bool NoInfs : 1;
bool NoSignedZeros : 1;
bool AllowReciprocal : 1;
bool VectorReduction : 1;
bool AllowContract : 1;
+ bool ApproximateFuncs : 1;
+ bool AllowReassociation : 1;
public:
/// Default constructor turns off all optimization flags.
SDNodeFlags()
: AnyDefined(false), NoUnsignedWrap(false), NoSignedWrap(false),
- Exact(false), UnsafeAlgebra(false), NoNaNs(false), NoInfs(false),
+ Exact(false), NoNaNs(false), NoInfs(false),
NoSignedZeros(false), AllowReciprocal(false), VectorReduction(false),
- AllowContract(false) {}
+ AllowContract(false), ApproximateFuncs(false),
+ AllowReassociation(false) {}
+
+ /// Propagate the fast-math-flags from an IR FPMathOperator.
+ void copyFMF(const FPMathOperator &FPMO) {
+ setNoNaNs(FPMO.hasNoNaNs());
+ setNoInfs(FPMO.hasNoInfs());
+ setNoSignedZeros(FPMO.hasNoSignedZeros());
+ setAllowReciprocal(FPMO.hasAllowReciprocal());
+ setAllowContract(FPMO.hasAllowContract());
+ setApproximateFuncs(FPMO.hasApproxFunc());
+ setAllowReassociation(FPMO.hasAllowReassoc());
+ }
/// Sets the state of the flags to the defined state.
void setDefined() { AnyDefined = true; }
@@ -391,10 +407,6 @@ public:
setDefined();
Exact = b;
}
- void setUnsafeAlgebra(bool b) {
- setDefined();
- UnsafeAlgebra = b;
- }
void setNoNaNs(bool b) {
setDefined();
NoNaNs = b;
@@ -419,18 +431,32 @@ public:
setDefined();
AllowContract = b;
}
+ void setApproximateFuncs(bool b) {
+ setDefined();
+ ApproximateFuncs = b;
+ }
+ void setAllowReassociation(bool b) {
+ setDefined();
+ AllowReassociation = b;
+ }
// These are accessors for each flag.
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
bool hasNoSignedWrap() const { return NoSignedWrap; }
bool hasExact() const { return Exact; }
- bool hasUnsafeAlgebra() const { return UnsafeAlgebra; }
bool hasNoNaNs() const { return NoNaNs; }
bool hasNoInfs() const { return NoInfs; }
bool hasNoSignedZeros() const { return NoSignedZeros; }
bool hasAllowReciprocal() const { return AllowReciprocal; }
bool hasVectorReduction() const { return VectorReduction; }
bool hasAllowContract() const { return AllowContract; }
+ bool hasApproximateFuncs() const { return ApproximateFuncs; }
+ bool hasAllowReassociation() const { return AllowReassociation; }
+
+ bool isFast() const {
+ return NoSignedZeros && AllowReciprocal && NoNaNs && NoInfs &&
+ AllowContract && ApproximateFuncs && AllowReassociation;
+ }
/// Clear any flags in this flag set that aren't also set in Flags.
/// If the given Flags are undefined then don't do anything.
@@ -440,13 +466,14 @@ public:
NoUnsignedWrap &= Flags.NoUnsignedWrap;
NoSignedWrap &= Flags.NoSignedWrap;
Exact &= Flags.Exact;
- UnsafeAlgebra &= Flags.UnsafeAlgebra;
NoNaNs &= Flags.NoNaNs;
NoInfs &= Flags.NoInfs;
NoSignedZeros &= Flags.NoSignedZeros;
AllowReciprocal &= Flags.AllowReciprocal;
VectorReduction &= Flags.VectorReduction;
AllowContract &= Flags.AllowContract;
+ ApproximateFuncs &= Flags.ApproximateFuncs;
+ AllowReassociation &= Flags.AllowReassociation;
}
};
@@ -466,11 +493,13 @@ protected:
friend class SDNode;
friend class MemIntrinsicSDNode;
friend class MemSDNode;
+ friend class SelectionDAG;
uint16_t HasDebugValue : 1;
uint16_t IsMemIntrinsic : 1;
+ uint16_t IsDivergent : 1;
};
- enum { NumSDNodeBits = 2 };
+ enum { NumSDNodeBits = 3 };
class ConstantSDNodeBitfields {
friend class ConstantSDNode;
@@ -540,7 +569,7 @@ protected:
static_assert(sizeof(ConstantSDNodeBitfields) <= 2, "field too wide");
static_assert(sizeof(MemSDNodeBitfields) <= 2, "field too wide");
static_assert(sizeof(LSBaseSDNodeBitfields) <= 2, "field too wide");
- static_assert(sizeof(LoadSDNodeBitfields) <= 4, "field too wide");
+ static_assert(sizeof(LoadSDNodeBitfields) <= 2, "field too wide");
static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide");
private:
@@ -662,6 +691,8 @@ public:
bool getHasDebugValue() const { return SDNodeBits.HasDebugValue; }
void setHasDebugValue(bool b) { SDNodeBits.HasDebugValue = b; }
+ bool isDivergent() const { return SDNodeBits.IsDivergent; }
+
/// Return true if there are no uses of this node.
bool use_empty() const { return UseList == nullptr; }
@@ -796,16 +827,44 @@ public:
/// searches to be performed in parallel, caching of results across
/// queries and incremental addition to Worklist. Stops early if N is
/// found but will resume. Remember to clear Visited and Worklists
- /// if DAG changes.
+ /// if DAG changes. MaxSteps gives a maximum number of nodes to visit before
+ /// giving up. The TopologicalPrune flag signals that positive NodeIds are
+ /// topologically ordered (Operands have strictly smaller node id) and search
+ /// can be pruned leveraging this.
static bool hasPredecessorHelper(const SDNode *N,
SmallPtrSetImpl<const SDNode *> &Visited,
SmallVectorImpl<const SDNode *> &Worklist,
- unsigned int MaxSteps = 0) {
+ unsigned int MaxSteps = 0,
+ bool TopologicalPrune = false) {
+ SmallVector<const SDNode *, 8> DeferredNodes;
if (Visited.count(N))
return true;
+
+ // Node Id's are assigned in three places: As a topological
+ // ordering (> 0), during legalization (results in values set to
+ // 0), new nodes (set to -1). If N has a topolgical id then we
+ // know that all nodes with ids smaller than it cannot be
+ // successors and we need not check them. Filter out all node
+ // that can't be matches. We add them to the worklist before exit
+ // in case of multiple calls. Note that during selection the topological id
+ // may be violated if a node's predecessor is selected before it. We mark
+ // this at selection negating the id of unselected successors and
+ // restricting topological pruning to positive ids.
+
+ int NId = N->getNodeId();
+ // If we Invalidated the Id, reconstruct original NId.
+ if (NId < -1)
+ NId = -(NId + 1);
+
+ bool Found = false;
while (!Worklist.empty()) {
const SDNode *M = Worklist.pop_back_val();
- bool Found = false;
+ int MId = M->getNodeId();
+ if (TopologicalPrune && M->getOpcode() != ISD::TokenFactor && (NId > 0) &&
+ (MId > 0) && (MId < NId)) {
+ DeferredNodes.push_back(M);
+ continue;
+ }
for (const SDValue &OpV : M->op_values()) {
SDNode *Op = OpV.getNode();
if (Visited.insert(Op).second)
@@ -814,11 +873,16 @@ public:
Found = true;
}
if (Found)
- return true;
+ break;
if (MaxSteps != 0 && Visited.size() >= MaxSteps)
- return false;
+ break;
}
- return false;
+ // Push deferred nodes back on worklist.
+ Worklist.append(DeferredNodes.begin(), DeferredNodes.end());
+ // If we bailed early, conservatively return found.
+ if (MaxSteps != 0 && Visited.size() >= MaxSteps)
+ return true;
+ return Found;
}
/// Return true if all the users of N are contained in Nodes.
@@ -884,6 +948,7 @@ public:
const SDNodeFlags getFlags() const { return Flags; }
void setFlags(SDNodeFlags NewFlags) { Flags = NewFlags; }
+ bool isFast() { return Flags.isFast(); }
/// Clear any flags in this node that aren't also set in Flags.
/// If Flags is not in a defined state then this has no effect.
@@ -1089,10 +1154,18 @@ inline const DebugLoc &SDValue::getDebugLoc() const {
return Node->getDebugLoc();
}
+inline void SDValue::dump() const {
+ return Node->dump();
+}
+
inline void SDValue::dump(const SelectionDAG *G) const {
return Node->dump(G);
}
+inline void SDValue::dumpr() const {
+ return Node->dumpr();
+}
+
inline void SDValue::dumpr(const SelectionDAG *G) const {
return Node->dumpr(G);
}
@@ -1173,7 +1246,7 @@ protected:
public:
MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTs,
- EVT MemoryVT, MachineMemOperand *MMO);
+ EVT memvt, MachineMemOperand *MMO);
bool readMem() const { return MMO->isLoad(); }
bool writeMem() const { return MMO->isStore(); }
@@ -1190,7 +1263,8 @@ public:
/// encoding of the volatile flag, as well as bits used by subclasses. This
/// function should only be used to compute a FoldingSetNodeID value.
/// The HasDebugValue bit is masked out because CSE map needs to match
- /// nodes with debug info with nodes without debug info.
+ /// nodes with debug info with nodes without debug info. Same is about
+ /// isDivergent bit.
unsigned getRawSubclassData() const {
uint16_t Data;
union {
@@ -1199,6 +1273,7 @@ public:
};
memcpy(&RawSDNodeBits, &this->RawSDNodeBits, sizeof(this->RawSDNodeBits));
SDNodeBits.HasDebugValue = 0;
+ SDNodeBits.IsDivergent = false;
memcpy(&Data, &RawSDNodeBits, sizeof(RawSDNodeBits));
return Data;
}
@@ -1267,6 +1342,7 @@ public:
N->getOpcode() == ISD::ATOMIC_LOAD_ADD ||
N->getOpcode() == ISD::ATOMIC_LOAD_SUB ||
N->getOpcode() == ISD::ATOMIC_LOAD_AND ||
+ N->getOpcode() == ISD::ATOMIC_LOAD_CLR ||
N->getOpcode() == ISD::ATOMIC_LOAD_OR ||
N->getOpcode() == ISD::ATOMIC_LOAD_XOR ||
N->getOpcode() == ISD::ATOMIC_LOAD_NAND ||
@@ -1318,6 +1394,7 @@ public:
N->getOpcode() == ISD::ATOMIC_LOAD_ADD ||
N->getOpcode() == ISD::ATOMIC_LOAD_SUB ||
N->getOpcode() == ISD::ATOMIC_LOAD_AND ||
+ N->getOpcode() == ISD::ATOMIC_LOAD_CLR ||
N->getOpcode() == ISD::ATOMIC_LOAD_OR ||
N->getOpcode() == ISD::ATOMIC_LOAD_XOR ||
N->getOpcode() == ISD::ATOMIC_LOAD_NAND ||
@@ -1421,9 +1498,8 @@ class ConstantSDNode : public SDNode {
const ConstantInt *Value;
- ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val,
- const DebugLoc &DL, EVT VT)
- : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL,
+ ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, EVT VT)
+ : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DebugLoc(),
getSDVTList(VT)),
Value(val) {
ConstantSDNodeBits.IsOpaque = isOpaque;
@@ -1459,10 +1535,9 @@ class ConstantFPSDNode : public SDNode {
const ConstantFP *Value;
- ConstantFPSDNode(bool isTarget, const ConstantFP *val, const DebugLoc &DL,
- EVT VT)
- : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, DL,
- getSDVTList(VT)),
+ ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT)
+ : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0,
+ DebugLoc(), getSDVTList(VT)),
Value(val) {}
public:
@@ -1519,10 +1594,10 @@ bool isOneConstant(SDValue V);
bool isBitwiseNot(SDValue V);
/// Returns the SDNode if it is a constant splat BuildVector or constant int.
-ConstantSDNode *isConstOrConstSplat(SDValue V);
+ConstantSDNode *isConstOrConstSplat(SDValue N);
/// Returns the SDNode if it is a constant splat BuildVector or constant float.
-ConstantFPSDNode *isConstOrConstSplatFP(SDValue V);
+ConstantFPSDNode *isConstOrConstSplatFP(SDValue N);
class GlobalAddressSDNode : public SDNode {
friend class SelectionDAG;
@@ -1533,7 +1608,7 @@ class GlobalAddressSDNode : public SDNode {
GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL,
const GlobalValue *GA, EVT VT, int64_t o,
- unsigned char TargetFlags);
+ unsigned char TF);
public:
const GlobalValue *getGlobal() const { return TheGlobal; }
@@ -1714,13 +1789,13 @@ public:
unsigned MinSplatBits = 0,
bool isBigEndian = false) const;
- /// \brief Returns the splatted value or a null value if this is not a splat.
+ /// Returns the splatted value or a null value if this is not a splat.
///
/// If passed a non-null UndefElements bitvector, it will resize it to match
/// the vector width and set the bits where elements are undef.
SDValue getSplatValue(BitVector *UndefElements = nullptr) const;
- /// \brief Returns the splatted constant or null if this is not a constant
+ /// Returns the splatted constant or null if this is not a constant
/// splat.
///
/// If passed a non-null UndefElements bitvector, it will resize it to match
@@ -1728,7 +1803,7 @@ public:
ConstantSDNode *
getConstantSplatNode(BitVector *UndefElements = nullptr) const;
- /// \brief Returns the splatted constant FP or null if this is not a constant
+ /// Returns the splatted constant FP or null if this is not a constant
/// FP splat.
///
/// If passed a non-null UndefElements bitvector, it will resize it to match
@@ -1736,7 +1811,7 @@ public:
ConstantFPSDNode *
getConstantFPSplatNode(BitVector *UndefElements = nullptr) const;
- /// \brief If this is a constant FP splat and the splatted constant FP is an
+ /// If this is a constant FP splat and the splatted constant FP is an
/// exact power or 2, return the log base 2 integer value. Otherwise,
/// return -1.
///
@@ -2120,13 +2195,14 @@ public:
: MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {}
// In the both nodes address is Op1, mask is Op2:
- // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value
- // MaskedScatterSDNode (Chain, value, mask, base, index)
+ // MaskedGatherSDNode (Chain, passthru, mask, base, index, scale)
+ // MaskedScatterSDNode (Chain, value, mask, base, index, scale)
// Mask is a vector of i1 elements
const SDValue &getBasePtr() const { return getOperand(3); }
const SDValue &getIndex() const { return getOperand(4); }
const SDValue &getMask() const { return getOperand(2); }
const SDValue &getValue() const { return getOperand(1); }
+ const SDValue &getScale() const { return getOperand(5); }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::MGATHER ||
@@ -2329,6 +2405,17 @@ namespace ISD {
cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;
}
+ /// Attempt to match a unary predicate against a scalar/splat constant or
+ /// every element of a constant BUILD_VECTOR.
+ bool matchUnaryPredicate(SDValue Op,
+ std::function<bool(ConstantSDNode *)> Match);
+
+ /// Attempt to match a binary predicate against a pair of scalar/splat
+ /// constants or every element of a pair of constant BUILD_VECTORs.
+ bool matchBinaryPredicate(
+ SDValue LHS, SDValue RHS,
+ std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match);
+
} // end namespace ISD
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h
index 3a91e363f923..334267d9828b 100644
--- a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h
+++ b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h
@@ -578,9 +578,9 @@ class raw_ostream;
assert(!MI.isInsideBundle() &&
"Instructions inside bundles should use bundle start's slot.");
assert(mi2iMap.find(&MI) == mi2iMap.end() && "Instr already indexed.");
- // Numbering DBG_VALUE instructions could cause code generation to be
+ // Numbering debug instructions could cause code generation to be
// affected by debug information.
- assert(!MI.isDebugValue() && "Cannot number DBG_VALUE instructions.");
+ assert(!MI.isDebugInstr() && "Cannot number debug instructions.");
assert(MI.getParent() != nullptr && "Instr must be added to function.");
@@ -674,10 +674,10 @@ class raw_ostream;
idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb));
renumberIndexes(newItr);
- std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare());
+ llvm::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare());
}
- /// \brief Free the resources that were required to maintain a SlotIndex.
+ /// Free the resources that were required to maintain a SlotIndex.
///
/// Once an index is no longer needed (for instance because the instruction
/// at that index has been moved), the resources required to maintain the
diff --git a/contrib/llvm/include/llvm/CodeGen/StackMaps.h b/contrib/llvm/include/llvm/CodeGen/StackMaps.h
index 4407114d2741..3c9850265737 100644
--- a/contrib/llvm/include/llvm/CodeGen/StackMaps.h
+++ b/contrib/llvm/include/llvm/CodeGen/StackMaps.h
@@ -29,7 +29,7 @@ class MCStreamer;
class raw_ostream;
class TargetRegisterInfo;
-/// \brief MI-level stackmap operands.
+/// MI-level stackmap operands.
///
/// MI stackmap operations take the form:
/// <id>, <numBytes>, live args...
@@ -60,7 +60,7 @@ public:
}
};
-/// \brief MI-level patchpoint operands.
+/// MI-level patchpoint operands.
///
/// MI patchpoint operations take the form:
/// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
@@ -137,7 +137,7 @@ public:
return getVarIdx();
}
- /// \brief Get the next scratch register operand index.
+ /// Get the next scratch register operand index.
unsigned getNextScratchIdx(unsigned StartIdx = 0) const;
};
@@ -236,15 +236,15 @@ public:
FnInfos.clear();
}
- /// \brief Generate a stackmap record for a stackmap instruction.
+ /// Generate a stackmap record for a stackmap instruction.
///
/// MI must be a raw STACKMAP, not a PATCHPOINT.
void recordStackMap(const MachineInstr &MI);
- /// \brief Generate a stackmap record for a patchpoint instruction.
+ /// Generate a stackmap record for a patchpoint instruction.
void recordPatchPoint(const MachineInstr &MI);
- /// \brief Generate a stackmap record for a statepoint instruction.
+ /// 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
@@ -293,11 +293,11 @@ private:
MachineInstr::const_mop_iterator MOE, LocationVec &Locs,
LiveOutVec &LiveOuts) const;
- /// \brief Create a live-out register record for the given register @p Reg.
+ /// Create a live-out register record for the given register @p Reg.
LiveOutReg createLiveOutReg(unsigned Reg,
const TargetRegisterInfo *TRI) const;
- /// \brief Parse the register live-out mask and return a vector of live-out
+ /// Parse the register live-out mask and return a vector of live-out
/// registers that need to be recorded in the stackmap.
LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;
@@ -311,16 +311,16 @@ private:
MachineInstr::const_mop_iterator MOE,
bool recordResult = false);
- /// \brief Emit the stackmap header.
+ /// Emit the stackmap header.
void emitStackmapHeader(MCStreamer &OS);
- /// \brief Emit the function frame record for each function.
+ /// Emit the function frame record for each function.
void emitFunctionFrameRecords(MCStreamer &OS);
- /// \brief Emit the constant pool.
+ /// Emit the constant pool.
void emitConstantPoolEntries(MCStreamer &OS);
- /// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call.
+ /// Emit the callsite info for each stackmap/patchpoint intrinsic call.
void emitCallsiteEntries(MCStreamer &OS);
void print(raw_ostream &OS);
diff --git a/contrib/llvm/include/llvm/CodeGen/StackProtector.h b/contrib/llvm/include/llvm/CodeGen/StackProtector.h
index 72de212d0df9..a506ac636a17 100644
--- a/contrib/llvm/include/llvm/CodeGen/StackProtector.h
+++ b/contrib/llvm/include/llvm/CodeGen/StackProtector.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Pass.h"
@@ -35,24 +36,11 @@ class TargetMachine;
class Type;
class StackProtector : public FunctionPass {
-public:
- /// SSPLayoutKind. Stack Smashing Protection (SSP) rules require that
- /// vulnerable stack allocations are located close the stack protector.
- enum SSPLayoutKind {
- SSPLK_None, ///< Did not trigger a stack protector. No effect on data
- ///< layout.
- SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest
- ///< to the stack protector.
- SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest
- ///< to the stack protector.
- SSPLK_AddrOf ///< The address of this allocation is exposed and
- ///< triggered protection. 3rd closest to the protector.
- };
-
+private:
/// A mapping of AllocaInsts to their required SSP layout.
- using SSPLayoutMap = ValueMap<const AllocaInst *, SSPLayoutKind>;
+ using SSPLayoutMap = DenseMap<const AllocaInst *,
+ MachineFrameInfo::SSPLayoutKind>;
-private:
const TargetMachine *TM = nullptr;
/// TLI - Keep a pointer of a TargetLowering to consult for determining
@@ -70,7 +58,7 @@ private:
/// AllocaInst triggers a stack protector.
SSPLayoutMap Layout;
- /// \brief The minimum size of buffers that will receive stack smashing
+ /// The minimum size of buffers that will receive stack smashing
/// protection when -fstack-protection is used.
unsigned SSPBufferSize = 0;
@@ -107,7 +95,7 @@ private:
bool ContainsProtectableArray(Type *Ty, bool &IsLarge, bool Strong = false,
bool InStruct = false) const;
- /// \brief Check whether a stack allocation has its address taken.
+ /// Check whether a stack allocation has its address taken.
bool HasAddressTaken(const Instruction *AI);
/// RequiresStackProtector - Check whether or not this function needs a
@@ -123,14 +111,12 @@ public:
void getAnalysisUsage(AnalysisUsage &AU) const override;
- SSPLayoutKind getSSPLayout(const AllocaInst *AI) const;
-
// Return true if StackProtector is supposed to be handled by SelectionDAG.
bool shouldEmitSDCheck(const BasicBlock &BB) const;
- void adjustForColoring(const AllocaInst *From, const AllocaInst *To);
-
bool runOnFunction(Function &Fn) override;
+
+ void copyToMachineFrameInfo(MachineFrameInfo &MFI) const;
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h b/contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h
index 8646a15599cb..7d138f585171 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h
@@ -14,8 +14,8 @@
#ifndef LLVM_CODEGEN_TARGETCALLINGCONV_H
#define LLVM_CODEGEN_TARGETCALLINGCONV_H
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <climits>
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h
index 61f1cf07bcf2..f8effee998e3 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h
@@ -158,6 +158,10 @@ public:
return false;
}
+ /// Returns true if the target can safely skip saving callee-saved registers
+ /// for noreturn nounwind functions.
+ virtual bool enableCalleeSaveSkip(const MachineFunction &MF) const;
+
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
virtual void emitPrologue(MachineFunction &MF,
@@ -341,6 +345,14 @@ public:
return false;
return true;
}
+
+ /// Return initial CFA offset value i.e. the one valid at the beginning of the
+ /// function (before any stack operations).
+ virtual int getInitialCFAOffset(const MachineFunction &MF) const;
+
+ /// Return initial CFA register value i.e. the one valid at the beginning of
+ /// the function (before any stack operations).
+ virtual unsigned getInitialCFARegister(const MachineFunction &MF) const;
};
} // End llvm namespace
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 57dee3bb44b3..b5bc561d834c 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -18,12 +18,14 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/None.h"
+#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineCombinerPattern.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineOutliner.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/BranchProbability.h"
@@ -79,7 +81,7 @@ public:
/// Given a machine instruction descriptor, returns the register
/// class constraint for OpNum, or NULL.
- const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum,
+ const TargetRegisterClass *getRegClass(const MCInstrDesc &MCID, unsigned OpNum,
const TargetRegisterInfo *TRI,
const MachineFunction &MF) const;
@@ -225,6 +227,17 @@ public:
return 0;
}
+ /// Optional extension of isLoadFromStackSlot that returns the number of
+ /// bytes loaded from the stack. This must be implemented if a backend
+ /// supports partial stack slot spills/loads to further disambiguate
+ /// what the load does.
+ virtual unsigned isLoadFromStackSlot(const MachineInstr &MI,
+ int &FrameIndex,
+ unsigned &MemBytes) const {
+ MemBytes = 0;
+ return isLoadFromStackSlot(MI, FrameIndex);
+ }
+
/// Check for post-frame ptr elimination stack locations as well.
/// This uses a heuristic so it isn't reliable for correctness.
virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr &MI,
@@ -252,6 +265,17 @@ public:
return 0;
}
+ /// Optional extension of isStoreToStackSlot that returns the number of
+ /// bytes stored to the stack. This must be implemented if a backend
+ /// supports partial stack slot spills/loads to further disambiguate
+ /// what the store does.
+ virtual unsigned isStoreToStackSlot(const MachineInstr &MI,
+ int &FrameIndex,
+ unsigned &MemBytes) const {
+ MemBytes = 0;
+ return isStoreToStackSlot(MI, FrameIndex);
+ }
+
/// Check for post-frame ptr elimination stack locations as well.
/// This uses a heuristic, so it isn't reliable for correctness.
virtual unsigned isStoreToStackSlotPostFE(const MachineInstr &MI,
@@ -325,7 +349,7 @@ public:
unsigned SubIdx, const MachineInstr &Orig,
const TargetRegisterInfo &TRI) const;
- /// \brief Clones instruction or the whole instruction bundle \p Orig and
+ /// Clones instruction or the whole instruction bundle \p Orig and
/// insert into \p MBB before \p InsertBefore. The target may update operands
/// that are required to be unique.
///
@@ -635,8 +659,8 @@ public:
return true;
}
- /// Generate code to reduce the loop iteration by one and check if the loop is
- /// finished. Return the value/register of the the new loop count. We need
+ /// Generate code to reduce the loop iteration by one and check if the loop
+ /// is finished. Return the value/register of the new loop count. We need
/// this function when peeling off one or more iterations of a loop. This
/// function assumes the nth iteration is peeled first.
virtual unsigned reduceLoopCount(MachineBasicBlock &MBB, MachineInstr *IndVar,
@@ -822,6 +846,15 @@ public:
llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!");
}
+ /// If the specific machine instruction is a instruction that moves/copies
+ /// value from one register to another register return true along with
+ /// @Source machine operand and @Destination machine operand.
+ virtual bool isCopyInstr(const MachineInstr &MI,
+ const MachineOperand *&SourceOpNum,
+ const MachineOperand *&Destination) const {
+ return false;
+ }
+
/// Store the specified register of the given register class to the specified
/// stack frame index. The store instruction is to be added to the given
/// machine basic block before the specified machine instruction. If isKill
@@ -876,7 +909,7 @@ public:
/// The new instruction is inserted before MI, and the client is responsible
/// for removing the old instruction.
MachineInstr *foldMemoryOperand(MachineInstr &MI, ArrayRef<unsigned> Ops,
- int FrameIndex,
+ int FI,
LiveIntervals *LIS = nullptr) const;
/// Same as the previous version except it allows folding of any load and
@@ -928,13 +961,13 @@ public:
/// \param InsInstrs - Vector of new instructions that implement P
/// \param DelInstrs - Old instructions, including Root, that could be
/// replaced by InsInstr
- /// \param InstrIdxForVirtReg - map of virtual register to instruction in
+ /// \param InstIdxForVirtReg - map of virtual register to instruction in
/// InsInstr that defines it
virtual void genAlternativeCodeSequence(
MachineInstr &Root, MachineCombinerPattern Pattern,
SmallVectorImpl<MachineInstr *> &InsInstrs,
SmallVectorImpl<MachineInstr *> &DelInstrs,
- DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const;
+ DenseMap<unsigned, unsigned> &InstIdxForVirtReg) const;
/// Attempt to reassociate \P Root and \P Prev according to \P Pattern to
/// reduce critical path length.
@@ -983,7 +1016,7 @@ protected:
return nullptr;
}
- /// \brief Target-dependent implementation of getRegSequenceInputs.
+ /// Target-dependent implementation of getRegSequenceInputs.
///
/// \returns true if it is possible to build the equivalent
/// REG_SEQUENCE inputs with the pair \p MI, \p DefIdx. False otherwise.
@@ -997,7 +1030,7 @@ protected:
return false;
}
- /// \brief Target-dependent implementation of getExtractSubregInputs.
+ /// Target-dependent implementation of getExtractSubregInputs.
///
/// \returns true if it is possible to build the equivalent
/// EXTRACT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise.
@@ -1011,7 +1044,7 @@ protected:
return false;
}
- /// \brief Target-dependent implementation of getInsertSubregInputs.
+ /// Target-dependent implementation of getInsertSubregInputs.
///
/// \returns true if it is possible to build the equivalent
/// INSERT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise.
@@ -1433,7 +1466,7 @@ public:
return 0;
}
- /// \brief Return the minimum clearance before an instruction that reads an
+ /// Return the minimum clearance before an instruction that reads an
/// unused register.
///
/// For example, AVX instructions may copy part of a register operand into
@@ -1500,7 +1533,7 @@ public:
return false;
}
- /// \brief Return the value to use for the MachineCSE's LookAheadLimit,
+ /// Return the value to use for the MachineCSE's LookAheadLimit,
/// which is a heuristic used for CSE'ing phys reg defs.
virtual unsigned getMachineCSELookAheadLimit() const {
// The default lookahead is small to prevent unprofitable quadratic
@@ -1569,64 +1602,32 @@ public:
return false;
}
- /// \brief Describes the number of instructions that it will take to call and
- /// construct a frame for a given outlining candidate.
- struct MachineOutlinerInfo {
- /// Number of instructions to call an outlined function for this candidate.
- unsigned CallOverhead;
-
- /// \brief Number of instructions to construct an outlined function frame
- /// for this candidate.
- unsigned FrameOverhead;
-
- /// \brief Represents the specific instructions that must be emitted to
- /// construct a call to this candidate.
- unsigned CallConstructionID;
-
- /// \brief Represents the specific instructions that must be emitted to
- /// construct a frame for this candidate's outlined function.
- unsigned FrameConstructionID;
-
- MachineOutlinerInfo() {}
- MachineOutlinerInfo(unsigned CallOverhead, unsigned FrameOverhead,
- unsigned CallConstructionID,
- unsigned FrameConstructionID)
- : CallOverhead(CallOverhead), FrameOverhead(FrameOverhead),
- CallConstructionID(CallConstructionID),
- FrameConstructionID(FrameConstructionID) {}
- };
-
- /// \brief Returns a \p MachineOutlinerInfo struct containing target-specific
+ /// Returns a \p outliner::OutlinedFunction struct containing target-specific
/// information for a set of outlining candidates.
- virtual MachineOutlinerInfo getOutlininingCandidateInfo(
- std::vector<
- std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
- &RepeatedSequenceLocs) const {
+ virtual outliner::OutlinedFunction getOutliningCandidateInfo(
+ std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
llvm_unreachable(
- "Target didn't implement TargetInstrInfo::getOutliningOverhead!");
+ "Target didn't implement TargetInstrInfo::getOutliningCandidateInfo!");
}
- /// Represents how an instruction should be mapped by the outliner.
- /// \p Legal instructions are those which are safe to outline.
- /// \p Illegal instructions are those which cannot be outlined.
- /// \p Invisible instructions are instructions which can be outlined, but
- /// shouldn't actually impact the outlining result.
- enum MachineOutlinerInstrType { Legal, Illegal, Invisible };
-
/// Returns how or if \p MI should be outlined.
- virtual MachineOutlinerInstrType getOutliningType(MachineInstr &MI) const {
+ virtual outliner::InstrType
+ getOutliningType(MachineBasicBlock::iterator &MIT, unsigned Flags) const {
llvm_unreachable(
"Target didn't implement TargetInstrInfo::getOutliningType!");
}
- /// Insert a custom epilogue for outlined functions.
- /// This may be empty, in which case no epilogue or return statement will be
- /// emitted.
- virtual void insertOutlinerEpilogue(MachineBasicBlock &MBB,
- MachineFunction &MF,
- const MachineOutlinerInfo &MInfo) const {
+ /// Returns target-defined flags defining properties of the MBB for
+ /// the outliner.
+ virtual unsigned getMachineOutlinerMBBFlags(MachineBasicBlock &MBB) const {
+ return 0x0;
+ }
+
+ /// Insert a custom frame for outlined functions.
+ virtual void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,
+ const outliner::OutlinedFunction &OF) const {
llvm_unreachable(
- "Target didn't implement TargetInstrInfo::insertOutlinerEpilogue!");
+ "Target didn't implement TargetInstrInfo::buildOutlinedFrame!");
}
/// Insert a call to an outlined function into the program.
@@ -1635,20 +1636,11 @@ public:
virtual MachineBasicBlock::iterator
insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
MachineBasicBlock::iterator &It, MachineFunction &MF,
- const MachineOutlinerInfo &MInfo) const {
+ const outliner::Candidate &C) const {
llvm_unreachable(
"Target didn't implement TargetInstrInfo::insertOutlinedCall!");
}
- /// Insert a custom prologue for outlined functions.
- /// This may be empty, in which case no prologue will be emitted.
- virtual void insertOutlinerPrologue(MachineBasicBlock &MBB,
- MachineFunction &MF,
- const MachineOutlinerInfo &MInfo) const {
- llvm_unreachable(
- "Target didn't implement TargetInstrInfo::insertOutlinerPrologue!");
- }
-
/// Return true if the function can safely be outlined from.
/// A function \p MF is considered safe for outlining if an outlined function
/// produced from instructions in F will produce a program which produces the
@@ -1659,13 +1651,18 @@ public:
"TargetInstrInfo::isFunctionSafeToOutlineFrom!");
}
+ /// Return true if the function should be outlined from by default.
+ virtual bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const {
+ return false;
+ }
+
private:
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;
unsigned CatchRetOpcode;
unsigned ReturnOpcode;
};
-/// \brief Provide DenseMapInfo for TargetInstrInfo::RegSubRegPair.
+/// Provide DenseMapInfo for TargetInstrInfo::RegSubRegPair.
template <> struct DenseMapInfo<TargetInstrInfo::RegSubRegPair> {
using RegInfo = DenseMapInfo<unsigned>;
@@ -1679,7 +1676,7 @@ template <> struct DenseMapInfo<TargetInstrInfo::RegSubRegPair> {
RegInfo::getTombstoneKey());
}
- /// \brief Reuse getHashValue implementation from
+ /// Reuse getHashValue implementation from
/// std::pair<unsigned, unsigned>.
static unsigned getHashValue(const TargetInstrInfo::RegSubRegPair &Val) {
std::pair<unsigned, unsigned> PairVal = std::make_pair(Val.Reg, Val.SubReg);
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLowering.h b/contrib/llvm/include/llvm/CodeGen/TargetLowering.h
index cea8472caa35..d5ff71cf9ac2 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -29,9 +29,9 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Analysis/DivergenceAnalysis.h"
#include "llvm/CodeGen/DAGCombine.h"
#include "llvm/CodeGen/ISDOpcodes.h"
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/RuntimeLibcalls.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
@@ -52,6 +52,7 @@
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MachineValueType.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
@@ -222,7 +223,7 @@ public:
virtual ~TargetLoweringBase() = default;
protected:
- /// \brief Initialize all of the actions to default values.
+ /// Initialize all of the actions to default values.
void initActions();
public:
@@ -253,7 +254,8 @@ public:
/// A documentation for this function would be nice...
virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const;
- EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const;
+ EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL,
+ bool LegalTypes = true) const;
/// Returns the type to be used for the index operand of:
/// ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT,
@@ -421,17 +423,17 @@ public:
return true;
}
- /// \brief Return true if it is cheap to speculate a call to intrinsic cttz.
+ /// 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.
+ /// Return true if it is cheap to speculate a call to intrinsic ctlz.
virtual bool isCheapToSpeculateCtlz() const {
return false;
}
- /// \brief Return true if ctlz instruction is fast.
+ /// Return true if ctlz instruction is fast.
virtual bool isCtlzFast() const {
return false;
}
@@ -444,13 +446,13 @@ public:
return false;
}
- /// \brief Return true if it is cheaper to split the store of a merged int val
+ /// Return true if it is cheaper to split the store of a merged int val
/// from a pair of smaller values into multiple stores.
virtual bool isMultiStoresCheaperThanBitsMerge(EVT LTy, EVT HTy) const {
return false;
}
- /// \brief Return if the target supports combining a
+ /// Return if the target supports combining a
/// chain like:
/// \code
/// %andResult = and %val1, #mask
@@ -507,7 +509,30 @@ public:
return hasAndNotCompare(X);
}
- /// \brief Return true if the target wants to use the optimization that
+ /// There are two ways to clear extreme bits (either low or high):
+ /// Mask: x & (-1 << y) (the instcombine canonical form)
+ /// Shifts: x >> y << y
+ /// Return true if the variant with 2 shifts is preferred.
+ /// Return false if there is no preference.
+ virtual bool preferShiftsToClearExtremeBits(SDValue X) const {
+ // By default, let's assume that no one prefers shifts.
+ return false;
+ }
+
+ /// Should we tranform the IR-optimal check for whether given truncation
+ /// down into KeptBits would be truncating or not:
+ /// (add %x, (1 << (KeptBits-1))) srccond (1 << KeptBits)
+ /// Into it's more traditional form:
+ /// ((%x << C) a>> C) dstcond %x
+ /// Return true if we should transform.
+ /// Return false if there is no preference.
+ virtual bool shouldTransformSignedTruncationCheck(EVT XVT,
+ unsigned KeptBits) const {
+ // By default, let's assume that no one prefers shifts.
+ return false;
+ }
+
+ /// 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; }
@@ -746,10 +771,10 @@ public:
/// operations don't trap except for integer divide and remainder.
virtual bool canOpTrap(unsigned Op, EVT VT) const;
- /// Similar to isShuffleMaskLegal. This is used by Targets can use this to
- /// indicate if there is a suitable VECTOR_SHUFFLE that can be used to replace
- /// a VAND with a constant pool entry.
- virtual bool isVectorClearMaskLegal(const SmallVectorImpl<int> &/*Mask*/,
+ /// Similar to isShuffleMaskLegal. Targets can use this to indicate if there
+ /// is a suitable VECTOR_SHUFFLE that can be used to replace a VAND with a
+ /// constant pool entry.
+ virtual bool isVectorClearMaskLegal(ArrayRef<int> /*Mask*/,
EVT /*VT*/) const {
return false;
}
@@ -765,6 +790,39 @@ public:
return OpActions[(unsigned)VT.getSimpleVT().SimpleTy][Op];
}
+ LegalizeAction getStrictFPOperationAction(unsigned Op, EVT VT) const {
+ unsigned EqOpc;
+ switch (Op) {
+ default: llvm_unreachable("Unexpected FP pseudo-opcode");
+ case ISD::STRICT_FADD: EqOpc = ISD::FADD; break;
+ case ISD::STRICT_FSUB: EqOpc = ISD::FSUB; break;
+ case ISD::STRICT_FMUL: EqOpc = ISD::FMUL; break;
+ case ISD::STRICT_FDIV: EqOpc = ISD::FDIV; break;
+ case ISD::STRICT_FSQRT: EqOpc = ISD::FSQRT; break;
+ case ISD::STRICT_FPOW: EqOpc = ISD::FPOW; break;
+ case ISD::STRICT_FPOWI: EqOpc = ISD::FPOWI; break;
+ case ISD::STRICT_FMA: EqOpc = ISD::FMA; break;
+ case ISD::STRICT_FSIN: EqOpc = ISD::FSIN; break;
+ case ISD::STRICT_FCOS: EqOpc = ISD::FCOS; break;
+ case ISD::STRICT_FEXP: EqOpc = ISD::FEXP; break;
+ case ISD::STRICT_FEXP2: EqOpc = ISD::FEXP2; break;
+ case ISD::STRICT_FLOG: EqOpc = ISD::FLOG; break;
+ case ISD::STRICT_FLOG10: EqOpc = ISD::FLOG10; break;
+ case ISD::STRICT_FLOG2: EqOpc = ISD::FLOG2; break;
+ case ISD::STRICT_FRINT: EqOpc = ISD::FRINT; break;
+ case ISD::STRICT_FNEARBYINT: EqOpc = ISD::FNEARBYINT; break;
+ }
+
+ auto Action = getOperationAction(EqOpc, VT);
+
+ // We don't currently handle Custom or Promote for strict FP pseudo-ops.
+ // For now, we just expand for those cases.
+ if (Action != Legal)
+ Action = Expand;
+
+ return Action;
+ }
+
/// Return true if the specified operation is legal on this target or can be
/// made legal with custom lowering. This is used to help guide high-level
/// lowering decisions.
@@ -812,7 +870,7 @@ public:
bool rangeFitsInWord(const APInt &Low, const APInt &High,
const DataLayout &DL) const {
// FIXME: Using the pointer type doesn't seem ideal.
- uint64_t BW = DL.getPointerSizeInBits();
+ uint64_t BW = DL.getIndexSizeInBits(0u);
uint64_t Range = (High - Low).getLimitedValue(UINT64_MAX - 1) + 1;
return Range <= BW;
}
@@ -820,7 +878,7 @@ public:
/// Return true if lowering to a jump table is suitable for a set of case
/// clusters which may contain \p NumCases cases, \p Range range of values.
/// FIXME: This function check the maximum table size and density, but the
- /// minimum size is not checked. It would be nice if the the minimum size is
+ /// minimum size is not checked. It would be nice if the minimum size is
/// also combined within this function. Currently, the minimum size check is
/// performed in findJumpTable() in SelectionDAGBuiler and
/// getEstimatedNumberOfCaseClusters() in BasicTTIImpl.
@@ -986,9 +1044,14 @@ public:
/// Return true if the specified condition code is legal on this target.
bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const {
- return
- getCondCodeAction(CC, VT) == Legal ||
- getCondCodeAction(CC, VT) == Custom;
+ return getCondCodeAction(CC, VT) == Legal;
+ }
+
+ /// Return true if the specified condition code is legal or custom on this
+ /// target.
+ bool isCondCodeLegalOrCustom(ISD::CondCode CC, MVT VT) const {
+ return getCondCodeAction(CC, VT) == Legal ||
+ getCondCodeAction(CC, VT) == Custom;
}
/// If the action for this operation is to promote, this method returns the
@@ -1110,10 +1173,6 @@ public:
/// Certain combinations of ABIs, Targets and features require that types
/// are legal for some operations and not for other operations.
/// For MIPS all vector types must be passed through the integer register set.
- virtual MVT getRegisterTypeForCallingConv(MVT VT) const {
- return getRegisterType(VT);
- }
-
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context,
EVT VT) const {
return getRegisterType(Context, VT);
@@ -1172,7 +1231,7 @@ public:
return getPointerTy(DL).getSizeInBits();
}
- /// \brief Get maximum # of store operations permitted for llvm.memset
+ /// Get maximum # of store operations permitted for llvm.memset
///
/// This function returns the maximum number of store operations permitted
/// to replace a call to llvm.memset. The value is set by the target at the
@@ -1182,7 +1241,7 @@ public:
return OptSize ? MaxStoresPerMemsetOptSize : MaxStoresPerMemset;
}
- /// \brief Get maximum # of store operations permitted for llvm.memcpy
+ /// Get maximum # of store operations permitted for llvm.memcpy
///
/// This function returns the maximum number of store operations permitted
/// to replace a call to llvm.memcpy. The value is set by the target at the
@@ -1192,6 +1251,15 @@ public:
return OptSize ? MaxStoresPerMemcpyOptSize : MaxStoresPerMemcpy;
}
+ /// \brief Get maximum # of store operations to be glued together
+ ///
+ /// This function returns the maximum number of store operations permitted
+ /// to glue together during lowering of llvm.memcpy. The value is set by
+ // the target at the performance threshold for such a replacement.
+ virtual unsigned getMaxGluedStoresPerMemcpy() const {
+ return MaxGluedStoresPerMemcpy;
+ }
+
/// Get maximum # of load operations permitted for memcmp
///
/// This function returns the maximum number of load operations permitted
@@ -1202,7 +1270,19 @@ public:
return OptSize ? MaxLoadsPerMemcmpOptSize : MaxLoadsPerMemcmp;
}
- /// \brief Get maximum # of store operations permitted for llvm.memmove
+ /// For memcmp expansion when the memcmp result is only compared equal or
+ /// not-equal to 0, allow up to this number of load pairs per block. As an
+ /// example, this may allow 'memcmp(a, b, 3) == 0' in a single block:
+ /// a0 = load2bytes &a[0]
+ /// b0 = load2bytes &b[0]
+ /// a2 = load1byte &a[2]
+ /// b2 = load1byte &b[2]
+ /// r = cmp eq (a0 ^ b0 | a2 ^ b2), 0
+ virtual unsigned getMemcmpEqZeroLoadsPerBlock() const {
+ return 1;
+ }
+
+ /// Get maximum # of store operations permitted for llvm.memmove
///
/// This function returns the maximum number of store operations permitted
/// to replace a call to llvm.memmove. The value is set by the target at the
@@ -1212,7 +1292,7 @@ public:
return OptSize ? MaxStoresPerMemmoveOptSize : MaxStoresPerMemmove;
}
- /// \brief Determine if the target supports unaligned memory accesses.
+ /// Determine if the target supports unaligned memory accesses.
///
/// This function returns true if the target allows unaligned memory accesses
/// of the specified type in the given address space. If true, it also returns
@@ -1350,7 +1430,7 @@ public:
/// If the target has a standard location for the stack protector guard,
/// returns the address of that location. Otherwise, returns nullptr.
/// DEPRECATED: please override useLoadStackGuardNode and customize
- /// LOAD_STACK_GUARD, or customize @llvm.stackguard().
+ /// LOAD_STACK_GUARD, or customize \@llvm.stackguard().
virtual Value *getIRStackGuard(IRBuilder<> &IRB) const;
/// Inserts necessary declarations for SSP (stack protection) purpose.
@@ -1905,7 +1985,7 @@ public:
Type *Ty, unsigned AddrSpace,
Instruction *I = nullptr) const;
- /// \brief Return the cost of the scaling factor used in the addressing mode
+ /// Return the cost of the scaling factor used in the addressing mode
/// represented by AM for this target, for a load/store of the specified type.
///
/// If the AM is supported, the return value must be >= 0.
@@ -2098,11 +2178,14 @@ public:
return false;
}
- /// \brief Get the maximum supported factor for interleaved memory accesses.
+ /// Return true if the target has a vector blend instruction.
+ virtual bool hasVectorBlend() const { return false; }
+
+ /// Get the maximum supported factor for interleaved memory accesses.
/// Default to be the minimum interleave factor: 2.
virtual unsigned getMaxSupportedInterleaveFactor() const { return 2; }
- /// \brief Lower an interleaved load to target specific intrinsics. Return
+ /// Lower an interleaved load to target specific intrinsics. Return
/// true on success.
///
/// \p LI is the vector load instruction.
@@ -2116,7 +2199,7 @@ public:
return false;
}
- /// \brief Lower an interleaved store to target specific intrinsics. Return
+ /// Lower an interleaved store to target specific intrinsics. Return
/// true on success.
///
/// \p SI is the vector store instruction.
@@ -2189,7 +2272,7 @@ public:
return false;
}
- /// \brief Return true if it is beneficial to convert a load of a constant to
+ /// Return true if it is beneficial to convert a load of a constant to
/// just the constant itself.
/// On some targets it might be more efficient to use a combination of
/// arithmetic instructions to materialize the constant instead of loading it
@@ -2214,6 +2297,11 @@ public:
return false;
}
+ // Return true if CodeGenPrepare should consider splitting large offset of a
+ // GEP to make the GEP fit into the addressing mode and can be sunk into the
+ // same blocks of its users.
+ virtual bool shouldConsiderGEPOffsetSplit() const { return false; }
+
//===--------------------------------------------------------------------===//
// Runtime Library hooks
//
@@ -2453,7 +2541,7 @@ protected:
/// expected to be merged.
unsigned GatherAllAliasesMaxDepth;
- /// \brief Specify maximum number of store instructions per memset call.
+ /// Specify maximum number of store instructions per memset call.
///
/// When lowering \@llvm.memset this field specifies the maximum number of
/// store operations that may be substituted for the call to memset. Targets
@@ -2469,7 +2557,7 @@ protected:
/// to memset, used for functions with OptSize attribute.
unsigned MaxStoresPerMemsetOptSize;
- /// \brief Specify maximum bytes of store instructions per memcpy call.
+ /// Specify maximum bytes of store instructions per memcpy call.
///
/// When lowering \@llvm.memcpy this field specifies the maximum number of
/// store operations that may be substituted for a call to memcpy. Targets
@@ -2482,13 +2570,21 @@ protected:
/// constant size.
unsigned MaxStoresPerMemcpy;
+
+ /// \brief Specify max number of store instructions to glue in inlined memcpy.
+ ///
+ /// When memcpy is inlined based on MaxStoresPerMemcpy, specify maximum number
+ /// of store instructions to keep together. This helps in pairing and
+ // vectorization later on.
+ unsigned MaxGluedStoresPerMemcpy = 0;
+
/// Maximum number of store operations that may be substituted for a call to
/// memcpy, used for functions with OptSize attribute.
unsigned MaxStoresPerMemcpyOptSize;
unsigned MaxLoadsPerMemcmp;
unsigned MaxLoadsPerMemcmpOptSize;
- /// \brief Specify maximum bytes of store instructions per memmove call.
+ /// Specify maximum bytes of store instructions per memmove call.
///
/// When lowering \@llvm.memmove this field specifies the maximum number of
/// store instructions that may be substituted for a call to memmove. Targets
@@ -2520,6 +2616,16 @@ protected:
/// sequence of memory operands that is recognized by PrologEpilogInserter.
MachineBasicBlock *emitPatchPoint(MachineInstr &MI,
MachineBasicBlock *MBB) const;
+
+ /// Replace/modify the XRay custom event operands with target-dependent
+ /// details.
+ MachineBasicBlock *emitXRayCustomEvent(MachineInstr &MI,
+ MachineBasicBlock *MBB) const;
+
+ /// Replace/modify the XRay typed event operands with target-dependent
+ /// details.
+ MachineBasicBlock *emitXRayTypedEvent(MachineInstr &MI,
+ MachineBasicBlock *MBB) const;
};
/// This class defines information used to lower LLVM code to legal SelectionDAG
@@ -2539,6 +2645,16 @@ public:
bool isPositionIndependent() const;
+ virtual bool isSDNodeSourceOfDivergence(const SDNode *N,
+ FunctionLoweringInfo *FLI,
+ DivergenceAnalysis *DA) const {
+ return false;
+ }
+
+ virtual bool isSDNodeAlwaysUniform(const SDNode * N) const {
+ return false;
+ }
+
/// Returns true by value, base pointer and offset pointer and addressing mode
/// by reference if the node's address can be legally represented as
/// pre-indexed load / store address.
@@ -2690,6 +2806,30 @@ public:
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask,
DAGCombinerInfo &DCI) const;
+ /// Look at Vector Op. At this point, we know that only the DemandedElts
+ /// elements of the result of Op are ever used downstream. If we can use
+ /// this information to simplify Op, create a new simplified DAG node and
+ /// return true, storing the original and new nodes in TLO.
+ /// Otherwise, analyze the expression and return a mask of KnownUndef and
+ /// KnownZero elements for the expression (used to simplify the caller).
+ /// The KnownUndef/Zero elements may only be accurate for those bits
+ /// in the DemandedMask.
+ /// \p AssumeSingleUse When this parameter is true, this function will
+ /// attempt to simplify \p Op even if there are multiple uses.
+ /// Callers are responsible for correctly updating the DAG based on the
+ /// results of this function, because simply replacing replacing TLO.Old
+ /// with TLO.New will be incorrect when this parameter is true and TLO.Old
+ /// has multiple uses.
+ bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask,
+ APInt &KnownUndef, APInt &KnownZero,
+ TargetLoweringOpt &TLO, unsigned Depth = 0,
+ bool AssumeSingleUse = false) const;
+
+ /// Helper wrapper around SimplifyDemandedVectorElts
+ bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedElts,
+ APInt &KnownUndef, APInt &KnownZero,
+ DAGCombinerInfo &DCI) const;
+
/// Determine which of the bits specified in Mask are known to be either zero
/// or one and return them in the KnownZero/KnownOne bitsets. The DemandedElts
/// argument allows us to only collect the known bits that are shared by the
@@ -2718,6 +2858,15 @@ public:
const SelectionDAG &DAG,
unsigned Depth = 0) const;
+ /// Attempt to simplify any target nodes based on the demanded vector
+ /// elements, returning true on success. Otherwise, analyze the expression and
+ /// return a mask of KnownUndef and KnownZero elements for the expression
+ /// (used to simplify the caller). The KnownUndef/Zero elements may only be
+ /// accurate for those bits in the DemandedMask
+ virtual bool SimplifyDemandedVectorEltsForTargetNode(
+ SDValue Op, const APInt &DemandedElts, APInt &KnownUndef,
+ APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth = 0) const;
+
struct DAGCombinerInfo {
void *DC; // The DAG Combiner object.
CombineLevel Level;
@@ -2731,7 +2880,7 @@ public:
bool isBeforeLegalize() const { return Level == BeforeLegalizeTypes; }
bool isBeforeLegalizeOps() const { return Level < AfterLegalizeVectorOps; }
- bool isAfterLegalizeVectorOps() const {
+ bool isAfterLegalizeDAG() const {
return Level == AfterLegalizeDAG;
}
CombineLevel getDAGCombineLevel() { return Level; }
@@ -2753,12 +2902,8 @@ public:
/// from getBooleanContents().
bool isConstFalseVal(const SDNode *N) const;
- /// Return a constant of type VT that contains a true value that respects
- /// getBooleanContents()
- SDValue getConstTrueVal(SelectionDAG &DAG, EVT VT, const SDLoc &DL) const;
-
/// Return if \p N is a True value when extended to \p VT.
- bool isExtendedTrueVal(const ConstantSDNode *N, EVT VT, bool Signed) const;
+ bool isExtendedTrueVal(const ConstantSDNode *N, EVT VT, bool SExt) const;
/// Try to simplify a setcc built with the specified operands and cc. If it is
/// unable to simplify it, return a null SDValue.
@@ -3479,7 +3624,7 @@ public:
/// bounds the returned pointer is unspecified, but will be within the vector
/// bounds.
SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT,
- SDValue Idx) const;
+ SDValue Index) const;
//===--------------------------------------------------------------------===//
// Instruction Emitting Hooks
@@ -3518,6 +3663,13 @@ public:
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA,
SelectionDAG &DAG) const;
+ /// Expands target specific indirect branch for the case of JumpTable
+ /// expanasion.
+ virtual SDValue expandIndirectJTBranch(const SDLoc& dl, SDValue Value, SDValue Addr,
+ SelectionDAG &DAG) const {
+ return DAG.getNode(ISD::BRIND, dl, MVT::Other, Value, Addr);
+ }
+
// seteq(x, 0) -> truncate(srl(ctlz(zext(x)), log2(#bits)))
// If we're comparing for equality to zero and isCtlzFast is true, expose the
// fact that this can be implemented as a ctlz/srl pair, so that the dag
@@ -3528,6 +3680,11 @@ private:
SDValue simplifySetCCWithAnd(EVT VT, SDValue N0, SDValue N1,
ISD::CondCode Cond, DAGCombinerInfo &DCI,
const SDLoc &DL) const;
+
+ SDValue optimizeSetCCOfSignedTruncationCheck(EVT SCCVT, SDValue N0,
+ SDValue N1, ISD::CondCode Cond,
+ DAGCombinerInfo &DCI,
+ const SDLoc &DL) const;
};
/// Given an LLVM IR type and return type attributes, compute the return value
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 69de9f8cb35d..f5c7fc824ab4 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -15,9 +15,9 @@
#ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
#define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
namespace llvm {
@@ -36,16 +36,18 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
protected:
MCSymbolRefExpr::VariantKind PLTRelativeVariantKind =
MCSymbolRefExpr::VK_None;
+ const TargetMachine *TM;
public:
TargetLoweringObjectFileELF() = default;
~TargetLoweringObjectFileELF() override = default;
+ void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
+
/// Emit Obj-C garbage collection and linker options.
- void emitModuleMetadata(MCStreamer &Streamer, Module &M,
- const TargetMachine &TM) const override;
+ void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
- void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
+ void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &DL,
const MCSymbol *Sym) const override;
/// Given a constant with the SectionKind, return a section that it should be
@@ -98,8 +100,7 @@ public:
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
/// Emit the module flags that specify the garbage collection information.
- void emitModuleMetadata(MCStreamer &Streamer, Module &M,
- const TargetMachine &TM) const override;
+ void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
const TargetMachine &TM) const override;
@@ -153,8 +154,7 @@ public:
const TargetMachine &TM) const override;
/// Emit Obj-C garbage collection and linker options.
- void emitModuleMetadata(MCStreamer &Streamer, Module &M,
- const TargetMachine &TM) const override;
+ void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
MCSection *getStaticCtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;
@@ -163,6 +163,19 @@ public:
void emitLinkerFlagsForGlobal(raw_ostream &OS,
const GlobalValue *GV) const override;
+
+ void emitLinkerFlagsForUsed(raw_ostream &OS,
+ const GlobalValue *GV) const override;
+
+ const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
+ const GlobalValue *RHS,
+ const TargetMachine &TM) const override;
+
+ /// Given a mergeable constant with the specified size and relocation
+ /// information, return a section that it should be placed in.
+ MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
+ const Constant *C,
+ unsigned &Align) const override;
};
class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile {
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h b/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h
index 3ca31a970944..d0d959c4ae11 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h
@@ -22,7 +22,7 @@ namespace TargetOpcode {
enum {
#define HANDLE_TARGET_OPCODE(OPC) OPC,
#define HANDLE_TARGET_OPCODE_MARKER(IDENT, OPC) IDENT = OPC,
-#include "llvm/CodeGen/TargetOpcodes.def"
+#include "llvm/Support/TargetOpcodes.def"
};
} // end namespace TargetOpcode
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h b/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h
index da9841a0586e..5918c524d11c 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h
@@ -84,20 +84,6 @@ template <> struct isPodLike<IdentifyingPassPtr> {
/// This is an ImmutablePass solely for the purpose of exposing CodeGen options
/// to the internals of other CodeGen passes.
class TargetPassConfig : public ImmutablePass {
-public:
- /// Pseudo Pass IDs. These are defined within TargetPassConfig because they
- /// are unregistered pass IDs. They are only useful for use with
- /// TargetPassConfig APIs to identify multiple occurrences of the same pass.
- ///
-
- /// EarlyTailDuplicate - A clone of the TailDuplicate pass that runs early
- /// during codegen, on SSA form.
- static char EarlyTailDuplicateID;
-
- /// PostRAMachineLICM - A clone of the LICM pass that runs during late machine
- /// optimization after regalloc.
- static char PostRAMachineLICMID;
-
private:
PassManagerBase *PM = nullptr;
AnalysisID StartBefore = nullptr;
@@ -218,9 +204,6 @@ public:
/// Return true if the optimized regalloc pipeline is enabled.
bool getOptimizeRegAlloc() const;
- /// Return true if shrink wrapping is enabled.
- bool getEnableShrinkWrap() const;
-
/// Return true if the default global register allocator is in use and
/// has not be overriden on the command line with '-regalloc=...'
bool usingDefaultRegAlloc() const;
@@ -229,7 +212,7 @@ public:
/// representation to the MI representation.
/// Adds IR based lowering and target specific optimization passes and finally
/// the core instruction selection passes.
- /// \returns true if an error occured, false otherwise.
+ /// \returns true if an error occurred, false otherwise.
bool addISelPasses();
/// Add common target configurable passes that perform LLVM IR to IR
@@ -320,10 +303,6 @@ public:
/// verification is enabled.
void addVerifyPass(const std::string &Banner);
- /// Check whether or not GlobalISel should be enabled by default.
- /// Fallback/abort behavior is controlled via other methods.
- virtual bool isGlobalISelEnabled() const;
-
/// Check whether or not GlobalISel should abort on error.
/// When this is disabled, GlobalISel will fall back on SDISel instead of
/// erroring out.
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 81907538fb0b..538a5845466c 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -21,11 +21,11 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Printable.h"
#include <cassert>
@@ -238,12 +238,12 @@ private:
protected:
TargetRegisterInfo(const TargetRegisterInfoDesc *ID,
- regclass_iterator RegClassBegin,
- regclass_iterator RegClassEnd,
+ regclass_iterator RCB,
+ regclass_iterator RCE,
const char *const *SRINames,
const LaneBitmask *SRILaneMasks,
LaneBitmask CoveringLanes,
- const RegClassInfo *const RSI,
+ const RegClassInfo *const RCIs,
unsigned Mode = 0);
virtual ~TargetRegisterInfo();
@@ -444,6 +444,13 @@ public:
return false;
}
+ /// Returns the original SrcReg unless it is the target of a copy-like
+ /// operation, in which case we chain backwards through all such operations
+ /// to the ultimate source register. If a physical register is encountered,
+ /// we stop the search.
+ virtual unsigned lookThruCopyLike(unsigned SrcReg,
+ const MachineRegisterInfo *MRI) const;
+
/// Return a null-terminated list of all of the callee-saved registers on
/// this target. The register should be in the order of desired callee-save
/// stack frame offset. The first register is closest to the incoming stack
@@ -752,6 +759,9 @@ public:
virtual const RegClassWeight &getRegClassWeight(
const TargetRegisterClass *RC) const = 0;
+ /// Returns size in bits of a phys/virtual/generic register.
+ unsigned getRegSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI) const;
+
/// Get the weight in units of pressure for this register unit.
virtual unsigned getRegUnitWeight(unsigned RegUnit) const = 0;
@@ -961,7 +971,7 @@ public:
//===--------------------------------------------------------------------===//
/// Subtarget Hooks
- /// \brief SrcRC and DstRC will be morphed into NewRC if this returns true.
+ /// SrcRC and DstRC will be morphed into NewRC if this returns true.
virtual bool shouldCoalesce(MachineInstr *MI,
const TargetRegisterClass *SrcRC,
unsigned SubReg,
@@ -985,6 +995,12 @@ public:
/// of the set as well.
bool checkAllSuperRegsMarked(const BitVector &RegisterSet,
ArrayRef<MCPhysReg> Exceptions = ArrayRef<MCPhysReg>()) const;
+
+ virtual const TargetRegisterClass *
+ getConstrainedRegClassForOperand(const MachineOperand &MO,
+ const MachineRegisterInfo &MRI) const {
+ return nullptr;
+ }
};
//===----------------------------------------------------------------------===//
@@ -1151,7 +1167,8 @@ struct VirtReg2IndexFunctor {
///
/// Usage: OS << printReg(Reg, TRI, SubRegIdx) << '\n';
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI = nullptr,
- unsigned SubRegIdx = 0);
+ unsigned SubIdx = 0,
+ const MachineRegisterInfo *MRI = nullptr);
/// Create Printable object to print register units on a \ref raw_ostream.
///
@@ -1163,11 +1180,11 @@ Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI = nullptr,
/// Usage: OS << printRegUnit(Unit, TRI) << '\n';
Printable printRegUnit(unsigned Unit, const TargetRegisterInfo *TRI);
-/// \brief Create Printable object to print virtual registers and physical
+/// Create Printable object to print virtual registers and physical
/// registers on a \ref raw_ostream.
Printable printVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI);
-/// \brief Create Printable object to print register classes or register banks
+/// Create Printable object to print register classes or register banks
/// on a \ref raw_ostream.
Printable printRegClassOrBank(unsigned Reg, const MachineRegisterInfo &RegInfo,
const TargetRegisterInfo *TRI);
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h b/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h
index 1044f0bd27e6..6173925e23a1 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCSchedule.h"
@@ -45,24 +46,23 @@ class TargetSchedModel {
public:
TargetSchedModel() : SchedModel(MCSchedModel::GetDefaultSchedModel()) {}
- /// \brief Initialize the machine model for instruction scheduling.
+ /// Initialize the machine model for instruction scheduling.
///
/// The machine model API keeps a copy of the top-level MCSchedModel table
/// indices and may query TargetSubtargetInfo and TargetInstrInfo to resolve
/// dynamic properties.
- void init(const MCSchedModel &sm, const TargetSubtargetInfo *sti,
- const TargetInstrInfo *tii);
+ void init(const TargetSubtargetInfo *TSInfo);
/// Return the MCSchedClassDesc for this instruction.
const MCSchedClassDesc *resolveSchedClass(const MachineInstr *MI) const;
- /// \brief TargetSubtargetInfo getter.
+ /// TargetSubtargetInfo getter.
const TargetSubtargetInfo *getSubtargetInfo() const { return STI; }
- /// \brief TargetInstrInfo getter.
+ /// TargetInstrInfo getter.
const TargetInstrInfo *getInstrInfo() const { return TII; }
- /// \brief Return true if this machine model includes an instruction-level
+ /// Return true if this machine model includes an instruction-level
/// scheduling model.
///
/// This is more detailed than the course grain IssueWidth and default
@@ -71,7 +71,7 @@ public:
const MCSchedModel *getMCSchedModel() const { return &SchedModel; }
- /// \brief Return true if this machine model includes cycle-to-cycle itinerary
+ /// Return true if this machine model includes cycle-to-cycle itinerary
/// data.
///
/// This models scheduling at each stage in the processor pipeline.
@@ -83,35 +83,35 @@ public:
return nullptr;
}
- /// \brief Return true if this machine model includes an instruction-level
+ /// Return true if this machine model includes an instruction-level
/// scheduling model or cycle-to-cycle itinerary data.
bool hasInstrSchedModelOrItineraries() const {
return hasInstrSchedModel() || hasInstrItineraries();
}
- /// \brief Identify the processor corresponding to the current subtarget.
+ /// Identify the processor corresponding to the current subtarget.
unsigned getProcessorID() const { return SchedModel.getProcessorID(); }
- /// \brief Maximum number of micro-ops that may be scheduled per cycle.
+ /// Maximum number of micro-ops that may be scheduled per cycle.
unsigned getIssueWidth() const { return SchedModel.IssueWidth; }
- /// \brief Return true if new group must begin.
+ /// Return true if new group must begin.
bool mustBeginGroup(const MachineInstr *MI,
const MCSchedClassDesc *SC = nullptr) const;
- /// \brief Return true if current group must end.
+ /// Return true if current group must end.
bool mustEndGroup(const MachineInstr *MI,
const MCSchedClassDesc *SC = nullptr) const;
- /// \brief Return the number of issue slots required for this MI.
+ /// Return the number of issue slots required for this MI.
unsigned getNumMicroOps(const MachineInstr *MI,
const MCSchedClassDesc *SC = nullptr) const;
- /// \brief Get the number of kinds of resources for this target.
+ /// Get the number of kinds of resources for this target.
unsigned getNumProcResourceKinds() const {
return SchedModel.getNumProcResourceKinds();
}
- /// \brief Get a processor resource by ID for convenience.
+ /// Get a processor resource by ID for convenience.
const MCProcResourceDesc *getProcResource(unsigned PIdx) const {
return SchedModel.getProcResource(PIdx);
}
@@ -126,7 +126,7 @@ public:
using ProcResIter = const MCWriteProcResEntry *;
- // \brief Get an iterator into the processor resources consumed by this
+ // Get an iterator into the processor resources consumed by this
// scheduling class.
ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const {
// The subtarget holds a single resource table for all processors.
@@ -136,34 +136,34 @@ public:
return STI->getWriteProcResEnd(SC);
}
- /// \brief Multiply the number of units consumed for a resource by this factor
+ /// Multiply the number of units consumed for a resource by this factor
/// to normalize it relative to other resources.
unsigned getResourceFactor(unsigned ResIdx) const {
return ResourceFactors[ResIdx];
}
- /// \brief Multiply number of micro-ops by this factor to normalize it
+ /// Multiply number of micro-ops by this factor to normalize it
/// relative to other resources.
unsigned getMicroOpFactor() const {
return MicroOpFactor;
}
- /// \brief Multiply cycle count by this factor to normalize it relative to
+ /// Multiply cycle count by this factor to normalize it relative to
/// other resources. This is the number of resource units per cycle.
unsigned getLatencyFactor() const {
return ResourceLCM;
}
- /// \brief Number of micro-ops that may be buffered for OOO execution.
+ /// Number of micro-ops that may be buffered for OOO execution.
unsigned getMicroOpBufferSize() const { return SchedModel.MicroOpBufferSize; }
- /// \brief Number of resource units that may be buffered for OOO execution.
+ /// Number of resource units that may be buffered for OOO execution.
/// \return The buffer size in resource units or -1 for unlimited.
int getResourceBufferSize(unsigned PIdx) const {
return SchedModel.getProcResource(PIdx)->BufferSize;
}
- /// \brief Compute operand latency based on the available machine model.
+ /// Compute operand latency based on the available machine model.
///
/// Compute and return the latency of the given data dependent def and use
/// when the operand indices are already known. UseMI may be NULL for an
@@ -172,7 +172,7 @@ public:
const MachineInstr *UseMI, unsigned UseOperIdx)
const;
- /// \brief Compute the instruction latency based on the available machine
+ /// Compute the instruction latency based on the available machine
/// model.
///
/// Compute and return the expected latency of this instruction independent of
@@ -185,18 +185,20 @@ public:
/// if converter after moving it to TargetSchedModel).
unsigned computeInstrLatency(const MachineInstr *MI,
bool UseDefaultDefLatency = true) const;
+ unsigned computeInstrLatency(const MCInst &Inst) const;
unsigned computeInstrLatency(unsigned Opcode) const;
- /// \brief Output dependency latency of a pair of defs of the same register.
+ /// Output dependency latency of a pair of defs of the same register.
///
/// This is typically one cycle.
- unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx,
+ unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
const MachineInstr *DepMI) const;
- /// \brief Compute the reciprocal throughput of the given instruction.
- Optional<double> computeInstrRThroughput(const MachineInstr *MI) const;
- Optional<double> computeInstrRThroughput(unsigned Opcode) const;
+ /// Compute the reciprocal throughput of the given instruction.
+ double computeReciprocalThroughput(const MachineInstr *MI) const;
+ double computeReciprocalThroughput(const MCInst &MI) const;
+ double computeReciprocalThroughput(unsigned Opcode) const;
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
index 9d99cba347ce..227e591f5a7d 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
+++ b/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
@@ -144,7 +144,7 @@ public:
return 0;
}
- /// \brief True if the subtarget should run MachineScheduler after aggressive
+ /// True if the subtarget should run MachineScheduler after aggressive
/// coalescing.
///
/// This currently replaces the SelectionDAG scheduler with the "source" order
@@ -152,14 +152,14 @@ public:
/// TargetLowering preference). It does not yet disable the postRA scheduler.
virtual bool enableMachineScheduler() const;
- /// \brief Support printing of [latency:throughput] comment in output .S file.
+ /// Support printing of [latency:throughput] comment in output .S file.
virtual bool supportPrintSchedInfo() const { return false; }
- /// \brief True if the machine scheduler should disable the TLI preference
+ /// True if the machine scheduler should disable the TLI preference
/// for preRA scheduling with the source level scheduler.
virtual bool enableMachineSchedDefaultSched() const { return true; }
- /// \brief True if the subtarget should enable joining global copies.
+ /// True if the subtarget should enable joining global copies.
///
/// By default this is enabled if the machine scheduler is enabled, but
/// can be overridden.
@@ -171,13 +171,13 @@ public:
/// which is the preferred way to influence this.
virtual bool enablePostRAScheduler() const;
- /// \brief True if the subtarget should run the atomic expansion pass.
+ /// True if the subtarget should run the atomic expansion pass.
virtual bool enableAtomicExpand() const;
/// True if the subtarget should run the indirectbr expansion pass.
virtual bool enableIndirectBrExpand() const;
- /// \brief Override generic scheduling policy within a region.
+ /// Override generic scheduling policy within a region.
///
/// This is a convenient way for targets that don't provide any custom
/// scheduling heuristics (no custom MachineSchedStrategy) to make
@@ -185,7 +185,7 @@ public:
virtual void overrideSchedPolicy(MachineSchedPolicy &Policy,
unsigned NumRegionInstrs) const {}
- // \brief Perform target specific adjustments to the latency of a schedule
+ // Perform target specific adjustments to the latency of a schedule
// dependency.
virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep &dep) const {}
@@ -200,13 +200,13 @@ public:
return CriticalPathRCs.clear();
}
- // \brief Provide an ordered list of schedule DAG mutations for the post-RA
+ // Provide an ordered list of schedule DAG mutations for the post-RA
// scheduler.
virtual void getPostRAMutations(
std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
}
- // \brief Provide an ordered list of schedule DAG mutations for the machine
+ // Provide an ordered list of schedule DAG mutations for the machine
// pipeliner.
virtual void getSMSMutations(
std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
@@ -218,25 +218,25 @@ public:
return CodeGenOpt::Default;
}
- /// \brief True if the subtarget should run the local reassignment
+ /// True if the subtarget should run the local reassignment
/// heuristic of the register allocator.
/// This heuristic may be compile time intensive, \p OptLevel provides
/// a finer grain to tune the register allocator.
virtual bool enableRALocalReassignment(CodeGenOpt::Level OptLevel) const;
- /// \brief True if the subtarget should consider the cost of local intervals
+ /// True if the subtarget should consider the cost of local intervals
/// created by a split candidate when choosing the best split candidate. This
/// heuristic may be compile time intensive.
virtual bool enableAdvancedRASplitCost() const;
- /// \brief Enable use of alias analysis during code generation (during MI
+ /// Enable use of alias analysis during code generation (during MI
/// scheduling, DAGCombine, etc.).
virtual bool useAA() const;
- /// \brief Enable the use of the early if conversion pass.
+ /// Enable the use of the early if conversion pass.
virtual bool enableEarlyIfConversion() const { return false; }
- /// \brief Return PBQPConstraint(s) for the target.
+ /// Return PBQPConstraint(s) for the target.
///
/// Override to provide custom PBQP constraints.
virtual std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const {
@@ -249,8 +249,11 @@ public:
virtual bool enableSubRegLiveness() const { return false; }
/// Returns string representation of scheduler comment
- std::string getSchedInfoStr(const MachineInstr &MI) const override;
+ std::string getSchedInfoStr(const MachineInstr &MI) const;
std::string getSchedInfoStr(MCInst const &MCI) const override;
+
+ /// This is called after a .mir file was loaded.
+ virtual void mirFileLoaded(MachineFunction &MF) const;
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h
index 40d501edde10..d2ef4a94f8e2 100644
--- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h
+++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h
@@ -16,8 +16,8 @@
#ifndef LLVM_CODEGEN_VALUETYPES_H
#define LLVM_CODEGEN_VALUETYPES_H
-#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <cstdint>
diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.td b/contrib/llvm/include/llvm/CodeGen/ValueTypes.td
index 73c7fb4ce4b3..0abb4ece1d14 100644
--- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.td
+++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.td
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
//
// Value types - These values correspond to the register types defined in the
-// ValueTypes.h file. If you update anything here, you must update it there as
-// well!
+// MachineValueTypes.h file. If you update anything here, you must update it
+// there as well!
//
//===----------------------------------------------------------------------===//
@@ -69,7 +69,7 @@ def v4i32 : ValueType<128, 43>; // 4 x i32 vector value
def v8i32 : ValueType<256, 44>; // 8 x i32 vector value
def v16i32 : ValueType<512, 45>; // 16 x i32 vector value
def v32i32 : ValueType<1024,46>; // 32 x i32 vector value
-def v64i32 : ValueType<2048,47>; // 32 x i32 vector value
+def v64i32 : ValueType<2048,47>; // 64 x i32 vector value
def v1i64 : ValueType<64 , 48>; // 1 x i64 vector value
def v2i64 : ValueType<128, 49>; // 2 x i64 vector value
@@ -145,6 +145,7 @@ def x86mmx : ValueType<64 , 109>; // X86 MMX value
def FlagVT : ValueType<0 , 110>; // Pre-RA sched glue
def isVoid : ValueType<0 , 111>; // Produces no value
def untyped: ValueType<8 , 112>; // Produces an untyped value
+def ExceptRef: ValueType<0, 113>; // WebAssembly's except_ref type
def token : ValueType<0 , 248>; // TokenTy
def MetadataVT: ValueType<0, 249>; // Metadata
diff --git a/contrib/llvm/include/llvm/CodeGen/VirtRegMap.h b/contrib/llvm/include/llvm/CodeGen/VirtRegMap.h
index 3b06f0393114..6a8e50a7e5f5 100644
--- a/contrib/llvm/include/llvm/CodeGen/VirtRegMap.h
+++ b/contrib/llvm/include/llvm/CodeGen/VirtRegMap.h
@@ -90,24 +90,24 @@ class TargetInstrInfo;
void grow();
- /// @brief returns true if the specified virtual register is
+ /// returns true if the specified virtual register is
/// mapped to a physical register
bool hasPhys(unsigned virtReg) const {
return getPhys(virtReg) != NO_PHYS_REG;
}
- /// @brief returns the physical register mapped to the specified
+ /// returns the physical register mapped to the specified
/// virtual register
unsigned getPhys(unsigned virtReg) const {
assert(TargetRegisterInfo::isVirtualRegister(virtReg));
return Virt2PhysMap[virtReg];
}
- /// @brief creates a mapping for the specified virtual register to
+ /// creates a mapping for the specified virtual register to
/// the specified physical register
void assignVirt2Phys(unsigned virtReg, MCPhysReg physReg);
- /// @brief clears the specified virtual register's, physical
+ /// clears the specified virtual register's, physical
/// register mapping
void clearVirt(unsigned virtReg) {
assert(TargetRegisterInfo::isVirtualRegister(virtReg));
@@ -116,26 +116,26 @@ class TargetInstrInfo;
Virt2PhysMap[virtReg] = NO_PHYS_REG;
}
- /// @brief clears all virtual to physical register mappings
+ /// clears all virtual to physical register mappings
void clearAllVirt() {
Virt2PhysMap.clear();
grow();
}
- /// @brief returns true if VirtReg is assigned to its preferred physreg.
+ /// returns true if VirtReg is assigned to its preferred physreg.
bool hasPreferredPhys(unsigned VirtReg);
- /// @brief returns true if VirtReg has a known preferred register.
+ /// returns true if VirtReg has a known preferred register.
/// This returns false if VirtReg has a preference that is a virtual
/// register that hasn't been assigned yet.
bool hasKnownPreference(unsigned VirtReg);
- /// @brief records virtReg is a split live interval from SReg.
+ /// records virtReg is a split live interval from SReg.
void setIsSplitFromReg(unsigned virtReg, unsigned SReg) {
Virt2SplitMap[virtReg] = SReg;
}
- /// @brief returns the live interval virtReg is split from.
+ /// returns the live interval virtReg is split from.
unsigned getPreSplitReg(unsigned virtReg) const {
return Virt2SplitMap[virtReg];
}
@@ -149,7 +149,7 @@ class TargetInstrInfo;
return Orig ? Orig : VirtReg;
}
- /// @brief returns true if the specified virtual register is not
+ /// returns true if the specified virtual register is not
/// mapped to a stack slot or rematerialized.
bool isAssignedReg(unsigned virtReg) const {
if (getStackSlot(virtReg) == NO_STACK_SLOT)
@@ -159,20 +159,20 @@ class TargetInstrInfo;
return (Virt2SplitMap[virtReg] && Virt2PhysMap[virtReg] != NO_PHYS_REG);
}
- /// @brief returns the stack slot mapped to the specified virtual
+ /// returns the stack slot mapped to the specified virtual
/// register
int getStackSlot(unsigned virtReg) const {
assert(TargetRegisterInfo::isVirtualRegister(virtReg));
return Virt2StackSlotMap[virtReg];
}
- /// @brief create a mapping for the specifed virtual register to
+ /// create a mapping for the specifed virtual register to
/// the next available stack slot
int assignVirt2StackSlot(unsigned virtReg);
- /// @brief create a mapping for the specified virtual register to
+ /// create a mapping for the specified virtual register to
/// the specified stack slot
- void assignVirt2StackSlot(unsigned virtReg, int frameIndex);
+ void assignVirt2StackSlot(unsigned virtReg, int SS);
void print(raw_ostream &OS, const Module* M = nullptr) const override;
void dump() const;
diff --git a/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h b/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h
new file mode 100644
index 000000000000..3ad6760d8813
--- /dev/null
+++ b/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h
@@ -0,0 +1,80 @@
+//===--- llvm/CodeGen/WasmEHFuncInfo.h --------------------------*- 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 Wasm exception handling schemes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H
+#define LLVM_CODEGEN_WASMEHFUNCINFO_H
+
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/IR/BasicBlock.h"
+
+namespace llvm {
+
+using BBOrMBB = PointerUnion<const BasicBlock *, MachineBasicBlock *>;
+
+struct WasmEHFuncInfo {
+ // When there is an entry <A, B>, if an exception is not caught by A, it
+ // should next unwind to the EH pad B.
+ DenseMap<BBOrMBB, BBOrMBB> EHPadUnwindMap;
+ // For entry <A, B>, A is a BB with an instruction that may throw
+ // (invoke/cleanupret in LLVM IR, call/rethrow in the backend) and B is an EH
+ // pad that A unwinds to.
+ DenseMap<BBOrMBB, BBOrMBB> ThrowUnwindMap;
+
+ // Helper functions
+ const BasicBlock *getEHPadUnwindDest(const BasicBlock *BB) const {
+ return EHPadUnwindMap.lookup(BB).get<const BasicBlock *>();
+ }
+ void setEHPadUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) {
+ EHPadUnwindMap[BB] = Dest;
+ }
+ const BasicBlock *getThrowUnwindDest(BasicBlock *BB) const {
+ return ThrowUnwindMap.lookup(BB).get<const BasicBlock *>();
+ }
+ void setThrowUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) {
+ ThrowUnwindMap[BB] = Dest;
+ }
+ bool hasEHPadUnwindDest(const BasicBlock *BB) const {
+ return EHPadUnwindMap.count(BB);
+ }
+ bool hasThrowUnwindDest(const BasicBlock *BB) const {
+ return ThrowUnwindMap.count(BB);
+ }
+
+ MachineBasicBlock *getEHPadUnwindDest(MachineBasicBlock *MBB) const {
+ return EHPadUnwindMap.lookup(MBB).get<MachineBasicBlock *>();
+ }
+ void setEHPadUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) {
+ EHPadUnwindMap[MBB] = Dest;
+ }
+ MachineBasicBlock *getThrowUnwindDest(MachineBasicBlock *MBB) const {
+ return ThrowUnwindMap.lookup(MBB).get<MachineBasicBlock *>();
+ }
+ void setThrowUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) {
+ ThrowUnwindMap[MBB] = Dest;
+ }
+ bool hasEHPadUnwindDest(MachineBasicBlock *MBB) const {
+ return EHPadUnwindMap.count(MBB);
+ }
+ bool hasThrowUnwindDest(MachineBasicBlock *MBB) const {
+ return ThrowUnwindMap.count(MBB);
+ }
+};
+
+// Analyze the IR in the given function to build WasmEHFuncInfo.
+void calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &EHInfo);
+
+} // namespace llvm
+
+#endif // LLVM_CODEGEN_WASMEHFUNCINFO_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h
index 9f3a753ad1ae..9dbeb438f4ae 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h
@@ -61,6 +61,30 @@ template <typename Kind> struct RemappedRecord {
SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings;
};
+template <typename Record, typename Func>
+Error forEachCodeViewRecord(ArrayRef<uint8_t> StreamBuffer, Func F) {
+ while (!StreamBuffer.empty()) {
+ if (StreamBuffer.size() < sizeof(RecordPrefix))
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+
+ const RecordPrefix *Prefix =
+ reinterpret_cast<const RecordPrefix *>(StreamBuffer.data());
+
+ size_t RealLen = Prefix->RecordLen + 2;
+ if (StreamBuffer.size() < RealLen)
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+
+ ArrayRef<uint8_t> Data = StreamBuffer.take_front(RealLen);
+ StreamBuffer = StreamBuffer.drop_front(RealLen);
+
+ Record R(static_cast<decltype(Record::Type)>((uint16_t)Prefix->RecordKind),
+ Data);
+ if (auto EC = F(R))
+ return EC;
+ }
+ return Error::success();
+}
+
/// Read a complete record from a stream at a random offset.
template <typename Kind>
inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream,
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
index df55e181364c..b765ba1abb4d 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
@@ -20,7 +20,7 @@ class TypeCollection;
class TypeVisitorCallbacks;
enum VisitorDataSource {
- VDS_BytesPresent, // The record bytes are passed into the the visitation
+ VDS_BytesPresent, // The record bytes are passed into the visitation
// function. The algorithm should first deserialize them
// before passing them on through the pipeline.
VDS_BytesExternal // The record bytes are not present, and it is the
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h
index 1a4f510c24ab..4ce9f68cffd9 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h
@@ -22,8 +22,8 @@
namespace llvm {
namespace codeview {
-/// Distinguishes individual records in .debug$T section or PDB type stream. The
-/// documentation and headers talk about this as the "leaf" type.
+/// Distinguishes individual records in .debug$T or .debug$P section or PDB type
+/// stream. The documentation and headers talk about this as the "leaf" type.
enum class TypeRecordKind : uint16_t {
#define TYPE_RECORD(lf_ename, value, name) name = value,
#include "CodeViewTypes.def"
@@ -531,7 +531,7 @@ enum LineFlags : uint16_t {
LF_HaveColumns = 1, // CV_LINES_HAVE_COLUMNS
};
-/// Data in the the SUBSEC_FRAMEDATA subection.
+/// Data in the SUBSEC_FRAMEDATA subection.
struct FrameData {
support::ulittle32_t RvaStart;
support::ulittle32_t CodeSize;
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
index 3f0660294866..6da8893bd61a 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
@@ -15,254 +15,254 @@
#define CV_REGISTER(name, value)
#endif
-// This currently only contains the "register subset shraed by all processor
+// This currently only contains the "register subset shared by all processor
// types" (ERR etc.) and the x86 registers.
-CV_REGISTER(ERR, 30000)
-CV_REGISTER(TEB, 30001)
-CV_REGISTER(TIMER, 30002)
-CV_REGISTER(EFAD1, 30003)
-CV_REGISTER(EFAD2, 30004)
-CV_REGISTER(EFAD3, 30005)
-CV_REGISTER(VFRAME, 30006)
-CV_REGISTER(HANDLE, 30007)
-CV_REGISTER(PARAMS, 30008)
-CV_REGISTER(LOCALS, 30009)
-CV_REGISTER(TID, 30010)
-CV_REGISTER(ENV, 30011)
-CV_REGISTER(CMDLN, 30012)
+CV_REGISTER(CVRegERR, 30000)
+CV_REGISTER(CVRegTEB, 30001)
+CV_REGISTER(CVRegTIMER, 30002)
+CV_REGISTER(CVRegEFAD1, 30003)
+CV_REGISTER(CVRegEFAD2, 30004)
+CV_REGISTER(CVRegEFAD3, 30005)
+CV_REGISTER(CVRegVFRAME, 30006)
+CV_REGISTER(CVRegHANDLE, 30007)
+CV_REGISTER(CVRegPARAMS, 30008)
+CV_REGISTER(CVRegLOCALS, 30009)
+CV_REGISTER(CVRegTID, 30010)
+CV_REGISTER(CVRegENV, 30011)
+CV_REGISTER(CVRegCMDLN, 30012)
-CV_REGISTER(NONE, 0)
-CV_REGISTER(AL, 1)
-CV_REGISTER(CL, 2)
-CV_REGISTER(DL, 3)
-CV_REGISTER(BL, 4)
-CV_REGISTER(AH, 5)
-CV_REGISTER(CH, 6)
-CV_REGISTER(DH, 7)
-CV_REGISTER(BH, 8)
-CV_REGISTER(AX, 9)
-CV_REGISTER(CX, 10)
-CV_REGISTER(DX, 11)
-CV_REGISTER(BX, 12)
-CV_REGISTER(SP, 13)
-CV_REGISTER(BP, 14)
-CV_REGISTER(SI, 15)
-CV_REGISTER(DI, 16)
-CV_REGISTER(EAX, 17)
-CV_REGISTER(ECX, 18)
-CV_REGISTER(EDX, 19)
-CV_REGISTER(EBX, 20)
-CV_REGISTER(ESP, 21)
-CV_REGISTER(EBP, 22)
-CV_REGISTER(ESI, 23)
-CV_REGISTER(EDI, 24)
-CV_REGISTER(ES, 25)
-CV_REGISTER(CS, 26)
-CV_REGISTER(SS, 27)
-CV_REGISTER(DS, 28)
-CV_REGISTER(FS, 29)
-CV_REGISTER(GS, 30)
-CV_REGISTER(IP, 31)
-CV_REGISTER(FLAGS, 32)
-CV_REGISTER(EIP, 33)
-CV_REGISTER(EFLAGS, 34)
-CV_REGISTER(TEMP, 40)
-CV_REGISTER(TEMPH, 41)
-CV_REGISTER(QUOTE, 42)
-CV_REGISTER(PCDR3, 43)
-CV_REGISTER(PCDR4, 44)
-CV_REGISTER(PCDR5, 45)
-CV_REGISTER(PCDR6, 46)
-CV_REGISTER(PCDR7, 47)
-CV_REGISTER(CR0, 80)
-CV_REGISTER(CR1, 81)
-CV_REGISTER(CR2, 82)
-CV_REGISTER(CR3, 83)
-CV_REGISTER(CR4, 84)
-CV_REGISTER(DR0, 90)
-CV_REGISTER(DR1, 91)
-CV_REGISTER(DR2, 92)
-CV_REGISTER(DR3, 93)
-CV_REGISTER(DR4, 94)
-CV_REGISTER(DR5, 95)
-CV_REGISTER(DR6, 96)
-CV_REGISTER(DR7, 97)
-CV_REGISTER(GDTR, 110)
-CV_REGISTER(GDTL, 111)
-CV_REGISTER(IDTR, 112)
-CV_REGISTER(IDTL, 113)
-CV_REGISTER(LDTR, 114)
-CV_REGISTER(TR, 115)
+CV_REGISTER(CVRegNONE, 0)
+CV_REGISTER(CVRegAL, 1)
+CV_REGISTER(CVRegCL, 2)
+CV_REGISTER(CVRegDL, 3)
+CV_REGISTER(CVRegBL, 4)
+CV_REGISTER(CVRegAH, 5)
+CV_REGISTER(CVRegCH, 6)
+CV_REGISTER(CVRegDH, 7)
+CV_REGISTER(CVRegBH, 8)
+CV_REGISTER(CVRegAX, 9)
+CV_REGISTER(CVRegCX, 10)
+CV_REGISTER(CVRegDX, 11)
+CV_REGISTER(CVRegBX, 12)
+CV_REGISTER(CVRegSP, 13)
+CV_REGISTER(CVRegBP, 14)
+CV_REGISTER(CVRegSI, 15)
+CV_REGISTER(CVRegDI, 16)
+CV_REGISTER(CVRegEAX, 17)
+CV_REGISTER(CVRegECX, 18)
+CV_REGISTER(CVRegEDX, 19)
+CV_REGISTER(CVRegEBX, 20)
+CV_REGISTER(CVRegESP, 21)
+CV_REGISTER(CVRegEBP, 22)
+CV_REGISTER(CVRegESI, 23)
+CV_REGISTER(CVRegEDI, 24)
+CV_REGISTER(CVRegES, 25)
+CV_REGISTER(CVRegCS, 26)
+CV_REGISTER(CVRegSS, 27)
+CV_REGISTER(CVRegDS, 28)
+CV_REGISTER(CVRegFS, 29)
+CV_REGISTER(CVRegGS, 30)
+CV_REGISTER(CVRegIP, 31)
+CV_REGISTER(CVRegFLAGS, 32)
+CV_REGISTER(CVRegEIP, 33)
+CV_REGISTER(CVRegEFLAGS, 34)
+CV_REGISTER(CVRegTEMP, 40)
+CV_REGISTER(CVRegTEMPH, 41)
+CV_REGISTER(CVRegQUOTE, 42)
+CV_REGISTER(CVRegPCDR3, 43)
+CV_REGISTER(CVRegPCDR4, 44)
+CV_REGISTER(CVRegPCDR5, 45)
+CV_REGISTER(CVRegPCDR6, 46)
+CV_REGISTER(CVRegPCDR7, 47)
+CV_REGISTER(CVRegCR0, 80)
+CV_REGISTER(CVRegCR1, 81)
+CV_REGISTER(CVRegCR2, 82)
+CV_REGISTER(CVRegCR3, 83)
+CV_REGISTER(CVRegCR4, 84)
+CV_REGISTER(CVRegDR0, 90)
+CV_REGISTER(CVRegDR1, 91)
+CV_REGISTER(CVRegDR2, 92)
+CV_REGISTER(CVRegDR3, 93)
+CV_REGISTER(CVRegDR4, 94)
+CV_REGISTER(CVRegDR5, 95)
+CV_REGISTER(CVRegDR6, 96)
+CV_REGISTER(CVRegDR7, 97)
+CV_REGISTER(CVRegGDTR, 110)
+CV_REGISTER(CVRegGDTL, 111)
+CV_REGISTER(CVRegIDTR, 112)
+CV_REGISTER(CVRegIDTL, 113)
+CV_REGISTER(CVRegLDTR, 114)
+CV_REGISTER(CVRegTR, 115)
-CV_REGISTER(PSEUDO1, 116)
-CV_REGISTER(PSEUDO2, 117)
-CV_REGISTER(PSEUDO3, 118)
-CV_REGISTER(PSEUDO4, 119)
-CV_REGISTER(PSEUDO5, 120)
-CV_REGISTER(PSEUDO6, 121)
-CV_REGISTER(PSEUDO7, 122)
-CV_REGISTER(PSEUDO8, 123)
-CV_REGISTER(PSEUDO9, 124)
+CV_REGISTER(CVRegPSEUDO1, 116)
+CV_REGISTER(CVRegPSEUDO2, 117)
+CV_REGISTER(CVRegPSEUDO3, 118)
+CV_REGISTER(CVRegPSEUDO4, 119)
+CV_REGISTER(CVRegPSEUDO5, 120)
+CV_REGISTER(CVRegPSEUDO6, 121)
+CV_REGISTER(CVRegPSEUDO7, 122)
+CV_REGISTER(CVRegPSEUDO8, 123)
+CV_REGISTER(CVRegPSEUDO9, 124)
-CV_REGISTER(ST0, 128)
-CV_REGISTER(ST1, 129)
-CV_REGISTER(ST2, 130)
-CV_REGISTER(ST3, 131)
-CV_REGISTER(ST4, 132)
-CV_REGISTER(ST5, 133)
-CV_REGISTER(ST6, 134)
-CV_REGISTER(ST7, 135)
-CV_REGISTER(CTRL, 136)
-CV_REGISTER(STAT, 137)
-CV_REGISTER(TAG, 138)
-CV_REGISTER(FPIP, 139)
-CV_REGISTER(FPCS, 140)
-CV_REGISTER(FPDO, 141)
-CV_REGISTER(FPDS, 142)
-CV_REGISTER(ISEM, 143)
-CV_REGISTER(FPEIP, 144)
-CV_REGISTER(FPEDO, 145)
+CV_REGISTER(CVRegST0, 128)
+CV_REGISTER(CVRegST1, 129)
+CV_REGISTER(CVRegST2, 130)
+CV_REGISTER(CVRegST3, 131)
+CV_REGISTER(CVRegST4, 132)
+CV_REGISTER(CVRegST5, 133)
+CV_REGISTER(CVRegST6, 134)
+CV_REGISTER(CVRegST7, 135)
+CV_REGISTER(CVRegCTRL, 136)
+CV_REGISTER(CVRegSTAT, 137)
+CV_REGISTER(CVRegTAG, 138)
+CV_REGISTER(CVRegFPIP, 139)
+CV_REGISTER(CVRegFPCS, 140)
+CV_REGISTER(CVRegFPDO, 141)
+CV_REGISTER(CVRegFPDS, 142)
+CV_REGISTER(CVRegISEM, 143)
+CV_REGISTER(CVRegFPEIP, 144)
+CV_REGISTER(CVRegFPEDO, 145)
-CV_REGISTER(MM0, 146)
-CV_REGISTER(MM1, 147)
-CV_REGISTER(MM2, 148)
-CV_REGISTER(MM3, 149)
-CV_REGISTER(MM4, 150)
-CV_REGISTER(MM5, 151)
-CV_REGISTER(MM6, 152)
-CV_REGISTER(MM7, 153)
+CV_REGISTER(CVRegMM0, 146)
+CV_REGISTER(CVRegMM1, 147)
+CV_REGISTER(CVRegMM2, 148)
+CV_REGISTER(CVRegMM3, 149)
+CV_REGISTER(CVRegMM4, 150)
+CV_REGISTER(CVRegMM5, 151)
+CV_REGISTER(CVRegMM6, 152)
+CV_REGISTER(CVRegMM7, 153)
-CV_REGISTER(XMM0, 154)
-CV_REGISTER(XMM1, 155)
-CV_REGISTER(XMM2, 156)
-CV_REGISTER(XMM3, 157)
-CV_REGISTER(XMM4, 158)
-CV_REGISTER(XMM5, 159)
-CV_REGISTER(XMM6, 160)
-CV_REGISTER(XMM7, 161)
+CV_REGISTER(CVRegXMM0, 154)
+CV_REGISTER(CVRegXMM1, 155)
+CV_REGISTER(CVRegXMM2, 156)
+CV_REGISTER(CVRegXMM3, 157)
+CV_REGISTER(CVRegXMM4, 158)
+CV_REGISTER(CVRegXMM5, 159)
+CV_REGISTER(CVRegXMM6, 160)
+CV_REGISTER(CVRegXMM7, 161)
-CV_REGISTER(MXCSR, 211)
+CV_REGISTER(CVRegMXCSR, 211)
-CV_REGISTER(EDXEAX, 212)
+CV_REGISTER(CVRegEDXEAX, 212)
-CV_REGISTER(EMM0L, 220)
-CV_REGISTER(EMM1L, 221)
-CV_REGISTER(EMM2L, 222)
-CV_REGISTER(EMM3L, 223)
-CV_REGISTER(EMM4L, 224)
-CV_REGISTER(EMM5L, 225)
-CV_REGISTER(EMM6L, 226)
-CV_REGISTER(EMM7L, 227)
+CV_REGISTER(CVRegEMM0L, 220)
+CV_REGISTER(CVRegEMM1L, 221)
+CV_REGISTER(CVRegEMM2L, 222)
+CV_REGISTER(CVRegEMM3L, 223)
+CV_REGISTER(CVRegEMM4L, 224)
+CV_REGISTER(CVRegEMM5L, 225)
+CV_REGISTER(CVRegEMM6L, 226)
+CV_REGISTER(CVRegEMM7L, 227)
-CV_REGISTER(EMM0H, 228)
-CV_REGISTER(EMM1H, 229)
-CV_REGISTER(EMM2H, 230)
-CV_REGISTER(EMM3H, 231)
-CV_REGISTER(EMM4H, 232)
-CV_REGISTER(EMM5H, 233)
-CV_REGISTER(EMM6H, 234)
-CV_REGISTER(EMM7H, 235)
+CV_REGISTER(CVRegEMM0H, 228)
+CV_REGISTER(CVRegEMM1H, 229)
+CV_REGISTER(CVRegEMM2H, 230)
+CV_REGISTER(CVRegEMM3H, 231)
+CV_REGISTER(CVRegEMM4H, 232)
+CV_REGISTER(CVRegEMM5H, 233)
+CV_REGISTER(CVRegEMM6H, 234)
+CV_REGISTER(CVRegEMM7H, 235)
-CV_REGISTER(MM00, 236)
-CV_REGISTER(MM01, 237)
-CV_REGISTER(MM10, 238)
-CV_REGISTER(MM11, 239)
-CV_REGISTER(MM20, 240)
-CV_REGISTER(MM21, 241)
-CV_REGISTER(MM30, 242)
-CV_REGISTER(MM31, 243)
-CV_REGISTER(MM40, 244)
-CV_REGISTER(MM41, 245)
-CV_REGISTER(MM50, 246)
-CV_REGISTER(MM51, 247)
-CV_REGISTER(MM60, 248)
-CV_REGISTER(MM61, 249)
-CV_REGISTER(MM70, 250)
-CV_REGISTER(MM71, 251)
+CV_REGISTER(CVRegMM00, 236)
+CV_REGISTER(CVRegMM01, 237)
+CV_REGISTER(CVRegMM10, 238)
+CV_REGISTER(CVRegMM11, 239)
+CV_REGISTER(CVRegMM20, 240)
+CV_REGISTER(CVRegMM21, 241)
+CV_REGISTER(CVRegMM30, 242)
+CV_REGISTER(CVRegMM31, 243)
+CV_REGISTER(CVRegMM40, 244)
+CV_REGISTER(CVRegMM41, 245)
+CV_REGISTER(CVRegMM50, 246)
+CV_REGISTER(CVRegMM51, 247)
+CV_REGISTER(CVRegMM60, 248)
+CV_REGISTER(CVRegMM61, 249)
+CV_REGISTER(CVRegMM70, 250)
+CV_REGISTER(CVRegMM71, 251)
-CV_REGISTER(BND0, 396)
-CV_REGISTER(BND1, 397)
-CV_REGISTER(BND2, 398)
+CV_REGISTER(CVRegBND0, 396)
+CV_REGISTER(CVRegBND1, 397)
+CV_REGISTER(CVRegBND2, 398)
-CV_REGISTER(XMM8, 252)
-CV_REGISTER(XMM9, 253)
-CV_REGISTER(XMM10, 254)
-CV_REGISTER(XMM11, 255)
-CV_REGISTER(XMM12, 256)
-CV_REGISTER(XMM13, 257)
-CV_REGISTER(XMM14, 258)
-CV_REGISTER(XMM15, 259)
+CV_REGISTER(CVRegXMM8, 252)
+CV_REGISTER(CVRegXMM9, 253)
+CV_REGISTER(CVRegXMM10, 254)
+CV_REGISTER(CVRegXMM11, 255)
+CV_REGISTER(CVRegXMM12, 256)
+CV_REGISTER(CVRegXMM13, 257)
+CV_REGISTER(CVRegXMM14, 258)
+CV_REGISTER(CVRegXMM15, 259)
-CV_REGISTER(SIL, 324)
-CV_REGISTER(DIL, 325)
-CV_REGISTER(BPL, 326)
-CV_REGISTER(SPL, 327)
+CV_REGISTER(CVRegSIL, 324)
+CV_REGISTER(CVRegDIL, 325)
+CV_REGISTER(CVRegBPL, 326)
+CV_REGISTER(CVRegSPL, 327)
-CV_REGISTER(RAX, 328)
-CV_REGISTER(RBX, 329)
-CV_REGISTER(RCX, 330)
-CV_REGISTER(RDX, 331)
-CV_REGISTER(RSI, 332)
-CV_REGISTER(RDI, 333)
-CV_REGISTER(RBP, 334)
-CV_REGISTER(RSP, 335)
+CV_REGISTER(CVRegRAX, 328)
+CV_REGISTER(CVRegRBX, 329)
+CV_REGISTER(CVRegRCX, 330)
+CV_REGISTER(CVRegRDX, 331)
+CV_REGISTER(CVRegRSI, 332)
+CV_REGISTER(CVRegRDI, 333)
+CV_REGISTER(CVRegRBP, 334)
+CV_REGISTER(CVRegRSP, 335)
-CV_REGISTER(R8, 336)
-CV_REGISTER(R9, 337)
-CV_REGISTER(R10, 338)
-CV_REGISTER(R11, 339)
-CV_REGISTER(R12, 340)
-CV_REGISTER(R13, 341)
-CV_REGISTER(R14, 342)
-CV_REGISTER(R15, 343)
+CV_REGISTER(CVRegR8, 336)
+CV_REGISTER(CVRegR9, 337)
+CV_REGISTER(CVRegR10, 338)
+CV_REGISTER(CVRegR11, 339)
+CV_REGISTER(CVRegR12, 340)
+CV_REGISTER(CVRegR13, 341)
+CV_REGISTER(CVRegR14, 342)
+CV_REGISTER(CVRegR15, 343)
-CV_REGISTER(R8B, 344)
-CV_REGISTER(R9B, 345)
-CV_REGISTER(R10B, 346)
-CV_REGISTER(R11B, 347)
-CV_REGISTER(R12B, 348)
-CV_REGISTER(R13B, 349)
-CV_REGISTER(R14B, 350)
-CV_REGISTER(R15B, 351)
+CV_REGISTER(CVRegR8B, 344)
+CV_REGISTER(CVRegR9B, 345)
+CV_REGISTER(CVRegR10B, 346)
+CV_REGISTER(CVRegR11B, 347)
+CV_REGISTER(CVRegR12B, 348)
+CV_REGISTER(CVRegR13B, 349)
+CV_REGISTER(CVRegR14B, 350)
+CV_REGISTER(CVRegR15B, 351)
-CV_REGISTER(R8W, 352)
-CV_REGISTER(R9W, 353)
-CV_REGISTER(R10W, 354)
-CV_REGISTER(R11W, 355)
-CV_REGISTER(R12W, 356)
-CV_REGISTER(R13W, 357)
-CV_REGISTER(R14W, 358)
-CV_REGISTER(R15W, 359)
+CV_REGISTER(CVRegR8W, 352)
+CV_REGISTER(CVRegR9W, 353)
+CV_REGISTER(CVRegR10W, 354)
+CV_REGISTER(CVRegR11W, 355)
+CV_REGISTER(CVRegR12W, 356)
+CV_REGISTER(CVRegR13W, 357)
+CV_REGISTER(CVRegR14W, 358)
+CV_REGISTER(CVRegR15W, 359)
-CV_REGISTER(R8D, 360)
-CV_REGISTER(R9D, 361)
-CV_REGISTER(R10D, 362)
-CV_REGISTER(R11D, 363)
-CV_REGISTER(R12D, 364)
-CV_REGISTER(R13D, 365)
-CV_REGISTER(R14D, 366)
-CV_REGISTER(R15D, 367)
+CV_REGISTER(CVRegR8D, 360)
+CV_REGISTER(CVRegR9D, 361)
+CV_REGISTER(CVRegR10D, 362)
+CV_REGISTER(CVRegR11D, 363)
+CV_REGISTER(CVRegR12D, 364)
+CV_REGISTER(CVRegR13D, 365)
+CV_REGISTER(CVRegR14D, 366)
+CV_REGISTER(CVRegR15D, 367)
// cvconst.h defines both CV_REG_YMM0 (252) and CV_AMD64_YMM0 (368). Keep the
// original prefix to distinguish them.
-CV_REGISTER(AMD64_YMM0, 368)
-CV_REGISTER(AMD64_YMM1, 369)
-CV_REGISTER(AMD64_YMM2, 370)
-CV_REGISTER(AMD64_YMM3, 371)
-CV_REGISTER(AMD64_YMM4, 372)
-CV_REGISTER(AMD64_YMM5, 373)
-CV_REGISTER(AMD64_YMM6, 374)
-CV_REGISTER(AMD64_YMM7, 375)
-CV_REGISTER(AMD64_YMM8, 376)
-CV_REGISTER(AMD64_YMM9, 377)
-CV_REGISTER(AMD64_YMM10, 378)
-CV_REGISTER(AMD64_YMM11, 379)
-CV_REGISTER(AMD64_YMM12, 380)
-CV_REGISTER(AMD64_YMM13, 381)
-CV_REGISTER(AMD64_YMM14, 382)
-CV_REGISTER(AMD64_YMM15, 383)
+CV_REGISTER(CVRegAMD64_YMM0, 368)
+CV_REGISTER(CVRegAMD64_YMM1, 369)
+CV_REGISTER(CVRegAMD64_YMM2, 370)
+CV_REGISTER(CVRegAMD64_YMM3, 371)
+CV_REGISTER(CVRegAMD64_YMM4, 372)
+CV_REGISTER(CVRegAMD64_YMM5, 373)
+CV_REGISTER(CVRegAMD64_YMM6, 374)
+CV_REGISTER(CVRegAMD64_YMM7, 375)
+CV_REGISTER(CVRegAMD64_YMM8, 376)
+CV_REGISTER(CVRegAMD64_YMM9, 377)
+CV_REGISTER(CVRegAMD64_YMM10, 378)
+CV_REGISTER(CVRegAMD64_YMM11, 379)
+CV_REGISTER(CVRegAMD64_YMM12, 380)
+CV_REGISTER(CVRegAMD64_YMM13, 381)
+CV_REGISTER(CVRegAMD64_YMM14, 382)
+CV_REGISTER(CVRegAMD64_YMM15, 383)
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
index 69ce9606a670..e9a479dba496 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
@@ -87,6 +87,8 @@ TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine)
TYPE_RECORD(LF_METHODLIST, 0x1206, MethodOverloadList)
+TYPE_RECORD(LF_PRECOMP, 0x1509, Precomp)
+TYPE_RECORD(LF_ENDPRECOMP, 0x0014, EndPrecomp)
// 16 bit type records.
CV_TYPE(LF_MODIFIER_16t, 0x0001)
@@ -106,7 +108,6 @@ CV_TYPE(LF_NOTTRAN, 0x0010)
CV_TYPE(LF_DIMARRAY_16t, 0x0011)
CV_TYPE(LF_VFTPATH_16t, 0x0012)
CV_TYPE(LF_PRECOMP_16t, 0x0013)
-CV_TYPE(LF_ENDPRECOMP, 0x0014)
CV_TYPE(LF_OEM_16t, 0x0015)
CV_TYPE(LF_TYPESERVER_ST, 0x0016)
@@ -181,7 +182,6 @@ CV_TYPE(LF_MANAGED_ST, 0x140f)
CV_TYPE(LF_ST_MAX, 0x1500)
CV_TYPE(LF_TYPESERVER, 0x1501)
CV_TYPE(LF_DIMARRAY, 0x1508)
-CV_TYPE(LF_PRECOMP, 0x1509)
CV_TYPE(LF_ALIAS, 0x150a)
CV_TYPE(LF_DEFARG, 0x150b)
CV_TYPE(LF_FRIENDFCN, 0x150c)
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h
index 7f0f10e4fbfa..bebc960223cc 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
@@ -66,19 +67,26 @@ public:
uint32_t insert(StringRef S);
// Return the ID for string S. Assumes S exists in the table.
- uint32_t getStringId(StringRef S) const;
+ uint32_t getIdForString(StringRef S) const;
+
+ StringRef getStringForId(uint32_t Id) const;
uint32_t calculateSerializedSize() const override;
Error commit(BinaryStreamWriter &Writer) const override;
uint32_t size() const;
- StringMap<uint32_t>::const_iterator begin() const { return Strings.begin(); }
+ StringMap<uint32_t>::const_iterator begin() const {
+ return StringToId.begin();
+ }
+
+ StringMap<uint32_t>::const_iterator end() const { return StringToId.end(); }
- StringMap<uint32_t>::const_iterator end() const { return Strings.end(); }
+ std::vector<uint32_t> sortedIds() const;
private:
- StringMap<uint32_t> Strings;
+ DenseMap<uint32_t, StringRef> IdToString;
+ StringMap<uint32_t> StringToId;
uint32_t StringSize = 1;
};
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
index d8ac3343c15f..c4704168ed34 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
@@ -69,9 +69,22 @@ public:
ArrayRef<ArrayRef<uint8_t>> records() const;
ArrayRef<GloballyHashedType> hashes() const;
- using CreateRecord = llvm::function_ref<ArrayRef<uint8_t>()>;
+ template <typename CreateFunc>
+ TypeIndex insertRecordAs(GloballyHashedType Hash, size_t RecordSize,
+ CreateFunc Create) {
+ auto Result = HashedRecords.try_emplace(Hash, nextTypeIndex());
+
+ if (LLVM_UNLIKELY(Result.second)) {
+ uint8_t *Stable = RecordStorage.Allocate<uint8_t>(RecordSize);
+ MutableArrayRef<uint8_t> Data(Stable, RecordSize);
+ SeenRecords.push_back(Create(Data));
+ SeenHashes.push_back(Hash);
+ }
+
+ // Update the caller's copy of Record to point a stable copy.
+ return Result.first->second;
+ }
- TypeIndex insertRecordAs(GloballyHashedType Hash, CreateRecord Create);
TypeIndex insertRecordBytes(ArrayRef<uint8_t> Data);
TypeIndex insertRecord(ContinuationRecordBuilder &Builder);
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
index 16d78692c839..383f7dd9fb6a 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
@@ -26,7 +26,7 @@
namespace llvm {
namespace codeview {
-/// \brief Provides amortized O(1) random access to a CodeView type stream.
+/// Provides amortized O(1) random access to a CodeView type stream.
/// Normally to access a type from a type stream, you must know its byte
/// offset into the type stream, because type records are variable-lengthed.
/// However, this is not the way we prefer to access them. For example, given
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h
index 741337533701..1f732d29a538 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h
@@ -58,7 +58,10 @@ struct LocallyHashedType {
}
};
-enum class GlobalTypeHashAlg : uint16_t { SHA1 = 0 };
+enum class GlobalTypeHashAlg : uint16_t {
+ SHA1 = 0, // standard 20-byte SHA1 hash
+ SHA1_8 // last 8-bytes of standard SHA1 hash
+};
/// A globally hashed type represents a hash value that is sufficient to
/// uniquely identify a record across multiple type streams or type sequences.
@@ -77,10 +80,10 @@ struct GloballyHashedType {
GloballyHashedType(StringRef H)
: GloballyHashedType(ArrayRef<uint8_t>(H.bytes_begin(), H.bytes_end())) {}
GloballyHashedType(ArrayRef<uint8_t> H) {
- assert(H.size() == 20);
- ::memcpy(Hash.data(), H.data(), 20);
+ assert(H.size() == 8);
+ ::memcpy(Hash.data(), H.data(), 8);
}
- std::array<uint8_t, 20> Hash;
+ std::array<uint8_t, 8> Hash;
/// Given a sequence of bytes representing a record, compute a global hash for
/// this record. Due to the nature of global hashes incorporating the hashes
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
index 508bdd395f74..61ebdf878ce7 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
@@ -330,6 +330,10 @@ public:
return !!(Attrs & uint32_t(PointerOptions::Unaligned));
}
+ bool isRestrict() const {
+ return !!(Attrs & uint32_t(PointerOptions::Restrict));
+ }
+
TypeIndex ReferentType;
uint32_t Attrs;
Optional<MemberPointerInfo> MemberInfo;
@@ -892,6 +896,33 @@ public:
TypeIndex ContinuationIndex;
};
+// LF_PRECOMP
+class PrecompRecord : public TypeRecord {
+public:
+ PrecompRecord() = default;
+ explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
+ uint32_t getStartTypeIndex() const { return StartTypeIndex; }
+ uint32_t getTypesCount() const { return TypesCount; }
+ uint32_t getSignature() const { return Signature; }
+ StringRef getPrecompFilePath() const { return PrecompFilePath; }
+
+ uint32_t StartTypeIndex;
+ uint32_t TypesCount;
+ uint32_t Signature;
+ StringRef PrecompFilePath;
+};
+
+// LF_ENDPRECOMP
+class EndPrecompRecord : public TypeRecord {
+public:
+ EndPrecompRecord() = default;
+ explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
+ uint32_t getSignature() const { return Signature; }
+
+ uint32_t Signature;
+};
} // end namespace codeview
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index 59e216abcb11..583740d2eb4b 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -23,7 +23,7 @@ struct GloballyHashedType;
class GlobalTypeTableBuilder;
class MergingTypeTableBuilder;
-/// \brief Merge one set of type records into another. This method assumes
+/// Merge one set of type records into another. This method assumes
/// that all records are type records, and there are no Id records present.
///
/// \param Dest The table to store the re-written type records into.
@@ -40,7 +40,7 @@ Error mergeTypeRecords(MergingTypeTableBuilder &Dest,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &Types);
-/// \brief Merge one set of id records into another. This method assumes
+/// Merge one set of id records into another. This method assumes
/// that all records are id records, and there are no Type records present.
/// However, since Id records can refer back to Type records, this method
/// assumes that the referenced type records have also been merged into
@@ -65,7 +65,7 @@ Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &Ids);
-/// \brief Merge a unified set of type and id records, splitting them into
+/// Merge a unified set of type and id records, splitting them into
/// separate output streams.
///
/// \param DestIds The table to store the re-written id records into.
diff --git a/contrib/llvm/include/llvm/DebugInfo/DIContext.h b/contrib/llvm/include/llvm/DebugInfo/DIContext.h
index abace9378607..f89eb34fdd77 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DIContext.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DIContext.h
@@ -31,6 +31,7 @@ namespace llvm {
struct DILineInfo {
std::string FileName;
std::string FunctionName;
+ Optional<StringRef> Source;
uint32_t Line = 0;
uint32_t Column = 0;
uint32_t StartLine = 0;
@@ -159,6 +160,7 @@ struct DIDumpOptions {
bool ShowForm = false;
bool SummarizeTypes = false;
bool Verbose = false;
+ bool DisplayRawContents = false;
/// Return default option set for printing a single DIE without children.
static DIDumpOptions getForSingleDIE() {
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 0bade10f6201..1d448728338f 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
#define LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
@@ -20,18 +21,76 @@
namespace llvm {
class raw_ostream;
+class ScopedPrinter;
+
+/// The accelerator tables are designed to allow efficient random access
+/// (using a symbol name as a key) into debug info by providing an index of the
+/// debug info DIEs. This class implements the common functionality of Apple and
+/// DWARF 5 accelerator tables.
+/// TODO: Generalize the rest of the AppleAcceleratorTable interface and move it
+/// to this class.
+class DWARFAcceleratorTable {
+protected:
+ DWARFDataExtractor AccelSection;
+ DataExtractor StringSection;
+
+public:
+ /// An abstract class representing a single entry in the accelerator tables.
+ class Entry {
+ protected:
+ SmallVector<DWARFFormValue, 3> Values;
+
+ Entry() = default;
+
+ // Make these protected so only (final) subclasses can be copied around.
+ Entry(const Entry &) = default;
+ Entry(Entry &&) = default;
+ Entry &operator=(const Entry &) = default;
+ Entry &operator=(Entry &&) = default;
+ ~Entry() = default;
+
+
+ public:
+ /// Returns the Offset of the Compilation Unit associated with this
+ /// Accelerator Entry or None if the Compilation Unit offset is not recorded
+ /// in this Accelerator Entry.
+ virtual Optional<uint64_t> getCUOffset() const = 0;
+
+ /// Returns the Tag of the Debug Info Entry associated with this
+ /// Accelerator Entry or None if the Tag is not recorded in this
+ /// Accelerator Entry.
+ virtual Optional<dwarf::Tag> getTag() const = 0;
+
+ /// Returns the raw values of fields in the Accelerator Entry. In general,
+ /// these can only be interpreted with the help of the metadata in the
+ /// owning Accelerator Table.
+ ArrayRef<DWARFFormValue> getValues() const { return Values; }
+ };
+
+ DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
+ DataExtractor StringSection)
+ : AccelSection(AccelSection), StringSection(StringSection) {}
+ virtual ~DWARFAcceleratorTable();
+
+ virtual llvm::Error extract() = 0;
+ virtual void dump(raw_ostream &OS) const = 0;
+
+ DWARFAcceleratorTable(const DWARFAcceleratorTable &) = delete;
+ void operator=(const DWARFAcceleratorTable &) = delete;
+};
/// This implements the Apple accelerator table format, a precursor of the
/// DWARF 5 accelerator table format.
-/// TODO: Factor out a common base class for both formats.
-class DWARFAcceleratorTable {
+class AppleAcceleratorTable : public DWARFAcceleratorTable {
struct Header {
uint32_t Magic;
uint16_t Version;
uint16_t HashFunction;
- uint32_t NumBuckets;
- uint32_t NumHashes;
+ uint32_t BucketCount;
+ uint32_t HashCount;
uint32_t HeaderDataLength;
+
+ void dump(ScopedPrinter &W) const;
};
struct HeaderData {
@@ -40,22 +99,51 @@ class DWARFAcceleratorTable {
uint32_t DIEOffsetBase;
SmallVector<std::pair<AtomType, Form>, 3> Atoms;
+
+ Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const;
};
struct Header Hdr;
struct HeaderData HdrData;
- DWARFDataExtractor AccelSection;
- DataExtractor StringSection;
bool IsValid = false;
+ /// Returns true if we should continue scanning for entries or false if we've
+ /// reached the last (sentinel) entry of encountered a parsing error.
+ bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms,
+ uint32_t *DataOffset) const;
+
public:
- /// An iterator for the entries associated with one key. Each entry can have
- /// multiple DWARFFormValues.
- class ValueIterator : public std::iterator<std::input_iterator_tag,
- ArrayRef<DWARFFormValue>> {
- const DWARFAcceleratorTable *AccelTable = nullptr;
- SmallVector<DWARFFormValue, 3> AtomForms; ///< The decoded data entry.
+ /// Apple-specific implementation of an Accelerator Entry.
+ class Entry final : public DWARFAcceleratorTable::Entry {
+ const HeaderData *HdrData = nullptr;
+
+ Entry(const HeaderData &Data);
+ Entry() = default;
+
+ void extract(const AppleAcceleratorTable &AccelTable, uint32_t *Offset);
+
+ public:
+ Optional<uint64_t> getCUOffset() const override;
+
+ /// Returns the Section Offset of the Debug Info Entry associated with this
+ /// Accelerator Entry or None if the DIE offset is not recorded in this
+ /// Accelerator Entry. The returned offset is relative to the start of the
+ /// Section containing the DIE.
+ Optional<uint64_t> getDIESectionOffset() const;
+ Optional<dwarf::Tag> getTag() const override;
+
+ /// Returns the value of the Atom in this Accelerator Entry, if the Entry
+ /// contains such Atom.
+ Optional<DWARFFormValue> lookup(HeaderData::AtomType Atom) const;
+
+ friend class AppleAcceleratorTable;
+ friend class ValueIterator;
+ };
+
+ class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
+ const AppleAcceleratorTable *AccelTable = nullptr;
+ Entry Current; ///< The current entry.
unsigned DataOffset = 0; ///< Offset into the section.
unsigned Data = 0; ///< Current data entry.
unsigned NumData = 0; ///< Number of data entries.
@@ -64,13 +152,11 @@ public:
void Next();
public:
/// Construct a new iterator for the entries at \p DataOffset.
- ValueIterator(const DWARFAcceleratorTable &AccelTable, unsigned DataOffset);
+ ValueIterator(const AppleAcceleratorTable &AccelTable, unsigned DataOffset);
/// End marker.
ValueIterator() = default;
- const ArrayRef<DWARFFormValue> operator*() const {
- return AtomForms;
- }
+ const Entry &operator*() const { return Current; }
ValueIterator &operator++() { Next(); return *this; }
ValueIterator operator++(int) {
ValueIterator I = *this;
@@ -85,16 +171,18 @@ public:
}
};
-
- DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
+ AppleAcceleratorTable(const DWARFDataExtractor &AccelSection,
DataExtractor StringSection)
- : AccelSection(AccelSection), StringSection(StringSection) {}
+ : DWARFAcceleratorTable(AccelSection, StringSection) {}
- llvm::Error extract();
+ llvm::Error extract() override;
uint32_t getNumBuckets();
uint32_t getNumHashes();
uint32_t getSizeHdr();
uint32_t getHeaderDataLength();
+
+ /// Return the Atom description, which can be used to interpret the raw values
+ /// of the Accelerator Entries in this table.
ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc();
bool validateForms();
@@ -107,10 +195,404 @@ public:
/// related to the input hash data offset.
/// DieTag is the tag of the DIE
std::pair<uint32_t, dwarf::Tag> readAtoms(uint32_t &HashDataOffset);
- void dump(raw_ostream &OS) const;
+ void dump(raw_ostream &OS) const override;
+
+ /// Look up all entries in the accelerator table matching \c Key.
+ iterator_range<ValueIterator> equal_range(StringRef Key) const;
+};
+
+/// .debug_names section consists of one or more units. Each unit starts with a
+/// header, which is followed by a list of compilation units, local and foreign
+/// type units.
+///
+/// These may be followed by an (optional) hash lookup table, which consists of
+/// an array of buckets and hashes similar to the apple tables above. The only
+/// difference is that the hashes array is 1-based, and consequently an empty
+/// bucket is denoted by 0 and not UINT32_MAX.
+///
+/// Next is the name table, which consists of an array of names and array of
+/// entry offsets. This is different from the apple tables, which store names
+/// next to the actual entries.
+///
+/// The structure of the entries is described by an abbreviations table, which
+/// comes after the name table. Unlike the apple tables, which have a uniform
+/// entry structure described in the header, each .debug_names entry may have
+/// different index attributes (DW_IDX_???) attached to it.
+///
+/// The last segment consists of a list of entries, which is a 0-terminated list
+/// referenced by the name table and interpreted with the help of the
+/// abbreviation table.
+class DWARFDebugNames : public DWARFAcceleratorTable {
+ /// The fixed-size part of a Dwarf 5 Name Index header
+ struct HeaderPOD {
+ uint32_t UnitLength;
+ uint16_t Version;
+ uint16_t Padding;
+ uint32_t CompUnitCount;
+ uint32_t LocalTypeUnitCount;
+ uint32_t ForeignTypeUnitCount;
+ uint32_t BucketCount;
+ uint32_t NameCount;
+ uint32_t AbbrevTableSize;
+ uint32_t AugmentationStringSize;
+ };
+
+public:
+ class NameIndex;
+ class NameIterator;
+ class ValueIterator;
+
+ /// Dwarf 5 Name Index header.
+ struct Header : public HeaderPOD {
+ SmallString<8> AugmentationString;
+
+ Error extract(const DWARFDataExtractor &AS, uint32_t *Offset);
+ void dump(ScopedPrinter &W) const;
+ };
+
+ /// Index attribute and its encoding.
+ struct AttributeEncoding {
+ dwarf::Index Index;
+ dwarf::Form Form;
+
+ constexpr AttributeEncoding(dwarf::Index Index, dwarf::Form Form)
+ : Index(Index), Form(Form) {}
+
+ friend bool operator==(const AttributeEncoding &LHS,
+ const AttributeEncoding &RHS) {
+ return LHS.Index == RHS.Index && LHS.Form == RHS.Form;
+ }
+ };
+
+ /// Abbreviation describing the encoding of Name Index entries.
+ struct Abbrev {
+ uint32_t Code; ///< Abbreviation code
+ dwarf::Tag Tag; ///< Dwarf Tag of the described entity.
+ std::vector<AttributeEncoding> Attributes; ///< List of index attributes.
+
+ Abbrev(uint32_t Code, dwarf::Tag Tag,
+ std::vector<AttributeEncoding> Attributes)
+ : Code(Code), Tag(Tag), Attributes(std::move(Attributes)) {}
+
+ void dump(ScopedPrinter &W) const;
+ };
+
+ /// DWARF v5-specific implementation of an Accelerator Entry.
+ class Entry final : public DWARFAcceleratorTable::Entry {
+ const NameIndex *NameIdx;
+ const Abbrev *Abbr;
+
+ Entry(const NameIndex &NameIdx, const Abbrev &Abbr);
+
+ public:
+ Optional<uint64_t> getCUOffset() const override;
+ Optional<dwarf::Tag> getTag() const override { return tag(); }
+
+ /// Returns the Index into the Compilation Unit list of the owning Name
+ /// Index or None if this Accelerator Entry does not have an associated
+ /// Compilation Unit. It is up to the user to verify that the returned Index
+ /// is valid in the owning NameIndex (or use getCUOffset(), which will
+ /// handle that check itself). Note that entries in NameIndexes which index
+ /// just a single Compilation Unit are implicitly associated with that unit,
+ /// so this function will return 0 even without an explicit
+ /// DW_IDX_compile_unit attribute.
+ Optional<uint64_t> getCUIndex() const;
+
+ /// .debug_names-specific getter, which always succeeds (DWARF v5 index
+ /// entries always have a tag).
+ dwarf::Tag tag() const { return Abbr->Tag; }
+
+ /// Returns the Offset of the DIE within the containing CU or TU.
+ Optional<uint64_t> getDIEUnitOffset() const;
+
+ /// Return the Abbreviation that can be used to interpret the raw values of
+ /// this Accelerator Entry.
+ const Abbrev &getAbbrev() const { return *Abbr; }
+
+ /// Returns the value of the Index Attribute in this Accelerator Entry, if
+ /// the Entry contains such Attribute.
+ Optional<DWARFFormValue> lookup(dwarf::Index Index) const;
+
+ void dump(ScopedPrinter &W) const;
+
+ friend class NameIndex;
+ friend class ValueIterator;
+ };
+
+ /// Error returned by NameIndex::getEntry to report it has reached the end of
+ /// the entry list.
+ class SentinelError : public ErrorInfo<SentinelError> {
+ public:
+ static char ID;
+
+ void log(raw_ostream &OS) const override { OS << "Sentinel"; }
+ std::error_code convertToErrorCode() const override;
+ };
+
+private:
+ /// DenseMapInfo for struct Abbrev.
+ struct AbbrevMapInfo {
+ static Abbrev getEmptyKey();
+ static Abbrev getTombstoneKey();
+ static unsigned getHashValue(uint32_t Code) {
+ return DenseMapInfo<uint32_t>::getHashValue(Code);
+ }
+ static unsigned getHashValue(const Abbrev &Abbr) {
+ return getHashValue(Abbr.Code);
+ }
+ static bool isEqual(uint32_t LHS, const Abbrev &RHS) {
+ return LHS == RHS.Code;
+ }
+ static bool isEqual(const Abbrev &LHS, const Abbrev &RHS) {
+ return LHS.Code == RHS.Code;
+ }
+ };
+
+public:
+ /// A single entry in the Name Table (Dwarf 5 sect. 6.1.1.4.6) of the Name
+ /// Index.
+ class NameTableEntry {
+ DataExtractor StrData;
+
+ uint32_t Index;
+ uint32_t StringOffset;
+ uint32_t EntryOffset;
+
+ public:
+ NameTableEntry(const DataExtractor &StrData, uint32_t Index,
+ uint32_t StringOffset, uint32_t EntryOffset)
+ : StrData(StrData), Index(Index), StringOffset(StringOffset),
+ EntryOffset(EntryOffset) {}
+
+ /// Return the index of this name in the parent Name Index.
+ uint32_t getIndex() const { return Index; }
+
+ /// Returns the offset of the name of the described entities.
+ uint32_t getStringOffset() const { return StringOffset; }
+
+ /// Return the string referenced by this name table entry or nullptr if the
+ /// string offset is not valid.
+ const char *getString() const {
+ uint32_t Off = StringOffset;
+ return StrData.getCStr(&Off);
+ }
+
+ /// Returns the offset of the first Entry in the list.
+ uint32_t getEntryOffset() const { return EntryOffset; }
+ };
+
+ /// Represents a single accelerator table within the Dwarf 5 .debug_names
+ /// section.
+ class NameIndex {
+ DenseSet<Abbrev, AbbrevMapInfo> Abbrevs;
+ struct Header Hdr;
+ const DWARFDebugNames &Section;
+
+ // Base of the whole unit and of various important tables, as offsets from
+ // the start of the section.
+ uint32_t Base;
+ uint32_t CUsBase;
+ uint32_t BucketsBase;
+ uint32_t HashesBase;
+ uint32_t StringOffsetsBase;
+ uint32_t EntryOffsetsBase;
+ uint32_t EntriesBase;
+
+ void dumpCUs(ScopedPrinter &W) const;
+ void dumpLocalTUs(ScopedPrinter &W) const;
+ void dumpForeignTUs(ScopedPrinter &W) const;
+ void dumpAbbreviations(ScopedPrinter &W) const;
+ bool dumpEntry(ScopedPrinter &W, uint32_t *Offset) const;
+ void dumpName(ScopedPrinter &W, const NameTableEntry &NTE,
+ Optional<uint32_t> Hash) const;
+ void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const;
+
+ Expected<AttributeEncoding> extractAttributeEncoding(uint32_t *Offset);
+
+ Expected<std::vector<AttributeEncoding>>
+ extractAttributeEncodings(uint32_t *Offset);
+
+ Expected<Abbrev> extractAbbrev(uint32_t *Offset);
+
+ public:
+ NameIndex(const DWARFDebugNames &Section, uint32_t Base)
+ : Section(Section), Base(Base) {}
+
+ /// Reads offset of compilation unit CU. CU is 0-based.
+ uint32_t getCUOffset(uint32_t CU) const;
+ uint32_t getCUCount() const { return Hdr.CompUnitCount; }
+
+ /// Reads offset of local type unit TU, TU is 0-based.
+ uint32_t getLocalTUOffset(uint32_t TU) const;
+ uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; }
+
+ /// Reads signature of foreign type unit TU. TU is 0-based.
+ uint64_t getForeignTUSignature(uint32_t TU) const;
+ uint32_t getForeignTUCount() const { return Hdr.ForeignTypeUnitCount; }
+
+ /// Reads an entry in the Bucket Array for the given Bucket. The returned
+ /// value is a (1-based) index into the Names, StringOffsets and
+ /// EntryOffsets arrays. The input Bucket index is 0-based.
+ uint32_t getBucketArrayEntry(uint32_t Bucket) const;
+ uint32_t getBucketCount() const { return Hdr.BucketCount; }
+
+ /// Reads an entry in the Hash Array for the given Index. The input Index
+ /// is 1-based.
+ uint32_t getHashArrayEntry(uint32_t Index) const;
+
+ /// Reads an entry in the Name Table for the given Index. The Name Table
+ /// consists of two arrays -- String Offsets and Entry Offsets. The returned
+ /// offsets are relative to the starts of respective sections. Input Index
+ /// is 1-based.
+ NameTableEntry getNameTableEntry(uint32_t Index) const;
+
+ uint32_t getNameCount() const { return Hdr.NameCount; }
+
+ const DenseSet<Abbrev, AbbrevMapInfo> &getAbbrevs() const {
+ return Abbrevs;
+ }
+
+ Expected<Entry> getEntry(uint32_t *Offset) const;
+
+ /// Look up all entries in this Name Index matching \c Key.
+ iterator_range<ValueIterator> equal_range(StringRef Key) const;
+
+ NameIterator begin() const { return NameIterator(this, 1); }
+ NameIterator end() const { return NameIterator(this, getNameCount() + 1); }
+
+ llvm::Error extract();
+ uint32_t getUnitOffset() const { return Base; }
+ uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; }
+ void dump(ScopedPrinter &W) const;
+
+ friend class DWARFDebugNames;
+ };
+
+ class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
+
+ /// The Name Index we are currently iterating through. The implementation
+ /// relies on the fact that this can also be used as an iterator into the
+ /// "NameIndices" vector in the Accelerator section.
+ const NameIndex *CurrentIndex = nullptr;
+
+ /// Whether this is a local iterator (searches in CurrentIndex only) or not
+ /// (searches all name indices).
+ bool IsLocal;
+
+ Optional<Entry> CurrentEntry;
+ unsigned DataOffset = 0; ///< Offset into the section.
+ std::string Key; ///< The Key we are searching for.
+ Optional<uint32_t> Hash; ///< Hash of Key, if it has been computed.
+
+ bool getEntryAtCurrentOffset();
+ Optional<uint32_t> findEntryOffsetInCurrentIndex();
+ bool findInCurrentIndex();
+ void searchFromStartOfCurrentIndex();
+ void next();
+
+ /// Set the iterator to the "end" state.
+ void setEnd() { *this = ValueIterator(); }
+
+ public:
+ /// Create a "begin" iterator for looping over all entries in the
+ /// accelerator table matching Key. The iterator will run through all Name
+ /// Indexes in the section in sequence.
+ ValueIterator(const DWARFDebugNames &AccelTable, StringRef Key);
+
+ /// Create a "begin" iterator for looping over all entries in a specific
+ /// Name Index. Other indices in the section will not be visited.
+ ValueIterator(const NameIndex &NI, StringRef Key);
+
+ /// End marker.
+ ValueIterator() = default;
+
+ const Entry &operator*() const { return *CurrentEntry; }
+ ValueIterator &operator++() {
+ next();
+ return *this;
+ }
+ ValueIterator operator++(int) {
+ ValueIterator I = *this;
+ next();
+ return I;
+ }
+
+ friend bool operator==(const ValueIterator &A, const ValueIterator &B) {
+ return A.CurrentIndex == B.CurrentIndex && A.DataOffset == B.DataOffset;
+ }
+ friend bool operator!=(const ValueIterator &A, const ValueIterator &B) {
+ return !(A == B);
+ }
+ };
+
+ class NameIterator {
+
+ /// The Name Index we are iterating through.
+ const NameIndex *CurrentIndex;
+
+ /// The current name in the Name Index.
+ uint32_t CurrentName;
+
+ void next() {
+ assert(CurrentName <= CurrentIndex->getNameCount());
+ ++CurrentName;
+ }
+
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = NameTableEntry;
+ using difference_type = uint32_t;
+ using pointer = NameTableEntry *;
+ using reference = NameTableEntry; // We return entries by value.
+
+ /// Creates an iterator whose initial position is name CurrentName in
+ /// CurrentIndex.
+ NameIterator(const NameIndex *CurrentIndex, uint32_t CurrentName)
+ : CurrentIndex(CurrentIndex), CurrentName(CurrentName) {}
+
+ NameTableEntry operator*() const {
+ return CurrentIndex->getNameTableEntry(CurrentName);
+ }
+ NameIterator &operator++() {
+ next();
+ return *this;
+ }
+ NameIterator operator++(int) {
+ NameIterator I = *this;
+ next();
+ return I;
+ }
+
+ friend bool operator==(const NameIterator &A, const NameIterator &B) {
+ return A.CurrentIndex == B.CurrentIndex && A.CurrentName == B.CurrentName;
+ }
+ friend bool operator!=(const NameIterator &A, const NameIterator &B) {
+ return !(A == B);
+ }
+ };
+
+private:
+ SmallVector<NameIndex, 0> NameIndices;
+ DenseMap<uint32_t, const NameIndex *> CUToNameIndex;
+
+public:
+ DWARFDebugNames(const DWARFDataExtractor &AccelSection,
+ DataExtractor StringSection)
+ : DWARFAcceleratorTable(AccelSection, StringSection) {}
+
+ llvm::Error extract() override;
+ void dump(raw_ostream &OS) const override;
/// Look up all entries in the accelerator table matching \c Key.
iterator_range<ValueIterator> equal_range(StringRef Key) const;
+
+ using const_iterator = SmallVector<NameIndex, 0>::const_iterator;
+ const_iterator begin() const { return NameIndices.begin(); }
+ const_iterator end() const { return NameIndices.end(); }
+
+ /// Return the Name Index covering the compile unit at CUOffset, or nullptr if
+ /// there is no Name Index covering that unit.
+ const NameIndex *getCUNameIndex(uint32_t CUOffset);
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
new file mode 100644
index 000000000000..5a7df5c353e8
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
@@ -0,0 +1,68 @@
+//===- DWARFAddressRange.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_DWARF_DWARFADDRESSRANGE_H
+#define LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H
+
+#include "llvm/DebugInfo/DIContext.h"
+#include <cstdint>
+#include <tuple>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+struct DWARFAddressRange {
+ uint64_t LowPC;
+ uint64_t HighPC;
+ uint64_t SectionIndex;
+
+ DWARFAddressRange() = default;
+
+ /// Used for unit testing.
+ DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0)
+ : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {}
+
+ /// Returns true if LowPC is smaller or equal to HighPC. This accounts for
+ /// dead-stripped ranges.
+ bool valid() const { return LowPC <= HighPC; }
+
+ /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC).
+ bool intersects(const DWARFAddressRange &RHS) const {
+ assert(valid() && RHS.valid());
+ // Empty ranges can't intersect.
+ if (LowPC == HighPC || RHS.LowPC == RHS.HighPC)
+ return false;
+ return LowPC < RHS.HighPC && RHS.LowPC < HighPC;
+ }
+
+ /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC).
+ bool contains(const DWARFAddressRange &RHS) const {
+ assert(valid() && RHS.valid());
+ return LowPC <= RHS.LowPC && RHS.HighPC <= HighPC;
+ }
+
+ void dump(raw_ostream &OS, uint32_t AddressSize,
+ DIDumpOptions DumpOpts = {}) const;
+};
+
+static inline bool operator<(const DWARFAddressRange &LHS,
+ const DWARFAddressRange &RHS) {
+ return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC);
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R);
+
+/// DWARFAddressRangesVector - represents a set of absolute address ranges.
+using DWARFAddressRangesVector = std::vector<DWARFAddressRange>;
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
index a18adf87bf8e..c219ca75e640 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
@@ -18,13 +18,13 @@ namespace llvm {
class DWARFCompileUnit : public DWARFUnit {
public:
DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, const DWARFSection &LS, bool LE,
- bool IsDWO, const DWARFUnitSectionBase &UnitSection,
- const DWARFUnitIndex::Entry *Entry)
- : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
- UnitSection, Entry) {}
+ bool IsDWO, const DWARFUnitSectionBase &UnitSection)
+ : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
+ UnitSection) {}
// VTable anchor.
~DWARFCompileUnit() override;
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 2ddbc4b91ba2..fe7430c9f04c 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -34,6 +34,7 @@
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Host.h"
#include <cstdint>
@@ -43,7 +44,6 @@
namespace llvm {
-class DataExtractor;
class MCRegisterInfo;
class MemoryBuffer;
class raw_ostream;
@@ -69,10 +69,11 @@ class DWARFContext : public DIContext {
std::unique_ptr<DWARFDebugFrame> DebugFrame;
std::unique_ptr<DWARFDebugFrame> EHFrame;
std::unique_ptr<DWARFDebugMacro> Macro;
- std::unique_ptr<DWARFAcceleratorTable> AppleNames;
- std::unique_ptr<DWARFAcceleratorTable> AppleTypes;
- std::unique_ptr<DWARFAcceleratorTable> AppleNamespaces;
- std::unique_ptr<DWARFAcceleratorTable> AppleObjC;
+ std::unique_ptr<DWARFDebugNames> Names;
+ std::unique_ptr<AppleAcceleratorTable> AppleNames;
+ std::unique_ptr<AppleAcceleratorTable> AppleTypes;
+ std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
+ std::unique_ptr<AppleAcceleratorTable> AppleObjC;
DWARFUnitSection<DWARFCompileUnit> DWOCUs;
std::deque<DWARFUnitSection<DWARFTypeUnit>> DWOTUs;
@@ -204,6 +205,9 @@ public:
DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
+ /// Return the compile unit that includes an offset (relative to .debug_info).
+ DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
+
/// Get a DIE given an exact offset.
DWARFDie getDIEForOffset(uint32_t Offset);
@@ -243,19 +247,36 @@ public:
const DWARFDebugMacro *getDebugMacro();
/// Get a reference to the parsed accelerator table object.
- const DWARFAcceleratorTable &getAppleNames();
+ const DWARFDebugNames &getDebugNames();
/// Get a reference to the parsed accelerator table object.
- const DWARFAcceleratorTable &getAppleTypes();
+ const AppleAcceleratorTable &getAppleNames();
/// Get a reference to the parsed accelerator table object.
- const DWARFAcceleratorTable &getAppleNamespaces();
+ const AppleAcceleratorTable &getAppleTypes();
/// Get a reference to the parsed accelerator table object.
- const DWARFAcceleratorTable &getAppleObjC();
+ const AppleAcceleratorTable &getAppleNamespaces();
+
+ /// Get a reference to the parsed accelerator table object.
+ const AppleAcceleratorTable &getAppleObjC();
+
+ /// Get a pointer to a parsed line table corresponding to a compile unit.
+ /// Report any parsing issues as warnings on stderr.
+ const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
/// Get a pointer to a parsed line table corresponding to a compile unit.
- const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu);
+ /// Report any recoverable parsing problems using the callback.
+ Expected<const DWARFDebugLine::LineTable *>
+ getLineTableForUnit(DWARFUnit *U,
+ std::function<void(Error)> RecoverableErrorCallback);
+
+ DataExtractor getStringExtractor() const {
+ return DataExtractor(DObj->getStringSection(), false, 0);
+ }
+ DataExtractor getLineStringExtractor() const {
+ return DataExtractor(DObj->getLineStringSection(), false, 0);
+ }
/// Wraps the returned DIEs for a given address.
struct DIEsForAddress {
@@ -303,9 +324,6 @@ public:
Error loadRegisterInfo(const object::ObjectFile &Obj);
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);
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
index a379d9c85b38..10e146b70ec7 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
@@ -44,6 +44,13 @@ public:
uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const {
return getRelocatedValue(getAddressSize(), Off, SecIx);
}
+
+ /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
+ /// There is a DWARF encoding that uses a PC-relative adjustment.
+ /// For these values, \p AbsPosOffset is used to fix them, which should
+ /// reflect the absolute address of this pointer.
+ Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
+ uint64_t AbsPosOffset = 0) const;
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
index dfbbb95076e8..ab46fac39f7c 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
@@ -43,6 +43,7 @@ public:
uint64_t Length;
uint64_t getEndAddress() const { return Address + Length; }
+ void dump(raw_ostream &OS, uint32_t AddressSize) const;
};
private:
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index a711fb295444..ff1c7fb38389 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -10,40 +10,290 @@
#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
-#include "llvm/Support/DataExtractor.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <vector>
namespace llvm {
-class FrameEntry;
class raw_ostream;
-/// \brief A parsed .debug_frame or .eh_frame section
-///
+namespace dwarf {
+
+/// Represent a sequence of Call Frame Information instructions that, when read
+/// in order, construct a table mapping PC to frame state. This can also be
+/// referred to as "CFI rules" in DWARF literature to avoid confusion with
+/// computer programs in the broader sense, and in this context each instruction
+/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5
+/// manual, "6.4.1 Structure of Call Frame Information".
+class CFIProgram {
+public:
+ typedef SmallVector<uint64_t, 2> Operands;
+
+ /// An instruction consists of a DWARF CFI opcode and an optional sequence of
+ /// operands. If it refers to an expression, then this expression has its own
+ /// sequence of operations and operands handled separately by DWARFExpression.
+ struct Instruction {
+ Instruction(uint8_t Opcode) : Opcode(Opcode) {}
+
+ uint8_t Opcode;
+ Operands Ops;
+ // Associated DWARF expression in case this instruction refers to one
+ Optional<DWARFExpression> Expression;
+ };
+
+ using InstrList = std::vector<Instruction>;
+ using iterator = InstrList::iterator;
+ using const_iterator = InstrList::const_iterator;
+
+ iterator begin() { return Instructions.begin(); }
+ const_iterator begin() const { return Instructions.begin(); }
+ iterator end() { return Instructions.end(); }
+ const_iterator end() const { return Instructions.end(); }
+
+ unsigned size() const { return (unsigned)Instructions.size(); }
+ bool empty() const { return Instructions.empty(); }
+
+ CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
+ : CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor) {}
+
+ /// Parse and store a sequence of CFI instructions from Data,
+ /// starting at *Offset and ending at EndOffset. *Offset is updated
+ /// to EndOffset upon successful parsing, or indicates the offset
+ /// where a problem occurred in case an error is returned.
+ Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
+
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+ unsigned IndentLevel = 1) const;
+
+private:
+ std::vector<Instruction> Instructions;
+ const uint64_t CodeAlignmentFactor;
+ const int64_t DataAlignmentFactor;
+
+ /// Convenience method to add a new instruction with the given opcode.
+ void addInstruction(uint8_t Opcode) {
+ Instructions.push_back(Instruction(Opcode));
+ }
+
+ /// Add a new single-operand instruction.
+ void addInstruction(uint8_t Opcode, uint64_t Operand1) {
+ Instructions.push_back(Instruction(Opcode));
+ Instructions.back().Ops.push_back(Operand1);
+ }
+
+ /// Add a new instruction that has two operands.
+ void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
+ Instructions.push_back(Instruction(Opcode));
+ Instructions.back().Ops.push_back(Operand1);
+ Instructions.back().Ops.push_back(Operand2);
+ }
+
+ /// Types of operands to CFI instructions
+ /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
+ /// thus this type doesn't need to be explictly written to the file (this is
+ /// not a DWARF encoding). The relationship of instrs to operand types can
+ /// be obtained from getOperandTypes() and is only used to simplify
+ /// instruction printing.
+ enum OperandType {
+ OT_Unset,
+ OT_None,
+ OT_Address,
+ OT_Offset,
+ OT_FactoredCodeOffset,
+ OT_SignedFactDataOffset,
+ OT_UnsignedFactDataOffset,
+ OT_Register,
+ OT_Expression
+ };
+
+ /// Retrieve the array describing the types of operands according to the enum
+ /// above. This is indexed by opcode.
+ static ArrayRef<OperandType[2]> getOperandTypes();
+
+ /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
+ void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+ const Instruction &Instr, unsigned OperandIdx,
+ uint64_t Operand) const;
+};
+
+/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
+/// FDE.
+class FrameEntry {
+public:
+ enum FrameKind { FK_CIE, FK_FDE };
+
+ FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign,
+ int64_t DataAlign)
+ : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {}
+
+ virtual ~FrameEntry() {}
+
+ FrameKind getKind() const { return Kind; }
+ uint64_t getOffset() const { return Offset; }
+ uint64_t getLength() const { return Length; }
+ const CFIProgram &cfis() const { return CFIs; }
+ CFIProgram &cfis() { return CFIs; }
+
+ /// Dump the instructions in this CFI fragment
+ virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ bool IsEH) const = 0;
+
+protected:
+ const FrameKind Kind;
+
+ /// Offset of this entry in the section.
+ const uint64_t Offset;
+
+ /// Entry length as specified in DWARF.
+ const uint64_t Length;
+
+ CFIProgram CFIs;
+};
+
+/// DWARF Common Information Entry (CIE)
+class CIE : public FrameEntry {
+public:
+ // CIEs (and FDEs) are simply container classes, so the only sensible way to
+ // create them is by providing the full parsed contents in the constructor.
+ CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
+ SmallString<8> Augmentation, uint8_t AddressSize,
+ uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
+ int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
+ SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
+ uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
+ Optional<uint32_t> PersonalityEnc)
+ : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
+ DataAlignmentFactor),
+ Version(Version), Augmentation(std::move(Augmentation)),
+ AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
+ CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor),
+ ReturnAddressRegister(ReturnAddressRegister),
+ AugmentationData(std::move(AugmentationData)),
+ FDEPointerEncoding(FDEPointerEncoding),
+ LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality),
+ PersonalityEnc(PersonalityEnc) {}
+
+ static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
+
+ StringRef getAugmentationString() const { return Augmentation; }
+ uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
+ int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
+ uint8_t getVersion() const { return Version; }
+ uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
+ Optional<uint64_t> getPersonalityAddress() const { return Personality; }
+ Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; }
+
+ uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
+
+ uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
+
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ bool IsEH) const override;
+
+private:
+ /// The following fields are defined in section 6.4.1 of the DWARF standard v4
+ const uint8_t Version;
+ const SmallString<8> Augmentation;
+ const uint8_t AddressSize;
+ const uint8_t SegmentDescriptorSize;
+ const uint64_t CodeAlignmentFactor;
+ const int64_t DataAlignmentFactor;
+ const uint64_t ReturnAddressRegister;
+
+ // The following are used when the CIE represents an EH frame entry.
+ const SmallString<8> AugmentationData;
+ const uint32_t FDEPointerEncoding;
+ const uint32_t LSDAPointerEncoding;
+ const Optional<uint64_t> Personality;
+ const Optional<uint32_t> PersonalityEnc;
+};
+
+/// DWARF Frame Description Entry (FDE)
+class FDE : public FrameEntry {
+public:
+ // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
+ // an offset to the CIE (provided by parsing the FDE header). The CIE itself
+ // is obtained lazily once it's actually required.
+ FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
+ uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
+ Optional<uint64_t> LSDAAddress)
+ : FrameEntry(FK_FDE, Offset, Length,
+ Cie ? Cie->getCodeAlignmentFactor() : 0,
+ Cie ? Cie->getDataAlignmentFactor() : 0),
+ LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation),
+ AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
+
+ ~FDE() override = default;
+
+ const CIE *getLinkedCIE() const { return LinkedCIE; }
+ uint64_t getInitialLocation() const { return InitialLocation; }
+ uint64_t getAddressRange() const { return AddressRange; }
+ Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
+
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ bool IsEH) const override;
+
+ static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
+
+private:
+ /// The following fields are defined in section 6.4.1 of the DWARF standard v3
+ const uint64_t LinkedCIEOffset;
+ const uint64_t InitialLocation;
+ const uint64_t AddressRange;
+ const CIE *LinkedCIE;
+ const Optional<uint64_t> LSDAAddress;
+};
+
+} // end namespace dwarf
+
+/// A parsed .debug_frame or .eh_frame section
class DWARFDebugFrame {
// True if this is parsing an eh_frame section.
- bool IsEH;
+ const bool IsEH;
+ // Not zero for sane pointer values coming out of eh_frame
+ const uint64_t EHFrameAddress;
+
+ std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
+ using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
+
+ /// Return the entry at the given offset or nullptr.
+ dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
public:
- DWARFDebugFrame(bool IsEH);
+ // If IsEH is true, assume it is a .eh_frame section. Otherwise,
+ // it is a .debug_frame section. EHFrameAddress should be different
+ // than zero for correct parsing of .eh_frame addresses when they
+ // use a PC-relative encoding.
+ DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0);
~DWARFDebugFrame();
/// Dump the section data into the given stream.
- void dump(raw_ostream &OS, Optional<uint64_t> Offset) const;
+ void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ Optional<uint64_t> Offset) const;
- /// \brief Parse the section from raw data.
- /// data is assumed to be pointing to the beginning of the section.
- void parse(DataExtractor Data);
+ /// Parse the section from raw data. \p Data is assumed to contain the whole
+ /// frame section contents to be parsed.
+ void parse(DWARFDataExtractor Data);
/// Return whether the section has any entries.
bool empty() const { return Entries.empty(); }
- /// Return the entry at the given offset or nullptr.
- FrameEntry *getEntryAtOffset(uint64_t Offset) const;
+ /// DWARF Frame entries accessors
+ iterator begin() const { return Entries.begin(); }
+ iterator end() const { return Entries.end(); }
+ iterator_range<iterator> entries() const {
+ return iterator_range<iterator>(Entries.begin(), Entries.end());
+ }
-private:
- std::vector<std::unique_ptr<FrameEntry>> Entries;
+ uint64_t getEHFrameAddress() const { return EHFrameAddress; }
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
index de8ad4e5ef3c..5b2af34bbcf5 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -10,11 +10,14 @@
#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/Support/MD5.h"
#include <cstdint>
#include <map>
@@ -31,11 +34,30 @@ public:
struct FileNameEntry {
FileNameEntry() = default;
- StringRef Name;
+ DWARFFormValue Name;
uint64_t DirIdx = 0;
uint64_t ModTime = 0;
uint64_t Length = 0;
MD5::MD5Result Checksum;
+ DWARFFormValue Source;
+ };
+
+ /// Tracks which optional content types are present in a DWARF file name
+ /// entry format.
+ struct ContentTypeTracker {
+ ContentTypeTracker() = default;
+
+ /// Whether filename entries provide a modification timestamp.
+ bool HasModTime = false;
+ /// Whether filename entries provide a file size.
+ bool HasLength = false;
+ /// For v5, whether filename entries provide an MD5 checksum.
+ bool HasMD5 = false;
+ /// For v5, whether filename entries provide source text.
+ bool HasSource = false;
+
+ /// Update tracked content types with \p ContentType.
+ void trackContentType(dwarf::LineNumberEntryFormat ContentType);
};
struct Prologue {
@@ -47,7 +69,7 @@ public:
/// Version, address size (starting in v5), and DWARF32/64 format; these
/// parameters affect interpretation of forms (used in the directory and
/// file tables starting with v5).
- DWARFFormParams FormParams;
+ dwarf::FormParams FormParams;
/// The number of bytes following the prologue_length field to the beginning
/// of the first byte of the statement program itself.
uint64_t PrologueLength;
@@ -68,13 +90,13 @@ public:
uint8_t LineRange;
/// The number assigned to the first special opcode.
uint8_t OpcodeBase;
- /// For v5, whether filename entries provide an MD5 checksum.
- bool HasMD5;
+ /// This tracks which optional file format content types are present.
+ ContentTypeTracker ContentTypes;
std::vector<uint8_t> StandardOpcodeLengths;
- std::vector<StringRef> IncludeDirectories;
+ std::vector<DWARFFormValue> IncludeDirectories;
std::vector<FileNameEntry> FileNames;
- const DWARFFormParams getFormParams() const { return FormParams; }
+ const dwarf::FormParams getFormParams() const { return FormParams; }
uint16_t getVersion() const { return FormParams.Version; }
uint8_t getAddressSize() const { return FormParams.AddrSize; }
bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; }
@@ -83,6 +105,8 @@ public:
uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; }
+ bool totalLengthIsValid() const;
+
/// Length of the prologue in bytes.
uint32_t getLength() const {
return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) +
@@ -99,9 +123,9 @@ public:
}
void clear();
- void dump(raw_ostream &OS) const;
- bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
- const DWARFUnit *U = nullptr);
+ void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
+ Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
+ const DWARFContext &Ctx, const DWARFUnit *U = nullptr);
};
/// Standard .debug_line state machine structure.
@@ -219,12 +243,14 @@ public:
DILineInfoSpecifier::FileLineInfoKind Kind,
DILineInfo &Result) const;
- void dump(raw_ostream &OS) const;
+ void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
void clear();
/// Parse prologue and all rows.
- bool parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
- const DWARFUnit *U, raw_ostream *OS = nullptr);
+ Error parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
+ const DWARFContext &Ctx, const DWARFUnit *U,
+ std::function<void(Error)> RecoverableErrorCallback = warn,
+ raw_ostream *OS = nullptr);
using RowVector = std::vector<Row>;
using RowIter = RowVector::const_iterator;
@@ -238,11 +264,75 @@ public:
private:
uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq,
uint64_t Address) const;
+ Optional<StringRef>
+ getSourceByIndex(uint64_t FileIndex,
+ DILineInfoSpecifier::FileLineInfoKind Kind) const;
};
const LineTable *getLineTable(uint32_t Offset) const;
- const LineTable *getOrParseLineTable(DWARFDataExtractor &DebugLineData,
- uint32_t Offset, const DWARFUnit *U);
+ Expected<const LineTable *> getOrParseLineTable(
+ DWARFDataExtractor &DebugLineData, uint32_t Offset,
+ const DWARFContext &Ctx, const DWARFUnit *U,
+ std::function<void(Error)> RecoverableErrorCallback = warn);
+
+ /// Helper to allow for parsing of an entire .debug_line section in sequence.
+ class SectionParser {
+ public:
+ using cu_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range;
+ using tu_range =
+ iterator_range<std::deque<DWARFUnitSection<DWARFTypeUnit>>::iterator>;
+ using LineToUnitMap = std::map<uint64_t, DWARFUnit *>;
+
+ SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs,
+ tu_range TUs);
+
+ /// Get the next line table from the section. Report any issues via the
+ /// callbacks.
+ ///
+ /// \param RecoverableErrorCallback - any issues that don't prevent further
+ /// parsing of the table will be reported through this callback.
+ /// \param UnrecoverableErrorCallback - any issues that prevent further
+ /// parsing of the table will be reported through this callback.
+ /// \param OS - if not null, the parser will print information about the
+ /// table as it parses it.
+ LineTable
+ parseNext(function_ref<void(Error)> RecoverableErrorCallback = warn,
+ function_ref<void(Error)> UnrecoverableErrorCallback = warn,
+ raw_ostream *OS = nullptr);
+
+ /// Skip the current line table and go to the following line table (if
+ /// present) immediately.
+ ///
+ /// \param ErrorCallback - report any prologue parsing issues via this
+ /// callback.
+ void skip(function_ref<void(Error)> ErrorCallback = warn);
+
+ /// Indicates if the parser has parsed as much as possible.
+ ///
+ /// \note Certain problems with the line table structure might mean that
+ /// parsing stops before the end of the section is reached.
+ bool done() const { return Done; }
+
+ /// Get the offset the parser has reached.
+ uint32_t getOffset() const { return Offset; }
+
+ private:
+ DWARFUnit *prepareToParse(uint32_t Offset);
+ void moveToNextTable(uint32_t OldOffset, const Prologue &P);
+
+ LineToUnitMap LineToUnit;
+
+ DWARFDataExtractor &DebugLineData;
+ const DWARFContext &Context;
+ uint32_t Offset = 0;
+ bool Done = false;
+ };
+
+ /// Helper function for DWARFDebugLine parse functions, to report issues
+ /// identified during parsing.
+ ///
+ /// \param Err The Error to report.
+ static void warn(Error Err);
private:
struct ParsingState {
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
index a6d319a90457..9a73745fb6b4 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -42,7 +42,8 @@ public:
SmallVector<Entry, 2> Entries;
/// Dump this list on OS.
void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize,
- const MCRegisterInfo *MRI, unsigned Indent) const;
+ const MCRegisterInfo *MRI, uint64_t BaseAddress,
+ unsigned Indent) const;
};
private:
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
index 761871dc6255..cae4804e61d3 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
@@ -32,7 +32,7 @@ public:
/// The name of the object as given by the DW_AT_name attribute of the
/// referenced DIE.
- const char *Name;
+ StringRef Name;
};
/// Each table consists of sets of variable length entries. Each set describes
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index f9ec96366a53..ce7436d9faa3 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -10,8 +10,8 @@
#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
-#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include <cassert>
#include <cstdint>
#include <vector>
@@ -21,47 +21,6 @@ namespace llvm {
struct BaseAddress;
class raw_ostream;
-struct DWARFAddressRange {
- uint64_t LowPC;
- uint64_t HighPC;
- uint64_t SectionIndex;
-
- DWARFAddressRange() = default;
-
- /// Used for unit testing.
- DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0)
- : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {}
-
- /// Returns true if LowPC is smaller or equal to HighPC. This accounts for
- /// dead-stripped ranges.
- bool valid() const { return LowPC <= HighPC; }
-
- /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC).
- bool intersects(const DWARFAddressRange &RHS) const {
- // Empty ranges can't intersect.
- if (LowPC == HighPC || RHS.LowPC == RHS.HighPC)
- return false;
- return (LowPC < RHS.HighPC) && (HighPC > RHS.LowPC);
- }
-
- /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC).
- bool contains(const DWARFAddressRange &RHS) const {
- if (LowPC <= RHS.LowPC && RHS.LowPC <= HighPC)
- return LowPC <= RHS.HighPC && RHS.HighPC <= HighPC;
- return false;
- }
-};
-
-static inline bool operator<(const DWARFAddressRange &LHS,
- const DWARFAddressRange &RHS) {
- return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC);
-}
-
-raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R);
-
-/// DWARFAddressRangesVector - represents a set of absolute address ranges.
-using DWARFAddressRangesVector = std::vector<DWARFAddressRange>;
-
class DWARFDebugRangeList {
public:
struct RangeListEntry {
@@ -112,7 +71,7 @@ public:
void clear();
void dump(raw_ostream &OS) const;
- bool extract(const DWARFDataExtractor &data, uint32_t *offset_ptr);
+ Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr);
const std::vector<RangeListEntry> &getEntries() { return Entries; }
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
new file mode 100644
index 000000000000..e2e8ab5ed219
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
@@ -0,0 +1,60 @@
+//===- DWARFDebugRnglists.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_DWARFDEBUGRNGLISTS_H
+#define LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFListTable.h"
+#include <cstdint>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+class Error;
+class raw_ostream;
+
+/// A class representing a single range list entry.
+struct RangeListEntry : public DWARFListEntryBase {
+ /// The values making up the range list entry. Most represent a range with
+ /// a start and end address or a start address and a length. Others are
+ /// single value base addresses or end-of-list with no values. The unneeded
+ /// values are semantically undefined, but initialized to 0.
+ uint64_t Value0;
+ uint64_t Value1;
+
+ Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr);
+ void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
+ uint64_t &CurrentBase, DIDumpOptions DumpOpts) const;
+ bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; }
+};
+
+/// A class representing a single rangelist.
+class DWARFDebugRnglist : public DWARFListType<RangeListEntry> {
+public:
+ /// Build a DWARFAddressRangesVector from a rangelist.
+ DWARFAddressRangesVector
+ getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const;
+};
+
+class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> {
+public:
+ DWARFDebugRnglistTable()
+ : DWARFListTableBase(/* SectionName = */ ".debug_rnglists",
+ /* HeaderString = */ "ranges:",
+ /* ListTypeString = */ "range") {}
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
index 75fc5995c5b2..6e6b57cbcbd4 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -16,9 +16,9 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include <cassert>
#include <cstdint>
#include <iterator>
@@ -104,12 +104,24 @@ public:
/// invalid DWARFDie instance if it doesn't.
DWARFDie getSibling() const;
+ /// Get the previous sibling of this DIE object.
+ ///
+ /// \returns a valid DWARFDie instance if this object has a sibling or an
+ /// invalid DWARFDie instance if it doesn't.
+ DWARFDie getPreviousSibling() const;
+
/// Get the first child of this DIE object.
///
/// \returns a valid DWARFDie instance if this object has children or an
/// invalid DWARFDie instance if it doesn't.
DWARFDie getFirstChild() const;
+ /// Get the last child of this DIE object.
+ ///
+ /// \returns a valid null DWARFDie instance if this object has children or an
+ /// invalid DWARFDie instance if it doesn't.
+ DWARFDie getLastChild() const;
+
/// Dump the DIE and all of its attributes to the supplied stream.
///
/// \param OS the stream to use for output.
@@ -207,7 +219,7 @@ public:
///
/// \returns a address range vector that might be empty if no address range
/// information is available.
- DWARFAddressRangesVector getAddressRanges() const;
+ Expected<DWARFAddressRangesVector> getAddressRanges() const;
/// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any
/// of its children.
@@ -288,6 +300,7 @@ public:
explicit attribute_iterator(DWARFDie D, bool End);
attribute_iterator &operator++();
+ attribute_iterator &operator--();
explicit operator bool() const { return AttrValue.isValid(); }
const DWARFAttribute &operator*() const { return AttrValue; }
bool operator==(const attribute_iterator &X) const { return Index == X.Index; }
@@ -306,26 +319,23 @@ inline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) {
return LHS.getOffset() < RHS.getOffset();
}
-class DWARFDie::iterator : public iterator_facade_base<iterator,
- std::forward_iterator_tag,
- const DWARFDie> {
+class DWARFDie::iterator
+ : public iterator_facade_base<iterator, std::bidirectional_iterator_tag,
+ const DWARFDie> {
DWARFDie Die;
- void skipNull() {
- if (Die && Die.isNULL())
- Die = DWARFDie();
- }
public:
iterator() = default;
explicit iterator(DWARFDie D) : Die(D) {
- // If we start out with only a Null DIE then invalidate.
- skipNull();
}
iterator &operator++() {
Die = Die.getSibling();
- // Don't include the NULL die when iterating.
- skipNull();
+ return *this;
+ }
+
+ iterator &operator--() {
+ Die = Die.getPreviousSibling();
return *this;
}
@@ -341,7 +351,7 @@ inline DWARFDie::iterator DWARFDie::begin() const {
}
inline DWARFDie::iterator DWARFDie::end() const {
- return iterator();
+ return iterator(getLastChild());
}
inline iterator_range<DWARFDie::iterator> DWARFDie::children() const {
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
index dcd486f3fb13..3fad68a9b48b 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
@@ -93,12 +93,13 @@ public:
/// An iterator to go through the expression operations.
class iterator
- : public iterator_facade_base<iterator, std::forward_iterator_tag, Operation> {
+ : public iterator_facade_base<iterator, std::forward_iterator_tag,
+ Operation> {
friend class DWARFExpression;
- DWARFExpression *Expr;
+ const DWARFExpression *Expr;
uint32_t Offset;
Operation Op;
- iterator(DWARFExpression *Expr, uint32_t Offset)
+ iterator(const DWARFExpression *Expr, uint32_t Offset)
: Expr(Expr), Offset(Offset) {
Op.Error =
Offset >= Expr->Data.getData().size() ||
@@ -127,10 +128,11 @@ public:
assert(AddressSize == 8 || AddressSize == 4);
}
- iterator begin() { return iterator(this, 0); }
- iterator end() { return iterator(this, Data.getData().size()); }
+ iterator begin() const { return iterator(this, 0); }
+ iterator end() const { return iterator(this, Data.getData().size()); }
- void print(raw_ostream &OS, const MCRegisterInfo *RegInfo);
+ void print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
+ bool IsEH = false) const;
private:
DataExtractor Data;
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index d32053519ec4..1b5f71c946f9 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -20,38 +20,10 @@
namespace llvm {
+class DWARFContext;
class DWARFUnit;
class raw_ostream;
-/// A helper struct for DWARFFormValue methods, providing information that
-/// allows it to know the byte size of DW_FORM values that vary in size
-/// depending on the DWARF version, address byte size, or DWARF32/DWARF64.
-struct DWARFFormParams {
- uint16_t Version;
- uint8_t AddrSize;
- dwarf::DwarfFormat Format;
-
- /// The definition of the size of form DW_FORM_ref_addr depends on the
- /// version. In DWARF v2 it's the size of an address; after that, it's the
- /// size of a reference.
- uint8_t getRefAddrByteSize() const {
- if (Version == 2)
- return AddrSize;
- return getDwarfOffsetByteSize();
- }
-
- /// The size of a reference is determined by the DWARF 32/64-bit format.
- uint8_t getDwarfOffsetByteSize() const {
- switch (Format) {
- case dwarf::DwarfFormat::DWARF32:
- return 4;
- case dwarf::DwarfFormat::DWARF64:
- return 8;
- }
- llvm_unreachable("Invalid Format value");
- }
-};
-
class DWARFFormValue {
public:
enum FormClass {
@@ -83,7 +55,7 @@ private:
dwarf::Form Form; /// Form for this value.
ValueType Value; /// Contains all data for the form.
const DWARFUnit *U = nullptr; /// Remember the DWARFUnit at extract time.
-
+ const DWARFContext *C = nullptr; /// Context for extract time.
public:
DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {}
@@ -106,10 +78,17 @@ public:
/// Extracts a value in \p Data at offset \p *OffsetPtr. The information
/// in \p FormParams is needed to interpret some forms. The optional
- /// \p Unit allows extracting information if the form refers to other
- /// sections (e.g., .debug_str).
+ /// \p Context and \p Unit allows extracting information if the form refers
+ /// to other sections (e.g., .debug_str).
bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
- DWARFFormParams FormParams, const DWARFUnit *U = nullptr);
+ dwarf::FormParams FormParams,
+ const DWARFContext *Context = nullptr,
+ const DWARFUnit *Unit = nullptr);
+
+ bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
+ dwarf::FormParams FormParams, const DWARFUnit *U) {
+ return extractValue(Data, OffsetPtr, FormParams, nullptr, U);
+ }
bool isInlinedCStr() const {
return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr;
@@ -127,19 +106,6 @@ public:
Optional<uint64_t> getAsCStringOffset() const;
Optional<uint64_t> getAsReferenceUVal() const;
- /// Get the fixed byte size for a given form.
- ///
- /// If the form has a fixed byte size, then an Optional with a value will be
- /// returned. If the form is always encoded using a variable length storage
- /// format (ULEB or SLEB numbers or blocks) then None will be returned.
- ///
- /// \param Form DWARF form to get the fixed byte size for.
- /// \param FormParams DWARF parameters to help interpret forms.
- /// \returns Optional<uint8_t> value with the fixed byte size or None if
- /// \p Form doesn't have a fixed byte size.
- static Optional<uint8_t> getFixedByteSize(dwarf::Form Form,
- const DWARFFormParams FormParams);
-
/// Skip a form's value in \p DebugInfoData at the offset specified by
/// \p OffsetPtr.
///
@@ -150,7 +116,7 @@ public:
/// \param Params DWARF parameters to help interpret forms.
/// \returns true on success, false if the form was not skipped.
bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
- const DWARFFormParams Params) const {
+ const dwarf::FormParams Params) const {
return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params);
}
@@ -165,7 +131,8 @@ public:
/// \param FormParams DWARF parameters to help interpret forms.
/// \returns true on success, false if the form was not skipped.
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
- uint32_t *OffsetPtr, const DWARFFormParams FormParams);
+ uint32_t *OffsetPtr,
+ const dwarf::FormParams FormParams);
private:
void dumpString(raw_ostream &OS) const;
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h
new file mode 100644
index 000000000000..ab12f3bc08b0
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h
@@ -0,0 +1,278 @@
+//===- DWARFListTable.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_DWARFLISTTABLE_H
+#define LLVM_DEBUGINFO_DWARFLISTTABLE_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+/// A base class for DWARF list entries, such as range or location list
+/// entries.
+struct DWARFListEntryBase {
+ /// The offset at which the entry is located in the section.
+ uint32_t Offset;
+ /// The DWARF encoding (DW_RLE_* or DW_LLE_*).
+ uint8_t EntryKind;
+ /// The index of the section this entry belongs to.
+ uint64_t SectionIndex;
+};
+
+/// A base class for lists of entries that are extracted from a particular
+/// section, such as range lists or location lists.
+template <typename ListEntryType> class DWARFListType {
+ using EntryType = ListEntryType;
+ using ListEntries = std::vector<EntryType>;
+
+protected:
+ ListEntries Entries;
+
+public:
+ // FIXME: We need to consolidate the various verions of "createError"
+ // that are used in the DWARF consumer. Until then, this is a workaround.
+ Error createError(const char *, const char *, uint32_t);
+
+ const ListEntries &getEntries() const { return Entries; }
+ bool empty() const { return Entries.empty(); }
+ void clear() { Entries.clear(); }
+ Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
+ uint32_t *OffsetPtr, StringRef SectionName,
+ StringRef ListStringName);
+};
+
+/// A class representing the header of a list table such as the range list
+/// table in the .debug_rnglists section.
+class DWARFListTableHeader {
+ struct Header {
+ /// The total length of the entries for this table, not including the length
+ /// field itself.
+ uint32_t Length = 0;
+ /// 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 selector on the target architecture.
+ /// If the target system uses a flat address space, this value is 0.
+ uint8_t SegSize;
+ /// The number of offsets that follow the header before the range lists.
+ uint32_t OffsetEntryCount;
+ };
+
+ Header HeaderData;
+ /// The offset table, which contains offsets to the individual list entries.
+ /// It is used by forms such as DW_FORM_rnglistx.
+ /// FIXME: Generate the table and use the appropriate forms.
+ std::vector<uint32_t> Offsets;
+ /// The table's format, either DWARF32 or DWARF64.
+ dwarf::DwarfFormat Format;
+ /// The offset at which the header (and hence the table) is located within
+ /// its section.
+ uint32_t HeaderOffset;
+ /// The name of the section the list is located in.
+ StringRef SectionName;
+ /// A characterization of the list for dumping purposes, e.g. "range" or
+ /// "location".
+ StringRef ListTypeString;
+
+public:
+ DWARFListTableHeader(StringRef SectionName, StringRef ListTypeString)
+ : SectionName(SectionName), ListTypeString(ListTypeString) {}
+
+ void clear() {
+ HeaderData = {};
+ Offsets.clear();
+ }
+ uint32_t getHeaderOffset() const { return HeaderOffset; }
+ uint8_t getAddrSize() const { return HeaderData.AddrSize; }
+ uint32_t getLength() const { return HeaderData.Length; }
+ StringRef getSectionName() const { return SectionName; }
+ StringRef getListTypeString() const { return ListTypeString; }
+ dwarf::DwarfFormat getFormat() const { return Format; }
+
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
+ Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
+ if (Index < Offsets.size())
+ return Offsets[Index];
+ return None;
+ }
+
+ /// Extract the table header and the array of offsets.
+ Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
+
+ /// Returns the length of the table, including the length field, or 0 if the
+ /// length has not been determined (e.g. because the table has not yet been
+ /// parsed, or there was a problem in parsing).
+ uint32_t length() const;
+};
+
+/// A class representing a table of lists as specified in the DWARF v5
+/// standard for location lists and range lists. The table consists of a header
+/// followed by an array of offsets into a DWARF section, followed by zero or
+/// more list entries. The list entries are kept in a map where the keys are
+/// the lists' section offsets.
+template <typename DWARFListType> class DWARFListTableBase {
+ DWARFListTableHeader Header;
+ /// A mapping between file offsets and lists. It is used to find a particular
+ /// list based on an offset (obtained from DW_AT_ranges, for example).
+ std::map<uint32_t, DWARFListType> ListMap;
+ /// This string is displayed as a heading before the list is dumped
+ /// (e.g. "ranges:").
+ StringRef HeaderString;
+
+protected:
+ DWARFListTableBase(StringRef SectionName, StringRef HeaderString,
+ StringRef ListTypeString)
+ : Header(SectionName, ListTypeString), HeaderString(HeaderString) {}
+
+public:
+ void clear() {
+ Header.clear();
+ ListMap.clear();
+ }
+ /// Extract the table header and the array of offsets.
+ Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) {
+ return Header.extract(Data, OffsetPtr);
+ }
+ /// Extract an entire table, including all list entries.
+ Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
+ /// Look up a list based on a given offset. Extract it and enter it into the
+ /// list map if necessary.
+ Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset);
+
+ uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); }
+ uint8_t getAddrSize() const { return Header.getAddrSize(); }
+
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
+
+ /// Return the contents of the offset entry designated by a given index.
+ Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
+ return Header.getOffsetEntry(Index);
+ }
+ /// Return the size of the table header including the length but not including
+ /// the offsets. This is dependent on the table format, which is unambiguously
+ /// derived from parsing the table.
+ uint8_t getHeaderSize() const {
+ switch (Header.getFormat()) {
+ case dwarf::DwarfFormat::DWARF32:
+ return 12;
+ case dwarf::DwarfFormat::DWARF64:
+ return 20;
+ }
+ llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
+ }
+
+ uint32_t length() { return Header.length(); }
+};
+
+template <typename DWARFListType>
+Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
+ uint32_t *OffsetPtr) {
+ clear();
+ if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
+ return E;
+
+ Data.setAddressSize(Header.getAddrSize());
+ uint32_t End = getHeaderOffset() + Header.length();
+ while (*OffsetPtr < End) {
+ DWARFListType CurrentList;
+ uint32_t Off = *OffsetPtr;
+ if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr,
+ Header.getSectionName(),
+ Header.getListTypeString()))
+ return E;
+ ListMap[Off] = CurrentList;
+ }
+
+ assert(*OffsetPtr == End &&
+ "mismatch between expected length of table and length "
+ "of extracted data");
+ return Error::success();
+}
+
+template <typename ListEntryType>
+Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
+ uint32_t HeaderOffset, uint32_t End,
+ uint32_t *OffsetPtr,
+ StringRef SectionName,
+ StringRef ListTypeString) {
+ if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
+ return createError("invalid %s list offset 0x%" PRIx32,
+ ListTypeString.data(), *OffsetPtr);
+ Entries.clear();
+ while (*OffsetPtr < End) {
+ ListEntryType Entry;
+ if (Error E = Entry.extract(Data, End, OffsetPtr))
+ return E;
+ Entries.push_back(Entry);
+ if (Entry.isSentinel())
+ return Error::success();
+ }
+ return createError("no end of list marker detected at end of %s table "
+ "starting at offset 0x%" PRIx32,
+ SectionName.data(), HeaderOffset);
+}
+
+template <typename DWARFListType>
+void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS,
+ DIDumpOptions DumpOpts) const {
+ Header.dump(OS, DumpOpts);
+ OS << HeaderString << "\n";
+
+ // Determine the length of the longest encoding string we have in the table,
+ // so we can align the output properly. We only need this in verbose mode.
+ size_t MaxEncodingStringLength = 0;
+ if (DumpOpts.Verbose) {
+ for (const auto &List : ListMap)
+ for (const auto &Entry : List.second.getEntries())
+ MaxEncodingStringLength =
+ std::max(MaxEncodingStringLength,
+ dwarf::RangeListEncodingString(Entry.EntryKind).size());
+ }
+
+ uint64_t CurrentBase = 0;
+ for (const auto &List : ListMap)
+ for (const auto &Entry : List.second.getEntries())
+ Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase,
+ DumpOpts);
+}
+
+template <typename DWARFListType>
+Expected<DWARFListType>
+DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
+ uint32_t Offset) {
+ auto Entry = ListMap.find(Offset);
+ if (Entry != ListMap.end())
+ return Entry->second;
+
+ // Extract the list from the section and enter it into the list map.
+ DWARFListType List;
+ uint32_t End = getHeaderOffset() + Header.length();
+ uint32_t StartingOffset = Offset;
+ if (Error E =
+ List.extract(Data, getHeaderOffset(), End, &Offset,
+ Header.getSectionName(), Header.getListTypeString()))
+ return std::move(E);
+ ListMap[StartingOffset] = List;
+ return List;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFLISTTABLE_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h
index 167eb2da5ba0..6e8f370f4aea 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h
@@ -42,8 +42,10 @@ public:
virtual StringRef getDebugFrameSection() const { return ""; }
virtual StringRef getEHFrameSection() const { return ""; }
virtual const DWARFSection &getLineSection() const { return Dummy; }
+ virtual StringRef getLineStringSection() const { return ""; }
virtual StringRef getStringSection() const { return ""; }
virtual const DWARFSection &getRangeSection() const { return Dummy; }
+ virtual const DWARFSection &getRnglistsSection() const { return Dummy; }
virtual StringRef getMacinfoSection() const { return ""; }
virtual StringRef getPubNamesSection() const { return ""; }
virtual StringRef getPubTypesSection() const { return ""; }
@@ -61,12 +63,14 @@ public:
return Dummy;
}
virtual const DWARFSection &getRangeDWOSection() const { return Dummy; }
+ virtual const DWARFSection &getRnglistsDWOSection() const { return Dummy; }
virtual const DWARFSection &getAddrSection() const { return Dummy; }
virtual const DWARFSection &getAppleNamesSection() const { return Dummy; }
virtual const DWARFSection &getAppleTypesSection() const { return Dummy; }
virtual const DWARFSection &getAppleNamespacesSection() const {
return Dummy;
}
+ virtual const DWARFSection &getDebugNamesSection() const { return Dummy; }
virtual const DWARFSection &getAppleObjCSection() const { return Dummy; }
virtual StringRef getCUIndexSection() const { return ""; }
virtual StringRef getGdbIndexSection() const { return ""; }
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
index a7842454f435..cb5a78ee3dbf 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -24,29 +24,21 @@ struct DWARFSection;
class raw_ostream;
class DWARFTypeUnit : public DWARFUnit {
-private:
- uint64_t TypeHash;
- uint32_t TypeOffset;
-
public:
DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
const DWARFSection &LS, bool LE, bool IsDWO,
- const DWARFUnitSectionBase &UnitSection,
- const DWARFUnitIndex::Entry *Entry)
- : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
- UnitSection, Entry) {}
+ const DWARFUnitSectionBase &UnitSection)
+ : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
+ UnitSection) {}
- uint32_t getHeaderSize() const override {
- return DWARFUnit::getHeaderSize() + 12;
- }
+ uint64_t getTypeHash() const { return getHeader().getTypeHash(); }
+ uint32_t getTypeOffset() const { return getHeader().getTypeOffset(); }
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {});
static const DWARFSectionKind Section = DW_SECT_TYPES;
-
-protected:
- bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override;
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index 3cec58383f87..988a7958184c 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -18,6 +18,7 @@
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
@@ -40,6 +41,66 @@ class DWARFContext;
class DWARFDebugAbbrev;
class DWARFUnit;
+/// Base class describing the header of any kind of "unit." Some information
+/// is specific to certain unit types. We separate this class out so we can
+/// parse the header before deciding what specific kind of unit to construct.
+class DWARFUnitHeader {
+ // Offset within section.
+ uint32_t Offset = 0;
+ // Version, address size, and DWARF format.
+ dwarf::FormParams FormParams;
+ uint32_t Length = 0;
+ uint64_t AbbrOffset = 0;
+
+ // For DWO units only.
+ const DWARFUnitIndex::Entry *IndexEntry = nullptr;
+
+ // For type units only.
+ uint64_t TypeHash = 0;
+ uint32_t TypeOffset = 0;
+
+ // For v5 split or skeleton compile units only.
+ Optional<uint64_t> DWOId;
+
+ // Unit type as parsed, or derived from the section kind.
+ uint8_t UnitType = 0;
+
+ // Size as parsed. uint8_t for compactness.
+ uint8_t Size = 0;
+
+public:
+ /// Parse a unit header from \p debug_info starting at \p offset_ptr.
+ bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info,
+ uint32_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO,
+ const DWARFUnitIndex *Index = nullptr);
+ uint32_t getOffset() const { return Offset; }
+ const dwarf::FormParams &getFormParams() const { return FormParams; }
+ uint16_t getVersion() const { return FormParams.Version; }
+ dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
+ uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
+ uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
+ uint8_t getDwarfOffsetByteSize() const {
+ return FormParams.getDwarfOffsetByteSize();
+ }
+ uint32_t getLength() const { return Length; }
+ uint64_t getAbbrOffset() const { return AbbrOffset; }
+ Optional<uint64_t> getDWOId() const { return DWOId; }
+ void setDWOId(uint64_t Id) {
+ assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value");
+ DWOId = Id;
+ }
+ const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; }
+ uint64_t getTypeHash() const { return TypeHash; }
+ uint32_t getTypeOffset() const { return TypeOffset; }
+ uint8_t getUnitType() const { return UnitType; }
+ bool isTypeUnit() const {
+ return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type;
+ }
+ uint8_t getSize() const { return Size; }
+ // FIXME: Support DWARF64.
+ uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
+};
+
/// Base class for all DWARFUnitSection classes. This provides the
/// functionality common to all unit types.
class DWARFUnitSectionBase {
@@ -56,7 +117,8 @@ public:
protected:
~DWARFUnitSectionBase() = default;
- virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
+ virtual void parseImpl(DWARFContext &Context, const DWARFObject &Obj,
+ const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, const DWARFSection &LS,
@@ -116,14 +178,14 @@ public:
}
private:
- void parseImpl(DWARFContext &Context, const DWARFSection &Section,
- const DWARFDebugAbbrev *DA, const DWARFSection *RS,
- StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
- const DWARFSection &LS, bool LE, bool IsDWO,
- bool Lazy) override {
+ void parseImpl(DWARFContext &Context, const DWARFObject &Obj,
+ const DWARFSection &Section, const DWARFDebugAbbrev *DA,
+ const DWARFSection *RS, StringRef SS, const DWARFSection &SOS,
+ const DWARFSection *AOS, const DWARFSection &LS, bool LE,
+ bool IsDWO, bool Lazy) override {
if (Parsed)
return;
- DataExtractor Data(Section.Data, LE, 0);
+ DWARFDataExtractor Data(Obj, Section, LE, 0);
if (!Parser) {
const DWARFUnitIndex *Index = nullptr;
if (IsDWO)
@@ -132,11 +194,12 @@ private:
&LS](uint32_t Offset) -> std::unique_ptr<UnitType> {
if (!Data.isValidOffset(Offset))
return nullptr;
- auto U = llvm::make_unique<UnitType>(
- Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this,
- Index ? Index->getFromOffset(Offset) : nullptr);
- if (!U->extract(Data, &Offset))
+ DWARFUnitHeader Header;
+ if (!Header.extract(Context, Data, &Offset, UnitType::Section, Index))
return nullptr;
+ auto U = llvm::make_unique<UnitType>(
+ Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
+ *this);
return U;
};
}
@@ -168,9 +231,10 @@ struct BaseAddress {
/// Represents a unit's contribution to the string offsets table.
struct StrOffsetsContributionDescriptor {
uint64_t Base = 0;
+ /// The contribution size not including the header.
uint64_t Size = 0;
/// Format and version.
- DWARFFormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
+ dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size,
uint8_t Version, dwarf::DwarfFormat Format)
@@ -193,6 +257,7 @@ class DWARFUnit {
/// Section containing this DWARFUnit.
const DWARFSection &InfoSection;
+ DWARFUnitHeader Header;
const DWARFDebugAbbrev *Abbrev;
const DWARFSection *RangeSection;
uint32_t RangeSectionBase;
@@ -205,63 +270,28 @@ class DWARFUnit {
bool isDWO;
const DWARFUnitSectionBase &UnitSection;
- // Version, address size, and DWARF format.
- DWARFFormParams FormParams;
/// Start, length, and DWARF format of the unit's contribution to the string
/// offsets table (DWARF v5).
Optional<StrOffsetsContributionDescriptor> StringOffsetsTableContribution;
- uint32_t Offset;
- uint32_t Length;
+ /// A table of range lists (DWARF v5 and later).
+ Optional<DWARFDebugRnglistTable> RngListTable;
+
mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
- uint64_t AbbrOffset;
- uint8_t UnitType;
llvm::Optional<BaseAddress> BaseAddr;
/// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray;
- /// The vector of inlined subroutine DIEs that we can map directly to from
- /// their subprogram below.
- std::vector<DWARFDie> InlinedSubroutineDIEs;
-
- /// A type representing a subprogram DIE and a map (built using a sorted
- /// vector) into that subprogram's inlined subroutine DIEs.
- struct SubprogramDIEAddrInfo {
- DWARFDie SubprogramDIE;
-
- uint64_t SubprogramBasePC;
-
- /// A vector sorted to allow mapping from a relative PC to the inlined
- /// subroutine DIE with the most specific address range covering that PC.
- ///
- /// The PCs are relative to the `SubprogramBasePC`.
- ///
- /// The vector is sorted in ascending order of the first int which
- /// represents the relative PC for an interval in the map. The second int
- /// represents the index into the `InlinedSubroutineDIEs` vector of the DIE
- /// that interval maps to. An index of '-1` indicates an empty mapping. The
- /// interval covered is from the `.first` relative PC to the next entry's
- /// `.first` relative PC.
- std::vector<std::pair<uint32_t, int32_t>> InlinedSubroutineDIEAddrMap;
- };
-
- /// Vector of the subprogram DIEs and their subroutine address maps.
- std::vector<SubprogramDIEAddrInfo> SubprogramDIEAddrInfos;
-
- /// A vector sorted to allow mapping from a PC to the subprogram DIE (and
- /// associated addr map) index. Subprograms with overlapping PC ranges aren't
- /// supported here. Nothing will crash, but the mapping may be inaccurate.
- /// This vector may also contain "empty" ranges marked by an address with
- /// a DIE index of '-1'.
- std::vector<std::pair<uint64_t, int64_t>> SubprogramDIEAddrMap;
+ /// Map from range's start address to end address and corresponding DIE.
+ /// IntervalMap does not support range removal, as a result, we use the
+ /// std::map::upper_bound for address range lookup.
+ std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
using die_iterator_range =
iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
std::shared_ptr<DWARFUnit> DWO;
- const DWARFUnitIndex::Entry *IndexEntry;
-
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) {
auto First = DieArray.data();
assert(Die >= First && Die < First + DieArray.size());
@@ -269,10 +299,10 @@ class DWARFUnit {
}
protected:
- virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
+ const DWARFUnitHeader &getHeader() const { return Header; }
- /// Size in bytes of the unit header.
- virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; }
+ /// Size in bytes of the parsed unit header.
+ uint32_t getHeaderSize() const { return Header.getSize(); }
/// Find the unit's contribution to the string offsets table and determine its
/// length and form. The given offset is expected to be derived from the unit
@@ -291,16 +321,28 @@ protected:
public:
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFUnitHeader &Header,
const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS,
const DWARFSection &SOS, const DWARFSection *AOS,
const DWARFSection &LS, bool LE, bool IsDWO,
- const DWARFUnitSectionBase &UnitSection,
- const DWARFUnitIndex::Entry *IndexEntry = nullptr);
+ const DWARFUnitSectionBase &UnitSection);
virtual ~DWARFUnit();
DWARFContext& getContext() const { return Context; }
-
+ uint32_t getOffset() const { return Header.getOffset(); }
+ const dwarf::FormParams &getFormParams() const {
+ return Header.getFormParams();
+ }
+ uint16_t getVersion() const { return Header.getVersion(); }
+ uint8_t getAddressByteSize() const { return Header.getAddressByteSize(); }
+ uint8_t getRefAddrByteSize() const { return Header.getRefAddrByteSize(); }
+ uint8_t getDwarfOffsetByteSize() const {
+ return Header.getDwarfOffsetByteSize();
+ }
+ uint32_t getLength() const { return Header.getLength(); }
+ uint8_t getUnitType() const { return Header.getUnitType(); }
+ uint32_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
const DWARFSection &getLineSection() const { return LineSection; }
StringRef getStringSection() const { return StringSection; }
const DWARFSection &getStringOffsetSection() const {
@@ -312,6 +354,9 @@ public:
AddrOffsetSectionBase = Base;
}
+ /// Recursively update address to Die map.
+ void updateAddressDieMap(DWARFDie Die);
+
void setRangesSection(const DWARFSection *RS, uint32_t Base) {
RangeSection = RS;
RangeSectionBase = Base;
@@ -326,31 +371,18 @@ public:
return DataExtractor(StringSection, false, 0);
}
-
- 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;
+ /// Extract the range list referenced by this compile unit from the
+ /// .debug_ranges section. If the extraction is unsuccessful, an error
+ /// is returned. Successful extraction requires that the compile unit
+ /// has already been extracted.
+ Error 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; }
const Optional<StrOffsetsContributionDescriptor> &
getStringOffsetsTableContribution() const {
return StringOffsetsTableContribution;
}
- const DWARFFormParams &getFormParams() const { return FormParams; }
- uint16_t getVersion() const { return FormParams.Version; }
- dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
- uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
- uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
- uint8_t getDwarfOffsetByteSize() const {
- return FormParams.getDwarfOffsetByteSize();
- }
uint8_t getDwarfStringOffsetsByteSize() const {
assert(StringOffsetsTableContribution);
@@ -364,8 +396,6 @@ public:
const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
- uint8_t getUnitType() const { return UnitType; }
-
static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
switch (UnitType) {
case dwarf::DW_UT_compile:
@@ -383,7 +413,7 @@ public:
return false;
}
- /// \brief Return the number of bytes for the header of a unit of
+ /// Return the number of bytes for the header of a unit of
/// UnitType type.
///
/// This function must be called with a valid unit type which in
@@ -403,9 +433,7 @@ public:
llvm_unreachable("Invalid UnitType.");
}
- llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; }
-
- void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; }
+ llvm::Optional<BaseAddress> getBaseAddress();
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
extractDIEsIfNeeded(ExtractUnitDIEOnly);
@@ -415,7 +443,29 @@ public:
}
const char *getCompilationDir();
- Optional<uint64_t> getDWOId();
+ Optional<uint64_t> getDWOId() {
+ extractDIEsIfNeeded(/*CUDieOnly*/ true);
+ return getHeader().getDWOId();
+ }
+ void setDWOId(uint64_t NewID) { Header.setDWOId(NewID); }
+
+ /// Return a vector of address ranges resulting from a (possibly encoded)
+ /// range list starting at a given offset in the appropriate ranges section.
+ Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint32_t Offset);
+
+ /// Return a vector of address ranges retrieved from an encoded range
+ /// list whose offset is found via a table lookup given an index (DWARF v5
+ /// and later).
+ Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index);
+
+ /// Return a rangelist's offset based on an index. The index designates
+ /// an entry in the rangelist table's offset array and is supplied by
+ /// DW_FORM_rnglistx.
+ Optional<uint32_t> getRnglistOffset(uint32_t Index) {
+ if (RngListTable)
+ return RngListTable->getOffsetEntry(Index);
+ return None;
+ }
void collectAddressRanges(DWARFAddressRangesVector &CURanges);
@@ -433,14 +483,14 @@ public:
/// 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
+ /// 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.
+ /// 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
@@ -450,7 +500,7 @@ public:
return getDIEIndex(D.getDebugInfoEntry());
}
- /// \brief Return the DIE object at the given index.
+ /// Return the DIE object at the given index.
DWARFDie getDIEAtIndex(unsigned Index) {
assert(Index < DieArray.size());
return DWARFDie(this, &DieArray[Index]);
@@ -458,9 +508,11 @@ public:
DWARFDie getParent(const DWARFDebugInfoEntry *Die);
DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
+ DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die);
DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die);
+ DWARFDie getLastChild(const DWARFDebugInfoEntry *Die);
- /// \brief Return the DIE object for a given offset inside the
+ /// Return the DIE object for a given offset inside the
/// unit's DIE vector.
///
/// The unit needs to have its DIEs extracted for this method to work.
@@ -478,7 +530,7 @@ public:
}
uint32_t getLineTableOffset() const {
- if (IndexEntry)
+ if (auto IndexEntry = Header.getIndexEntry())
if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE))
return Contrib->Offset;
return 0;
@@ -491,7 +543,9 @@ public:
private:
/// Size in bytes of the .debug_info data associated with this compile unit.
- size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); }
+ size_t getDebugInfoSize() const {
+ return Header.getLength() + 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.
@@ -507,9 +561,6 @@ private:
/// parseDWO - Parses .dwo file for current compile unit. Returns true if
/// it was actually constructed.
bool parseDWO();
-
- void buildSubprogramDIEAddrMap();
- void buildInlinedSubroutineDIEAddrMap(SubprogramDIEAddrInfo &SPInfo);
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
index 0d920abe3231..a829510a219d 100644
--- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
+++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -11,7 +11,8 @@
#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include <cstdint>
@@ -24,7 +25,7 @@ struct DWARFAttribute;
class DWARFContext;
class DWARFDie;
class DWARFUnit;
-class DWARFAcceleratorTable;
+class DWARFCompileUnit;
class DWARFDataExtractor;
class DWARFDebugAbbrev;
class DataExtractor;
@@ -109,7 +110,7 @@ private:
/// \param Abbrev Pointer to the abbreviations section we are verifying
/// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo.
///
- /// \returns The number of errors that occured during verification.
+ /// \returns The number of errors that occurred during verification.
unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev);
/// Verifies the header of a unit in the .debug_info section.
@@ -151,14 +152,14 @@ private:
/// type of the unit DIE.
///
/// \returns true if the content is verified successfully, false otherwise.
- bool verifyUnitContents(DWARFUnit Unit, uint8_t UnitType = 0);
+ bool verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType = 0);
/// Verify that all Die ranges are valid.
///
/// This function currently checks for:
/// - cases in which lowPC >= highPC
///
- /// \returns Number of errors that occured during verification.
+ /// \returns Number of errors that occurred during verification.
unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
/// Verifies the attribute's DWARF attribute and its value.
@@ -170,7 +171,7 @@ private:
/// \param Die The DWARF DIE that owns the attribute value
/// \param AttrValue The DWARF attribute value to check
///
- /// \returns NumErrors The number of errors occured during verification of
+ /// \returns NumErrors The number of errors occurred during verification of
/// attributes' values in a .debug_info section unit
unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
DWARFAttribute &AttrValue);
@@ -185,7 +186,7 @@ private:
/// \param Die The DWARF DIE that owns the attribute value
/// \param AttrValue The DWARF attribute value to check
///
- /// \returns NumErrors The number of errors occured during verification of
+ /// \returns NumErrors The number of errors occurred during verification of
/// attributes' forms in a .debug_info section unit
unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);
@@ -197,11 +198,11 @@ private:
/// around, that it doesn't create invalid references by failing to relocate
/// CU relative and absolute references.
///
- /// \returns NumErrors The number of errors occured during verification of
+ /// \returns NumErrors The number of errors occurred during verification of
/// references for the .debug_info section
unsigned verifyDebugInfoReferences();
- /// Verify the the DW_AT_stmt_list encoding and value and ensure that no
+ /// Verify the DW_AT_stmt_list encoding and value and ensure that no
/// compile units that have the same DW_AT_stmt_list value.
void verifyDebugLineStmtOffsets();
@@ -228,9 +229,42 @@ private:
/// \param StrData pointer to the string section
/// \param SectionName the name of the table we're verifying
///
- /// \returns The number of errors occured during verification
- unsigned verifyAccelTable(const DWARFSection *AccelSection,
- DataExtractor *StrData, const char *SectionName);
+ /// \returns The number of errors occurred during verification
+ unsigned verifyAppleAccelTable(const DWARFSection *AccelSection,
+ DataExtractor *StrData,
+ const char *SectionName);
+
+ unsigned verifyDebugNamesCULists(const DWARFDebugNames &AccelTable);
+ unsigned verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
+ const DataExtractor &StrData);
+ unsigned verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI);
+ unsigned verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI,
+ const DWARFDebugNames::Abbrev &Abbr,
+ DWARFDebugNames::AttributeEncoding AttrEnc);
+ unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI,
+ const DWARFDebugNames::NameTableEntry &NTE);
+ unsigned verifyNameIndexCompleteness(const DWARFDie &Die,
+ const DWARFDebugNames::NameIndex &NI);
+
+ /// Verify that the DWARF v5 accelerator table is valid.
+ ///
+ /// This function currently checks that:
+ /// - Headers individual Name Indices fit into the section and can be parsed.
+ /// - Abbreviation tables can be parsed and contain valid index attributes
+ /// with correct form encodings.
+ /// - The CU lists reference existing compile units.
+ /// - The buckets have a valid index, or they are empty.
+ /// - All names are reachable via the hash table (they have the correct hash,
+ /// and the hash is in the correct bucket).
+ /// - Information in the index entries is complete (all required entries are
+ /// present) and consistent with the debug_info section DIEs.
+ ///
+ /// \param AccelSection section containing the acceleration table
+ /// \param StrData string section
+ ///
+ /// \returns The number of errors occurred during verification
+ unsigned verifyDebugNames(const DWARFSection &AccelSection,
+ const DataExtractor &StrData);
public:
DWARFVerifier(raw_ostream &S, DWARFContext &D,
diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h
index 19e5c31b3076..3de98c4ecba8 100644
--- a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h
+++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h
@@ -20,11 +20,13 @@
#include <vector>
namespace llvm {
+class FileBufferByteStream;
+class WritableBinaryStream;
namespace msf {
class MSFBuilder {
public:
- /// \brief Create a new `MSFBuilder`.
+ /// Create a new `MSFBuilder`.
///
/// \param BlockSize The internal block size used by the PDB file. See
/// isValidBlockSize() for a list of valid block sizes.
@@ -109,7 +111,10 @@ public:
/// Finalize the layout and build the headers and structures that describe the
/// MSF layout and can be written directly to the MSF file.
- Expected<MSFLayout> build();
+ Expected<MSFLayout> generateLayout();
+
+ /// Write the MSF layout to the underlying file.
+ Expected<FileBufferByteStream> commit(StringRef Path, MSFLayout &Layout);
BumpPtrAllocator &getAllocator() { return Allocator; }
diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h
index f28415d4e603..2db2b71df4a7 100644
--- a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h
+++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h
@@ -52,6 +52,16 @@ struct SuperBlock {
struct MSFLayout {
MSFLayout() = default;
+ uint32_t mainFpmBlock() const {
+ assert(SB->FreeBlockMapBlock == 1 || SB->FreeBlockMapBlock == 2);
+ return SB->FreeBlockMapBlock;
+ }
+
+ uint32_t alternateFpmBlock() const {
+ // If mainFpmBlock is 1, this is 2. If mainFpmBlock is 2, this is 1.
+ return 3U - mainFpmBlock();
+ }
+
const SuperBlock *SB = nullptr;
BitVector FreePageMap;
ArrayRef<support::ulittle32_t> DirectoryBlocks;
@@ -59,7 +69,7 @@ struct MSFLayout {
std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
};
-/// \brief Describes the layout of a stream in an MSF layout. A "stream" here
+/// Describes the layout of a stream in an MSF layout. A "stream" here
/// is defined as any logical unit of data which may be arranged inside the MSF
/// file as a sequence of (possibly discontiguous) blocks. When we want to read
/// from a particular MSF Stream, we fill out a stream layout structure and the
@@ -71,7 +81,7 @@ public:
std::vector<support::ulittle32_t> Blocks;
};
-/// \brief Determine the layout of the FPM stream, given the MSF layout. An FPM
+/// Determine the layout of the FPM stream, given the MSF layout. An FPM
/// stream spans 1 or more blocks, each at equally spaced intervals throughout
/// the file.
MSFStreamLayout getFpmStreamLayout(const MSFLayout &Msf,
@@ -108,14 +118,40 @@ inline uint32_t getFpmIntervalLength(const MSFLayout &L) {
return L.SB->BlockSize;
}
-inline uint32_t getNumFpmIntervals(const MSFLayout &L,
- bool IncludeUnusedFpmData = false) {
- if (IncludeUnusedFpmData)
- return divideCeil(L.SB->NumBlocks, L.SB->BlockSize);
+/// Given an MSF with the specified block size and number of blocks, determine
+/// how many pieces the specified Fpm is split into.
+/// \p BlockSize - the block size of the MSF
+/// \p NumBlocks - the total number of blocks in the MSF
+/// \p IncludeUnusedFpmData - When true, this will count every block that is
+/// both in the file and matches the form of an FPM block, even if some of
+/// those FPM blocks are unused (a single FPM block can describe the
+/// allocation status of up to 32,767 blocks, although one appears only
+/// every 4,096 blocks). So there are 8x as many blocks that match the
+/// form as there are blocks that are necessary to describe the allocation
+/// status of the file. When this parameter is false, these extraneous
+/// trailing blocks are not counted.
+inline uint32_t getNumFpmIntervals(uint32_t BlockSize, uint32_t NumBlocks,
+ bool IncludeUnusedFpmData, int FpmNumber) {
+ assert(FpmNumber == 1 || FpmNumber == 2);
+ if (IncludeUnusedFpmData) {
+ // This calculation determines how many times a number of the form
+ // BlockSize * k + N appears in the range [0, NumBlocks). We only need to
+ // do this when unused data is included, since the number of blocks dwarfs
+ // the number of fpm blocks.
+ return divideCeil(NumBlocks - FpmNumber, BlockSize);
+ }
// We want the minimum number of intervals required, where each interval can
// represent BlockSize * 8 blocks.
- return divideCeil(L.SB->NumBlocks, 8 * L.SB->BlockSize);
+ return divideCeil(NumBlocks, 8 * BlockSize);
+}
+
+inline uint32_t getNumFpmIntervals(const MSFLayout &L,
+ bool IncludeUnusedFpmData = false,
+ bool AltFpm = false) {
+ return getNumFpmIntervals(L.SB->BlockSize, L.SB->NumBlocks,
+ IncludeUnusedFpmData,
+ AltFpm ? L.alternateFpmBlock() : L.mainFpmBlock());
}
Error validateSuperBlock(const SuperBlock &SB);
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h
new file mode 100644
index 000000000000..39490a4b2209
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h
@@ -0,0 +1,40 @@
+//==- DIAEnumInjectedSources.h - DIA Injected Sources 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_DIA_DIAENUMINJECTEDSOURCES_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
+
+namespace llvm {
+namespace pdb {
+class DIASession;
+
+class DIAEnumInjectedSources : public IPDBEnumChildren<IPDBInjectedSource> {
+public:
+ explicit DIAEnumInjectedSources(
+ const DIASession &PDBSession,
+ CComPtr<IDiaEnumInjectedSources> DiaEnumerator);
+
+ uint32_t getChildCount() const override;
+ ChildTypePtr getChildAtIndex(uint32_t Index) const override;
+ ChildTypePtr getNext() override;
+ void reset() override;
+ DIAEnumInjectedSources *clone() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaEnumInjectedSources> Enumerator;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h
new file mode 100644
index 000000000000..52c9563b5d5f
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h
@@ -0,0 +1,40 @@
+//==- DIAEnumSectionContribs.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_DIA_DIAENUMSECTIONCONTRIBS_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSECTIONCONTRIBS_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
+
+namespace llvm {
+namespace pdb {
+class DIASession;
+
+class DIAEnumSectionContribs : public IPDBEnumChildren<IPDBSectionContrib> {
+public:
+ explicit DIAEnumSectionContribs(
+ const DIASession &PDBSession,
+ CComPtr<IDiaEnumSectionContribs> DiaEnumerator);
+
+ uint32_t getChildCount() const override;
+ ChildTypePtr getChildAtIndex(uint32_t Index) const override;
+ ChildTypePtr getNext() override;
+ void reset() override;
+ DIAEnumSectionContribs *clone() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaEnumSectionContribs> Enumerator;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMSECTIONCONTRIBS_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h
new file mode 100644
index 000000000000..635508da84ea
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h
@@ -0,0 +1,38 @@
+//===- DIAInjectedSource.h - DIA impl for IPDBInjectedSource ----*- 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_DIAINJECTEDSOURCE_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
+
+namespace llvm {
+namespace pdb {
+class DIASession;
+
+class DIAInjectedSource : public IPDBInjectedSource {
+public:
+ explicit DIAInjectedSource(CComPtr<IDiaInjectedSource> DiaSourceFile);
+
+ uint32_t getCrc32() const override;
+ uint64_t getCodeByteSize() const override;
+ std::string getFileName() const override;
+ std::string getObjectFileName() const override;
+ std::string getVirtualFileName() const override;
+ PDB_SourceCompression getCompression() const override;
+ std::string getCode() const override;
+
+private:
+ CComPtr<IDiaInjectedSource> SourceFile;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
index 2d6c44905ce0..dfb35647055a 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
@@ -30,10 +30,31 @@ public:
findChildren(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags) const override;
std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByAddr(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags,
+ uint32_t Section, uint32_t Offset) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
+ uint64_t VA) const override;
+ std::unique_ptr<IPDBEnumSymbols>
findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
uint32_t RVA) const override;
+
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const override;
std::unique_ptr<IPDBEnumSymbols>
findInlineFramesByRVA(uint32_t RVA) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByVA(uint64_t VA) const override;
+
+ std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override;
void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const override;
void getFrontEndVersion(VersionInfo &Version) const override;
@@ -82,6 +103,7 @@ public:
uint32_t getSizeInUdt() const override;
uint32_t getSlot() const override;
std::string getSourceFileName() const override;
+ std::unique_ptr<IPDBLineNumber> getSrcLineOnTypeDefn() const override;
uint32_t getStride() const override;
uint32_t getSubTypeId() const override;
std::string getSymbolsFileName() const override;
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h
new file mode 100644
index 000000000000..4688f1f91a89
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h
@@ -0,0 +1,55 @@
+//===- DIASectionContrib.h - DIA Impl. of IPDBSectionContrib ------ 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_DIASECTIONCONTRIB_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIASECTIONCONTRIB_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
+
+namespace llvm {
+namespace pdb {
+class DIASession;
+
+class DIASectionContrib : public IPDBSectionContrib {
+public:
+ explicit DIASectionContrib(const DIASession &PDBSession,
+ CComPtr<IDiaSectionContrib> DiaSection);
+
+ std::unique_ptr<PDBSymbolCompiland> getCompiland() 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;
+ bool isNotPaged() const override;
+ bool hasCode() const override;
+ bool hasCode16Bit() const override;
+ bool hasInitializedData() const override;
+ bool hasUninitializedData() const override;
+ bool isRemoved() const override;
+ bool hasComdat() const override;
+ bool isDiscardable() const override;
+ bool isNotCached() const override;
+ bool isShared() const override;
+ bool isExecutable() const override;
+ bool isReadable() const override;
+ bool isWritable() const override;
+ uint32_t getDataCrc32() const override;
+ uint32_t getRelocationsCrc32() const override;
+ uint32_t getCompilandId() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaSectionContrib> Section;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_DIA_DIASECTIONCONTRIB_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
index 66bd7a7e9c4e..a63659439389 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
@@ -30,18 +30,33 @@ public:
std::unique_ptr<IPDBSession> &Session);
uint64_t getLoadAddress() const override;
- void setLoadAddress(uint64_t Address) override;
+ bool setLoadAddress(uint64_t Address) override;
std::unique_ptr<PDBSymbolExe> getGlobalScope() override;
std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
+ bool addressForVA(uint64_t VA, uint32_t &Section,
+ uint32_t &Offset) const override;
+ bool addressForRVA(uint32_t RVA, uint32_t &Section,
+ uint32_t &Offset) const override;
+
std::unique_ptr<PDBSymbol>
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+ std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
+ PDB_SymType Type) const override;
+ std::unique_ptr<PDBSymbol>
+ findSymbolBySectOffset(uint32_t Section, uint32_t Offset,
+ PDB_SymType Type) const override;
std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland,
const IPDBSourceFile &File) const override;
std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const override;
std::unique_ptr<IPDBEnumSourceFiles>
findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern,
@@ -65,9 +80,14 @@ public:
std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override;
std::unique_ptr<IPDBEnumTables> getEnumTables() const override;
+
+ std::unique_ptr<IPDBEnumInjectedSources> getInjectedSources() const override;
+
+ std::unique_ptr<IPDBEnumSectionContribs> getSectionContribs() const override;
+
private:
CComPtr<IDiaSession> Session;
};
-}
-}
+} // namespace pdb
+} // namespace llvm
#endif
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h
index 3b4a348289df..92ebc04ae5a4 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h
@@ -22,14 +22,6 @@
#define NOMINMAX
#endif
-// llvm/Support/Debug.h unconditionally #defines DEBUG as a macro.
-// DIA headers #define it if it is not already defined, so we have
-// an order of includes problem. The real fix is to make LLVM use
-// something less generic than DEBUG, such as LLVM_DEBUG(), but it's
-// fairly prevalent. So for now, we save the definition state and
-// restore it.
-#pragma push_macro("DEBUG")
-
// atlbase.h has to come before windows.h
#include <atlbase.h>
#include <windows.h>
@@ -39,6 +31,4 @@
#include <dia2.h>
#include <diacreate.h>
-#pragma pop_macro("DEBUG")
-
#endif // LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h
new file mode 100644
index 000000000000..aa843e05de70
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h
@@ -0,0 +1,31 @@
+//===- DIAUtils.h - Utility functions for working with DIA ------*- 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_DIAUTILS_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/ConvertUTF.h"
+
+template <typename Obj>
+std::string invokeBstrMethod(Obj &Object,
+ HRESULT (__stdcall Obj::*Func)(BSTR *)) {
+ CComBSTR Str16;
+ HRESULT Result = (Object.*Func)(&Str16);
+ if (S_OK != Result)
+ return std::string();
+
+ std::string Str8;
+ llvm::ArrayRef<char> StrBytes(reinterpret_cast<char *>(Str16.m_str),
+ Str16.ByteLength());
+ llvm::convertUTF16ToUTF8String(StrBytes, Str8);
+ return Str8;
+}
+
+#endif // LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h
new file mode 100644
index 000000000000..e75d64af92bb
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h
@@ -0,0 +1,42 @@
+//===- IPDBInjectedSource.h - base class for PDB injected 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_IPDBINJECTEDSOURCE_H
+#define LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H
+
+#include "PDBTypes.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+class raw_ostream;
+
+namespace pdb {
+
+/// IPDBInjectedSource defines an interface used to represent source files
+/// which were injected directly into the PDB file during the compilation
+/// process. This is used, for example, to add natvis files to a PDB, but
+/// in theory could be used to add arbitrary source code.
+class IPDBInjectedSource {
+public:
+ virtual ~IPDBInjectedSource();
+
+ virtual uint32_t getCrc32() const = 0;
+ virtual uint64_t getCodeByteSize() const = 0;
+ virtual std::string getFileName() const = 0;
+ virtual std::string getObjectFileName() const = 0;
+ virtual std::string getVirtualFileName() const = 0;
+ virtual PDB_SourceCompression getCompression() const = 0;
+ virtual std::string getCode() const = 0;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
index 18b9423378a0..bcb2eaa35630 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
@@ -42,10 +42,31 @@ public:
findChildren(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags) const = 0;
virtual std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByAddr(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags,
+ uint32_t Section, uint32_t Offset) const = 0;
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
+ uint64_t VA) 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>
+ findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const = 0;
virtual std::unique_ptr<IPDBEnumSymbols>
findInlineFramesByRVA(uint32_t RVA) const = 0;
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByVA(uint64_t VA) const = 0;
+
+ virtual std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const = 0;
+ virtual std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const = 0;
+ virtual std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const = 0;
+ virtual std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByVA(uint64_t VA, uint32_t Length) const = 0;
virtual void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const = 0;
virtual void getBackEndVersion(VersionInfo &Version) const = 0;
@@ -94,6 +115,8 @@ public:
virtual uint32_t getSizeInUdt() const = 0;
virtual uint32_t getSlot() const = 0;
virtual std::string getSourceFileName() const = 0;
+ virtual std::unique_ptr<IPDBLineNumber>
+ getSrcLineOnTypeDefn() const = 0;
virtual uint32_t getStride() const = 0;
virtual uint32_t getSubTypeId() const = 0;
virtual std::string getSymbolsFileName() const = 0;
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h
new file mode 100644
index 000000000000..4fda62404672
--- /dev/null
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h
@@ -0,0 +1,50 @@
+//==- IPDBSectionContrib.h - Interfaces for PDB SectionContribs --*- 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_IPDBSECTIONCONTRIB_H
+#define LLVM_DEBUGINFO_PDB_IPDBSECTIONCONTRIB_H
+
+#include "PDBTypes.h"
+
+namespace llvm {
+namespace pdb {
+
+/// IPDBSectionContrib defines an interface used to represent section
+/// contributions whose information are stored in the PDB.
+class IPDBSectionContrib {
+public:
+ virtual ~IPDBSectionContrib();
+
+ virtual std::unique_ptr<PDBSymbolCompiland> getCompiland() 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 bool isNotPaged() const = 0;
+ virtual bool hasCode() const = 0;
+ virtual bool hasCode16Bit() const = 0;
+ virtual bool hasInitializedData() const = 0;
+ virtual bool hasUninitializedData() const = 0;
+ virtual bool isRemoved() const = 0;
+ virtual bool hasComdat() const = 0;
+ virtual bool isDiscardable() const = 0;
+ virtual bool isNotCached() const = 0;
+ virtual bool isShared() const = 0;
+ virtual bool isExecutable() const = 0;
+ virtual bool isReadable() const = 0;
+ virtual bool isWritable() const = 0;
+ virtual uint32_t getDataCrc32() const = 0;
+ virtual uint32_t getRelocationsCrc32() const = 0;
+ virtual uint32_t getCompilandId() const = 0;
+};
+}
+}
+
+#endif // LLVM_DEBUGINFO_PDB_IPDBSECTIONCONTRIB_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
index 6291289de5bf..88ec517bc4a5 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
@@ -28,10 +28,15 @@ public:
virtual ~IPDBSession();
virtual uint64_t getLoadAddress() const = 0;
- virtual void setLoadAddress(uint64_t Address) = 0;
+ virtual bool setLoadAddress(uint64_t Address) = 0;
virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() = 0;
virtual std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const = 0;
+ virtual bool addressForVA(uint64_t VA, uint32_t &Section,
+ uint32_t &Offset) const = 0;
+ virtual bool addressForRVA(uint32_t RVA, uint32_t &Section,
+ uint32_t &Offset) const = 0;
+
template <typename T>
std::unique_ptr<T> getConcreteSymbolById(uint32_t SymbolId) const {
return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId));
@@ -39,12 +44,22 @@ public:
virtual std::unique_ptr<PDBSymbol>
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0;
+ virtual std::unique_ptr<PDBSymbol>
+ findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const = 0;
+ virtual std::unique_ptr<PDBSymbol>
+ findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+ PDB_SymType Type) const = 0;
virtual std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland,
const IPDBSourceFile &File) const = 0;
virtual std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0;
+ virtual std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const = 0;
+ virtual std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const = 0;
virtual std::unique_ptr<IPDBEnumSourceFiles>
findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern,
@@ -69,8 +84,14 @@ public:
virtual std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const = 0;
virtual std::unique_ptr<IPDBEnumTables> getEnumTables() const = 0;
+
+ virtual std::unique_ptr<IPDBEnumInjectedSources>
+ getInjectedSources() const = 0;
+
+ virtual std::unique_ptr<IPDBEnumSectionContribs>
+ getSectionContribs() const = 0;
};
-}
-}
+} // namespace pdb
+} // namespace llvm
#endif
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
index 8200f51e3da9..9eef4041d0a1 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
@@ -47,6 +47,8 @@ public:
uint32_t getRecordLength() const;
+ const SectionContrib &getSectionContrib() const;
+
private:
StringRef ModuleName;
StringRef ObjFileName;
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
index c918a5d5e976..ce4d07917755 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
@@ -49,6 +49,7 @@ public:
void setPdbFilePathNI(uint32_t NI);
void setObjFileName(StringRef Name);
+ void setFirstSectionContrib(const SectionContrib &SC);
void addSymbol(codeview::CVSymbol Symbol);
void
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h
index 4be113f28d6f..280615bdb507 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h
@@ -38,9 +38,9 @@ class DbiStream {
friend class DbiStreamBuilder;
public:
- DbiStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream);
+ explicit DbiStream(std::unique_ptr<BinaryStream> Stream);
~DbiStream();
- Error reload();
+ Error reload(PDBFile *Pdb);
PdbRaw_DbiVer getDbiVersion() const;
uint32_t getAge() const;
@@ -63,6 +63,8 @@ public:
PDB_Machine getMachineType() const;
+ const DbiStreamHeader *getHeader() const { return Header; }
+
BinarySubstreamRef getSectionContributionData() const;
BinarySubstreamRef getSecMapSubstreamData() const;
BinarySubstreamRef getModiSubstreamData() const;
@@ -87,12 +89,11 @@ public:
private:
Error initializeSectionContributionData();
- Error initializeSectionHeadersData();
+ Error initializeSectionHeadersData(PDBFile *Pdb);
Error initializeSectionMapData();
- Error initializeFpoRecords();
+ Error initializeFpoRecords(PDBFile *Pdb);
- PDBFile &Pdb;
- std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::unique_ptr<BinaryStream> Stream;
PDBStringTable ECNames;
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
index ad4a0d1bcb6b..51befcdac775 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Support/Error.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
@@ -46,10 +47,12 @@ public:
void setVersionHeader(PdbRaw_DbiVer V);
void setAge(uint32_t A);
void setBuildNumber(uint16_t B);
+ void setBuildNumber(uint8_t Major, uint8_t Minor);
void setPdbDllVersion(uint16_t V);
void setPdbDllRbld(uint16_t R);
void setFlags(uint16_t F);
void setMachineType(PDB_Machine M);
+ void setMachineType(COFF::MachineTypes M);
void setSectionMap(ArrayRef<SecMapEntry> SecMap);
// Add given bytes as a new stream.
@@ -121,7 +124,7 @@ private:
MutableBinaryByteStream FileInfoBuffer;
std::vector<SectionContrib> SectionContribs;
ArrayRef<SecMapEntry> SectionMap;
- llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams;
+ std::array<Optional<DebugStream>, (int)DbgHeaderType::Max> DbgStreams;
};
}
}
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h
index 05c70c4f2175..34cc6179688b 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h
@@ -12,6 +12,9 @@
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
@@ -26,80 +29,303 @@ class BinaryStreamWriter;
namespace pdb {
-class HashTableIterator;
+Error readSparseBitVector(BinaryStreamReader &Stream, SparseBitVector<> &V);
+Error writeSparseBitVector(BinaryStreamWriter &Writer, SparseBitVector<> &Vec);
+template <typename ValueT, typename TraitsT> class HashTable;
+
+template <typename ValueT, typename TraitsT>
+class HashTableIterator
+ : public iterator_facade_base<HashTableIterator<ValueT, TraitsT>,
+ std::forward_iterator_tag,
+ std::pair<uint32_t, ValueT>> {
+ friend HashTable<ValueT, TraitsT>;
+
+ HashTableIterator(const HashTable<ValueT, TraitsT> &Map, uint32_t Index,
+ bool IsEnd)
+ : Map(&Map), Index(Index), IsEnd(IsEnd) {}
+
+public:
+ HashTableIterator(const HashTable<ValueT, TraitsT> &Map) : Map(&Map) {
+ int I = Map.Present.find_first();
+ if (I == -1) {
+ Index = 0;
+ IsEnd = true;
+ } else {
+ Index = static_cast<uint32_t>(I);
+ IsEnd = false;
+ }
+ }
+
+ HashTableIterator &operator=(const HashTableIterator &R) {
+ Map = R.Map;
+ return *this;
+ }
+ bool operator==(const HashTableIterator &R) const {
+ if (IsEnd && R.IsEnd)
+ return true;
+ if (IsEnd != R.IsEnd)
+ return false;
+
+ return (Map == R.Map) && (Index == R.Index);
+ }
+ const std::pair<uint32_t, ValueT> &operator*() const {
+ assert(Map->Present.test(Index));
+ return Map->Buckets[Index];
+ }
+ HashTableIterator &operator++() {
+ while (Index < Map->Buckets.size()) {
+ ++Index;
+ if (Map->Present.test(Index))
+ return *this;
+ }
+
+ IsEnd = true;
+ return *this;
+ }
+
+private:
+ bool isEnd() const { return IsEnd; }
+ uint32_t index() const { return Index; }
+
+ const HashTable<ValueT, TraitsT> *Map;
+ uint32_t Index;
+ bool IsEnd;
+};
+
+template <typename T> struct PdbHashTraits {};
+
+template <> struct PdbHashTraits<uint32_t> {
+ uint32_t hashLookupKey(uint32_t N) const { return N; }
+ uint32_t storageKeyToLookupKey(uint32_t N) const { return N; }
+ uint32_t lookupKeyToStorageKey(uint32_t N) { return N; }
+};
+
+template <typename ValueT, typename TraitsT = PdbHashTraits<ValueT>>
class HashTable {
- friend class HashTableIterator;
+ using iterator = HashTableIterator<ValueT, TraitsT>;
+ friend iterator;
struct Header {
support::ulittle32_t Size;
support::ulittle32_t Capacity;
};
- using BucketList = std::vector<std::pair<uint32_t, uint32_t>>;
+ using BucketList = std::vector<std::pair<uint32_t, ValueT>>;
public:
- HashTable();
- explicit HashTable(uint32_t Capacity);
+ HashTable() { Buckets.resize(8); }
+
+ explicit HashTable(TraitsT Traits) : HashTable(8, std::move(Traits)) {}
+ HashTable(uint32_t Capacity, TraitsT Traits) : Traits(Traits) {
+ Buckets.resize(Capacity);
+ }
+
+ Error load(BinaryStreamReader &Stream) {
+ const Header *H;
+ if (auto EC = Stream.readObject(H))
+ return EC;
+ if (H->Capacity == 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid Hash Table Capacity");
+ if (H->Size > maxLoad(H->Capacity))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid Hash Table Size");
+
+ Buckets.resize(H->Capacity);
+
+ if (auto EC = readSparseBitVector(Stream, Present))
+ return EC;
+ if (Present.count() != H->Size)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Present bit vector does not match size!");
+
+ if (auto EC = readSparseBitVector(Stream, Deleted))
+ return EC;
+ if (Present.intersects(Deleted))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Present bit vector interesects deleted!");
- Error load(BinaryStreamReader &Stream);
+ for (uint32_t P : Present) {
+ if (auto EC = Stream.readInteger(Buckets[P].first))
+ return EC;
+ const ValueT *Value;
+ if (auto EC = Stream.readObject(Value))
+ return EC;
+ Buckets[P].second = *Value;
+ }
- uint32_t calculateSerializedLength() const;
- Error commit(BinaryStreamWriter &Writer) const;
+ return Error::success();
+ }
- void clear();
+ uint32_t calculateSerializedLength() const {
+ uint32_t Size = sizeof(Header);
- uint32_t capacity() const;
- uint32_t size() const;
+ constexpr int BitsPerWord = 8 * sizeof(uint32_t);
- HashTableIterator begin() const;
- HashTableIterator end() const;
- HashTableIterator find(uint32_t K);
+ int NumBitsP = Present.find_last() + 1;
+ int NumBitsD = Deleted.find_last() + 1;
- void set(uint32_t K, uint32_t V);
- void remove(uint32_t K);
- uint32_t get(uint32_t K);
+ uint32_t NumWordsP = alignTo(NumBitsP, BitsPerWord) / BitsPerWord;
+ uint32_t NumWordsD = alignTo(NumBitsD, BitsPerWord) / BitsPerWord;
+
+ // Present bit set number of words (4 bytes), followed by that many actual
+ // words (4 bytes each).
+ Size += sizeof(uint32_t);
+ Size += NumWordsP * sizeof(uint32_t);
+
+ // Deleted bit set number of words (4 bytes), followed by that many actual
+ // words (4 bytes each).
+ Size += sizeof(uint32_t);
+ Size += NumWordsD * sizeof(uint32_t);
+
+ // One (Key, ValueT) pair for each entry Present.
+ Size += (sizeof(uint32_t) + sizeof(ValueT)) * size();
+
+ return Size;
+ }
+
+ Error commit(BinaryStreamWriter &Writer) const {
+ Header H;
+ H.Size = size();
+ H.Capacity = capacity();
+ if (auto EC = Writer.writeObject(H))
+ return EC;
+
+ if (auto EC = writeSparseBitVector(Writer, Present))
+ return EC;
+
+ if (auto EC = writeSparseBitVector(Writer, Deleted))
+ return EC;
+
+ for (const auto &Entry : *this) {
+ if (auto EC = Writer.writeInteger(Entry.first))
+ return EC;
+ if (auto EC = Writer.writeObject(Entry.second))
+ return EC;
+ }
+ return Error::success();
+ }
+
+ void clear() {
+ Buckets.resize(8);
+ Present.clear();
+ Deleted.clear();
+ }
+
+ bool empty() const { return size() == 0; }
+ uint32_t capacity() const { return Buckets.size(); }
+ uint32_t size() const { return Present.count(); }
+
+ iterator begin() const { return iterator(*this); }
+ iterator end() const { return iterator(*this, 0, true); }
+
+ /// Find the entry whose key has the specified hash value, using the specified
+ /// traits defining hash function and equality.
+ template <typename Key> iterator find_as(const Key &K) const {
+ uint32_t H = Traits.hashLookupKey(K) % capacity();
+ uint32_t I = H;
+ Optional<uint32_t> FirstUnused;
+ do {
+ if (isPresent(I)) {
+ if (Traits.storageKeyToLookupKey(Buckets[I].first) == K)
+ return iterator(*this, I, false);
+ } else {
+ if (!FirstUnused)
+ FirstUnused = I;
+ // Insertion occurs via linear probing from the slot hint, and will be
+ // inserted at the first empty / deleted location. Therefore, if we are
+ // probing and find a location that is neither present nor deleted, then
+ // nothing must have EVER been inserted at this location, and thus it is
+ // not possible for a matching value to occur later.
+ if (!isDeleted(I))
+ break;
+ }
+ I = (I + 1) % capacity();
+ } while (I != H);
+
+ // The only way FirstUnused would not be set is if every single entry in the
+ // table were Present. But this would violate the load factor constraints
+ // that we impose, so it should never happen.
+ assert(FirstUnused);
+ return iterator(*this, *FirstUnused, true);
+ }
+
+ /// Set the entry using a key type that the specified Traits can convert
+ /// from a real key to an internal key.
+ template <typename Key> bool set_as(const Key &K, ValueT V) {
+ return set_as_internal(K, std::move(V), None);
+ }
+
+ template <typename Key> ValueT get(const Key &K) const {
+ auto Iter = find_as(K);
+ assert(Iter != end());
+ return (*Iter).second;
+ }
protected:
bool isPresent(uint32_t K) const { return Present.test(K); }
bool isDeleted(uint32_t K) const { return Deleted.test(K); }
+ TraitsT Traits;
BucketList Buckets;
mutable SparseBitVector<> Present;
mutable SparseBitVector<> Deleted;
private:
- static uint32_t maxLoad(uint32_t capacity);
- void grow();
+ /// Set the entry using a key type that the specified Traits can convert
+ /// from a real key to an internal key.
+ template <typename Key>
+ bool set_as_internal(const Key &K, ValueT V, Optional<uint32_t> InternalKey) {
+ auto Entry = find_as(K);
+ if (Entry != end()) {
+ assert(isPresent(Entry.index()));
+ assert(Traits.storageKeyToLookupKey(Buckets[Entry.index()].first) == K);
+ // We're updating, no need to do anything special.
+ Buckets[Entry.index()].second = V;
+ return false;
+ }
- static Error readSparseBitVector(BinaryStreamReader &Stream,
- SparseBitVector<> &V);
- static Error writeSparseBitVector(BinaryStreamWriter &Writer,
- SparseBitVector<> &Vec);
-};
+ auto &B = Buckets[Entry.index()];
+ assert(!isPresent(Entry.index()));
+ assert(Entry.isEnd());
+ B.first = InternalKey ? *InternalKey : Traits.lookupKeyToStorageKey(K);
+ B.second = V;
+ Present.set(Entry.index());
+ Deleted.reset(Entry.index());
-class HashTableIterator
- : public iterator_facade_base<HashTableIterator, std::forward_iterator_tag,
- std::pair<uint32_t, uint32_t>> {
- friend class HashTable;
+ grow();
- HashTableIterator(const HashTable &Map, uint32_t Index, bool IsEnd);
+ assert((find_as(K)) != end());
+ return true;
+ }
-public:
- HashTableIterator(const HashTable &Map);
+ static uint32_t maxLoad(uint32_t capacity) { return capacity * 2 / 3 + 1; }
- HashTableIterator &operator=(const HashTableIterator &R);
- bool operator==(const HashTableIterator &R) const;
- const std::pair<uint32_t, uint32_t> &operator*() const;
- HashTableIterator &operator++();
+ void grow() {
+ uint32_t S = size();
+ uint32_t MaxLoad = maxLoad(capacity());
+ if (S < maxLoad(capacity()))
+ return;
+ assert(capacity() != UINT32_MAX && "Can't grow Hash table!");
-private:
- bool isEnd() const { return IsEnd; }
- uint32_t index() const { return Index; }
+ uint32_t NewCapacity = (capacity() <= INT32_MAX) ? MaxLoad * 2 : UINT32_MAX;
- const HashTable *Map;
- uint32_t Index;
- bool IsEnd;
+ // Growing requires rebuilding the table and re-hashing every item. Make a
+ // copy with a larger capacity, insert everything into the copy, then swap
+ // it in.
+ HashTable NewMap(NewCapacity, Traits);
+ for (auto I : Present) {
+ auto LookupKey = Traits.storageKeyToLookupKey(Buckets[I].first);
+ NewMap.set_as_internal(LookupKey, Buckets[I].second, Buckets[I].first);
+ }
+
+ Buckets.swap(NewMap.Buckets);
+ std::swap(Present, NewMap.Present);
+ std::swap(Deleted, NewMap.Deleted);
+ assert(capacity() == NewCapacity);
+ assert(size() == S);
+ }
};
} // end namespace pdb
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h
index fb8271cb5ebc..8c52b042f289 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h
@@ -30,12 +30,14 @@ class InfoStream {
friend class InfoStreamBuilder;
public:
- InfoStream(std::unique_ptr<msf::MappedBlockStream> Stream);
+ InfoStream(std::unique_ptr<BinaryStream> Stream);
Error reload();
uint32_t getStreamSize() const;
+ const InfoStreamHeader *getHeader() const { return Header; }
+
bool containsIdStream() const;
PdbRaw_ImplVer getVersion() const;
uint32_t getSignature() const;
@@ -50,29 +52,13 @@ public:
BinarySubstreamRef getNamedStreamsBuffer() const;
- uint32_t getNamedStreamIndex(llvm::StringRef Name) const;
- iterator_range<StringMapConstIterator<uint32_t>> named_streams() const;
+ Expected<uint32_t> getNamedStreamIndex(llvm::StringRef Name) const;
+ StringMap<uint32_t> named_streams() const;
private:
- std::unique_ptr<msf::MappedBlockStream> Stream;
-
- // PDB file format version. We only support VC70. See the enumeration
- // `PdbRaw_ImplVer` for the other possible values.
- uint32_t Version;
-
- // A 32-bit signature unique across all PDBs. This is generated with
- // a call to time() when the PDB is written, but obviously this is not
- // universally unique.
- uint32_t Signature;
-
- // The number of times the PDB has been written. Might also be used to
- // ensure that the PDB matches the executable.
- uint32_t Age;
+ std::unique_ptr<BinaryStream> Stream;
- // Due to the aforementioned limitations with `Signature`, this is a new
- // signature present on VC70 and higher PDBs which is guaranteed to be
- // universally unique.
- codeview::GUID Guid;
+ const InfoStreamHeader *Header;
BinarySubstreamRef SubNamedStreams;
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h
index c6cb0e221e70..419e8ada06f7 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h
@@ -40,6 +40,10 @@ public:
void setGuid(codeview::GUID G);
void addFeature(PdbRaw_FeatureSig Sig);
+ uint32_t getAge() const { return Age; }
+ codeview::GUID getGuid() const { return Guid; }
+ Optional<uint32_t> getSignature() const { return Signature; }
+
uint32_t finalize();
Error finalizeMsfLayout();
@@ -52,8 +56,8 @@ private:
std::vector<PdbRaw_FeatureSig> Features;
PdbRaw_ImplVer Ver;
- uint32_t Sig;
uint32_t Age;
+ Optional<uint32_t> Signature;
codeview::GUID Guid;
NamedStreamMap &NamedStreams;
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
index 17a82b7ce12d..01b8f1b5da56 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
@@ -25,32 +25,45 @@ class BinaryStreamWriter;
namespace pdb {
+class NamedStreamMap;
+
+struct NamedStreamMapTraits {
+ NamedStreamMap *NS;
+
+ explicit NamedStreamMapTraits(NamedStreamMap &NS);
+ uint16_t hashLookupKey(StringRef S) const;
+ StringRef storageKeyToLookupKey(uint32_t Offset) const;
+ uint32_t lookupKeyToStorageKey(StringRef S);
+};
+
class NamedStreamMap {
friend class NamedStreamMapBuilder;
- struct FinalizationInfo {
- uint32_t StringDataBytes = 0;
- uint32_t SerializedLength = 0;
- };
-
public:
NamedStreamMap();
Error load(BinaryStreamReader &Stream);
Error commit(BinaryStreamWriter &Writer) const;
- uint32_t finalize();
+ uint32_t calculateSerializedLength() const;
uint32_t size() const;
bool get(StringRef Stream, uint32_t &StreamNo) const;
void set(StringRef Stream, uint32_t StreamNo);
- void remove(StringRef Stream);
- const StringMap<uint32_t> &getStringMap() const { return Mapping; }
- iterator_range<StringMapConstIterator<uint32_t>> entries() const;
+
+ uint32_t appendStringData(StringRef S);
+ StringRef getString(uint32_t Offset) const;
+ uint32_t hashString(uint32_t Offset) const;
+
+ StringMap<uint32_t> entries() const;
private:
- Optional<FinalizationInfo> FinalizedInfo;
- HashTable FinalizedHashTable;
- StringMap<uint32_t> Mapping;
+ NamedStreamMapTraits HashTraits;
+ /// Closed hash table from Offset -> StreamNumber, where Offset is the offset
+ /// of the stream name in NamesBuffer.
+ HashTable<support::ulittle32_t, NamedStreamMapTraits> OffsetIndexMap;
+
+ /// Buffer of string data.
+ std::vector<char> NamesBuffer;
};
} // end namespace pdb
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
index 931b93fb7266..5b70ecfa2056 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
@@ -35,10 +35,31 @@ public:
findChildren(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags) const override;
std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByAddr(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags,
+ uint32_t Section, uint32_t Offset) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
+ uint64_t VA) const override;
+ std::unique_ptr<IPDBEnumSymbols>
findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
uint32_t RVA) const override;
+
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const override;
std::unique_ptr<IPDBEnumSymbols>
findInlineFramesByRVA(uint32_t RVA) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByVA(uint64_t VA) const override;
+
+ std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override;
void getDataBytes(SmallVector<uint8_t, 32> &Bytes) const override;
void getFrontEndVersion(VersionInfo &Version) const override;
@@ -87,6 +108,7 @@ public:
uint32_t getSizeInUdt() const override;
uint32_t getSlot() const override;
std::string getSourceFileName() const override;
+ std::unique_ptr<IPDBLineNumber> getSrcLineOnTypeDefn() const override;
uint32_t getStride() const override;
uint32_t getSubTypeId() const override;
std::string getSymbolsFileName() const override;
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
index 2e68ced46bfe..aff7ef2f8f21 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
@@ -49,18 +49,33 @@ public:
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
uint64_t getLoadAddress() const override;
- void setLoadAddress(uint64_t Address) override;
+ bool setLoadAddress(uint64_t Address) override;
std::unique_ptr<PDBSymbolExe> getGlobalScope() override;
std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
+ bool addressForVA(uint64_t VA, uint32_t &Section,
+ uint32_t &Offset) const override;
+ bool addressForRVA(uint32_t RVA, uint32_t &Section,
+ uint32_t &Offset) const override;
+
std::unique_ptr<PDBSymbol>
findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+ std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
+ PDB_SymType Type) const override;
+ std::unique_ptr<PDBSymbol>
+ findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+ PDB_SymType Type) const override;
std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland,
const IPDBSourceFile &File) const override;
std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const override;
std::unique_ptr<IPDBEnumSourceFiles>
findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern,
@@ -85,6 +100,10 @@ public:
std::unique_ptr<IPDBEnumTables> getEnumTables() const override;
+ std::unique_ptr<IPDBEnumInjectedSources> getInjectedSources() const override;
+
+ std::unique_ptr<IPDBEnumSectionContribs> getSectionContribs() const override;
+
PDBFile &getPDBFile() { return *Pdb; }
const PDBFile &getPDBFile() const { return *Pdb; }
@@ -94,7 +113,7 @@ private:
std::vector<std::unique_ptr<NativeRawSymbol>> SymbolCache;
DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
};
-}
-}
+} // namespace pdb
+} // namespace llvm
#endif
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
index 7ed164bee9ee..7f9c4cf9fa83 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
@@ -17,9 +17,11 @@
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
#include <memory>
#include <vector>
@@ -54,12 +56,34 @@ public:
Error commit(StringRef Filename);
Expected<uint32_t> getNamedStreamIndex(StringRef Name) const;
- Error addNamedStream(StringRef Name, uint32_t Size);
+ Error addNamedStream(StringRef Name, StringRef Data);
+ void addInjectedSource(StringRef Name, std::unique_ptr<MemoryBuffer> Buffer);
private:
- Expected<msf::MSFLayout> finalizeMsfLayout();
+ struct InjectedSourceDescriptor {
+ // The full name of the stream that contains the contents of this injected
+ // source. This is built as a concatenation of the literal "/src/files"
+ // plus the "vname".
+ std::string StreamName;
+
+ // The exact name of the file name as specified by the user.
+ uint32_t NameIndex;
+
+ // The string table index of the "vname" of the file. As far as we
+ // understand, this is the same as the name, except it is lowercased and
+ // forward slashes are converted to backslashes.
+ uint32_t VNameIndex;
+ std::unique_ptr<MemoryBuffer> Content;
+ };
+
+ Error finalizeMsfLayout();
+ Expected<uint32_t> allocateNamedStream(StringRef Name, uint32_t Size);
void commitFpm(WritableBinaryStream &MsfBuffer, const msf::MSFLayout &Layout);
+ void commitInjectedSources(WritableBinaryStream &MsfBuffer,
+ const msf::MSFLayout &Layout);
+ void commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
+ const msf::MSFLayout &Layout);
BumpPtrAllocator &Allocator;
@@ -71,7 +95,13 @@ private:
std::unique_ptr<TpiStreamBuilder> Ipi;
PDBStringTableBuilder Strings;
+ StringTableHashTraits InjectedSourceHashTraits;
+ HashTable<SrcHeaderBlockEntry, StringTableHashTraits> InjectedSourceTable;
+
+ SmallVector<InjectedSourceDescriptor, 2> InjectedSources;
+
NamedStreamMap NamedStreams;
+ DenseMap<uint32_t, std::string> NamedStreamData;
};
}
}
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
index b57707ee7923..0f81c18eafe6 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
@@ -31,6 +31,16 @@ struct MSFLayout;
namespace pdb {
class PDBFileBuilder;
+class PDBStringTableBuilder;
+
+struct StringTableHashTraits {
+ PDBStringTableBuilder *Table;
+
+ explicit StringTableHashTraits(PDBStringTableBuilder &Table);
+ uint32_t hashLookupKey(StringRef S) const;
+ StringRef storageKeyToLookupKey(uint32_t Offset) const;
+ uint32_t lookupKeyToStorageKey(StringRef S);
+};
class PDBStringTableBuilder {
public:
@@ -38,6 +48,9 @@ public:
// Returns the ID for S.
uint32_t insert(StringRef S);
+ uint32_t getIdForString(StringRef S) const;
+ StringRef getStringForId(uint32_t Id) const;
+
uint32_t calculateSerializedSize() const;
Error commit(BinaryStreamWriter &Writer) const;
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h
index bb1d097b5123..fbbd3318d958 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h
@@ -32,6 +32,8 @@ enum PdbRaw_ImplVer : uint32_t {
PdbImplVC140 = 20140508,
};
+enum class PdbRaw_SrcHeaderBlockVer : uint32_t { SrcVerOne = 19980827 };
+
enum class PdbRaw_FeatureSig : uint32_t {
VC110 = PdbImplVC110,
VC140 = PdbImplVC140,
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h
index 8cc083685265..19f592d562e4 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h
@@ -112,6 +112,8 @@ struct DbiBuildNo {
static const uint16_t BuildMajorMask = 0x7F00;
static const uint16_t BuildMajorShift = 8;
+
+ static const uint16_t NewVersionFormatMask = 0x8000;
};
/// The fixed size header that appears at the beginning of the DBI Stream.
@@ -175,18 +177,6 @@ struct DbiStreamHeader {
};
static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!");
-struct SectionContribEntry {
- support::ulittle16_t Section;
- char Padding1[2];
- support::little32_t Offset;
- support::little32_t Size;
- support::ulittle32_t Characteristics;
- support::ulittle16_t ModuleIndex;
- char Padding2[2];
- support::ulittle32_t DataCrc;
- support::ulittle32_t RelocCrc;
-};
-
/// The header preceeding the File Info Substream of the DBI stream.
struct FileInfoSubstreamHeader {
/// Total # of modules, should match number of records in the ModuleInfo
@@ -228,7 +218,7 @@ struct ModuleInfoHeader {
support::ulittle32_t Mod;
/// First section contribution of this module.
- SectionContribEntry SC;
+ SectionContrib SC;
/// See ModInfoFlags definition.
support::ulittle16_t Flags;
@@ -328,6 +318,34 @@ struct PDBStringTableHeader {
const uint32_t PDBStringTableSignature = 0xEFFEEFFE;
+/// The header preceding the /src/headerblock stream.
+struct SrcHeaderBlockHeader {
+ support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration.
+ support::ulittle32_t Size; // Size of entire stream.
+ uint64_t FileTime; // Time stamp (Windows FILETIME format).
+ support::ulittle32_t Age; // Age
+ uint8_t Padding[44]; // Pad to 64 bytes.
+};
+static_assert(sizeof(SrcHeaderBlockHeader) == 64, "Incorrect struct size!");
+
+/// A single file record entry within the /src/headerblock stream.
+struct SrcHeaderBlockEntry {
+ support::ulittle32_t Size; // Record Length.
+ support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration.
+ support::ulittle32_t CRC; // CRC of the original file contents.
+ support::ulittle32_t FileSize; // Size of original source file.
+ support::ulittle32_t FileNI; // String table index of file name.
+ support::ulittle32_t ObjNI; // String table index of object name.
+ support::ulittle32_t VFileNI; // String table index of virtual file name.
+ uint8_t Compression; // PDB_SourceCompression enumeration.
+ uint8_t IsVirtual; // Is this a virtual file (injected)?
+ short Padding; // Pad to 4 bytes.
+ char Reserved[8];
+};
+
+constexpr int I = sizeof(SrcHeaderBlockEntry);
+static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!");
+
} // namespace pdb
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h
index d3475205a6c2..b77939929ecf 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h
@@ -51,7 +51,7 @@ public:
uint32_t getNumHashBuckets() const;
FixedStreamArray<support::ulittle32_t> getHashValues() const;
FixedStreamArray<codeview::TypeIndexOffset> getTypeIndexOffsets() const;
- HashTable &getHashAdjusters();
+ HashTable<support::ulittle32_t> &getHashAdjusters();
codeview::CVTypeRange types(bool *HadError) const;
const codeview::CVTypeArray &typeArray() const { return TypeRecords; }
@@ -75,7 +75,7 @@ private:
std::unique_ptr<BinaryStream> HashStream;
FixedStreamArray<support::ulittle32_t> HashValues;
FixedStreamArray<codeview::TypeIndexOffset> TypeIndexOffsets;
- HashTable HashAdjusters;
+ HashTable<support::ulittle32_t> HashAdjusters;
const TpiStreamHeader *Header;
};
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h
index 778121c8eb79..3c9a19801f89 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h
@@ -34,6 +34,8 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag);
raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access);
raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type);
raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine);
+raw_ostream &operator<<(raw_ostream &OS,
+ const PDB_SourceCompression &Compression);
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version);
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
index 26788017cf32..9549089c7eb4 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
@@ -34,6 +34,7 @@ public:
FORWARD_SYMBOL_METHOD(getName)
std::string getSourceFileName() const;
+ std::string getSourceFileFullPath() const;
};
}
}
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h
index ad4285df4d44..76b14bf17784 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H
#define LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H
+#include "IPDBLineNumber.h"
#include "PDBSymbol.h"
#include "PDBTypes.h"
@@ -53,9 +54,11 @@ public:
FORWARD_SYMBOL_METHOD(getValue)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
FORWARD_SYMBOL_METHOD(isVolatileType)
-};
+ std::unique_ptr<IPDBEnumLineNumbers> getLineNumbers() const;
+ uint32_t getCompilandId() const;
+};
+} // namespace pdb
} // namespace llvm
-}
#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
index c2f02ea6f126..05d585d25763 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H
#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H
+#include "IPDBLineNumber.h"
#include "PDBSymbol.h"
#include "PDBSymbolTypeFunctionSig.h"
#include "PDBTypes.h"
@@ -38,7 +39,9 @@ public:
FORWARD_SYMBOL_METHOD(getAddressSection)
FORWARD_SYMBOL_ID_METHOD(getClassParent)
FORWARD_SYMBOL_METHOD(isCompilerGenerated)
+ FORWARD_SYMBOL_METHOD(isConstructorVirtualBase)
FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(isCxxReturnUdt)
FORWARD_SYMBOL_METHOD(hasCustomCallingConvention)
FORWARD_SYMBOL_METHOD(hasFarReturn)
FORWARD_SYMBOL_METHOD(hasAlloca)
@@ -76,6 +79,9 @@ public:
FORWARD_SYMBOL_METHOD(getVirtualAddress)
FORWARD_SYMBOL_METHOD(getVirtualBaseOffset)
FORWARD_SYMBOL_METHOD(isVolatileType)
+
+ std::unique_ptr<IPDBEnumLineNumbers> getLineNumbers() const;
+ uint32_t getCompilandId() const;
};
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
index c5ae3c51162c..ddbe7e58f183 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H
#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H
+#include "IPDBLineNumber.h"
#include "PDBSymbol.h"
#include "PDBSymbolTypeBuiltin.h"
#include "PDBTypes.h"
@@ -38,6 +39,7 @@ public:
FORWARD_SYMBOL_METHOD(getLength)
FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSrcLineOnTypeDefn)
FORWARD_SYMBOL_METHOD(isNested)
FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
FORWARD_SYMBOL_METHOD(isPacked)
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
index 8de54e70701d..abd4cf5effa2 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
@@ -31,6 +31,8 @@ public:
void dumpRight(PDBSymDumper &Dumper) const override;
void dumpArgList(raw_ostream &OS) const;
+ bool isCVarArgs() const;
+
FORWARD_SYMBOL_METHOD(getCallingConvention)
FORWARD_SYMBOL_ID_METHOD(getClassParent)
FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType)
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
index c502d4e77afe..7612ebac31dd 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
@@ -32,7 +32,11 @@ public:
FORWARD_SYMBOL_METHOD(getLength)
FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(isReference)
+ FORWARD_SYMBOL_METHOD(isRValueReference)
+ FORWARD_SYMBOL_METHOD(isPointerToDataMember)
+ FORWARD_SYMBOL_METHOD(isPointerToMemberFunction)
FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getPointeeType)
+ FORWARD_SYMBOL_METHOD(isRestrictedType)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
index e9e7fe8c9865..e259b6dca3d5 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
+#include "IPDBLineNumber.h"
#include "IPDBSession.h"
#include "PDBSymbol.h"
#include "PDBSymbolTypeBaseClass.h"
@@ -45,6 +46,7 @@ public:
FORWARD_SYMBOL_METHOD(getLength)
FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSrcLineOnTypeDefn)
FORWARD_SYMBOL_METHOD(isNested)
FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
FORWARD_SYMBOL_METHOD(isPacked)
@@ -53,6 +55,7 @@ public:
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape)
FORWARD_SYMBOL_METHOD(isVolatileType)
+ FORWARD_SYMBOL_METHOD(getAccess)
};
}
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h
index a6c6da37d1cc..da6cb1d26771 100644
--- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h
+++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h
@@ -23,7 +23,9 @@ namespace llvm {
namespace pdb {
class IPDBDataStream;
+class IPDBInjectedSource;
class IPDBLineNumber;
+class IPDBSectionContrib;
class IPDBSourceFile;
class IPDBTable;
class PDBSymDumper;
@@ -65,6 +67,8 @@ using IPDBEnumSourceFiles = IPDBEnumChildren<IPDBSourceFile>;
using IPDBEnumDataStreams = IPDBEnumChildren<IPDBDataStream>;
using IPDBEnumLineNumbers = IPDBEnumChildren<IPDBLineNumber>;
using IPDBEnumTables = IPDBEnumChildren<IPDBTable>;
+using IPDBEnumInjectedSources = IPDBEnumChildren<IPDBInjectedSource>;
+using IPDBEnumSectionContribs = IPDBEnumChildren<IPDBSectionContrib>;
/// Specifies which PDB reader implementation is to be used. Only a value
/// of PDB_ReaderType::DIA is currently supported, but Native is in the works.
@@ -96,13 +100,18 @@ enum PDB_NameSearchFlags {
NS_CaseInsensitive = 0x2,
NS_FileNameExtMatch = 0x4,
NS_Regex = 0x8,
- NS_UndecoratedName = 0x10
+ NS_UndecoratedName = 0x10,
+
+ // For backward compatibility.
+ NS_CaseInFileNameExt = NS_CaseInsensitive | NS_FileNameExtMatch,
+ NS_CaseRegex = NS_Regex | NS_CaseSensitive,
+ NS_CaseInRex = NS_Regex | NS_CaseInsensitive
};
/// 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 };
+enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2, SHA256 = 3 };
/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented
/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
@@ -133,6 +142,13 @@ enum class PDB_Machine {
WceMipsV2 = 0x169
};
+enum class PDB_SourceCompression {
+ None,
+ RunLengthEncoded,
+ Huffman,
+ LZ,
+};
+
/// 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
@@ -209,6 +225,7 @@ enum class PDB_LocType {
IlRel,
MetaData,
Constant,
+ RegRelAliasIndir,
Max
};
@@ -218,11 +235,24 @@ 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 };
+enum class PDB_StackFrameType : uint16_t {
+ FPO,
+ KernelTrap,
+ KernelTSS,
+ EBP,
+ FrameData,
+ Unknown = 0xffff
+};
-/// 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 MemoryTypeEnum enumeration, and are
+/// documented here: https://msdn.microsoft.com/en-us/library/ms165609.aspx.
+enum class PDB_MemoryType : uint16_t {
+ Code,
+ Data,
+ Stack,
+ HeapCode,
+ Any = 0xffff
+};
/// These values correspond to the Basictype enumeration, and are documented
/// here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx
@@ -244,13 +274,15 @@ enum class PDB_BuiltinType {
Complex = 28,
Bitfield = 29,
BSTR = 30,
- HResult = 31
+ HResult = 31,
+ Char16 = 32,
+ Char32 = 33
};
/// These values correspond to the flags that can be combined to control the
/// return of an undecorated name for a C++ decorated name, and are documented
/// here: https://msdn.microsoft.com/en-us/library/kszfk0fs.aspx
-enum PDB_UndnameFlags: uint32_t {
+enum PDB_UndnameFlags : uint32_t {
Undname_Complete = 0x0,
Undname_NoLeadingUnderscores = 0x1,
Undname_NoMsKeywords = 0x2,
diff --git a/contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
index 6480aef109c6..289148f569db 100644
--- a/contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -90,11 +90,11 @@ private:
const ObjectFile *Obj,
const std::string &ArchName);
- /// \brief Returns pair of pointers to object and debug object.
+ /// Returns pair of pointers to object and debug object.
Expected<ObjectPair> getOrCreateObjectPair(const std::string &Path,
const std::string &ArchName);
- /// \brief Return a pointer to object file at specified path, for a specified
+ /// Return a pointer to object file at specified path, for a specified
/// architecture (e.g. if path refers to a Mach-O universal binary, only one
/// object file from it will be returned).
Expected<ObjectFile *> getOrCreateObject(const std::string &Path,
@@ -102,14 +102,14 @@ private:
std::map<std::string, std::unique_ptr<SymbolizableModule>> Modules;
- /// \brief Contains cached results of getOrCreateObjectPair().
+ /// Contains cached results of getOrCreateObjectPair().
std::map<std::pair<std::string, std::string>, ObjectPair>
ObjectPairForPathArch;
- /// \brief Contains parsed binary for each path, or parsing error.
+ /// Contains parsed binary for each path, or parsing error.
std::map<std::string, OwningBinary<Binary>> BinaryForPath;
- /// \brief Parsed object file for path/architecture pair, where "path" refers
+ /// Parsed object file for path/architecture pair, where "path" refers
/// to Mach-O universal binary.
std::map<std::pair<std::string, std::string>, std::unique_ptr<ObjectFile>>
ObjectForUBPathAndArch;
diff --git a/contrib/llvm/include/llvm/Demangle/Demangle.h b/contrib/llvm/include/llvm/Demangle/Demangle.h
index d2eb56b39f9b..df7753f23b87 100644
--- a/contrib/llvm/include/llvm/Demangle/Demangle.h
+++ b/contrib/llvm/include/llvm/Demangle/Demangle.h
@@ -16,13 +16,73 @@ namespace llvm {
/// The mangled_name is demangled into buf and returned. If the buffer is not
/// large enough, realloc is used to expand it.
///
-/// The *status will be set to
-/// unknown_error: -4
-/// invalid_args: -3
-/// invalid_mangled_name: -2
-/// memory_alloc_failure: -1
-/// success: 0
+/// The *status will be set to a value from the following enumeration
+enum : int {
+ demangle_unknown_error = -4,
+ demangle_invalid_args = -3,
+ demangle_invalid_mangled_name = -2,
+ demangle_memory_alloc_failure = -1,
+ demangle_success = 0,
+};
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
int *status);
-}
+char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
+ int *status);
+
+/// "Partial" demangler. This supports demangling a string into an AST
+/// (typically an intermediate stage in itaniumDemangle) and querying certain
+/// properties or partially printing the demangled name.
+struct ItaniumPartialDemangler {
+ ItaniumPartialDemangler();
+
+ ItaniumPartialDemangler(ItaniumPartialDemangler &&Other);
+ ItaniumPartialDemangler &operator=(ItaniumPartialDemangler &&Other);
+
+ /// Demangle into an AST. Subsequent calls to the rest of the member functions
+ /// implicitly operate on the AST this produces.
+ /// \return true on error, false otherwise
+ bool partialDemangle(const char *MangledName);
+
+ /// Just print the entire mangled name into Buf. Buf and N behave like the
+ /// second and third parameters to itaniumDemangle.
+ char *finishDemangle(char *Buf, size_t *N) const;
+
+ /// Get the base name of a function. This doesn't include trailing template
+ /// arguments, ie for "a::b<int>" this function returns "b".
+ char *getFunctionBaseName(char *Buf, size_t *N) const;
+
+ /// Get the context name for a function. For "a::b::c", this function returns
+ /// "a::b".
+ char *getFunctionDeclContextName(char *Buf, size_t *N) const;
+
+ /// Get the entire name of this function.
+ char *getFunctionName(char *Buf, size_t *N) const;
+
+ /// Get the parameters for this function.
+ char *getFunctionParameters(char *Buf, size_t *N) const;
+ char *getFunctionReturnType(char *Buf, size_t *N) const;
+
+ /// If this function has any any cv or reference qualifiers. These imply that
+ /// the function is a non-static member function.
+ bool hasFunctionQualifiers() const;
+
+ /// If this symbol describes a constructor or destructor.
+ bool isCtorOrDtor() const;
+
+ /// If this symbol describes a function.
+ bool isFunction() const;
+
+ /// If this symbol describes a variable.
+ bool isData() const;
+
+ /// If this symbol is a <special-name>. These are generally implicitly
+ /// generated by the implementation, such as vtables and typeinfo names.
+ bool isSpecialName() const;
+
+ ~ItaniumPartialDemangler();
+private:
+ void *RootNode;
+ void *Context;
+};
+} // namespace llvm
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h
index 77c23b46d320..b61cb24fa5fb 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -60,7 +60,7 @@ class ObjectFile;
} // end namespace object
-/// \brief Helper class for helping synchronize access to the global address map
+/// Helper class for helping synchronize access to the global address map
/// table. Access to this class should be serialized under a mutex.
class ExecutionEngineState {
public:
@@ -86,7 +86,7 @@ public:
return GlobalAddressReverseMap;
}
- /// \brief Erase an entry from the mapping table.
+ /// Erase an entry from the mapping table.
///
/// \returns The address that \p ToUnmap was happed to.
uint64_t RemoveMapping(StringRef Name);
@@ -94,7 +94,7 @@ public:
using FunctionCreator = std::function<void *(const std::string &)>;
-/// \brief Abstract interface for implementation execution of LLVM modules,
+/// Abstract interface for implementation execution of LLVM modules,
/// designed to support both interpreter and just-in-time (JIT) compiler
/// implementations.
class ExecutionEngine {
@@ -137,17 +137,15 @@ protected:
virtual char *getMemoryForGV(const GlobalVariable *GV);
static ExecutionEngine *(*MCJITCtor)(
- std::unique_ptr<Module> M,
- std::string *ErrorStr,
- std::shared_ptr<MCJITMemoryManager> MM,
- std::shared_ptr<JITSymbolResolver> SR,
- std::unique_ptr<TargetMachine> TM);
+ std::unique_ptr<Module> M, std::string *ErrorStr,
+ std::shared_ptr<MCJITMemoryManager> MM,
+ std::shared_ptr<LegacyJITSymbolResolver> SR,
+ std::unique_ptr<TargetMachine> TM);
static ExecutionEngine *(*OrcMCJITReplacementCtor)(
- std::string *ErrorStr,
- std::shared_ptr<MCJITMemoryManager> MM,
- std::shared_ptr<JITSymbolResolver> SR,
- std::unique_ptr<TargetMachine> TM);
+ std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MM,
+ std::shared_ptr<LegacyJITSymbolResolver> SR,
+ std::unique_ptr<TargetMachine> TM);
static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr);
@@ -532,7 +530,7 @@ private:
std::string *ErrorStr;
CodeGenOpt::Level OptLevel;
std::shared_ptr<MCJITMemoryManager> MemMgr;
- std::shared_ptr<JITSymbolResolver> Resolver;
+ std::shared_ptr<LegacyJITSymbolResolver> Resolver;
TargetOptions Options;
Optional<Reloc::Model> RelocModel;
Optional<CodeModel::Model> CMModel;
@@ -571,8 +569,7 @@ public:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
- EngineBuilder&
- setSymbolResolver(std::unique_ptr<JITSymbolResolver> SR);
+ EngineBuilder &setSymbolResolver(std::unique_ptr<LegacyJITSymbolResolver> SR);
/// setErrorStr - Set the error string to write to on error. This option
/// defaults to NULL.
@@ -637,7 +634,7 @@ public:
return *this;
}
- // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default.
+ // Use OrcMCJITReplacement instead of MCJIT. Off by default.
void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) {
this->UseOrcMCJITReplacement = UseOrcMCJITReplacement;
}
@@ -645,7 +642,7 @@ public:
void setEmulatedTLS(bool EmulatedTLS) {
this->EmulatedTLS = EmulatedTLS;
}
-
+
TargetMachine *selectTarget();
/// selectTarget - Pick a target either via -march or by guessing the native
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h b/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h
index ff7840f00a44..1ce772ccde95 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h
@@ -15,9 +15,11 @@
#ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
#define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
+#include "llvm-c/ExecutionEngine.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/Support/CBindingWrapping.h"
#include <cstdint>
#include <vector>
@@ -115,10 +117,21 @@ public:
}
#endif // USE_OPROFILE
+#if LLVM_USE_PERF
+ static JITEventListener *createPerfJITEventListener();
+#else
+ static JITEventListener *createPerfJITEventListener()
+ {
+ return nullptr;
+ }
+#endif // USE_PERF
+
private:
virtual void anchor();
};
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITEventListener, LLVMJITEventListenerRef)
+
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h b/contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h
index 933b3ea8e13d..53037c3dbc72 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h
@@ -19,8 +19,11 @@
#include <cstddef>
#include <cstdint>
#include <functional>
+#include <map>
+#include <set>
#include <string>
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -33,10 +36,10 @@ class BasicSymbolRef;
} // end namespace object
-/// @brief Represents an address in the target process's address space.
+/// Represents an address in the target process's address space.
using JITTargetAddress = uint64_t;
-/// @brief Flags for symbols in the JIT.
+/// Flags for symbols in the JIT.
class JITSymbolFlags {
public:
using UnderlyingType = uint8_t;
@@ -48,55 +51,74 @@ public:
Weak = 1U << 1,
Common = 1U << 2,
Absolute = 1U << 3,
- Exported = 1U << 4
+ Exported = 1U << 4,
+ Lazy = 1U << 5,
+ Materializing = 1U << 6
};
- /// @brief Default-construct a JITSymbolFlags instance.
+ static JITSymbolFlags stripTransientFlags(JITSymbolFlags Orig) {
+ return static_cast<FlagNames>(Orig.Flags & ~Lazy & ~Materializing);
+ }
+
+ /// Default-construct a JITSymbolFlags instance.
JITSymbolFlags() = default;
- /// @brief Construct a JITSymbolFlags instance from the given flags.
+ /// Construct a JITSymbolFlags instance from the given flags.
JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
- /// @brief Construct a JITSymbolFlags instance from the given flags and target
+ /// Construct a JITSymbolFlags instance from the given flags and target
/// flags.
JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
: Flags(Flags), TargetFlags(TargetFlags) {}
- /// @brief Return true if there was an error retrieving this symbol.
+ /// Return true if there was an error retrieving this symbol.
bool hasError() const {
return (Flags & HasError) == HasError;
}
- /// @brief Returns true if the Weak flag is set.
+ /// Returns true if this is a lazy symbol.
+ /// This flag is used internally by the JIT APIs to track
+ /// materialization states.
+ bool isLazy() const { return Flags & Lazy; }
+
+ /// Returns true if this symbol is in the process of being
+ /// materialized.
+ bool isMaterializing() const { return Flags & Materializing; }
+
+ /// Returns true if this symbol is fully materialized.
+ /// (i.e. neither lazy, nor materializing).
+ bool isMaterialized() const { return !(Flags & (Lazy | Materializing)); }
+
+ /// Returns true if the Weak flag is set.
bool isWeak() const {
return (Flags & Weak) == Weak;
}
- /// @brief Returns true if the Common flag is set.
+ /// Returns true if the Common flag is set.
bool isCommon() const {
return (Flags & Common) == Common;
}
- /// @brief Returns true if the symbol isn't weak or common.
- bool isStrongDefinition() const {
+ /// Returns true if the symbol isn't weak or common.
+ bool isStrong() const {
return !isWeak() && !isCommon();
}
- /// @brief Returns true if the Exported flag is set.
+ /// Returns true if the Exported flag is set.
bool isExported() const {
return (Flags & Exported) == Exported;
}
- /// @brief Implicitly convert to the underlying flags type.
+ /// Implicitly convert to the underlying flags type.
operator UnderlyingType&() { return Flags; }
- /// @brief Implicitly convert to the underlying flags type.
+ /// Implicitly convert to the underlying flags type.
operator const UnderlyingType&() const { return Flags; }
- /// @brief Return a reference to the target-specific flags.
+ /// Return a reference to the target-specific flags.
TargetFlagsType& getTargetFlags() { return TargetFlags; }
- /// @brief Return a reference to the target-specific flags.
+ /// Return a reference to the target-specific flags.
const TargetFlagsType& getTargetFlags() const { return TargetFlags; }
/// Construct a JITSymbolFlags value based on the flags of the given global
@@ -112,7 +134,7 @@ private:
TargetFlagsType TargetFlags = 0;
};
-/// @brief ARM-specific JIT symbol flags.
+/// ARM-specific JIT symbol flags.
/// FIXME: This should be moved into a target-specific header.
class ARMJITSymbolFlags {
public:
@@ -131,54 +153,59 @@ private:
JITSymbolFlags::TargetFlagsType Flags = 0;
};
-/// @brief Represents a symbol that has been evaluated to an address already.
+/// Represents a symbol that has been evaluated to an address already.
class JITEvaluatedSymbol {
public:
- /// @brief Create a 'null' symbol.
+ JITEvaluatedSymbol() = default;
+
+ /// Create a 'null' symbol.
JITEvaluatedSymbol(std::nullptr_t) {}
- /// @brief Create a symbol for the given address and flags.
+ /// Create a symbol for the given address and flags.
JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
: Address(Address), Flags(Flags) {}
- /// @brief An evaluated symbol converts to 'true' if its address is non-zero.
+ /// An evaluated symbol converts to 'true' if its address is non-zero.
explicit operator bool() const { return Address != 0; }
- /// @brief Return the address of this symbol.
+ /// Return the address of this symbol.
JITTargetAddress getAddress() const { return Address; }
- /// @brief Return the flags for this symbol.
+ /// Return the flags for this symbol.
JITSymbolFlags getFlags() const { return Flags; }
+ /// Set the flags for this symbol.
+ void setFlags(JITSymbolFlags Flags) { this->Flags = std::move(Flags); }
+
private:
JITTargetAddress Address = 0;
JITSymbolFlags Flags;
};
-/// @brief Represents a symbol in the JIT.
+/// Represents a symbol in the JIT.
class JITSymbol {
public:
using GetAddressFtor = std::function<Expected<JITTargetAddress>()>;
- /// @brief Create a 'null' symbol, used to represent a "symbol not found"
+ /// Create a 'null' symbol, used to represent a "symbol not found"
/// result from a successful (non-erroneous) lookup.
JITSymbol(std::nullptr_t)
: CachedAddr(0) {}
- /// @brief Create a JITSymbol representing an error in the symbol lookup
+ /// Create a JITSymbol representing an error in the symbol lookup
/// process (e.g. a network failure during a remote lookup).
JITSymbol(Error Err)
: Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
- /// @brief Create a symbol for a definition with a known address.
+ /// Create a symbol for a definition with a known address.
JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
: CachedAddr(Addr), Flags(Flags) {}
- /// @brief Construct a JITSymbol from a JITEvaluatedSymbol.
+ /// Construct a JITSymbol from a JITEvaluatedSymbol.
JITSymbol(JITEvaluatedSymbol Sym)
: CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
- /// @brief Create a symbol for a definition that doesn't have a known address
+ /// 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.
@@ -218,19 +245,19 @@ public:
CachedAddr.~JITTargetAddress();
}
- /// @brief Returns true if the symbol exists, false otherwise.
+ /// Returns true if the symbol exists, false otherwise.
explicit operator bool() const {
return !Flags.hasError() && (CachedAddr || GetAddress);
}
- /// @brief Move the error field value out of this JITSymbol.
+ /// Move the error field value out of this JITSymbol.
Error takeError() {
if (Flags.hasError())
return std::move(Err);
return Error::success();
}
- /// @brief Get the address of the symbol in the target address space. Returns
+ /// Get the address of the symbol in the target address space. Returns
/// '0' if the symbol does not exist.
Expected<JITTargetAddress> getAddress() {
assert(!Flags.hasError() && "getAddress called on error value");
@@ -256,11 +283,49 @@ private:
JITSymbolFlags Flags;
};
-/// \brief Symbol resolution.
+/// Symbol resolution interface.
+///
+/// Allows symbol flags and addresses to be looked up by name.
+/// Symbol queries are done in bulk (i.e. you request resolution of a set of
+/// symbols, rather than a single one) to reduce IPC overhead in the case of
+/// remote JITing, and expose opportunities for parallel compilation.
class JITSymbolResolver {
public:
+ using LookupSet = std::set<StringRef>;
+ using LookupResult = std::map<StringRef, JITEvaluatedSymbol>;
+ using LookupFlagsResult = std::map<StringRef, JITSymbolFlags>;
+
virtual ~JITSymbolResolver() = default;
+ /// Returns the fully resolved address and flags for each of the given
+ /// symbols.
+ ///
+ /// This method will return an error if any of the given symbols can not be
+ /// resolved, or if the resolution process itself triggers an error.
+ virtual Expected<LookupResult> lookup(const LookupSet &Symbols) = 0;
+
+ /// Returns the symbol flags for each of the given symbols.
+ ///
+ /// This method does NOT return an error if any of the given symbols is
+ /// missing. Instead, that symbol will be left out of the result map.
+ virtual Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) = 0;
+
+private:
+ virtual void anchor();
+};
+
+/// Legacy symbol resolution interface.
+class LegacyJITSymbolResolver : public JITSymbolResolver {
+public:
+ /// Performs lookup by, for each symbol, first calling
+ /// findSymbolInLogicalDylib and if that fails calling
+ /// findSymbol.
+ Expected<LookupResult> lookup(const LookupSet &Symbols) final;
+
+ /// Performs flags lookup by calling findSymbolInLogicalDylib and
+ /// returning the flags value for that symbol.
+ Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) final;
+
/// This method returns the address of the specified symbol if it exists
/// within the logical dynamic library represented by this JITSymbolResolver.
/// Unlike findSymbol, queries through this interface should return addresses
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index a961992c2147..8bd21a0e3dd6 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -22,6 +22,8 @@
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/Attributes.h"
@@ -56,7 +58,47 @@ class Value;
namespace orc {
-/// @brief Compile-on-demand layer.
+class ExtractingIRMaterializationUnit;
+
+class CompileOnDemandLayer2 : public IRLayer {
+ friend class ExtractingIRMaterializationUnit;
+
+public:
+ /// Builder for IndirectStubsManagers.
+ using IndirectStubsManagerBuilder =
+ std::function<std::unique_ptr<IndirectStubsManager>()>;
+
+ using GetAvailableContextFunction = std::function<LLVMContext &()>;
+
+ CompileOnDemandLayer2(ExecutionSession &ES, IRLayer &BaseLayer,
+ JITCompileCallbackManager &CCMgr,
+ IndirectStubsManagerBuilder BuildIndirectStubsManager,
+ GetAvailableContextFunction GetAvailableContext);
+
+ Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M) override;
+
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<Module> M) override;
+
+private:
+ using StubManagersMap =
+ std::map<const VSO *, std::unique_ptr<IndirectStubsManager>>;
+
+ IndirectStubsManager &getStubsManager(const VSO &V);
+
+ void emitExtractedFunctionsModule(MaterializationResponsibility R,
+ std::unique_ptr<Module> M);
+
+ mutable std::mutex CODLayerMutex;
+
+ IRLayer &BaseLayer;
+ JITCompileCallbackManager &CCMgr;
+ IndirectStubsManagerBuilder BuildIndirectStubsManager;
+ StubManagersMap StubsMgrs;
+ GetAvailableContextFunction GetAvailableContext;
+};
+
+/// Compile-on-demand layer.
///
/// When a module is added to this layer a stub is created for each of its
/// function definitions. The stubs and other global values are immediately
@@ -85,8 +127,6 @@ private:
return LambdaMaterializer<MaterializerFtor>(std::move(M));
}
- using BaseLayerModuleHandleT = typename BaseLayerT::ModuleHandleT;
-
// Provide type-erasure for the Modules and MemoryManagers.
template <typename ResourceT>
class ResourceOwner {
@@ -138,18 +178,22 @@ private:
};
struct LogicalDylib {
- using SymbolResolverFtor = std::function<JITSymbol(const std::string&)>;
-
struct SourceModuleEntry {
- std::shared_ptr<Module> SourceMod;
+ std::unique_ptr<Module> SourceMod;
std::set<Function*> StubsToClone;
};
using SourceModulesList = std::vector<SourceModuleEntry>;
using SourceModuleHandle = typename SourceModulesList::size_type;
- SourceModuleHandle
- addSourceModule(std::shared_ptr<Module> M) {
+ LogicalDylib() = default;
+
+ LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver,
+ std::unique_ptr<IndirectStubsMgrT> StubsMgr)
+ : K(std::move(K)), BackingResolver(std::move(BackingResolver)),
+ StubsMgr(std::move(StubsMgr)) {}
+
+ SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) {
SourceModuleHandle H = SourceModules.size();
SourceModules.push_back(SourceModuleEntry());
SourceModules.back().SourceMod = std::move(M);
@@ -168,8 +212,8 @@ private:
bool ExportedSymbolsOnly) {
if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly))
return Sym;
- for (auto BLH : BaseLayerHandles)
- if (auto Sym = BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly))
+ for (auto BLK : BaseLayerVModuleKeys)
+ if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
@@ -177,91 +221,94 @@ private:
}
Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
- for (auto &BLH : BaseLayerHandles)
- if (auto Err = BaseLayer.removeModule(BLH))
+ for (auto &BLK : BaseLayerVModuleKeys)
+ if (auto Err = BaseLayer.removeModule(BLK))
return Err;
return Error::success();
}
- std::shared_ptr<JITSymbolResolver> ExternalSymbolResolver;
+ VModuleKey K;
+ std::shared_ptr<SymbolResolver> BackingResolver;
std::unique_ptr<IndirectStubsMgrT> StubsMgr;
StaticGlobalRenamer StaticRenamer;
SourceModulesList SourceModules;
- std::vector<BaseLayerModuleHandleT> BaseLayerHandles;
+ std::vector<VModuleKey> BaseLayerVModuleKeys;
};
- using LogicalDylibList = std::list<LogicalDylib>;
-
public:
- /// @brief Handle to loaded module.
- using ModuleHandleT = typename LogicalDylibList::iterator;
-
- /// @brief Module partitioning functor.
+ /// Module partitioning functor.
using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
- /// @brief Builder for IndirectStubsManagers.
+ /// Builder for IndirectStubsManagers.
using IndirectStubsManagerBuilderT =
std::function<std::unique_ptr<IndirectStubsMgrT>()>;
- /// @brief Construct a compile-on-demand layer instance.
- CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition,
+ using SymbolResolverGetter =
+ std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>;
+
+ using SymbolResolverSetter =
+ std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>;
+
+ /// Construct a compile-on-demand layer instance.
+ CompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer,
+ SymbolResolverGetter GetSymbolResolver,
+ SymbolResolverSetter SetSymbolResolver,
+ PartitioningFtor Partition,
CompileCallbackMgrT &CallbackMgr,
IndirectStubsManagerBuilderT CreateIndirectStubsManager,
bool CloneStubsIntoPartitions = true)
- : BaseLayer(BaseLayer), Partition(std::move(Partition)),
- CompileCallbackMgr(CallbackMgr),
+ : ES(ES), BaseLayer(BaseLayer),
+ GetSymbolResolver(std::move(GetSymbolResolver)),
+ SetSymbolResolver(std::move(SetSymbolResolver)),
+ Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr),
CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
~CompileOnDemandLayer() {
// FIXME: Report error on log.
while (!LogicalDylibs.empty())
- consumeError(removeModule(LogicalDylibs.begin()));
+ consumeError(removeModule(LogicalDylibs.begin()->first));
}
- /// @brief Add a module to the compile-on-demand layer.
- Expected<ModuleHandleT>
- addModule(std::shared_ptr<Module> M,
- std::shared_ptr<JITSymbolResolver> Resolver) {
-
- LogicalDylibs.push_back(LogicalDylib());
- auto &LD = LogicalDylibs.back();
- LD.ExternalSymbolResolver = std::move(Resolver);
- LD.StubsMgr = CreateIndirectStubsManager();
+ /// Add a module to the compile-on-demand layer.
+ Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
- // Process each of the modules in this module set.
- if (auto Err = addLogicalModule(LD, std::move(M)))
- return std::move(Err);
+ assert(!LogicalDylibs.count(K) && "VModuleKey K already in use");
+ auto I = LogicalDylibs.insert(
+ LogicalDylibs.end(),
+ std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K),
+ CreateIndirectStubsManager())));
- return std::prev(LogicalDylibs.end());
+ return addLogicalModule(I->second, std::move(M));
}
- /// @brief Add extra modules to an existing logical module.
- Error addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) {
- return addLogicalModule(*H, std::move(M));
+ /// Add extra modules to an existing logical module.
+ Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) {
+ return addLogicalModule(LogicalDylibs[K], std::move(M));
}
- /// @brief Remove the module represented by the given handle.
+ /// Remove the module represented by the given key.
///
/// This will remove all modules in the layers below that were derived from
- /// the module represented by H.
- Error removeModule(ModuleHandleT H) {
- auto Err = H->removeModulesFromBaseLayer(BaseLayer);
- LogicalDylibs.erase(H);
+ /// the module represented by K.
+ Error removeModule(VModuleKey K) {
+ auto I = LogicalDylibs.find(K);
+ assert(I != LogicalDylibs.end() && "VModuleKey K not valid here");
+ auto Err = I->second.removeModulesFromBaseLayer(BaseLayer);
+ LogicalDylibs.erase(I);
return Err;
}
- /// @brief Search for the given named symbol.
+ /// 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 LDI = LogicalDylibs.begin(), LDE = LogicalDylibs.end();
- LDI != LDE; ++LDI) {
- if (auto Sym = LDI->StubsMgr->findStub(Name, ExportedSymbolsOnly))
+ for (auto &KV : LogicalDylibs) {
+ if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly))
return Sym;
- if (auto Sym = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
+ if (auto Sym = findSymbolIn(KV.first, Name, ExportedSymbolsOnly))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
@@ -269,14 +316,15 @@ public:
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of a symbol provided by this layer, or some layer
+ /// Get the address of a symbol provided by this layer, or some layer
/// below this one.
- JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
+ JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
- return H->findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
+ assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here");
+ return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
}
- /// @brief Update the stub for the given function to point at FnBodyAddr.
+ /// Update the stub for the given function to point at FnBodyAddr.
/// This can be used to support re-optimization.
/// @return true if the function exists and the stub is updated, false
/// otherwise.
@@ -302,15 +350,14 @@ public:
}
private:
-
- Error addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) {
+ Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) {
// Rename all static functions / globals to $static.X :
// This will unique the names across all modules in the logical dylib,
// simplifying symbol lookup.
LD.StaticRenamer.rename(*SrcMPtr);
- // Bump the linkage and rename any anonymous/privote members in SrcM to
+ // Bump the linkage and rename any anonymous/private members in SrcM to
// ensure that everything will resolve properly after we partition SrcM.
makeAllSymbolsExternallyAccessible(*SrcMPtr);
@@ -343,22 +390,21 @@ private:
// Create a callback, associate it with the stub for the function,
// and set the compile action to compile the partition containing the
// function.
- if (auto CCInfoOrErr = CompileCallbackMgr.getCompileCallback()) {
- auto &CCInfo = *CCInfoOrErr;
+ auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress {
+ if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
+ return *FnImplAddrOrErr;
+ else {
+ // FIXME: Report error, return to 'abort' or something similar.
+ consumeError(FnImplAddrOrErr.takeError());
+ return 0;
+ }
+ };
+ if (auto CCAddr =
+ CompileCallbackMgr.getCompileCallback(std::move(CompileAction)))
StubInits[MangledName] =
- std::make_pair(CCInfo.getAddress(),
- JITSymbolFlags::fromGlobalValue(F));
- CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
- if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
- return *FnImplAddrOrErr;
- else {
- // FIXME: Report error, return to 'abort' or something similar.
- consumeError(FnImplAddrOrErr.takeError());
- return 0;
- }
- });
- } else
- return CCInfoOrErr.takeError();
+ std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F));
+ else
+ return CCAddr.takeError();
}
if (auto Err = LD.StubsMgr->createStubs(StubInits))
@@ -396,9 +442,8 @@ private:
// Initializers may refer to functions declared (but not defined) in this
// module. Build a materializer to clone decls on demand.
- Error MaterializerErrors = Error::success();
auto Materializer = createLambdaMaterializer(
- [&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* {
+ [&LD, &GVsM](Value *V) -> Value* {
if (auto *F = dyn_cast<Function>(V)) {
// Decls in the original module just get cloned.
if (F->isDeclaration())
@@ -410,18 +455,8 @@ private:
const DataLayout &DL = GVsM->getDataLayout();
std::string FName = mangle(F->getName(), DL);
unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
- JITTargetAddress StubAddr = 0;
-
- // Get the address for the stub. If we encounter an error while
- // doing so, stash it in the MaterializerErrors variable and use a
- // null address as a placeholder.
- if (auto StubSym = LD.StubsMgr->findStub(FName, false)) {
- if (auto StubAddrOrErr = StubSym.getAddress())
- StubAddr = *StubAddrOrErr;
- else
- MaterializerErrors = joinErrors(std::move(MaterializerErrors),
- StubAddrOrErr.takeError());
- }
+ JITTargetAddress StubAddr =
+ LD.StubsMgr->findStub(FName, false).getAddress();
ConstantInt *StubAddrCI =
ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
@@ -450,29 +485,58 @@ private:
NewA->setAliasee(cast<Constant>(Init));
}
- if (MaterializerErrors)
- return MaterializerErrors;
-
// Build a resolver for the globals module and add it to the base layer.
- auto GVsResolver = createLambdaResolver(
- [this, &LD](const std::string &Name) -> JITSymbol {
- if (auto Sym = LD.StubsMgr->findStub(Name, false))
- return Sym;
- if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
- return Sym;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
- return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
+ auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
+ if (auto Sym = LD.StubsMgr->findStub(Name, false))
+ return Sym;
+
+ if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
+ return Sym;
+ else if (auto Err = Sym.takeError())
+ return std::move(Err);
+
+ return nullptr;
+ };
+
+ auto GVsResolver = createSymbolResolver(
+ [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
+ auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup);
+
+ if (!SymbolFlags) {
+ logAllUnhandledErrors(SymbolFlags.takeError(), errs(),
+ "CODLayer/GVsResolver flags lookup failed: ");
+ return SymbolFlagsMap();
+ }
+
+ if (SymbolFlags->size() == Symbols.size())
+ return *SymbolFlags;
+
+ SymbolNameSet NotFoundViaLegacyLookup;
+ for (auto &S : Symbols)
+ if (!SymbolFlags->count(S))
+ NotFoundViaLegacyLookup.insert(S);
+ auto SymbolFlags2 =
+ LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup);
+
+ for (auto &KV : SymbolFlags2)
+ (*SymbolFlags)[KV.first] = std::move(KV.second);
+
+ return *SymbolFlags;
},
- [&LD](const std::string &Name) {
- return LD.ExternalSymbolResolver->findSymbol(Name);
+ [this, &LD,
+ LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
+ SymbolNameSet Symbols) {
+ auto NotFoundViaLegacyLookup =
+ lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
+ return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup);
});
- if (auto GVsHOrErr =
- BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver)))
- LD.BaseLayerHandles.push_back(*GVsHOrErr);
- else
- return GVsHOrErr.takeError();
+ SetSymbolResolver(LD.K, std::move(GVsResolver));
+
+ if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM)))
+ return Err;
+
+ LD.BaseLayerVModuleKeys.push_back(LD.K);
return Error::success();
}
@@ -501,11 +565,11 @@ private:
JITTargetAddress CalledAddr = 0;
auto Part = Partition(F);
- if (auto PartHOrErr = emitPartition(LD, LMId, Part)) {
- auto &PartH = *PartHOrErr;
+ if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) {
+ auto &PartKey = *PartKeyOrErr;
for (auto *SubF : Part) {
std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
- if (auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false)) {
+ if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) {
if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) {
JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr;
@@ -526,15 +590,15 @@ private:
llvm_unreachable("Function not emitted for partition");
}
- LD.BaseLayerHandles.push_back(PartH);
+ LD.BaseLayerVModuleKeys.push_back(PartKey);
} else
- return PartHOrErr.takeError();
+ return PartKeyOrErr.takeError();
return CalledAddr;
}
template <typename PartitionT>
- Expected<BaseLayerModuleHandleT>
+ Expected<VModuleKey>
emitPartition(LogicalDylib &LD,
typename LogicalDylib::SourceModuleHandle LMId,
const PartitionT &Part) {
@@ -596,28 +660,62 @@ private:
for (auto *F : Part)
moveFunctionBody(*F, VMap, &Materializer);
+ auto K = ES.allocateVModule();
+
+ auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
+ return LD.findSymbol(BaseLayer, Name, false);
+ };
+
// Create memory manager and symbol resolver.
- auto Resolver = createLambdaResolver(
- [this, &LD](const std::string &Name) -> JITSymbol {
- if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
- return Sym;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
- return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
+ auto Resolver = createSymbolResolver(
+ [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
+ auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup);
+ if (!SymbolFlags) {
+ logAllUnhandledErrors(SymbolFlags.takeError(), errs(),
+ "CODLayer/SubResolver flags lookup failed: ");
+ return SymbolFlagsMap();
+ }
+
+ if (SymbolFlags->size() == Symbols.size())
+ return *SymbolFlags;
+
+ SymbolNameSet NotFoundViaLegacyLookup;
+ for (auto &S : Symbols)
+ if (!SymbolFlags->count(S))
+ NotFoundViaLegacyLookup.insert(S);
+
+ auto SymbolFlags2 =
+ LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup);
+
+ for (auto &KV : SymbolFlags2)
+ (*SymbolFlags)[KV.first] = std::move(KV.second);
+
+ return *SymbolFlags;
},
- [&LD](const std::string &Name) {
- return LD.ExternalSymbolResolver->findSymbol(Name);
+ [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
+ SymbolNameSet Symbols) {
+ auto NotFoundViaLegacyLookup =
+ lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup);
+ return LD.BackingResolver->lookup(Q,
+ std::move(NotFoundViaLegacyLookup));
});
+ SetSymbolResolver(K, std::move(Resolver));
+
+ if (auto Err = BaseLayer.addModule(std::move(K), std::move(M)))
+ return std::move(Err);
- return BaseLayer.addModule(std::move(M), std::move(Resolver));
+ return K;
}
+ ExecutionSession &ES;
BaseLayerT &BaseLayer;
+ SymbolResolverGetter GetSymbolResolver;
+ SymbolResolverSetter SetSymbolResolver;
PartitioningFtor Partition;
CompileCallbackMgrT &CompileCallbackMgr;
IndirectStubsManagerBuilderT CreateIndirectStubsManager;
- LogicalDylibList LogicalDylibs;
+ std::map<VModuleKey, LogicalDylib> LogicalDylibs;
bool CloneStubsIntoPartitions;
};
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index b9f7d6accc30..213a59124c85 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -16,13 +16,14 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
-#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
@@ -35,45 +36,51 @@ class Module;
namespace orc {
-/// @brief Simple compile functor: Takes a single IR module and returns an
-/// ObjectFile.
+/// Simple compile functor: Takes a single IR module and returns an ObjectFile.
+/// This compiler supports a single compilation thread and LLVMContext only.
+/// For multithreaded compilation, use MultiThreadedSimpleCompiler below.
class SimpleCompiler {
public:
+ using CompileResult = std::unique_ptr<MemoryBuffer>;
- using CompileResult = object::OwningBinary<object::ObjectFile>;
-
- /// @brief Construct a simple compile functor with the given target.
+ /// Construct a simple compile functor with the given target.
SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr)
: TM(TM), ObjCache(ObjCache) {}
- /// @brief Set an ObjectCache to query before compiling.
+ /// Set an ObjectCache to query before compiling.
void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
- /// @brief Compile a Module to an ObjectFile.
+ /// Compile a Module to an ObjectFile.
CompileResult operator()(Module &M) {
CompileResult CachedObject = tryToLoadFromObjectCache(M);
- if (CachedObject.getBinary())
+ if (CachedObject)
return CachedObject;
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);
- std::unique_ptr<MemoryBuffer> ObjBuffer(
- new ObjectMemoryBuffer(std::move(ObjBufferSV)));
- Expected<std::unique_ptr<object::ObjectFile>> Obj =
+ {
+ 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);
+ }
+
+ auto ObjBuffer =
+ llvm::make_unique<SmallVectorMemoryBuffer>(std::move(ObjBufferSV));
+ auto Obj =
object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
+
if (Obj) {
notifyObjectCompiled(M, *ObjBuffer);
- return CompileResult(std::move(*Obj), std::move(ObjBuffer));
+ return std::move(ObjBuffer);
}
+
// TODO: Actually report errors helpfully.
consumeError(Obj.takeError());
- return CompileResult(nullptr, nullptr);
+ return nullptr;
}
private:
@@ -82,19 +89,7 @@ private:
if (!ObjCache)
return CompileResult();
- std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M);
- if (!ObjBuffer)
- return CompileResult();
-
- Expected<std::unique_ptr<object::ObjectFile>> Obj =
- object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
- if (!Obj) {
- // TODO: Actually report errors helpfully.
- consumeError(Obj.takeError());
- return CompileResult();
- }
-
- return CompileResult(std::move(*Obj), std::move(ObjBuffer));
+ return ObjCache->getObject(&M);
}
void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer) {
@@ -106,6 +101,29 @@ private:
ObjectCache *ObjCache = nullptr;
};
+/// A thread-safe version of SimpleCompiler.
+///
+/// This class creates a new TargetMachine and SimpleCompiler instance for each
+/// compile.
+class MultiThreadedSimpleCompiler {
+public:
+ MultiThreadedSimpleCompiler(JITTargetMachineBuilder JTMB,
+ ObjectCache *ObjCache = nullptr)
+ : JTMB(std::move(JTMB)), ObjCache(ObjCache) {}
+
+ void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; }
+
+ std::unique_ptr<MemoryBuffer> operator()(Module &M) {
+ auto TM = cantFail(JTMB.createTargetMachine());
+ SimpleCompiler C(*TM, ObjCache);
+ return C(M);
+ }
+
+private:
+ JITTargetMachineBuilder JTMB;
+ ObjectCache *ObjCache = nullptr;
+};
+
} // end namespace orc
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Core.h
new file mode 100644
index 000000000000..fd03687cfc21
--- /dev/null
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Core.h
@@ -0,0 +1,779 @@
+//===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains core ORC APIs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
+#define LLVM_EXECUTIONENGINE_ORC_CORE_H
+
+#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
+#include "llvm/IR/Module.h"
+
+#include <list>
+#include <map>
+#include <memory>
+#include <set>
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+// Forward declare some classes.
+class AsynchronousSymbolQuery;
+class ExecutionSession;
+class MaterializationUnit;
+class MaterializationResponsibility;
+class VSO;
+
+/// VModuleKey provides a unique identifier (allocated and managed by
+/// ExecutionSessions) for a module added to the JIT.
+using VModuleKey = uint64_t;
+
+/// A set of symbol names (represented by SymbolStringPtrs for
+// efficiency).
+using SymbolNameSet = std::set<SymbolStringPtr>;
+
+/// Render a SymbolNameSet to an ostream.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
+
+/// A map from symbol names (as SymbolStringPtrs) to JITSymbols
+/// (address/flags pairs).
+using SymbolMap = std::map<SymbolStringPtr, JITEvaluatedSymbol>;
+
+/// Render a SymbolMap to an ostream.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
+
+/// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
+using SymbolFlagsMap = std::map<SymbolStringPtr, JITSymbolFlags>;
+
+/// Render a SymbolMap to an ostream.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &Symbols);
+
+/// A base class for materialization failures that allows the failing
+/// symbols to be obtained for logging.
+using SymbolDependenceMap = std::map<VSO *, SymbolNameSet>;
+
+/// Render a SymbolDependendeMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
+
+/// A list of VSO pointers.
+using VSOList = std::vector<VSO *>;
+
+/// Render a VSOList.
+raw_ostream &operator<<(raw_ostream &OS, const VSOList &VSOs);
+
+/// Callback to notify client that symbols have been resolved.
+using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
+
+/// Callback to notify client that symbols are ready for execution.
+using SymbolsReadyCallback = std::function<void(Error)>;
+
+/// Callback to register the dependencies for a given query.
+using RegisterDependenciesFunction =
+ std::function<void(const SymbolDependenceMap &)>;
+
+/// This can be used as the value for a RegisterDependenciesFunction if there
+/// are no dependants to register with.
+extern RegisterDependenciesFunction NoDependenciesToRegister;
+
+/// Used to notify a VSO that the given set of symbols failed to materialize.
+class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
+public:
+ static char ID;
+
+ FailedToMaterialize(SymbolNameSet Symbols);
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+ const SymbolNameSet &getSymbols() const { return Symbols; }
+
+private:
+ SymbolNameSet Symbols;
+};
+
+/// Used to notify clients when symbols can not be found during a lookup.
+class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
+public:
+ static char ID;
+
+ SymbolsNotFound(SymbolNameSet Symbols);
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+ const SymbolNameSet &getSymbols() const { return Symbols; }
+
+private:
+ SymbolNameSet Symbols;
+};
+
+/// Tracks responsibility for materialization, and mediates interactions between
+/// MaterializationUnits and VSOs.
+///
+/// An instance of this class is passed to MaterializationUnits when their
+/// materialize method is called. It allows MaterializationUnits to resolve and
+/// finalize symbols, or abandon materialization by notifying any unmaterialized
+/// symbols of an error.
+class MaterializationResponsibility {
+ friend class MaterializationUnit;
+public:
+ MaterializationResponsibility(MaterializationResponsibility &&) = default;
+ MaterializationResponsibility &
+ operator=(MaterializationResponsibility &&) = default;
+
+ /// Destruct a MaterializationResponsibility instance. In debug mode
+ /// this asserts that all symbols being tracked have been either
+ /// finalized or notified of an error.
+ ~MaterializationResponsibility();
+
+ /// Returns the target VSO that these symbols are being materialized
+ /// into.
+ VSO &getTargetVSO() const { return V; }
+
+ /// Returns the symbol flags map for this responsibility instance.
+ SymbolFlagsMap getSymbols() { return SymbolFlags; }
+
+ /// Returns the names of any symbols covered by this
+ /// MaterializationResponsibility object that have queries pending. This
+ /// information can be used to return responsibility for unrequested symbols
+ /// back to the VSO via the delegate method.
+ SymbolNameSet getRequestedSymbols();
+
+ /// Resolves the given symbols. Individual calls to this method may
+ /// resolve a subset of the symbols, but all symbols must have been
+ /// resolved prior to calling finalize.
+ void resolve(const SymbolMap &Symbols);
+
+ /// Finalizes all symbols tracked by this instance.
+ void finalize();
+
+ /// Adds new symbols to the VSO and this responsibility instance.
+ /// VSO entries start out in the materializing state.
+ ///
+ /// This method can be used by materialization units that want to add
+ /// additional symbols at materialization time (e.g. stubs, compile
+ /// callbacks, metadata).
+ Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
+
+ /// Notify all unfinalized symbols that an error has occurred.
+ /// This will remove all symbols covered by this MaterializationResponsibilty
+ /// from V, and send an error to any queries waiting on these symbols.
+ void failMaterialization();
+
+ /// Transfers responsibility to the given MaterializationUnit for all
+ /// symbols defined by that MaterializationUnit. This allows
+ /// materializers to break up work based on run-time information (e.g.
+ /// by introspecting which symbols have actually been looked up and
+ /// materializing only those).
+ void replace(std::unique_ptr<MaterializationUnit> MU);
+
+ /// Delegates responsibility for the given symbols to the returned
+ /// materialization responsibility. Useful for breaking up work between
+ /// threads, or different kinds of materialization processes.
+ MaterializationResponsibility delegate(const SymbolNameSet &Symbols);
+
+ void addDependencies(const SymbolStringPtr &Name,
+ const SymbolDependenceMap &Dependencies);
+
+ /// Add dependencies that apply to all symbols covered by this instance.
+ void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
+
+private:
+ /// Create a MaterializationResponsibility for the given VSO and
+ /// initial symbols.
+ MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags);
+
+ VSO &V;
+ SymbolFlagsMap SymbolFlags;
+};
+
+/// A MaterializationUnit represents a set of symbol definitions that can
+/// be materialized as a group, or individually discarded (when
+/// overriding definitions are encountered).
+///
+/// MaterializationUnits are used when providing lazy definitions of symbols to
+/// VSOs. The VSO will call materialize when the address of a symbol is
+/// requested via the lookup method. The VSO will call discard if a stronger
+/// definition is added or already present.
+class MaterializationUnit {
+public:
+ MaterializationUnit(SymbolFlagsMap InitalSymbolFlags)
+ : SymbolFlags(std::move(InitalSymbolFlags)) {}
+
+ virtual ~MaterializationUnit() {}
+
+ /// Return the set of symbols that this source provides.
+ const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
+
+ /// Called by materialization dispatchers (see
+ /// ExecutionSession::DispatchMaterializationFunction) to trigger
+ /// materialization of this MaterializationUnit.
+ void doMaterialize(VSO &V) {
+ materialize(MaterializationResponsibility(V, std::move(SymbolFlags)));
+ }
+
+ /// Called by VSOs to notify MaterializationUnits that the given symbol has
+ /// been overridden.
+ void doDiscard(const VSO &V, SymbolStringPtr Name) {
+ SymbolFlags.erase(Name);
+ discard(V, std::move(Name));
+ }
+
+protected:
+ SymbolFlagsMap SymbolFlags;
+
+private:
+ virtual void anchor();
+
+ /// Implementations of this method should materialize all symbols
+ /// in the materialzation unit, except for those that have been
+ /// previously discarded.
+ virtual void materialize(MaterializationResponsibility R) = 0;
+
+ /// Implementations of this method should discard the given symbol
+ /// from the source (e.g. if the source is an LLVM IR Module and the
+ /// symbol is a function, delete the function body or mark it available
+ /// externally).
+ virtual void discard(const VSO &V, SymbolStringPtr Name) = 0;
+};
+
+using MaterializationUnitList =
+ std::vector<std::unique_ptr<MaterializationUnit>>;
+
+/// A MaterializationUnit implementation for pre-existing absolute symbols.
+///
+/// All symbols will be resolved and marked ready as soon as the unit is
+/// materialized.
+class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
+public:
+ AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
+
+private:
+ void materialize(MaterializationResponsibility R) override;
+ void discard(const VSO &V, SymbolStringPtr Name) override;
+ static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
+
+ SymbolMap Symbols;
+};
+
+/// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
+/// Useful for inserting absolute symbols into a VSO. E.g.:
+/// \code{.cpp}
+/// VSO &V = ...;
+/// SymbolStringPtr Foo = ...;
+/// JITEvaluatedSymbol FooSym = ...;
+/// if (auto Err = V.define(absoluteSymbols({{Foo, FooSym}})))
+/// return Err;
+/// \endcode
+///
+inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
+absoluteSymbols(SymbolMap Symbols) {
+ return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>(
+ std::move(Symbols));
+}
+
+struct SymbolAliasMapEntry {
+ SymbolAliasMapEntry() = default;
+ SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
+ : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
+
+ SymbolStringPtr Aliasee;
+ JITSymbolFlags AliasFlags;
+};
+
+/// A map of Symbols to (Symbol, Flags) pairs.
+using SymbolAliasMap = std::map<SymbolStringPtr, SymbolAliasMapEntry>;
+
+/// A materialization unit for symbol aliases. Allows existing symbols to be
+/// aliased with alternate flags.
+class ReExportsMaterializationUnit : public MaterializationUnit {
+public:
+ /// SourceVSO is allowed to be nullptr, in which case the source VSO is
+ /// taken to be whatever VSO these definitions are materialized in. This
+ /// is useful for defining aliases within a VSO.
+ ///
+ /// Note: Care must be taken that no sets of aliases form a cycle, as such
+ /// a cycle will result in a deadlock when any symbol in the cycle is
+ /// resolved.
+ ReExportsMaterializationUnit(VSO *SourceVSO, SymbolAliasMap Aliases);
+
+private:
+ void materialize(MaterializationResponsibility R) override;
+ void discard(const VSO &V, SymbolStringPtr Name) override;
+ static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
+
+ VSO *SourceVSO = nullptr;
+ SymbolAliasMap Aliases;
+};
+
+/// Create a ReExportsMaterializationUnit with the given aliases.
+/// Useful for defining symbol aliases.: E.g., given a VSO V containing symbols
+/// "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" (for
+/// "bar") with:
+/// \code{.cpp}
+/// SymbolStringPtr Baz = ...;
+/// SymbolStringPtr Qux = ...;
+/// if (auto Err = V.define(symbolAliases({
+/// {Baz, { Foo, JITSymbolFlags::Exported }},
+/// {Qux, { Bar, JITSymbolFlags::Weak }}}))
+/// return Err;
+/// \endcode
+inline std::unique_ptr<ReExportsMaterializationUnit>
+symbolAliases(SymbolAliasMap Aliases) {
+ return llvm::make_unique<ReExportsMaterializationUnit>(nullptr,
+ std::move(Aliases));
+}
+
+/// Create a materialization unit for re-exporting symbols from another VSO
+/// with alternative names/flags.
+inline std::unique_ptr<ReExportsMaterializationUnit>
+reexports(VSO &SourceV, SymbolAliasMap Aliases) {
+ return llvm::make_unique<ReExportsMaterializationUnit>(&SourceV,
+ std::move(Aliases));
+}
+
+/// Build a SymbolAliasMap for the common case where you want to re-export
+/// symbols from another VSO with the same linkage/flags.
+Expected<SymbolAliasMap>
+buildSimpleReexportsAliasMap(VSO &SourceV, const SymbolNameSet &Symbols);
+
+/// Base utilities for ExecutionSession.
+class ExecutionSessionBase {
+ // FIXME: Remove this when we remove the old ORC layers.
+ friend class VSO;
+
+public:
+ /// For reporting errors.
+ using ErrorReporter = std::function<void(Error)>;
+
+ /// For dispatching MaterializationUnit::materialize calls.
+ using DispatchMaterializationFunction =
+ std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
+
+ /// Construct an ExecutionSessionBase.
+ ///
+ /// SymbolStringPools may be shared between ExecutionSessions.
+ ExecutionSessionBase(std::shared_ptr<SymbolStringPool> SSP = nullptr)
+ : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {}
+
+ /// Returns the SymbolStringPool for this ExecutionSession.
+ SymbolStringPool &getSymbolStringPool() const { return *SSP; }
+
+ /// Run the given lambda with the session mutex locked.
+ template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
+ std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
+ return F();
+ }
+
+ /// Set the error reporter function.
+ ExecutionSessionBase &setErrorReporter(ErrorReporter ReportError) {
+ this->ReportError = std::move(ReportError);
+ return *this;
+ }
+
+ /// Set the materialization dispatch function.
+ ExecutionSessionBase &setDispatchMaterialization(
+ DispatchMaterializationFunction DispatchMaterialization) {
+ this->DispatchMaterialization = std::move(DispatchMaterialization);
+ return *this;
+ }
+
+ /// Report a error for this execution session.
+ ///
+ /// Unhandled errors can be sent here to log them.
+ void reportError(Error Err) { ReportError(std::move(Err)); }
+
+ /// Allocate a module key for a new module to add to the JIT.
+ VModuleKey allocateVModule() { return ++LastKey; }
+
+ /// Return a module key to the ExecutionSession so that it can be
+ /// re-used. This should only be done once all resources associated
+ /// with the original key have been released.
+ void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
+ }
+
+ void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
+
+ using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
+ std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
+
+ /// A legacy lookup function for JITSymbolResolverAdapter.
+ /// Do not use -- this will be removed soon.
+ Expected<SymbolMap>
+ legacyLookup(ExecutionSessionBase &ES, LegacyAsyncLookupFunction AsyncLookup,
+ SymbolNameSet Names, bool WaiUntilReady,
+ RegisterDependenciesFunction RegisterDependencies);
+
+ /// Search the given VSO list for the given symbols.
+ ///
+ ///
+ /// The OnResolve callback will be called once all requested symbols are
+ /// resolved, or if an error occurs prior to resolution.
+ ///
+ /// The OnReady callback will be called once all requested symbols are ready,
+ /// or if an error occurs after resolution but before all symbols are ready.
+ ///
+ /// If all symbols are found, the RegisterDependencies function will be called
+ /// while the session lock is held. This gives clients a chance to register
+ /// dependencies for on the queried symbols for any symbols they are
+ /// materializing (if a MaterializationResponsibility instance is present,
+ /// this can be implemented by calling
+ /// MaterializationResponsibility::addDependencies). If there are no
+ /// dependenant symbols for this query (e.g. it is being made by a top level
+ /// client to get an address to call) then the value NoDependenciesToRegister
+ /// can be used.
+ void lookup(const VSOList &VSOs, const SymbolNameSet &Symbols,
+ SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
+ RegisterDependenciesFunction RegisterDependencies);
+
+ /// Blocking version of lookup above. Returns the resolved symbol map.
+ /// If WaitUntilReady is true (the default), will not return until all
+ /// requested symbols are ready (or an error occurs). If WaitUntilReady is
+ /// false, will return as soon as all requested symbols are resolved,
+ /// or an error occurs. If WaitUntilReady is false and an error occurs
+ /// after resolution, the function will return a success value, but the
+ /// error will be reported via reportErrors.
+ Expected<SymbolMap> lookup(const VSOList &VSOs, const SymbolNameSet &Symbols,
+ RegisterDependenciesFunction RegisterDependencies,
+ bool WaitUntilReady = true);
+
+ /// Materialize the given unit.
+ void dispatchMaterialization(VSO &V,
+ std::unique_ptr<MaterializationUnit> MU) {
+ DispatchMaterialization(V, std::move(MU));
+ }
+
+private:
+ static void logErrorsToStdErr(Error Err) {
+ logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
+ }
+
+ static void
+ materializeOnCurrentThread(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
+ MU->doMaterialize(V);
+ }
+
+ void runOutstandingMUs();
+
+ mutable std::recursive_mutex SessionMutex;
+ std::shared_ptr<SymbolStringPool> SSP;
+ VModuleKey LastKey = 0;
+ ErrorReporter ReportError = logErrorsToStdErr;
+ DispatchMaterializationFunction DispatchMaterialization =
+ materializeOnCurrentThread;
+
+ // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
+ // with callbacks from asynchronous queries.
+ mutable std::recursive_mutex OutstandingMUsMutex;
+ std::vector<std::pair<VSO *, std::unique_ptr<MaterializationUnit>>>
+ OutstandingMUs;
+};
+
+/// A symbol query that returns results via a callback when results are
+/// ready.
+///
+/// makes a callback when all symbols are available.
+class AsynchronousSymbolQuery {
+ friend class ExecutionSessionBase;
+ friend class VSO;
+
+public:
+
+ /// Create a query for the given symbols, notify-resolved and
+ /// notify-ready callbacks.
+ AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
+ SymbolsResolvedCallback NotifySymbolsResolved,
+ SymbolsReadyCallback NotifySymbolsReady);
+
+ /// Set the resolved symbol information for the given symbol name.
+ void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym);
+
+ /// Returns true if all symbols covered by this query have been
+ /// resolved.
+ bool isFullyResolved() const { return NotYetResolvedCount == 0; }
+
+ /// Call the NotifySymbolsResolved callback.
+ ///
+ /// This should only be called if all symbols covered by the query have been
+ /// resolved.
+ void handleFullyResolved();
+
+ /// Notify the query that a requested symbol is ready for execution.
+ void notifySymbolReady();
+
+ /// Returns true if all symbols covered by this query are ready.
+ bool isFullyReady() const { return NotYetReadyCount == 0; }
+
+ /// Calls the NotifySymbolsReady callback.
+ ///
+ /// This should only be called if all symbols covered by this query are ready.
+ void handleFullyReady();
+
+private:
+ void addQueryDependence(VSO &V, SymbolStringPtr Name);
+
+ void removeQueryDependence(VSO &V, const SymbolStringPtr &Name);
+
+ bool canStillFail();
+
+ void handleFailed(Error Err);
+
+ void detach();
+
+ SymbolsResolvedCallback NotifySymbolsResolved;
+ SymbolsReadyCallback NotifySymbolsReady;
+ SymbolDependenceMap QueryRegistrations;
+ SymbolMap ResolvedSymbols;
+ size_t NotYetResolvedCount;
+ size_t NotYetReadyCount;
+};
+
+/// A symbol table that supports asynchoronous symbol queries.
+///
+/// Represents a virtual shared object. Instances can not be copied or moved, so
+/// their addresses may be used as keys for resource management.
+/// VSO state changes must be made via an ExecutionSession to guarantee that
+/// they are synchronized with respect to other VSO operations.
+class VSO {
+ friend class AsynchronousSymbolQuery;
+ friend class ExecutionSession;
+ friend class ExecutionSessionBase;
+ friend class MaterializationResponsibility;
+public:
+ using FallbackDefinitionGeneratorFunction =
+ std::function<SymbolNameSet(VSO &Parent, const SymbolNameSet &Names)>;
+
+ using AsynchronousSymbolQuerySet =
+ std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
+
+ VSO(const VSO &) = delete;
+ VSO &operator=(const VSO &) = delete;
+ VSO(VSO &&) = delete;
+ VSO &operator=(VSO &&) = delete;
+
+ /// Get the name for this VSO.
+ const std::string &getName() const { return VSOName; }
+
+ /// Get a reference to the ExecutionSession for this VSO.
+ ExecutionSessionBase &getExecutionSession() const { return ES; }
+
+ /// Set a fallback defenition generator. If set, lookup and lookupFlags will
+ /// pass the unresolved symbols set to the fallback definition generator,
+ /// allowing it to add a new definition to the VSO.
+ void setFallbackDefinitionGenerator(
+ FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator) {
+ this->FallbackDefinitionGenerator = std::move(FallbackDefinitionGenerator);
+ }
+
+ /// Set the search order to be used when fixing up definitions in VSO.
+ /// This will replace the previous search order, and apply to any symbol
+ /// resolutions made for definitions in this VSO after the call to
+ /// setSearchOrder (even if the definition itself was added before the
+ /// call).
+ ///
+ /// If SearchThisVSOFirst is set, which by default it is, then this VSO will
+ /// add itself to the beginning of the SearchOrder (Clients should *not*
+ /// put this VSO in the list in this case, to avoid redundant lookups).
+ ///
+ /// If SearchThisVSOFirst is false then the search order will be used as
+ /// given. The main motivation for this feature is to support deliberate
+ /// shadowing of symbols in this VSO by a facade VSO. For example, the
+ /// facade may resolve function names to stubs, and the stubs may compile
+ /// lazily by looking up symbols in this dylib. Adding the facade dylib
+ /// as the first in the search order (instead of this dylib) ensures that
+ /// definitions within this dylib resolve to the lazy-compiling stubs,
+ /// rather than immediately materializing the definitions in this dylib.
+ void setSearchOrder(VSOList NewSearchOrder, bool SearchThisVSOFirst = true);
+
+ /// Add the given VSO to the search order for definitions in this VSO.
+ void addToSearchOrder(VSO &V);
+
+ /// Replace OldV with NewV in the search order if OldV is present. Otherwise
+ /// this operation is a no-op.
+ void replaceInSearchOrder(VSO &OldV, VSO &NewV);
+
+ /// Remove the given VSO from the search order for this VSO if it is
+ /// present. Otherwise this operation is a no-op.
+ void removeFromSearchOrder(VSO &V);
+
+ /// Do something with the search order (run under the session lock).
+ template <typename Func>
+ auto withSearchOrderDo(Func &&F)
+ -> decltype(F(std::declval<const VSOList &>())) {
+ return ES.runSessionLocked([&]() { return F(SearchOrder); });
+ }
+
+ /// Define all symbols provided by the materialization unit to be part
+ /// of the given VSO.
+ template <typename UniquePtrToMaterializationUnit>
+ typename std::enable_if<
+ std::is_convertible<
+ typename std::decay<UniquePtrToMaterializationUnit>::type,
+ std::unique_ptr<MaterializationUnit>>::value,
+ Error>::type
+ define(UniquePtrToMaterializationUnit &&MU) {
+ return ES.runSessionLocked([&, this]() -> Error {
+ assert(MU && "Can't define with a null MU");
+
+ if (auto Err = defineImpl(*MU))
+ return Err;
+
+ /// defineImpl succeeded.
+ auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
+ for (auto &KV : UMI->MU->getSymbols())
+ UnmaterializedInfos[KV.first] = UMI;
+
+ return Error::success();
+ });
+ }
+
+ /// Search the given VSO for the symbols in Symbols. If found, store
+ /// the flags for each symbol in Flags. Returns any unresolved symbols.
+ SymbolFlagsMap lookupFlags(const SymbolNameSet &Names);
+
+ /// Dump current VSO state to OS.
+ void dump(raw_ostream &OS);
+
+ /// FIXME: Remove this when we remove the old ORC layers.
+ /// Search the given VSOs in order for the symbols in Symbols. Results
+ /// (once they become available) will be returned via the given Query.
+ ///
+ /// If any symbol is not found then the unresolved symbols will be returned,
+ /// and the query will not be applied. The Query is not failed and can be
+ /// re-used in a subsequent lookup once the symbols have been added, or
+ /// manually failed.
+ SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
+ SymbolNameSet Names);
+
+private:
+ using AsynchronousSymbolQueryList =
+ std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
+
+ struct UnmaterializedInfo {
+ UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
+ : MU(std::move(MU)) {}
+
+ std::unique_ptr<MaterializationUnit> MU;
+ };
+
+ using UnmaterializedInfosMap =
+ std::map<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
+
+ struct MaterializingInfo {
+ AsynchronousSymbolQueryList PendingQueries;
+ SymbolDependenceMap Dependants;
+ SymbolDependenceMap UnfinalizedDependencies;
+ bool IsFinalized = false;
+ };
+
+ using MaterializingInfosMap = std::map<SymbolStringPtr, MaterializingInfo>;
+
+ using LookupImplActionFlags = enum {
+ None = 0,
+ NotifyFullyResolved = 1 << 0U,
+ NotifyFullyReady = 1 << 1U,
+ LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
+ };
+
+ VSO(ExecutionSessionBase &ES, std::string Name);
+
+ Error defineImpl(MaterializationUnit &MU);
+
+ SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
+ const SymbolNameSet &Names);
+
+ void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+ SymbolNameSet &Unresolved, MaterializationUnitList &MUs);
+
+ void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+ SymbolNameSet &Unresolved, MaterializationUnitList &MUs);
+
+ LookupImplActionFlags
+ lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+ std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
+ SymbolNameSet &Unresolved);
+
+ void detachQueryHelper(AsynchronousSymbolQuery &Q,
+ const SymbolNameSet &QuerySymbols);
+
+ void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI,
+ const SymbolStringPtr &DependantName,
+ MaterializingInfo &FinalizedMI);
+
+ Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
+
+ void replace(std::unique_ptr<MaterializationUnit> MU);
+
+ SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
+
+ void addDependencies(const SymbolStringPtr &Name,
+ const SymbolDependenceMap &Dependants);
+
+ void resolve(const SymbolMap &Resolved);
+
+ void finalize(const SymbolFlagsMap &Finalized);
+
+ void notifyFailed(const SymbolNameSet &FailedSymbols);
+
+ ExecutionSessionBase &ES;
+ std::string VSOName;
+ SymbolMap Symbols;
+ UnmaterializedInfosMap UnmaterializedInfos;
+ MaterializingInfosMap MaterializingInfos;
+ FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator;
+ VSOList SearchOrder;
+};
+
+/// An ExecutionSession represents a running JIT program.
+class ExecutionSession : public ExecutionSessionBase {
+public:
+ using ErrorReporter = std::function<void(Error)>;
+
+ using DispatchMaterializationFunction =
+ std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
+
+ /// Construct an ExecutionEngine.
+ ///
+ /// SymbolStringPools may be shared between ExecutionSessions.
+ ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr)
+ : ExecutionSessionBase(std::move(SSP)) {}
+
+ /// Add a new VSO to this ExecutionSession.
+ VSO &createVSO(std::string Name);
+
+private:
+ std::vector<std::unique_ptr<VSO>> VSOs;
+};
+
+/// Look up the given names in the given VSOs.
+/// VSOs will be searched in order and no VSO pointer may be null.
+/// All symbols must be found within the given VSOs or an error
+/// will be returned.
+Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names);
+
+/// Look up a symbol by searching a list of VSOs.
+Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name);
+
+/// Mangles symbol names then uniques them in the context of an
+/// ExecutionSession.
+class MangleAndInterner {
+public:
+ MangleAndInterner(ExecutionSessionBase &ES, const DataLayout &DL);
+ SymbolStringPtr operator()(StringRef Name);
+
+private:
+ ExecutionSessionBase &ES;
+ const DataLayout &DL;
+};
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_CORE_H
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index d9b45c6a1e29..e27f6e1e2cd6 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -17,13 +17,16 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Target/TargetOptions.h"
#include <algorithm>
#include <cstdint>
#include <string>
-#include <vector>
#include <utility>
+#include <vector>
namespace llvm {
@@ -31,18 +34,58 @@ class ConstantArray;
class GlobalVariable;
class Function;
class Module;
+class TargetMachine;
class Value;
namespace orc {
-/// @brief This iterator provides a convenient way to iterate over the elements
+/// A utility class for building TargetMachines for JITs.
+class JITTargetMachineBuilder {
+public:
+ JITTargetMachineBuilder(Triple TT);
+ static Expected<JITTargetMachineBuilder> detectHost();
+ Expected<std::unique_ptr<TargetMachine>> createTargetMachine();
+
+ JITTargetMachineBuilder &setArch(std::string Arch) {
+ this->Arch = std::move(Arch);
+ return *this;
+ }
+ JITTargetMachineBuilder &setCPU(std::string CPU) {
+ this->CPU = std::move(CPU);
+ return *this;
+ }
+ JITTargetMachineBuilder &setRelocationModel(Optional<Reloc::Model> RM) {
+ this->RM = std::move(RM);
+ return *this;
+ }
+ JITTargetMachineBuilder &setCodeModel(Optional<CodeModel::Model> CM) {
+ this->CM = std::move(CM);
+ return *this;
+ }
+ JITTargetMachineBuilder &
+ addFeatures(const std::vector<std::string> &FeatureVec);
+ SubtargetFeatures &getFeatures() { return Features; }
+ TargetOptions &getOptions() { return Options; }
+
+private:
+ Triple TT;
+ std::string Arch;
+ std::string CPU;
+ SubtargetFeatures Features;
+ TargetOptions Options;
+ Optional<Reloc::Model> RM;
+ Optional<CodeModel::Model> CM;
+ CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
+};
+
+/// This iterator provides a convenient way to iterate over the elements
/// of an llvm.global_ctors/llvm.global_dtors instance.
///
/// The easiest way to get hold of instances of this class is to use the
/// getConstructors/getDestructors functions.
class CtorDtorIterator {
public:
- /// @brief Accessor for an element of the global_ctors/global_dtors array.
+ /// Accessor for an element of the global_ctors/global_dtors array.
///
/// This class provides a read-only view of the element with any casts on
/// the function stripped away.
@@ -55,23 +98,23 @@ public:
Value *Data;
};
- /// @brief Construct an iterator instance. If End is true then this iterator
+ /// Construct an iterator instance. If End is true then this iterator
/// acts as the end of the range, otherwise it is the beginning.
CtorDtorIterator(const GlobalVariable *GV, bool End);
- /// @brief Test iterators for equality.
+ /// Test iterators for equality.
bool operator==(const CtorDtorIterator &Other) const;
- /// @brief Test iterators for inequality.
+ /// Test iterators for inequality.
bool operator!=(const CtorDtorIterator &Other) const;
- /// @brief Pre-increment iterator.
+ /// Pre-increment iterator.
CtorDtorIterator& operator++();
- /// @brief Post-increment iterator.
+ /// Post-increment iterator.
CtorDtorIterator operator++(int);
- /// @brief Dereference iterator. The resulting value provides a read-only view
+ /// Dereference iterator. The resulting value provides a read-only view
/// of this element of the global_ctors/global_dtors list.
Element operator*() const;
@@ -80,32 +123,31 @@ private:
unsigned I;
};
-/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// Create an iterator range over the entries of the llvm.global_ctors
/// array.
iterator_range<CtorDtorIterator> getConstructors(const Module &M);
-/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// Create an iterator range over the entries of the llvm.global_ctors
/// array.
iterator_range<CtorDtorIterator> getDestructors(const Module &M);
-/// @brief Convenience class for recording constructor/destructor names for
+/// Convenience class for recording constructor/destructor names for
/// later execution.
template <typename JITLayerT>
class CtorDtorRunner {
public:
- /// @brief Construct a CtorDtorRunner for the given range using the given
+ /// Construct a CtorDtorRunner for the given range using the given
/// name mangling function.
- CtorDtorRunner(std::vector<std::string> CtorDtorNames,
- typename JITLayerT::ModuleHandleT H)
- : CtorDtorNames(std::move(CtorDtorNames)), H(H) {}
+ CtorDtorRunner(std::vector<std::string> CtorDtorNames, VModuleKey K)
+ : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
- /// @brief Run the recorded constructors/destructors through the given JIT
+ /// Run the recorded constructors/destructors through the given JIT
/// layer.
Error runViaLayer(JITLayerT &JITLayer) const {
using CtorDtorTy = void (*)();
- for (const auto &CtorDtorName : CtorDtorNames)
- if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) {
+ for (const auto &CtorDtorName : CtorDtorNames) {
+ if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) {
if (auto AddrOrErr = CtorDtorSym.getAddress()) {
CtorDtorTy CtorDtor =
reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
@@ -118,15 +160,30 @@ public:
else
return make_error<JITSymbolNotFound>(CtorDtorName);
}
+ }
return Error::success();
}
private:
std::vector<std::string> CtorDtorNames;
- typename JITLayerT::ModuleHandleT H;
+ orc::VModuleKey K;
};
-/// @brief Support class for static dtor execution. For hosted (in-process) JITs
+class CtorDtorRunner2 {
+public:
+ CtorDtorRunner2(VSO &V) : V(V) {}
+ void add(iterator_range<CtorDtorIterator> CtorDtors);
+ Error run();
+
+private:
+ using CtorDtorList = std::vector<SymbolStringPtr>;
+ using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
+
+ VSO &V;
+ CtorDtorPriorityMap CtorDtorsByPriority;
+};
+
+/// Support class for static dtor execution. For hosted (in-process) JITs
/// only!
///
/// If a __cxa_atexit function isn't found C++ programs that use static
@@ -141,7 +198,26 @@ private:
/// the client determines that destructors should be run (generally at JIT
/// teardown or after a return from main), the runDestructors method should be
/// called.
-class LocalCXXRuntimeOverrides {
+class LocalCXXRuntimeOverridesBase {
+public:
+ /// Run any destructors recorded by the overriden __cxa_atexit function
+ /// (CXAAtExitOverride).
+ void runDestructors();
+
+protected:
+ template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) {
+ return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
+ }
+
+ using DestructorPtr = void (*)(void *);
+ using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
+ using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
+ CXXDestructorDataPairList DSOHandleOverride;
+ static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
+ void *DSOHandle);
+};
+
+class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
public:
/// Create a runtime-overrides class.
template <typename MangleFtorT>
@@ -158,32 +234,38 @@ public:
return nullptr;
}
- /// Run any destructors recorded by the overriden __cxa_atexit function
- /// (CXAAtExitOverride).
- void runDestructors();
-
private:
- template <typename PtrTy>
- JITTargetAddress toTargetAddress(PtrTy* P) {
- return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
- }
-
void addOverride(const std::string &Name, JITTargetAddress Addr) {
CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
}
StringMap<JITTargetAddress> CXXRuntimeOverrides;
+};
- using DestructorPtr = void (*)(void *);
- using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
- using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
- CXXDestructorDataPairList DSOHandleOverride;
- static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
- void *DSOHandle);
+class LocalCXXRuntimeOverrides2 : public LocalCXXRuntimeOverridesBase {
+public:
+ Error enable(VSO &V, MangleAndInterner &Mangler);
};
-} // end namespace orc
+/// A utility class to expose symbols found via dlsym to the JIT.
+///
+/// If an instance of this class is attached to a VSO as a fallback definition
+/// generator, then any symbol found in the given DynamicLibrary that passes
+/// the 'Allow' predicate will be added to the VSO.
+class DynamicLibraryFallbackGenerator {
+public:
+ using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
+ DynamicLibraryFallbackGenerator(sys::DynamicLibrary Dylib,
+ const DataLayout &DL, SymbolPredicate Allow);
+ SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names);
+private:
+ sys::DynamicLibrary Dylib;
+ SymbolPredicate Allow;
+ char GlobalPrefix;
+};
+
+} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
index 8a48c36f4141..a8a88d7cb2d2 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
@@ -27,7 +27,7 @@ class JITSymbolResolver;
namespace orc {
-/// @brief Global mapping layer.
+/// Global mapping layer.
///
/// This layer overrides the findSymbol method to first search a local symbol
/// table that the client can define. It can be used to inject new symbol
@@ -38,13 +38,13 @@ template <typename BaseLayerT>
class GlobalMappingLayer {
public:
- /// @brief Handle to an added module.
+ /// Handle to an added module.
using ModuleHandleT = typename BaseLayerT::ModuleHandleT;
- /// @brief Construct an GlobalMappingLayer with the given BaseLayer
+ /// Construct an GlobalMappingLayer with the given BaseLayer
GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
- /// @brief Add the given module to the JIT.
+ /// Add the given module to the JIT.
/// @return A handle for the added modules.
Expected<ModuleHandleT>
addModule(std::shared_ptr<Module> M,
@@ -52,20 +52,20 @@ public:
return BaseLayer.addModule(std::move(M), std::move(Resolver));
}
- /// @brief Remove the module set associated with the handle H.
+ /// Remove the module set associated with the handle H.
Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
- /// @brief Manually set the address to return for the given symbol.
+ /// Manually set the address to return for the given symbol.
void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) {
SymbolTable[Name] = Addr;
}
- /// @brief Remove the given symbol from the global mapping.
+ /// Remove the given symbol from the global mapping.
void eraseGlobalMapping(const std::string &Name) {
SymbolTable.erase(Name);
}
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
///
/// This method will first search the local symbol table, returning
/// any symbol found there. If the symbol is not found in the local
@@ -81,7 +81,7 @@ public:
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of the given symbol in the context of the of the
+ /// Get the address of the given symbol in the context of the of the
/// module represented by the handle H. This call is forwarded to the
/// base layer's implementation.
/// @param H The handle for the module to search in.
@@ -94,7 +94,7 @@ public:
return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
}
- /// @brief Immediately emit and finalize the module set represented by the
+ /// Immediately emit and finalize the module set represented by the
/// given handle.
/// @param H Handle for module set to emit/finalize.
Error emitAndFinalize(ModuleHandleT H) {
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index fadd334bed0f..ad6481548d59 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -16,7 +16,9 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
#include <memory>
#include <string>
@@ -26,7 +28,30 @@ class Module;
namespace orc {
-/// @brief Eager IR compiling layer.
+class IRCompileLayer2 : public IRLayer {
+public:
+ using CompileFunction =
+ std::function<Expected<std::unique_ptr<MemoryBuffer>>(Module &)>;
+
+ using NotifyCompiledFunction =
+ std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
+
+ IRCompileLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer,
+ CompileFunction Compile);
+
+ void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled);
+
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<Module> M) override;
+
+private:
+ mutable std::mutex IRLayerMutex;
+ ObjectLayer &BaseLayer;
+ CompileFunction Compile;
+ NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction();
+};
+
+/// Eager IR compiling layer.
///
/// This layer immediately compiles each IR module added via addModule to an
/// object file and adds this module file to the layer below, which must
@@ -34,36 +59,40 @@ namespace orc {
template <typename BaseLayerT, typename CompileFtor>
class IRCompileLayer {
public:
+ /// Callback type for notifications when modules are compiled.
+ using NotifyCompiledCallback =
+ std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
- /// @brief Handle to a compiled module.
- using ModuleHandleT = typename BaseLayerT::ObjHandleT;
-
- /// @brief Construct an IRCompileLayer with the given BaseLayer, which must
+ /// Construct an IRCompileLayer with the given BaseLayer, which must
/// implement the ObjectLayer concept.
- IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile)
- : BaseLayer(BaseLayer), Compile(std::move(Compile)) {}
+ IRCompileLayer(
+ BaseLayerT &BaseLayer, CompileFtor Compile,
+ NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback())
+ : BaseLayer(BaseLayer), Compile(std::move(Compile)),
+ NotifyCompiled(std::move(NotifyCompiled)) {}
- /// @brief Get a reference to the compiler functor.
+ /// Get a reference to the compiler functor.
CompileFtor& getCompiler() { return Compile; }
- /// @brief Compile the module, and add the resulting object to the base layer
- /// along with the given memory manager and symbol resolver.
- ///
- /// @return A handle for the added module.
- Expected<ModuleHandleT>
- addModule(std::shared_ptr<Module> M,
- std::shared_ptr<JITSymbolResolver> Resolver) {
- using CompileResult = decltype(Compile(*M));
- auto Obj = std::make_shared<CompileResult>(Compile(*M));
- return BaseLayer.addObject(std::move(Obj), std::move(Resolver));
+ /// (Re)set the NotifyCompiled callback.
+ void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) {
+ this->NotifyCompiled = std::move(NotifyCompiled);
}
- /// @brief Remove the module associated with the handle H.
- Error removeModule(ModuleHandleT H) {
- return BaseLayer.removeObject(H);
+ /// Compile the module, and add the resulting object to the base layer
+ /// along with the given memory manager and symbol resolver.
+ Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
+ if (auto Err = BaseLayer.addObject(std::move(K), Compile(*M)))
+ return Err;
+ if (NotifyCompiled)
+ NotifyCompiled(std::move(K), std::move(M));
+ return Error::success();
}
- /// @brief Search for the given named symbol.
+ /// Remove the module associated with the VModuleKey K.
+ Error removeModule(VModuleKey K) { return BaseLayer.removeObject(K); }
+
+ /// 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.
@@ -71,29 +100,28 @@ public:
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of the given symbol in compiled module represented
+ /// Get the address of the given symbol in compiled module represented
/// by the handle H. This call is forwarded to the base layer's
/// implementation.
- /// @param H The handle for the module to search in.
+ /// @param K The VModuleKey for the module 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.
- JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
+ JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
+ return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
- /// @brief Immediately emit and finalize the module represented by the given
+ /// Immediately emit and finalize the module represented by the given
/// handle.
- /// @param H Handle for module to emit/finalize.
- Error emitAndFinalize(ModuleHandleT H) {
- return BaseLayer.emitAndFinalize(H);
- }
+ /// @param K The VModuleKey for the module to emit/finalize.
+ Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
private:
BaseLayerT &BaseLayer;
CompileFtor Compile;
+ NotifyCompiledCallback NotifyCompiled;
};
} // end namespace orc
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
index 476061afda59..266a0f45b3e4 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
@@ -15,6 +15,7 @@
#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include <memory>
#include <string>
@@ -22,7 +23,32 @@ namespace llvm {
class Module;
namespace orc {
-/// @brief IR mutating layer.
+class IRTransformLayer2 : public IRLayer {
+public:
+
+ using TransformFunction =
+ std::function<Expected<std::unique_ptr<Module>>(std::unique_ptr<Module>)>;
+
+ IRTransformLayer2(ExecutionSession &ES, IRLayer &BaseLayer,
+ TransformFunction Transform = identityTransform);
+
+ void setTransform(TransformFunction Transform) {
+ this->Transform = std::move(Transform);
+ }
+
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<Module> M) override;
+
+ static std::unique_ptr<Module> identityTransform(std::unique_ptr<Module> M) {
+ return M;
+ }
+
+private:
+ IRLayer &BaseLayer;
+ TransformFunction Transform;
+};
+
+/// IR mutating layer.
///
/// This layer applies a user supplied transform to each module that is added,
/// then adds the transformed module to the layer below.
@@ -30,28 +56,23 @@ template <typename BaseLayerT, typename TransformFtor>
class IRTransformLayer {
public:
- /// @brief Handle to a set of added modules.
- using ModuleHandleT = typename BaseLayerT::ModuleHandleT;
-
- /// @brief Construct an IRTransformLayer with the given BaseLayer
+ /// Construct an IRTransformLayer with the given BaseLayer
IRTransformLayer(BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor())
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
- /// @brief Apply the transform functor to the module, then add the module to
+ /// Apply the transform functor to the module, then add the module to
/// the layer below, along with the memory manager and symbol resolver.
///
/// @return A handle for the added modules.
- Expected<ModuleHandleT>
- addModule(std::shared_ptr<Module> M,
- std::shared_ptr<JITSymbolResolver> Resolver) {
- return BaseLayer.addModule(Transform(std::move(M)), std::move(Resolver));
+ Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
+ return BaseLayer.addModule(std::move(K), Transform(std::move(M)));
}
- /// @brief Remove the module associated with the handle H.
- Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
+ /// Remove the module associated with the VModuleKey K.
+ Error removeModule(VModuleKey K) { return BaseLayer.removeModule(K); }
- /// @brief Search for the given named symbol.
+ /// 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.
@@ -59,30 +80,28 @@ public:
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of the given symbol in the context of the module
- /// represented by the handle H. This call is forwarded to the base
+ /// Get the address of the given symbol in the context of the module
+ /// represented by the VModuleKey K. This call is forwarded to the base
/// layer's implementation.
- /// @param H The handle for the module to search in.
+ /// @param K The VModuleKey for the module 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.
- JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
+ JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
+ return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
- /// @brief Immediately emit and finalize the module represented by the given
- /// handle.
- /// @param H Handle for module to emit/finalize.
- Error emitAndFinalize(ModuleHandleT H) {
- return BaseLayer.emitAndFinalize(H);
- }
+ /// Immediately emit and finalize the module represented by the given
+ /// VModuleKey.
+ /// @param K The VModuleKey for the module to emit/finalize.
+ Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
- /// @brief Access the transform functor directly.
+ /// Access the transform functor directly.
TransformFtor& getTransform() { return Transform; }
- /// @brief Access the mumate functor directly.
+ /// Access the mumate functor directly.
const TransformFtor& getTransform() const { return Transform; }
private:
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index 029b86a6d2ca..8b0b3fdb7df4 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Process.h"
@@ -46,98 +47,29 @@ class Value;
namespace orc {
-/// @brief Target-independent base class for compile callback management.
+/// Target-independent base class for compile callback management.
class JITCompileCallbackManager {
public:
- using CompileFtor = std::function<JITTargetAddress()>;
+ using CompileFunction = std::function<JITTargetAddress()>;
- /// @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 action for the callback.
- class CompileCallbackInfo {
- public:
- CompileCallbackInfo(JITTargetAddress Addr, CompileFtor &Compile)
- : Addr(Addr), Compile(Compile) {}
-
- JITTargetAddress getAddress() const { return Addr; }
- void setCompileAction(CompileFtor Compile) {
- this->Compile = std::move(Compile);
- }
-
- private:
- JITTargetAddress Addr;
- CompileFtor &Compile;
- };
-
- /// @brief Construct a JITCompileCallbackManager.
+ /// Construct a JITCompileCallbackManager.
/// @param ErrorHandlerAddress The address of an error handler in the target
/// process to be used if a compile callback fails.
- JITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress)
- : ErrorHandlerAddress(ErrorHandlerAddress) {}
+ JITCompileCallbackManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress)
+ : ES(ES), CallbacksVSO(ES.createVSO("<Callbacks>")),
+ ErrorHandlerAddress(ErrorHandlerAddress) {}
virtual ~JITCompileCallbackManager() = default;
- /// @brief Execute the callback for the given trampoline id. Called by the JIT
- /// to compile functions on demand.
- JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr) {
- auto I = ActiveTrampolines.find(TrampolineAddr);
- // 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.
- auto Compile = std::move(I->second);
- ActiveTrampolines.erase(I);
- AvailableTrampolines.push_back(TrampolineAddr);
-
- if (auto Addr = Compile())
- return Addr;
-
- return ErrorHandlerAddress;
- }
-
- /// @brief Reserve a compile callback.
- Expected<CompileCallbackInfo> getCompileCallback() {
- if (auto TrampolineAddrOrErr = getAvailableTrampolineAddr()) {
- const auto &TrampolineAddr = *TrampolineAddrOrErr;
- auto &Compile = this->ActiveTrampolines[TrampolineAddr];
- return CompileCallbackInfo(TrampolineAddr, Compile);
- } else
- return TrampolineAddrOrErr.takeError();
- }
-
- /// @brief Get a CompileCallbackInfo for an existing callback.
- CompileCallbackInfo getCompileCallbackInfo(JITTargetAddress TrampolineAddr) {
- auto I = ActiveTrampolines.find(TrampolineAddr);
- assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
- return CompileCallbackInfo(I->first, I->second);
- }
+ /// Reserve a compile callback.
+ Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
- /// @brief Release a compile callback.
- ///
- /// Note: Callbacks are auto-released after they execute. This method should
- /// only be called to manually release a callback that is not going to
- /// execute.
- void releaseCompileCallback(JITTargetAddress TrampolineAddr) {
- auto I = ActiveTrampolines.find(TrampolineAddr);
- assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
- ActiveTrampolines.erase(I);
- AvailableTrampolines.push_back(TrampolineAddr);
- }
+ /// Execute the callback for the given trampoline id. Called by the JIT
+ /// to compile functions on demand.
+ JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
protected:
- JITTargetAddress ErrorHandlerAddress;
-
- using TrampolineMapT = std::map<JITTargetAddress, CompileFtor>;
- TrampolineMapT ActiveTrampolines;
std::vector<JITTargetAddress> AvailableTrampolines;
private:
@@ -156,17 +88,25 @@ private:
virtual Error grow() = 0;
virtual void anchor();
+
+ std::mutex CCMgrMutex;
+ ExecutionSession &ES;
+ VSO &CallbacksVSO;
+ JITTargetAddress ErrorHandlerAddress;
+ std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
+ size_t NextCallbackId = 0;
};
-/// @brief Manage compile callbacks for in-process JITs.
+/// Manage compile callbacks for in-process JITs.
template <typename TargetT>
class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
public:
- /// @brief Construct a InProcessJITCompileCallbackManager.
+ /// Construct a InProcessJITCompileCallbackManager.
/// @param ErrorHandlerAddress The address of an error handler in the target
/// process to be used if a compile callback fails.
- LocalJITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ErrorHandlerAddress) {
+ LocalJITCompileCallbackManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress)
+ : JITCompileCallbackManager(ES, ErrorHandlerAddress) {
/// Set up the resolver block.
std::error_code EC;
ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
@@ -229,38 +169,38 @@ private:
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
};
-/// @brief Base class for managing collections of named indirect stubs.
+/// Base class for managing collections of named indirect stubs.
class IndirectStubsManager {
public:
- /// @brief Map type for initializing the manager. See init.
+ /// Map type for initializing the manager. See init.
using StubInitsMap = StringMap<std::pair<JITTargetAddress, JITSymbolFlags>>;
virtual ~IndirectStubsManager() = default;
- /// @brief Create a single stub with the given name, target address and flags.
+ /// Create a single stub with the given name, target address and flags.
virtual Error createStub(StringRef StubName, JITTargetAddress StubAddr,
JITSymbolFlags StubFlags) = 0;
- /// @brief Create StubInits.size() stubs with the given names, target
+ /// Create StubInits.size() stubs with the given names, target
/// addresses, and flags.
virtual Error createStubs(const StubInitsMap &StubInits) = 0;
- /// @brief Find the stub with the given name. If ExportedStubsOnly is true,
+ /// Find the stub with the given name. If ExportedStubsOnly is true,
/// this will only return a result if the stub's flags indicate that it
/// is exported.
- virtual JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
+ virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
- /// @brief Find the implementation-pointer for the stub.
- virtual JITSymbol findPointer(StringRef Name) = 0;
+ /// Find the implementation-pointer for the stub.
+ virtual JITEvaluatedSymbol findPointer(StringRef Name) = 0;
- /// @brief Change the value of the implementation pointer for the stub.
+ /// Change the value of the implementation pointer for the stub.
virtual Error updatePointer(StringRef Name, JITTargetAddress NewAddr) = 0;
private:
virtual void anchor();
};
-/// @brief IndirectStubsManager implementation for the host architecture, e.g.
+/// IndirectStubsManager implementation for the host architecture, e.g.
/// OrcX86_64. (See OrcArchitectureSupport.h).
template <typename TargetT>
class LocalIndirectStubsManager : public IndirectStubsManager {
@@ -286,7 +226,7 @@ public:
return Error::success();
}
- JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
+ JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
@@ -295,13 +235,13 @@ public:
assert(StubAddr && "Missing stub address");
auto StubTargetAddr =
static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
- auto StubSymbol = JITSymbol(StubTargetAddr, I->second.second);
+ auto StubSymbol = JITEvaluatedSymbol(StubTargetAddr, I->second.second);
if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
return nullptr;
return StubSymbol;
}
- JITSymbol findPointer(StringRef Name) override {
+ JITEvaluatedSymbol findPointer(StringRef Name) override {
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
@@ -310,7 +250,7 @@ public:
assert(PtrAddr && "Missing pointer address");
auto PtrTargetAddr =
static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
- return JITSymbol(PtrTargetAddr, I->second.second);
+ return JITEvaluatedSymbol(PtrTargetAddr, I->second.second);
}
Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
@@ -354,45 +294,45 @@ private:
StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
};
-/// @brief Create a local compile callback manager.
+/// Create a local compile callback manager.
///
/// The given target triple will determine the ABI, and the given
/// ErrorHandlerAddress will be used by the resulting compile callback
/// manager if a compile callback fails.
std::unique_ptr<JITCompileCallbackManager>
-createLocalCompileCallbackManager(const Triple &T,
+createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress);
-/// @brief Create a local indriect stubs manager builder.
+/// Create a local indriect stubs manager builder.
///
/// The given target triple will determine the ABI.
std::function<std::unique_ptr<IndirectStubsManager>()>
createLocalIndirectStubsManagerBuilder(const Triple &T);
-/// @brief Build a function pointer of FunctionType with the given constant
+/// Build a function pointer of FunctionType with the given constant
/// address.
///
/// Usage example: Turn a trampoline address into a function pointer constant
/// for use in a stub.
Constant *createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr);
-/// @brief Create a function pointer with the given type, name, and initializer
+/// Create a function pointer with the given type, name, and initializer
/// in the given Module.
GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name,
Constant *Initializer);
-/// @brief Turn a function declaration into a stub function that makes an
+/// Turn a function declaration into a stub function that makes an
/// indirect call using the given function pointer.
void makeStub(Function &F, Value &ImplPointer);
-/// @brief Raise linkage types and rename as necessary to ensure that all
+/// Raise linkage types and rename as necessary to ensure that all
/// symbols are accessible for other modules.
///
/// This should be called before partitioning a module to ensure that the
/// partitions retain access to each other's symbols.
void makeAllSymbolsExternallyAccessible(Module &M);
-/// @brief Clone a function declaration into a new module.
+/// Clone a function declaration into a new module.
///
/// This function can be used as the first step towards creating a callback
/// stub (see makeStub), or moving a function body (see moveFunctionBody).
@@ -407,7 +347,7 @@ void makeAllSymbolsExternallyAccessible(Module &M);
Function *cloneFunctionDecl(Module &Dst, const Function &F,
ValueToValueMapTy *VMap = nullptr);
-/// @brief Move the body of function 'F' to a cloned function declaration in a
+/// Move the body of function 'F' to a cloned function declaration in a
/// different module (See related cloneFunctionDecl).
///
/// If the target function declaration is not supplied via the NewF parameter
@@ -419,11 +359,11 @@ void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
ValueMaterializer *Materializer = nullptr,
Function *NewF = nullptr);
-/// @brief Clone a global variable declaration into a new module.
+/// Clone a global variable declaration into a new module.
GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
ValueToValueMapTy *VMap = nullptr);
-/// @brief Move global variable GV from its parent module to cloned global
+/// Move global variable GV from its parent module to cloned global
/// declaration in a different module.
///
/// If the target global declaration is not supplied via the NewGV parameter
@@ -436,11 +376,11 @@ void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
ValueMaterializer *Materializer = nullptr,
GlobalVariable *NewGV = nullptr);
-/// @brief Clone a global alias declaration into a new module.
+/// Clone a global alias declaration into a new module.
GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
ValueToValueMapTy &VMap);
-/// @brief Clone module flags metadata into the destination module.
+/// Clone module flags metadata into the destination module.
void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
ValueToValueMapTy &VMap);
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
new file mode 100644
index 000000000000..df655bd82006
--- /dev/null
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -0,0 +1,143 @@
+//===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for 3Bdetails.
+//
+//===----------------------------------------------------------------------===//
+//
+// An ORC-based JIT for compiling LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
+#define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
+
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+namespace orc {
+
+/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
+class LLJIT {
+public:
+ /// Create an LLJIT instance.
+ static Expected<std::unique_ptr<LLJIT>>
+ Create(std::unique_ptr<ExecutionSession> ES,
+ std::unique_ptr<TargetMachine> TM, DataLayout DL);
+
+ /// Returns a reference to the ExecutionSession for this JIT instance.
+ ExecutionSession &getExecutionSession() { return *ES; }
+
+ /// Returns a reference to the VSO representing the JIT'd main program.
+ VSO &getMainVSO() { return Main; }
+
+ /// Convenience method for defining an absolute symbol.
+ Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
+
+ /// Adds an IR module to the given VSO.
+ Error addIRModule(VSO &V, std::unique_ptr<Module> M);
+
+ /// Adds an IR module to the Main VSO.
+ Error addIRModule(std::unique_ptr<Module> M) {
+ return addIRModule(Main, std::move(M));
+ }
+
+ /// Look up a symbol in VSO V by the symbol's linker-mangled name (to look up
+ /// symbols based on their IR name use the lookup function instead).
+ Expected<JITEvaluatedSymbol> lookupLinkerMangled(VSO &V, StringRef Name);
+
+ /// Look up a symbol in the main VSO by the symbol's linker-mangled name (to
+ /// look up symbols based on their IR name use the lookup function instead).
+ Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
+ return lookupLinkerMangled(Main, Name);
+ }
+
+ /// Look up a symbol in VSO V based on its IR symbol name.
+ Expected<JITEvaluatedSymbol> lookup(VSO &V, StringRef UnmangledName) {
+ return lookupLinkerMangled(V, mangle(UnmangledName));
+ }
+
+ /// Look up a symbol in the main VSO based on its IR symbol name.
+ Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
+ return lookup(Main, UnmangledName);
+ }
+
+ /// Runs all not-yet-run static constructors.
+ Error runConstructors() { return CtorRunner.run(); }
+
+ /// Runs all not-yet-run static destructors.
+ Error runDestructors() { return DtorRunner.run(); }
+
+protected:
+ LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
+ DataLayout DL);
+
+ std::shared_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K);
+
+ std::string mangle(StringRef UnmangledName);
+
+ Error applyDataLayout(Module &M);
+
+ void recordCtorDtors(Module &M);
+
+ std::unique_ptr<ExecutionSession> ES;
+ VSO &Main;
+
+ std::unique_ptr<TargetMachine> TM;
+ DataLayout DL;
+
+ RTDyldObjectLinkingLayer2 ObjLinkingLayer;
+ IRCompileLayer2 CompileLayer;
+
+ CtorDtorRunner2 CtorRunner, DtorRunner;
+};
+
+/// An extended version of LLJIT that supports lazy function-at-a-time
+/// compilation of LLVM IR.
+class LLLazyJIT : public LLJIT {
+public:
+ /// Create an LLLazyJIT instance.
+ static Expected<std::unique_ptr<LLLazyJIT>>
+ Create(std::unique_ptr<ExecutionSession> ES,
+ std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx);
+
+ /// Set an IR transform (e.g. pass manager pipeline) to run on each function
+ /// when it is compiled.
+ void setLazyCompileTransform(IRTransformLayer2::TransformFunction Transform) {
+ TransformLayer.setTransform(std::move(Transform));
+ }
+
+ /// Add a module to be lazily compiled to VSO V.
+ Error addLazyIRModule(VSO &V, std::unique_ptr<Module> M);
+
+ /// Add a module to be lazily compiled to the main VSO.
+ Error addLazyIRModule(std::unique_ptr<Module> M) {
+ return addLazyIRModule(Main, std::move(M));
+ }
+
+private:
+ LLLazyJIT(std::unique_ptr<ExecutionSession> ES,
+ std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx,
+ std::unique_ptr<JITCompileCallbackManager> CCMgr,
+ std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
+
+ std::unique_ptr<JITCompileCallbackManager> CCMgr;
+ std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder;
+
+ IRTransformLayer2 TransformLayer;
+ CompileOnDemandLayer2 CODLayer;
+};
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
index 228392ae0d4a..7b6f3d2f92ab 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
@@ -23,7 +23,7 @@ namespace llvm {
namespace orc {
template <typename DylibLookupFtorT, typename ExternalLookupFtorT>
-class LambdaResolver : public JITSymbolResolver {
+class LambdaResolver : public LegacyJITSymbolResolver {
public:
LambdaResolver(DylibLookupFtorT DylibLookupFtor,
ExternalLookupFtorT ExternalLookupFtor)
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
new file mode 100644
index 000000000000..91bd4fb83e6f
--- /dev/null
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
@@ -0,0 +1,129 @@
+//===---------------- Layer.h -- Layer interfaces --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Layer interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_LAYER_H
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/IR/Module.h"
+
+namespace llvm {
+namespace orc {
+
+/// Interface for layers that accept LLVM IR.
+class IRLayer {
+public:
+ IRLayer(ExecutionSession &ES);
+ virtual ~IRLayer();
+
+ /// Returns the ExecutionSession for this layer.
+ ExecutionSession &getExecutionSession() { return ES; }
+
+ /// Adds a MaterializationUnit representing the given IR to the given VSO.
+ virtual Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M);
+
+ /// Emit should materialize the given IR.
+ virtual void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<Module> M) = 0;
+
+private:
+ ExecutionSession &ES;
+};
+
+/// IRMaterializationUnit is a convenient base class for MaterializationUnits
+/// wrapping LLVM IR. Represents materialization responsibility for all symbols
+/// in the given module. If symbols are overridden by other definitions, then
+/// their linkage is changed to available-externally.
+class IRMaterializationUnit : public MaterializationUnit {
+public:
+ using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
+
+ /// Create an IRMaterializationLayer. Scans the module to build the
+ /// SymbolFlags and SymbolToDefinition maps.
+ IRMaterializationUnit(ExecutionSession &ES, std::unique_ptr<Module> M);
+
+ /// Create an IRMaterializationLayer from a module, and pre-existing
+ /// SymbolFlags and SymbolToDefinition maps. The maps must provide
+ /// entries for each definition in M.
+ /// This constructor is useful for delegating work from one
+ /// IRMaterializationUnit to another.
+ IRMaterializationUnit(std::unique_ptr<Module> M, SymbolFlagsMap SymbolFlags,
+ SymbolNameToDefinitionMap SymbolToDefinition);
+
+protected:
+ std::unique_ptr<Module> M;
+ SymbolNameToDefinitionMap SymbolToDefinition;
+
+private:
+ void discard(const VSO &V, SymbolStringPtr Name) override;
+};
+
+/// MaterializationUnit that materializes modules by calling the 'emit' method
+/// on the given IRLayer.
+class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
+public:
+ BasicIRLayerMaterializationUnit(IRLayer &L, VModuleKey K,
+ std::unique_ptr<Module> M);
+private:
+
+ void materialize(MaterializationResponsibility R) override;
+
+ IRLayer &L;
+ VModuleKey K;
+};
+
+/// Interface for Layers that accept object files.
+class ObjectLayer {
+public:
+ ObjectLayer(ExecutionSession &ES);
+ virtual ~ObjectLayer();
+
+ /// Returns the execution session for this layer.
+ ExecutionSession &getExecutionSession() { return ES; }
+
+ /// Adds a MaterializationUnit representing the given IR to the given VSO.
+ virtual Error add(VSO &V, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
+
+ /// Emit should materialize the given IR.
+ virtual void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<MemoryBuffer> O) = 0;
+
+private:
+ ExecutionSession &ES;
+};
+
+/// Materializes the given object file (represented by a MemoryBuffer
+/// instance) by calling 'emit' on the given ObjectLayer.
+class BasicObjectLayerMaterializationUnit : public MaterializationUnit {
+public:
+
+
+ /// The MemoryBuffer should represent a valid object file.
+ /// If there is any chance that the file is invalid it should be validated
+ /// prior to constructing a BasicObjectLayerMaterializationUnit.
+ BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K,
+ std::unique_ptr<MemoryBuffer> O);
+
+private:
+ void materialize(MaterializationResponsibility R) override;
+ void discard(const VSO &V, SymbolStringPtr Name) override;
+
+ ObjectLayer &L;
+ VModuleKey K;
+ std::unique_ptr<MemoryBuffer> O;
+};
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LAYER_H
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
index b7e462e85d9d..46761b0ca7e1 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
@@ -32,23 +33,18 @@
namespace llvm {
namespace orc {
-/// @brief Lazy-emitting IR layer.
+/// Lazy-emitting IR layer.
///
/// This layer accepts LLVM IR Modules (via addModule), 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:
-
- using BaseLayerHandleT = typename BaseLayerT::ModuleHandleT;
-
private:
class EmissionDeferredModule {
public:
- EmissionDeferredModule(std::shared_ptr<Module> M,
- std::shared_ptr<JITSymbolResolver> Resolver)
- : M(std::move(M)), Resolver(std::move(Resolver)) {}
+ EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M)
+ : K(std::move(K)), M(std::move(M)) {}
JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
switch (EmitState) {
@@ -65,13 +61,11 @@ private:
return 0;
else if (this->EmitState == NotEmitted) {
this->EmitState = Emitting;
- if (auto HandleOrErr = this->emitToBaseLayer(B))
- Handle = std::move(*HandleOrErr);
- else
- return HandleOrErr.takeError();
+ if (auto Err = this->emitToBaseLayer(B))
+ return std::move(Err);
this->EmitState = Emitted;
}
- if (auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly))
+ if (auto Sym = B.findSymbolIn(K, PName, ExportedSymbolsOnly))
return Sym.getAddress();
else if (auto Err = Sym.takeError())
return std::move(Err);
@@ -89,13 +83,13 @@ private:
// RuntimeDyld that did the lookup), so just return a nullptr here.
return nullptr;
case Emitted:
- return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
+ return B.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
llvm_unreachable("Invalid emit-state.");
}
Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) {
- return EmitState != NotEmitted ? BaseLayer.removeModule(Handle)
+ return EmitState != NotEmitted ? BaseLayer.removeModule(K)
: Error::success();
}
@@ -104,10 +98,10 @@ private:
"Cannot emitAndFinalize while already emitting");
if (EmitState == NotEmitted) {
EmitState = Emitting;
- Handle = emitToBaseLayer(BaseLayer);
+ emitToBaseLayer(BaseLayer);
EmitState = Emitted;
}
- BaseLayer.emitAndFinalize(Handle);
+ BaseLayer.emitAndFinalize(K);
}
private:
@@ -135,11 +129,11 @@ private:
return buildMangledSymbols(Name, ExportedSymbolsOnly);
}
- Expected<BaseLayerHandleT> emitToBaseLayer(BaseLayerT &BaseLayer) {
+ Error emitToBaseLayer(BaseLayerT &BaseLayer) {
// 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.
MangledSymbols.reset();
- return BaseLayer.addModule(std::move(M), std::move(Resolver));
+ return BaseLayer.addModule(std::move(K), std::move(M));
}
// If the mangled name of the given GlobalValue matches the given search
@@ -192,46 +186,40 @@ private:
}
enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
- BaseLayerHandleT Handle;
- std::shared_ptr<Module> M;
- std::shared_ptr<JITSymbolResolver> Resolver;
+ VModuleKey K;
+ std::unique_ptr<Module> M;
mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
};
- using ModuleListT = std::list<std::unique_ptr<EmissionDeferredModule>>;
-
BaseLayerT &BaseLayer;
- ModuleListT ModuleList;
+ std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap;
public:
- /// @brief Handle to a loaded module.
- using ModuleHandleT = typename ModuleListT::iterator;
-
- /// @brief Construct a lazy emitting layer.
+ /// Construct a lazy emitting layer.
LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
- /// @brief Add the given module to the lazy emitting layer.
- Expected<ModuleHandleT>
- addModule(std::shared_ptr<Module> M,
- std::shared_ptr<JITSymbolResolver> Resolver) {
- return ModuleList.insert(
- ModuleList.end(),
- llvm::make_unique<EmissionDeferredModule>(std::move(M),
- std::move(Resolver)));
+ /// Add the given module to the lazy emitting layer.
+ Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
+ assert(!ModuleMap.count(K) && "VModuleKey K already in use");
+ ModuleMap[K] =
+ llvm::make_unique<EmissionDeferredModule>(std::move(K), std::move(M));
+ return Error::success();
}
- /// @brief Remove the module represented by the given handle.
+ /// Remove the module represented by the given handle.
///
/// This method will free the memory associated with the given module, both
/// in this layer, and the base layer.
- Error removeModule(ModuleHandleT H) {
- Error Err = (*H)->removeModuleFromBaseLayer(BaseLayer);
- ModuleList.erase(H);
- return Err;
+ Error removeModule(VModuleKey K) {
+ auto I = ModuleMap.find(K);
+ assert(I != ModuleMap.end() && "VModuleKey K not valid here");
+ auto EDM = std::move(I.second);
+ ModuleMap.erase(I);
+ return EDM->removeModuleFromBaseLayer(BaseLayer);
}
- /// @brief Search for the given named symbol.
+ /// 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.
@@ -243,26 +231,27 @@ public:
// If not found then search the deferred modules. 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 &DeferredMod : ModuleList)
- if (auto Symbol = DeferredMod->find(Name, ExportedSymbolsOnly, BaseLayer))
+ for (auto &KV : ModuleMap)
+ if (auto Symbol = KV.second->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 of
- /// compiled modules represented by the handle H.
- JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
+ /// Get the address of the given symbol in the context of the of
+ /// compiled modules represented by the key K.
+ JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
- return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer);
+ assert(ModuleMap.count(K) && "VModuleKey K not valid here");
+ return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer);
}
- /// @brief Immediately emit and finalize the module represented by the given
- /// handle.
- /// @param H Handle for module to emit/finalize.
- Error emitAndFinalize(ModuleHandleT H) {
- return (*H)->emitAndFinalize(BaseLayer);
+ /// Immediately emit and finalize the module represented by the given
+ /// key.
+ Error emitAndFinalize(VModuleKey K) {
+ assert(ModuleMap.count(K) && "VModuleKey K not valid here");
+ return ModuleMap[K]->emitAndFinalize(BaseLayer);
}
};
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h
new file mode 100644
index 000000000000..52c8c162ff0b
--- /dev/null
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h
@@ -0,0 +1,211 @@
+//===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains core ORC APIs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H
+#define LLVM_EXECUTIONENGINE_ORC_LEGACY_H
+
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+
+namespace llvm {
+namespace orc {
+
+/// SymbolResolver is a composable interface for looking up symbol flags
+/// and addresses using the AsynchronousSymbolQuery type. It will
+/// eventually replace the LegacyJITSymbolResolver interface as the
+/// stardard ORC symbol resolver type.
+///
+/// FIXME: SymbolResolvers should go away and be replaced with VSOs with
+/// defenition generators.
+class SymbolResolver {
+public:
+ virtual ~SymbolResolver() = default;
+
+ /// Returns the flags for each symbol in Symbols that can be found,
+ /// along with the set of symbol that could not be found.
+ virtual SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) = 0;
+
+ /// For each symbol in Symbols that can be found, assigns that symbols
+ /// value in Query. Returns the set of symbols that could not be found.
+ virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
+ SymbolNameSet Symbols) = 0;
+
+private:
+ virtual void anchor();
+};
+
+/// Implements SymbolResolver with a pair of supplied function objects
+/// for convenience. See createSymbolResolver.
+template <typename LookupFlagsFn, typename LookupFn>
+class LambdaSymbolResolver final : public SymbolResolver {
+public:
+ template <typename LookupFlagsFnRef, typename LookupFnRef>
+ LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
+ : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
+ Lookup(std::forward<LookupFnRef>(Lookup)) {}
+
+ SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
+ return LookupFlags(Symbols);
+ }
+
+ SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
+ SymbolNameSet Symbols) final {
+ return Lookup(std::move(Query), std::move(Symbols));
+ }
+
+private:
+ LookupFlagsFn LookupFlags;
+ LookupFn Lookup;
+};
+
+/// Creates a SymbolResolver implementation from the pair of supplied
+/// function objects.
+template <typename LookupFlagsFn, typename LookupFn>
+std::unique_ptr<LambdaSymbolResolver<
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFlagsFn>::type>::type,
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFn>::type>::type>>
+createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
+ using LambdaSymbolResolverImpl = LambdaSymbolResolver<
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFlagsFn>::type>::type,
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFn>::type>::type>;
+ return llvm::make_unique<LambdaSymbolResolverImpl>(
+ std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
+}
+
+class JITSymbolResolverAdapter : public JITSymbolResolver {
+public:
+ JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
+ MaterializationResponsibility *MR);
+ Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override;
+ Expected<LookupResult> lookup(const LookupSet &Symbols) override;
+
+private:
+ ExecutionSession &ES;
+ std::set<SymbolStringPtr> ResolvedStrings;
+ SymbolResolver &R;
+ MaterializationResponsibility *MR;
+};
+
+/// Use the given legacy-style FindSymbol function (i.e. a function that
+/// takes a const std::string& or StringRef and returns a JITSymbol) to
+/// find the flags for each symbol in Symbols and store their flags in
+/// SymbolFlags. If any JITSymbol returned by FindSymbol is in an error
+/// state the function returns immediately with that error, otherwise it
+/// returns the set of symbols not found.
+///
+/// Useful for implementing lookupFlags bodies that query legacy resolvers.
+template <typename FindSymbolFn>
+Expected<SymbolFlagsMap> lookupFlagsWithLegacyFn(const SymbolNameSet &Symbols,
+ FindSymbolFn FindSymbol) {
+ SymbolFlagsMap SymbolFlags;
+
+ for (auto &S : Symbols) {
+ if (JITSymbol Sym = FindSymbol(*S))
+ SymbolFlags[S] = Sym.getFlags();
+ else if (auto Err = Sym.takeError())
+ return std::move(Err);
+ }
+
+ return SymbolFlags;
+}
+
+/// Use the given legacy-style FindSymbol function (i.e. a function that
+/// takes a const std::string& or StringRef and returns a JITSymbol) to
+/// find the address and flags for each symbol in Symbols and store the
+/// result in Query. If any JITSymbol returned by FindSymbol is in an
+/// error then Query.notifyFailed(...) is called with that error and the
+/// function returns immediately. On success, returns the set of symbols
+/// not found.
+///
+/// Useful for implementing lookup bodies that query legacy resolvers.
+template <typename FindSymbolFn>
+SymbolNameSet
+lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
+ const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
+ SymbolNameSet SymbolsNotFound;
+ bool NewSymbolsResolved = false;
+
+ for (auto &S : Symbols) {
+ if (JITSymbol Sym = FindSymbol(*S)) {
+ if (auto Addr = Sym.getAddress()) {
+ Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
+ Query.notifySymbolReady();
+ NewSymbolsResolved = true;
+ } else {
+ ES.legacyFailQuery(Query, Addr.takeError());
+ return SymbolNameSet();
+ }
+ } else if (auto Err = Sym.takeError()) {
+ ES.legacyFailQuery(Query, std::move(Err));
+ return SymbolNameSet();
+ } else
+ SymbolsNotFound.insert(S);
+ }
+
+ if (NewSymbolsResolved && Query.isFullyResolved())
+ Query.handleFullyResolved();
+
+ if (NewSymbolsResolved && Query.isFullyReady())
+ Query.handleFullyReady();
+
+ return SymbolsNotFound;
+}
+
+/// An ORC SymbolResolver implementation that uses a legacy
+/// findSymbol-like function to perform lookup;
+template <typename LegacyLookupFn>
+class LegacyLookupFnResolver final : public SymbolResolver {
+public:
+ using ErrorReporter = std::function<void(Error)>;
+
+ LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
+ ErrorReporter ReportError)
+ : ES(ES), LegacyLookup(std::move(LegacyLookup)),
+ ReportError(std::move(ReportError)) {}
+
+ SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
+ if (auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup))
+ return std::move(*SymbolFlags);
+ else {
+ ReportError(SymbolFlags.takeError());
+ return SymbolFlagsMap();
+ }
+ }
+
+ SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
+ SymbolNameSet Symbols) final {
+ return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
+ }
+
+private:
+ ExecutionSession &ES;
+ LegacyLookupFn LegacyLookup;
+ ErrorReporter ReportError;
+};
+
+template <typename LegacyLookupFn>
+std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
+createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
+ std::function<void(Error)> ErrorReporter) {
+ return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
+ ES, std::move(LegacyLookup), std::move(ErrorReporter));
+}
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h
index 957b94912b3f..3dd3cfe05b8d 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h
@@ -15,14 +15,23 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
#define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
namespace llvm {
namespace orc {
+class NullResolver : public SymbolResolver {
+public:
+ SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) override;
+
+ SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
+ SymbolNameSet Symbols) override;
+};
+
/// SymbolResolver impliementation that rejects all resolution requests.
/// Useful for clients that have no cross-object fixups.
-class NullResolver : public JITSymbolResolver {
+class NullLegacyResolver : public LegacyJITSymbolResolver {
public:
JITSymbol findSymbol(const std::string &Name) final;
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
index cb47e7520b1a..c6b43a9c8ed6 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
@@ -15,6 +15,7 @@
#define LLVM_EXECUTIONENGINE_ORC_OBJECTTRANSFORMLAYER_H
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include <algorithm>
#include <memory>
#include <string>
@@ -22,7 +23,24 @@
namespace llvm {
namespace orc {
-/// @brief Object mutating layer.
+class ObjectTransformLayer2 : public ObjectLayer {
+public:
+ using TransformFunction =
+ std::function<Expected<std::unique_ptr<MemoryBuffer>>(
+ std::unique_ptr<MemoryBuffer>)>;
+
+ ObjectTransformLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer,
+ TransformFunction Transform);
+
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<MemoryBuffer> O) override;
+
+private:
+ ObjectLayer &BaseLayer;
+ TransformFunction Transform;
+};
+
+/// Object mutating layer.
///
/// This layer accepts sets of ObjectFiles (via addObject). It
/// immediately applies the user supplied functor to each object, then adds
@@ -30,29 +48,24 @@ namespace orc {
template <typename BaseLayerT, typename TransformFtor>
class ObjectTransformLayer {
public:
- /// @brief Handle to a set of added objects.
- using ObjHandleT = typename BaseLayerT::ObjHandleT;
-
- /// @brief Construct an ObjectTransformLayer with the given BaseLayer
+ /// Construct an ObjectTransformLayer with the given BaseLayer
ObjectTransformLayer(BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor())
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
- /// @brief Apply the transform functor to each object in the object set, then
+ /// Apply the transform functor to each object in the object set, then
/// add the resulting set of objects to the base layer, along with the
/// memory manager and symbol resolver.
///
/// @return A handle for the added objects.
- template <typename ObjectPtr>
- Expected<ObjHandleT> addObject(ObjectPtr Obj,
- std::shared_ptr<JITSymbolResolver> Resolver) {
- return BaseLayer.addObject(Transform(std::move(Obj)), std::move(Resolver));
+ template <typename ObjectPtr> Error addObject(VModuleKey K, ObjectPtr Obj) {
+ return BaseLayer.addObject(std::move(K), Transform(std::move(Obj)));
}
- /// @brief Remove the object set associated with the handle H.
- Error removeObject(ObjHandleT H) { return BaseLayer.removeObject(H); }
+ /// Remove the object set associated with the VModuleKey K.
+ Error removeObject(VModuleKey K) { return BaseLayer.removeObject(K); }
- /// @brief Search for the given named symbol.
+ /// 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.
@@ -60,36 +73,34 @@ public:
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of the given symbol in the context of the set of
- /// objects represented by the handle H. This call is forwarded to the
- /// base layer's implementation.
- /// @param H The handle for the object set to search in.
+ /// Get the address of the given symbol in the context of the set of
+ /// objects represented by the VModuleKey K. This call is forwarded to
+ /// the base layer's implementation.
+ /// @param K The VModuleKey associated with 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(ObjHandleT H, const std::string &Name,
+ JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
+ return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
- /// @brief Immediately emit and finalize the object set represented by the
- /// given handle.
- /// @param H Handle for object set to emit/finalize.
- Error emitAndFinalize(ObjHandleT H) {
- return BaseLayer.emitAndFinalize(H);
- }
+ /// Immediately emit and finalize the object set represented by the
+ /// given VModuleKey K.
+ Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
- /// @brief Map section addresses for the objects associated with the handle H.
- void mapSectionAddress(ObjHandleT H, const void *LocalAddress,
+ /// Map section addresses for the objects associated with the
+ /// VModuleKey K.
+ void mapSectionAddress(VModuleKey K, const void *LocalAddress,
JITTargetAddress TargetAddr) {
- BaseLayer.mapSectionAddress(H, LocalAddress, TargetAddr);
+ BaseLayer.mapSectionAddress(K, LocalAddress, TargetAddr);
}
- /// @brief Access the transform functor directly.
+ /// Access the transform functor directly.
TransformFtor &getTransform() { return Transform; }
- /// @brief Access the mumate functor directly.
+ /// Access the mumate functor directly.
const TransformFtor &getTransform() const { return Transform; }
private:
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
index e1b55649b9f2..581c598aff62 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
@@ -71,7 +71,7 @@ public:
}
};
-/// @brief Provide information about stub blocks generated by the
+/// Provide information about stub blocks generated by the
/// makeIndirectStubsBlock function.
template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
public:
@@ -92,16 +92,16 @@ public:
return *this;
}
- /// @brief Number of stubs in this block.
+ /// Number of stubs in this block.
unsigned getNumStubs() const { return NumStubs; }
- /// @brief Get a pointer to the stub at the given index, which must be in
+ /// Get a pointer to the stub at the given index, which must be in
/// the range 0 .. getNumStubs() - 1.
void *getStub(unsigned Idx) const {
return static_cast<char *>(StubsMem.base()) + Idx * StubSize;
}
- /// @brief Get a pointer to the implementation-pointer at the given index,
+ /// Get a pointer to the implementation-pointer at the given index,
/// which must be in the range 0 .. getNumStubs() - 1.
void **getPtr(unsigned Idx) const {
char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
@@ -124,18 +124,18 @@ public:
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
+ /// Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
- /// @brief Write the requsted number of trampolines into the given memory,
+ /// Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines);
- /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+ /// Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
@@ -145,7 +145,7 @@ public:
unsigned MinStubs, void *InitialPtrVal);
};
-/// @brief X86_64 code that's common to all ABIs.
+/// X86_64 code that's common to all ABIs.
///
/// X86_64 supports lazy JITing.
class OrcX86_64_Base {
@@ -155,13 +155,13 @@ public:
using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
- /// @brief Write the requsted number of trampolines into the given memory,
+ /// Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines);
- /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+ /// Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
@@ -171,7 +171,7 @@ public:
unsigned MinStubs, void *InitialPtrVal);
};
-/// @brief X86_64 support for SysV ABI (Linux, MacOSX).
+/// X86_64 support for SysV ABI (Linux, MacOSX).
///
/// X86_64_SysV supports lazy JITing.
class OrcX86_64_SysV : public OrcX86_64_Base {
@@ -181,13 +181,13 @@ public:
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
+ /// Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
};
-/// @brief X86_64 support for Win32.
+/// X86_64 support for Win32.
///
/// X86_64_Win32 supports lazy JITing.
class OrcX86_64_Win32 : public OrcX86_64_Base {
@@ -197,13 +197,13 @@ public:
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
+ /// Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
};
-/// @brief I386 support.
+/// I386 support.
///
/// I386 supports lazy JITing.
class OrcI386 {
@@ -217,18 +217,18 @@ public:
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
+ /// Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
- /// @brief Write the requsted number of trampolines into the given memory,
+ /// Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines);
- /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+ /// Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h
index e1ac87075ac0..dc60e8d74e97 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h
@@ -22,7 +22,9 @@ namespace orc {
enum class OrcErrorCode : int {
// RPC Errors
- JITSymbolNotFound = 1,
+ UnknownORCError = 1,
+ DuplicateDefinition,
+ JITSymbolNotFound,
RemoteAllocatorDoesNotExist,
RemoteAllocatorIdAlreadyInUse,
RemoteMProtectAddrUnrecognized,
@@ -39,6 +41,18 @@ enum class OrcErrorCode : int {
std::error_code orcError(OrcErrorCode ErrCode);
+class DuplicateDefinition : public ErrorInfo<DuplicateDefinition> {
+public:
+ static char ID;
+
+ DuplicateDefinition(std::string SymbolName);
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+ const std::string &getSymbolName() const;
+private:
+ std::string SymbolName;
+};
+
class JITSymbolNotFound : public ErrorInfo<JITSymbolNotFound> {
public:
static char ID;
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index 7179e5ff66fd..739e5ba47c12 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -63,7 +63,7 @@ public:
public:
~RemoteRTDyldMemoryManager() {
Client.destroyRemoteAllocator(Id);
- DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
+ LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
}
RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
@@ -79,9 +79,9 @@ public:
Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
uint8_t *Alloc = reinterpret_cast<uint8_t *>(
Unmapped.back().CodeAllocs.back().getLocalAddress());
- DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
- << SectionName << ": " << Alloc << " (" << Size
- << " bytes, alignment " << Alignment << ")\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
+ << SectionName << ": " << Alloc << " (" << Size
+ << " bytes, alignment " << Alignment << ")\n");
return Alloc;
}
@@ -92,18 +92,18 @@ public:
Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
uint8_t *Alloc = reinterpret_cast<uint8_t *>(
Unmapped.back().RODataAllocs.back().getLocalAddress());
- DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
- << SectionName << ": " << Alloc << " (" << Size
- << " bytes, alignment " << Alignment << ")\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
+ << SectionName << ": " << Alloc << " (" << Size
+ << " bytes, alignment " << Alignment << ")\n");
return Alloc;
} // else...
Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
uint8_t *Alloc = reinterpret_cast<uint8_t *>(
Unmapped.back().RWDataAllocs.back().getLocalAddress());
- DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
- << SectionName << ": " << Alloc << " (" << Size
- << " bytes, alignment " << Alignment << ")\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
+ << SectionName << ": " << Alloc << " (" << Size
+ << " bytes, alignment " << Alignment << ")\n");
return Alloc;
}
@@ -113,36 +113,36 @@ public:
uint32_t RWDataAlign) override {
Unmapped.push_back(ObjectAllocs());
- DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
if (CodeSize != 0) {
Unmapped.back().RemoteCodeAddr =
Client.reserveMem(Id, CodeSize, CodeAlign);
- DEBUG(dbgs() << " code: "
- << format("0x%016x", Unmapped.back().RemoteCodeAddr)
- << " (" << CodeSize << " bytes, alignment " << CodeAlign
- << ")\n");
+ LLVM_DEBUG(dbgs() << " code: "
+ << format("0x%016x", Unmapped.back().RemoteCodeAddr)
+ << " (" << CodeSize << " bytes, alignment "
+ << CodeAlign << ")\n");
}
if (RODataSize != 0) {
Unmapped.back().RemoteRODataAddr =
Client.reserveMem(Id, RODataSize, RODataAlign);
- DEBUG(dbgs() << " ro-data: "
- << format("0x%016x", Unmapped.back().RemoteRODataAddr)
- << " (" << RODataSize << " bytes, alignment "
- << RODataAlign << ")\n");
+ LLVM_DEBUG(dbgs() << " ro-data: "
+ << format("0x%016x", Unmapped.back().RemoteRODataAddr)
+ << " (" << RODataSize << " bytes, alignment "
+ << RODataAlign << ")\n");
}
if (RWDataSize != 0) {
Unmapped.back().RemoteRWDataAddr =
Client.reserveMem(Id, RWDataSize, RWDataAlign);
- DEBUG(dbgs() << " rw-data: "
- << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
- << " (" << RWDataSize << " bytes, alignment "
- << RWDataAlign << ")\n");
+ LLVM_DEBUG(dbgs() << " rw-data: "
+ << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
+ << " (" << RWDataSize << " bytes, alignment "
+ << RWDataAlign << ")\n");
}
}
@@ -162,7 +162,7 @@ public:
void notifyObjectLoaded(RuntimeDyld &Dyld,
const object::ObjectFile &Obj) override {
- DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
for (auto &ObjAllocs : Unmapped) {
mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
ObjAllocs.RemoteCodeAddr);
@@ -176,7 +176,7 @@ public:
}
bool finalizeMemory(std::string *ErrMsg = nullptr) override {
- DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
for (auto &ObjAllocs : Unfinalized) {
if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
@@ -261,7 +261,7 @@ public:
RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
ResourceIdMgr::ResourceId Id)
: Client(Client), Id(Id) {
- DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
+ LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
}
// Maps all allocations in Allocs to aligned blocks
@@ -270,8 +270,9 @@ public:
for (auto &Alloc : Allocs) {
NextAddr = alignTo(NextAddr, Alloc.getAlign());
Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
- DEBUG(dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress())
- << " -> " << format("0x%016x", NextAddr) << "\n");
+ LLVM_DEBUG(dbgs() << " "
+ << static_cast<void *>(Alloc.getLocalAddress())
+ << " -> " << format("0x%016x", NextAddr) << "\n");
Alloc.setRemoteAddress(NextAddr);
// Only advance NextAddr if it was non-null to begin with,
@@ -290,22 +291,23 @@ public:
assert(!Allocs.empty() && "No sections in allocated segment");
for (auto &Alloc : Allocs) {
- DEBUG(dbgs() << " copying section: "
- << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
- << format("0x%016x", Alloc.getRemoteAddress()) << " ("
- << Alloc.getSize() << " bytes)\n";);
+ LLVM_DEBUG(dbgs() << " copying section: "
+ << static_cast<void *>(Alloc.getLocalAddress())
+ << " -> "
+ << format("0x%016x", Alloc.getRemoteAddress())
+ << " (" << Alloc.getSize() << " bytes)\n";);
if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
Alloc.getSize()))
return true;
}
- DEBUG(dbgs() << " setting "
- << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
- << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
- << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
- << " permissions on block: "
- << format("0x%016x", RemoteSegmentAddr) << "\n");
+ LLVM_DEBUG(dbgs() << " setting "
+ << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
+ << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
+ << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
+ << " permissions on block: "
+ << format("0x%016x", RemoteSegmentAddr) << "\n");
if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
return true;
}
@@ -356,25 +358,25 @@ public:
return Error::success();
}
- JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
+ JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
auto Key = I->second.first;
auto Flags = I->second.second;
- auto StubSymbol = JITSymbol(getStubAddr(Key), Flags);
+ auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags);
if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
return nullptr;
return StubSymbol;
}
- JITSymbol findPointer(StringRef Name) override {
+ JITEvaluatedSymbol findPointer(StringRef Name) override {
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
auto Key = I->second.first;
auto Flags = I->second.second;
- return JITSymbol(getPtrAddr(Key), Flags);
+ return JITEvaluatedSymbol(getPtrAddr(Key), Flags);
}
Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
@@ -449,8 +451,9 @@ public:
class RemoteCompileCallbackManager : public JITCompileCallbackManager {
public:
RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
+ ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {}
+ : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {}
private:
Error grow() override {
@@ -475,10 +478,10 @@ public:
/// Channel is the ChannelT instance to communicate on. It is assumed that
/// the channel is ready to be read from and written to.
static Expected<std::unique_ptr<OrcRemoteTargetClient>>
- Create(rpc::RawByteChannel &Channel, std::function<void(Error)> ReportError) {
+ Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) {
Error Err = Error::success();
auto Client = std::unique_ptr<OrcRemoteTargetClient>(
- new OrcRemoteTargetClient(Channel, std::move(ReportError), Err));
+ new OrcRemoteTargetClient(Channel, ES, Err));
if (Err)
return std::move(Err);
return std::move(Client);
@@ -487,7 +490,8 @@ public:
/// Call the int(void) function at the given address in the target and return
/// its result.
Expected<int> callIntVoid(JITTargetAddress Addr) {
- DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
+ LLVM_DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr)
+ << "\n");
return callB<exec::CallIntVoid>(Addr);
}
@@ -495,16 +499,16 @@ public:
/// return its result.
Expected<int> callMain(JITTargetAddress Addr,
const std::vector<std::string> &Args) {
- DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
- << "\n");
+ LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
+ << format("0x%016x", Addr) << "\n");
return callB<exec::CallMain>(Addr, Args);
}
/// Call the void() function at the given address in the target and wait for
/// it to finish.
Error callVoidVoid(JITTargetAddress Addr) {
- DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
- << "\n");
+ LLVM_DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
+ << "\n");
return callB<exec::CallVoidVoid>(Addr);
}
@@ -531,12 +535,14 @@ public:
Expected<RemoteCompileCallbackManager &>
enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
+ assert(!CallbackManager && "CallbackManager already obtained");
+
// Emit the resolver block on the JIT server.
if (auto Err = callB<stubs::EmitResolverBlock>())
return std::move(Err);
// Create the callback manager.
- CallbackManager.emplace(*this, ErrorHandlerAddress);
+ CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
RemoteCompileCallbackManager &Mgr = *CallbackManager;
return Mgr;
}
@@ -554,10 +560,10 @@ public:
Error terminateSession() { return callB<utils::TerminateSession>(); }
private:
- OrcRemoteTargetClient(rpc::RawByteChannel &Channel,
- std::function<void(Error)> ReportError, Error &Err)
+ OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
+ Error &Err)
: rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
- ReportError(std::move(ReportError)) {
+ ES(ES) {
ErrorAsOutParameter EAO(&Err);
addHandler<utils::RequestCompile>(
@@ -577,7 +583,7 @@ private:
void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
- ReportError(std::move(Err));
+ ES.reportError(std::move(Err));
}
void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
@@ -592,7 +598,7 @@ private:
void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
IndirectStubOwnerIds.release(Id);
if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
- ReportError(std::move(Err));
+ ES.reportError(std::move(Err));
}
Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
@@ -625,7 +631,7 @@ private:
if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
return *AddrOrErr;
else {
- ReportError(AddrOrErr.takeError());
+ ES.reportError(AddrOrErr.takeError());
return 0;
}
}
@@ -633,7 +639,7 @@ private:
bool setProtections(ResourceIdMgr::ResourceId Id,
JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
- ReportError(std::move(Err));
+ ES.reportError(std::move(Err));
return true;
} else
return false;
@@ -641,7 +647,7 @@ private:
bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
- ReportError(std::move(Err));
+ ES.reportError(std::move(Err));
return true;
} else
return false;
@@ -653,6 +659,7 @@ private:
static Error doNothing() { return Error::success(); }
+ ExecutionSession &ES;
std::function<void(Error)> ReportError;
std::string RemoteTargetTriple;
uint32_t RemotePointerSize = 0;
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
index cf419d33004c..acbc1682fa5d 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
@@ -161,9 +161,9 @@ private:
IntVoidFnTy Fn =
reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));
- DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
+ LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
int Result = Fn();
- DEBUG(dbgs() << " Result = " << Result << "\n");
+ LLVM_DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
}
@@ -180,15 +180,13 @@ private:
for (auto &Arg : Args)
ArgV[Idx++] = Arg.c_str();
ArgV[ArgC] = 0;
- DEBUG(
- for (int Idx = 0; Idx < ArgC; ++Idx) {
- llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n";
- }
- );
+ LLVM_DEBUG(for (int Idx = 0; Idx < ArgC; ++Idx) {
+ llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n";
+ });
- DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
+ LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
int Result = Fn(ArgC, ArgV.get());
- DEBUG(dbgs() << " Result = " << Result << "\n");
+ LLVM_DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
}
@@ -199,9 +197,9 @@ private:
VoidVoidFnTy Fn =
reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));
- DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
+ LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
Fn();
- DEBUG(dbgs() << " Complete.\n");
+ LLVM_DEBUG(dbgs() << " Complete.\n");
return Error::success();
}
@@ -211,7 +209,7 @@ private:
if (I != Allocators.end())
return errorCodeToError(
orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse));
- DEBUG(dbgs() << " Created allocator " << Id << "\n");
+ LLVM_DEBUG(dbgs() << " Created allocator " << Id << "\n");
Allocators[Id] = Allocator();
return Error::success();
}
@@ -221,15 +219,16 @@ private:
if (I != IndirectStubsOwners.end())
return errorCodeToError(
orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse));
- DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
+ LLVM_DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
IndirectStubsOwners[Id] = ISBlockOwnerList();
return Error::success();
}
Error handleDeregisterEHFrames(JITTargetAddress TAddr, uint32_t Size) {
uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
- DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
- << ", Size = " << Size << " bytes\n");
+ LLVM_DEBUG(dbgs() << " Registering EH frames at "
+ << format("0x%016x", TAddr) << ", Size = " << Size
+ << " bytes\n");
EHFramesDeregister(Addr, Size);
return Error::success();
}
@@ -240,7 +239,7 @@ private:
return errorCodeToError(
orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
Allocators.erase(I);
- DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");
+ LLVM_DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");
return Error::success();
}
@@ -256,8 +255,8 @@ private:
Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
uint32_t NumStubsRequired) {
- DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
- << " stubs.\n");
+ LLVM_DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
+ << " stubs.\n");
auto StubOwnerItr = IndirectStubsOwners.find(Id);
if (StubOwnerItr == IndirectStubsOwners.end())
@@ -328,8 +327,8 @@ private:
Expected<JITTargetAddress> handleGetSymbolAddress(const std::string &Name) {
JITTargetAddress Addr = SymbolLookup(Name);
- DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr)
- << "\n");
+ LLVM_DEBUG(dbgs() << " Symbol '" << Name
+ << "' = " << format("0x%016x", Addr) << "\n");
return Addr;
}
@@ -340,12 +339,13 @@ private:
uint32_t PageSize = sys::Process::getPageSize();
uint32_t TrampolineSize = TargetT::TrampolineSize;
uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize;
- DEBUG(dbgs() << " Remote info:\n"
- << " triple = '" << ProcessTriple << "'\n"
- << " pointer size = " << PointerSize << "\n"
- << " page size = " << PageSize << "\n"
- << " trampoline size = " << TrampolineSize << "\n"
- << " indirect stub size = " << IndirectStubSize << "\n");
+ LLVM_DEBUG(dbgs() << " Remote info:\n"
+ << " triple = '" << ProcessTriple << "'\n"
+ << " pointer size = " << PointerSize << "\n"
+ << " page size = " << PageSize << "\n"
+ << " trampoline size = " << TrampolineSize << "\n"
+ << " indirect stub size = " << IndirectStubSize
+ << "\n");
return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize,
IndirectStubSize);
}
@@ -354,8 +354,8 @@ private:
uint64_t Size) {
uint8_t *Src = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(RSrc));
- DEBUG(dbgs() << " Reading " << Size << " bytes from "
- << format("0x%016x", RSrc) << "\n");
+ LLVM_DEBUG(dbgs() << " Reading " << Size << " bytes from "
+ << format("0x%016x", RSrc) << "\n");
std::vector<uint8_t> Buffer;
Buffer.resize(Size);
@@ -367,8 +367,9 @@ private:
Error handleRegisterEHFrames(JITTargetAddress TAddr, uint32_t Size) {
uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
- DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
- << ", Size = " << Size << " bytes\n");
+ LLVM_DEBUG(dbgs() << " Registering EH frames at "
+ << format("0x%016x", TAddr) << ", Size = " << Size
+ << " bytes\n");
EHFramesRegister(Addr, Size);
return Error::success();
}
@@ -384,8 +385,9 @@ private:
if (auto Err = Allocator.allocate(LocalAllocAddr, Size, Align))
return std::move(Err);
- DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr
- << " (" << Size << " bytes, alignment " << Align << ")\n");
+ LLVM_DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr
+ << " (" << Size << " bytes, alignment " << Align
+ << ")\n");
JITTargetAddress AllocAddr = static_cast<JITTargetAddress>(
reinterpret_cast<uintptr_t>(LocalAllocAddr));
@@ -401,10 +403,11 @@ private:
orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
auto &Allocator = I->second;
void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
- DEBUG(dbgs() << " Allocator " << Id << " set permissions on " << LocalAddr
- << " to " << (Flags & sys::Memory::MF_READ ? 'R' : '-')
- << (Flags & sys::Memory::MF_WRITE ? 'W' : '-')
- << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");
+ LLVM_DEBUG(dbgs() << " Allocator " << Id << " set permissions on "
+ << LocalAddr << " to "
+ << (Flags & sys::Memory::MF_READ ? 'R' : '-')
+ << (Flags & sys::Memory::MF_WRITE ? 'W' : '-')
+ << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");
return Allocator.setProtections(LocalAddr, Flags);
}
@@ -414,14 +417,14 @@ private:
}
Error handleWriteMem(DirectBufferWriter DBW) {
- DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
- << format("0x%016x", DBW.getDst()) << "\n");
+ LLVM_DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
+ << format("0x%016x", DBW.getDst()) << "\n");
return Error::success();
}
Error handleWritePtr(JITTargetAddress Addr, JITTargetAddress PtrVal) {
- DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr) << " = "
- << format("0x%016x", PtrVal) << "\n");
+ LLVM_DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr)
+ << " = " << format("0x%016x", PtrVal) << "\n");
uintptr_t *Ptr =
reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));
*Ptr = static_cast<uintptr_t>(PtrVal);
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h
index c278cb176853..47bd90bb1bad 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h
@@ -1631,7 +1631,7 @@ RPCAsyncDispatch<RPCEndpointT, Func> rpcAsyncDispatch(RPCEndpointT &Endpoint) {
return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint);
}
-/// \brief Allows a set of asynchrounous calls to be dispatched, and then
+/// Allows a set of asynchrounous calls to be dispatched, and then
/// waited on as a group.
class ParallelCallGroup {
public:
@@ -1640,7 +1640,7 @@ public:
ParallelCallGroup(const ParallelCallGroup &) = delete;
ParallelCallGroup &operator=(const ParallelCallGroup &) = delete;
- /// \brief Make as asynchronous call.
+ /// Make as asynchronous call.
template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs>
Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler,
const ArgTs &... Args) {
@@ -1669,7 +1669,7 @@ public:
return AsyncDispatch(std::move(WrappedHandler), Args...);
}
- /// \brief Blocks until all calls have been completed and their return value
+ /// Blocks until all calls have been completed and their return value
/// handlers run.
void wait() {
std::unique_lock<std::mutex> Lock(M);
@@ -1683,21 +1683,21 @@ private:
uint32_t NumOutstandingCalls = 0;
};
-/// @brief Convenience class for grouping RPC Functions into APIs that can be
+/// Convenience class for grouping RPC Functions into APIs that can be
/// negotiated as a block.
///
template <typename... Funcs>
class APICalls {
public:
- /// @brief Test whether this API contains Function F.
+ /// Test whether this API contains Function F.
template <typename F>
class Contains {
public:
static const bool value = false;
};
- /// @brief Negotiate all functions in this API.
+ /// Negotiate all functions in this API.
template <typename RPCEndpoint>
static Error negotiate(RPCEndpoint &R) {
return Error::success();
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index 246c57341f35..48b3f7a58ed7 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -18,6 +18,9 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
@@ -33,15 +36,62 @@
namespace llvm {
namespace orc {
-class RTDyldObjectLinkingLayerBase {
+class RTDyldObjectLinkingLayer2 : public ObjectLayer {
public:
+ /// Functor for receiving object-loaded notifications.
+ using NotifyLoadedFunction =
+ std::function<void(VModuleKey, const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &)>;
+
+ /// Functor for receiving finalization notifications.
+ using NotifyFinalizedFunction = std::function<void(VModuleKey)>;
- using ObjectPtr =
- std::shared_ptr<object::OwningBinary<object::ObjectFile>>;
+ using GetMemoryManagerFunction =
+ std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>;
+
+ /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
+ /// and NotifyFinalized functors.
+ RTDyldObjectLinkingLayer2(
+ ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
+ NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
+ NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction());
+
+ /// Emit the object.
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<MemoryBuffer> O) override;
+
+ /// Map section addresses for the object associated with the
+ /// VModuleKey K.
+ void mapSectionAddress(VModuleKey K, const void *LocalAddress,
+ JITTargetAddress TargetAddr) const;
+
+ /// Set the 'ProcessAllSections' flag.
+ ///
+ /// If set to true, all sections in each object file will be allocated using
+ /// the memory manager, rather than just the sections required for execution.
+ ///
+ /// This is kludgy, and may be removed in the future.
+ void setProcessAllSections(bool ProcessAllSections) {
+ this->ProcessAllSections = ProcessAllSections;
+ }
+
+private:
+ mutable std::mutex RTDyldLayerMutex;
+ GetMemoryManagerFunction GetMemoryManager;
+ NotifyLoadedFunction NotifyLoaded;
+ NotifyFinalizedFunction NotifyFinalized;
+ bool ProcessAllSections;
+ std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds;
+ std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
+};
+
+class RTDyldObjectLinkingLayerBase {
+public:
+ using ObjectPtr = std::unique_ptr<MemoryBuffer>;
protected:
- /// @brief Holds an object to be allocated/linked as a unit in the JIT.
+ /// Holds an object to be allocated/linked as a unit in the JIT.
///
/// An instance of this class will be created for each object added
/// via JITObjectLayer::addObject. Deleting the instance (via
@@ -55,7 +105,7 @@ protected:
void operator=(const LinkedObject&) = delete;
virtual ~LinkedObject() = default;
- virtual void finalize() = 0;
+ virtual Error finalize() = 0;
virtual JITSymbol::GetAddressFtor
getSymbolMaterializer(std::string Name) = 0;
@@ -79,15 +129,9 @@ protected:
StringMap<JITEvaluatedSymbol> SymbolTable;
bool Finalized = false;
};
-
- using LinkedObjectListT = std::list<std::unique_ptr<LinkedObject>>;
-
-public:
- /// @brief Handle to a loaded object.
- using ObjHandleT = LinkedObjectListT::iterator;
};
-/// @brief Bare bones object linking layer.
+/// 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
@@ -98,67 +142,93 @@ public:
using RTDyldObjectLinkingLayerBase::ObjectPtr;
- /// @brief Functor for receiving object-loaded notifications.
+ /// Functor for receiving object-loaded notifications.
using NotifyLoadedFtor =
- std::function<void(ObjHandleT, const ObjectPtr &Obj,
- const RuntimeDyld::LoadedObjectInfo &)>;
+ std::function<void(VModuleKey, const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &)>;
- /// @brief Functor for receiving finalization notifications.
- using NotifyFinalizedFtor = std::function<void(ObjHandleT)>;
+ /// Functor for receiving finalization notifications.
+ using NotifyFinalizedFtor =
+ std::function<void(VModuleKey, const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &)>;
-private:
+ /// Functor for receiving deallocation notifications.
+ using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
+private:
+ using OwnedObject = object::OwningBinary<object::ObjectFile>;
- template <typename MemoryManagerPtrT, typename SymbolResolverPtrT,
- typename FinalizerFtor>
+ template <typename MemoryManagerPtrT>
class ConcreteLinkedObject : public LinkedObject {
public:
- ConcreteLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr,
- SymbolResolverPtrT Resolver,
- FinalizerFtor Finalizer,
+ ConcreteLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
+ OwnedObject Obj, MemoryManagerPtrT MemMgr,
+ std::shared_ptr<SymbolResolver> Resolver,
bool ProcessAllSections)
- : MemMgr(std::move(MemMgr)),
- PFC(llvm::make_unique<PreFinalizeContents>(std::move(Obj),
- std::move(Resolver),
- std::move(Finalizer),
- ProcessAllSections)) {
+ : K(std::move(K)),
+ Parent(Parent),
+ MemMgr(std::move(MemMgr)),
+ PFC(llvm::make_unique<PreFinalizeContents>(
+ std::move(Obj), std::move(Resolver),
+ ProcessAllSections)) {
buildInitialSymbolTable(PFC->Obj);
}
~ConcreteLinkedObject() override {
- MemMgr->deregisterEHFrames();
- }
+ if (this->Parent.NotifyFreed)
+ this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
- void setHandle(ObjHandleT H) {
- PFC->Handle = H;
+ MemMgr->deregisterEHFrames();
}
- void finalize() override {
+ Error finalize() override {
assert(PFC && "mapSectionAddress called on finalized LinkedObject");
- RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);
- RTDyld.setProcessAllSections(PFC->ProcessAllSections);
- PFC->RTDyld = &RTDyld;
+ JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
+ nullptr);
+ PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
+ PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
+
+ Finalized = true;
+
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
+ PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
+
+ // Copy the symbol table out of the RuntimeDyld instance.
+ {
+ auto SymTab = PFC->RTDyld->getSymbolTable();
+ for (auto &KV : SymTab)
+ SymbolTable[KV.first] = KV.second;
+ }
+
+ if (Parent.NotifyLoaded)
+ Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
+
+ PFC->RTDyld->finalizeWithMemoryManagerLocking();
+
+ if (PFC->RTDyld->hasError())
+ return make_error<StringError>(PFC->RTDyld->getErrorString(),
+ inconvertibleErrorCode());
- this->Finalized = true;
- PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Obj),
- [&]() {
- this->updateSymbolTable(RTDyld);
- });
+ if (Parent.NotifyFinalized)
+ Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
// Release resources.
+ if (this->Parent.NotifyFreed)
+ ObjForNotify = std::move(PFC->Obj); // needed for callback
PFC = nullptr;
+ return Error::success();
}
JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
- return
- [this, Name]() {
- // The symbol may be materialized between the creation of this lambda
- // and its execution, so we need to double check.
- if (!this->Finalized)
- this->finalize();
- return this->getSymbol(Name, false).getAddress();
- };
+ return [this, Name]() -> Expected<JITTargetAddress> {
+ // The symbol may be materialized between the creation of this lambda
+ // and its execution, so we need to double check.
+ if (!this->Finalized)
+ if (auto Err = this->finalize())
+ return std::move(Err);
+ return this->getSymbol(Name, false).getAddress();
+ };
}
void mapSectionAddress(const void *LocalAddress,
@@ -169,9 +239,8 @@ private:
}
private:
-
- void buildInitialSymbolTable(const ObjectPtr &Obj) {
- for (auto &Symbol : Obj->getBinary()->symbols()) {
+ void buildInitialSymbolTable(const OwnedObject &Obj) {
+ for (auto &Symbol : Obj.getBinary()->symbols()) {
if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
continue;
Expected<StringRef> SymbolName = Symbol.getName();
@@ -186,65 +255,64 @@ private:
}
}
- void updateSymbolTable(const RuntimeDyld &RTDyld) {
- for (auto &SymEntry : SymbolTable)
- SymEntry.second = RTDyld.getSymbol(SymEntry.first());
- }
-
// Contains the information needed prior to finalization: the object files,
// memory manager, resolver, and flags needed for RuntimeDyld.
struct PreFinalizeContents {
- PreFinalizeContents(ObjectPtr Obj, SymbolResolverPtrT Resolver,
- FinalizerFtor Finalizer, bool ProcessAllSections)
- : Obj(std::move(Obj)), Resolver(std::move(Resolver)),
- Finalizer(std::move(Finalizer)),
- ProcessAllSections(ProcessAllSections) {}
+ PreFinalizeContents(OwnedObject Obj,
+ std::shared_ptr<SymbolResolver> Resolver,
+ bool ProcessAllSections)
+ : Obj(std::move(Obj)),
+ Resolver(std::move(Resolver)),
+ ProcessAllSections(ProcessAllSections) {}
- ObjectPtr Obj;
- SymbolResolverPtrT Resolver;
- FinalizerFtor Finalizer;
+ OwnedObject Obj;
+ std::shared_ptr<SymbolResolver> Resolver;
bool ProcessAllSections;
- ObjHandleT Handle;
- RuntimeDyld *RTDyld;
+ std::unique_ptr<RuntimeDyld> RTDyld;
};
+ VModuleKey K;
+ RTDyldObjectLinkingLayer &Parent;
MemoryManagerPtrT MemMgr;
+ OwnedObject ObjForNotify;
std::unique_ptr<PreFinalizeContents> PFC;
};
- template <typename MemoryManagerPtrT, typename SymbolResolverPtrT,
- typename FinalizerFtor>
- std::unique_ptr<
- ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT, FinalizerFtor>>
- createLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr,
- SymbolResolverPtrT Resolver,
- FinalizerFtor Finalizer,
+ template <typename MemoryManagerPtrT>
+ std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
+ createLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
+ OwnedObject Obj, MemoryManagerPtrT MemMgr,
+ std::shared_ptr<SymbolResolver> Resolver,
bool ProcessAllSections) {
- using LOS = ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT,
- FinalizerFtor>;
- return llvm::make_unique<LOS>(std::move(Obj), std::move(MemMgr),
- std::move(Resolver), std::move(Finalizer),
+ using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
+ return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
+ std::move(MemMgr), std::move(Resolver),
ProcessAllSections);
}
public:
+ struct Resources {
+ std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
+ std::shared_ptr<SymbolResolver> Resolver;
+ };
- /// @brief Functor for creating memory managers.
- using MemoryManagerGetter =
- std::function<std::shared_ptr<RuntimeDyld::MemoryManager>()>;
+ using ResourcesGetter = std::function<Resources(VModuleKey)>;
- /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
+ /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyFinalized functors.
RTDyldObjectLinkingLayer(
- MemoryManagerGetter GetMemMgr,
+ ExecutionSession &ES, ResourcesGetter GetResources,
NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
- NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
- : GetMemMgr(GetMemMgr),
+ NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
+ NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
+ : ES(ES), GetResources(std::move(GetResources)),
NotifyLoaded(std::move(NotifyLoaded)),
NotifyFinalized(std::move(NotifyFinalized)),
- ProcessAllSections(false) {}
+ NotifyFreed(std::move(NotifyFreed)),
+ ProcessAllSections(false) {
+ }
- /// @brief Set the 'ProcessAllSections' flag.
+ /// Set the 'ProcessAllSections' flag.
///
/// If set to true, all sections in each object file will be allocated using
/// the memory manager, rather than just the sections required for execution.
@@ -254,44 +322,26 @@ public:
this->ProcessAllSections = ProcessAllSections;
}
- /// @brief Add an object to the JIT.
- ///
- /// @return A handle that can be used to refer to the loaded object (for
- /// symbol searching, finalization, freeing memory, etc.).
- Expected<ObjHandleT> addObject(ObjectPtr Obj,
- std::shared_ptr<JITSymbolResolver> Resolver) {
- auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld,
- const ObjectPtr &ObjToLoad,
- std::function<void()> LOSHandleLoad) {
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
- RTDyld.loadObject(*ObjToLoad->getBinary());
-
- LOSHandleLoad();
-
- if (this->NotifyLoaded)
- this->NotifyLoaded(H, ObjToLoad, *Info);
+ /// Add an object to the JIT.
+ Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
- RTDyld.finalizeWithMemoryManagerLocking();
+ auto Obj =
+ object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
+ if (!Obj)
+ return Obj.takeError();
- if (this->NotifyFinalized)
- this->NotifyFinalized(H);
- };
+ assert(!LinkedObjects.count(K) && "VModuleKey already in use");
- auto LO =
- createLinkedObject(std::move(Obj), GetMemMgr(),
- std::move(Resolver), std::move(Finalizer),
- ProcessAllSections);
- // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle
- // below.
- auto *LOPtr = LO.get();
+ auto R = GetResources(K);
- ObjHandleT Handle = LinkedObjList.insert(LinkedObjList.end(), std::move(LO));
- LOPtr->setHandle(Handle);
+ LinkedObjects[K] = createLinkedObject(
+ *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
+ std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
- return Handle;
+ return Error::success();
}
- /// @brief Remove the object associated with handle H.
+ /// Remove the object associated with VModuleKey K.
///
/// All memory allocated for the object will be freed, and the sections and
/// symbols it provided will no longer be available. No attempt is made to
@@ -299,57 +349,64 @@ public:
/// 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.
- Error removeObject(ObjHandleT H) {
+ Error removeObject(VModuleKey K) {
+ assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
// How do we invalidate the symbols in H?
- LinkedObjList.erase(H);
+ LinkedObjects.erase(K);
return Error::success();
}
- /// @brief Search for the given named symbol.
+ /// 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 = LinkedObjList.begin(), E = LinkedObjList.end(); I != E;
- ++I)
- if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
- return Symbol;
+ for (auto &KV : LinkedObjects)
+ if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
+ return Sym;
+ else if (auto Err = Sym.takeError())
+ return std::move(Err);
return nullptr;
}
- /// @brief Search for the given named symbol in the context of the loaded
- /// object represented by the handle H.
- /// @param H The handle for the object to search in.
+ /// Search for the given named symbol in the context of the loaded
+ /// object represented by the VModuleKey K.
+ /// @param K The VModuleKey for the object 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.
- JITSymbol findSymbolIn(ObjHandleT H, StringRef Name,
+ JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
bool ExportedSymbolsOnly) {
- return (*H)->getSymbol(Name, ExportedSymbolsOnly);
+ assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
+ return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Map section addresses for the object associated with the handle H.
- void mapSectionAddress(ObjHandleT H, const void *LocalAddress,
+ /// Map section addresses for the object associated with the
+ /// VModuleKey K.
+ void mapSectionAddress(VModuleKey K, const void *LocalAddress,
JITTargetAddress TargetAddr) {
- (*H)->mapSectionAddress(LocalAddress, TargetAddr);
+ assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
+ LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
}
- /// @brief Immediately emit and finalize the object represented by the given
- /// handle.
- /// @param H Handle for object to emit/finalize.
- Error emitAndFinalize(ObjHandleT H) {
- (*H)->finalize();
- return Error::success();
+ /// Immediately emit and finalize the object represented by the given
+ /// VModuleKey.
+ /// @param K VModuleKey for object to emit/finalize.
+ Error emitAndFinalize(VModuleKey K) {
+ assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
+ return LinkedObjects[K]->finalize();
}
private:
+ ExecutionSession &ES;
- LinkedObjectListT LinkedObjList;
- MemoryManagerGetter GetMemMgr;
+ std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
+ ResourcesGetter GetResources;
NotifyLoadedFtor NotifyLoaded;
NotifyFinalizedFtor NotifyFinalized;
+ NotifyFreedFtor NotifyFreed;
bool ProcessAllSections = false;
};
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
index 17255954a99f..955e77607a18 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
@@ -306,8 +306,7 @@ public:
using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
- using ObjectPtr =
- std::shared_ptr<object::OwningBinary<object::ObjectFile>>;
+ using ObjectPtr = std::unique_ptr<MemoryBuffer>;
/// Create a RemoteObjectClientLayer that communicates with a
/// RemoteObjectServerLayer instance via the given RPCEndpoint.
@@ -323,15 +322,15 @@ public:
*this, &ThisT::lookupInLogicalDylib);
}
- /// @brief Add an object to the JIT.
+ /// Add an object to the JIT.
///
/// @return A handle that can be used to refer to the loaded object (for
/// symbol searching, finalization, freeing memory, etc.).
Expected<ObjHandleT>
- addObject(ObjectPtr Object, std::shared_ptr<JITSymbolResolver> Resolver) {
- StringRef ObjBuffer = Object->getBinary()->getData();
+ addObject(ObjectPtr ObjBuffer,
+ std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
if (auto HandleOrErr =
- this->Remote.template callB<AddObject>(ObjBuffer)) {
+ this->Remote.template callB<AddObject>(ObjBuffer->getBuffer())) {
auto &Handle = *HandleOrErr;
// FIXME: Return an error for this:
assert(!Resolvers.count(Handle) && "Handle already in use?");
@@ -341,26 +340,26 @@ public:
return HandleOrErr.takeError();
}
- /// @brief Remove the given object from the JIT.
+ /// Remove the given object from the JIT.
Error removeObject(ObjHandleT H) {
return this->Remote.template callB<RemoveObject>(H);
}
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
return remoteToJITSymbol(
this->Remote.template callB<FindSymbol>(Name,
ExportedSymbolsOnly));
}
- /// @brief Search for the given named symbol within the given context.
+ /// Search for the given named symbol within the given context.
JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {
return remoteToJITSymbol(
this->Remote.template callB<FindSymbolIn>(H, Name,
ExportedSymbolsOnly));
}
- /// @brief Immediately emit and finalize the object with the given handle.
+ /// Immediately emit and finalize the object with the given handle.
Error emitAndFinalize(ObjHandleT H) {
return this->Remote.template callB<EmitAndFinalize>(H);
}
@@ -386,7 +385,8 @@ private:
}
std::map<remote::ResourceIdMgr::ResourceId,
- std::shared_ptr<JITSymbolResolver>> Resolvers;
+ std::shared_ptr<LegacyJITSymbolResolver>>
+ Resolvers;
};
/// RemoteObjectServerLayer acts as a server and handling RPC calls for the
@@ -459,30 +459,21 @@ private:
Expected<ObjHandleT> addObject(std::string ObjBuffer) {
auto Buffer = llvm::make_unique<StringMemoryBuffer>(std::move(ObjBuffer));
- if (auto ObjectOrErr =
- object::ObjectFile::createObjectFile(Buffer->getMemBufferRef())) {
- auto Object =
- std::make_shared<object::OwningBinary<object::ObjectFile>>(
- std::move(*ObjectOrErr), std::move(Buffer));
+ auto Id = HandleIdMgr.getNext();
+ assert(!BaseLayerHandles.count(Id) && "Id already in use?");
- auto Id = HandleIdMgr.getNext();
- assert(!BaseLayerHandles.count(Id) && "Id already in use?");
+ auto Resolver = createLambdaResolver(
+ [this, Id](const std::string &Name) { return lookup(Id, Name); },
+ [this, Id](const std::string &Name) {
+ return lookupInLogicalDylib(Id, Name);
+ });
- auto Resolver =
- createLambdaResolver(
- [this, Id](const std::string &Name) { return lookup(Id, Name); },
- [this, Id](const std::string &Name) {
- return lookupInLogicalDylib(Id, Name);
- });
-
- if (auto HandleOrErr =
- BaseLayer.addObject(std::move(Object), std::move(Resolver))) {
- BaseLayerHandles[Id] = std::move(*HandleOrErr);
- return Id;
- } else
- return teeLog(HandleOrErr.takeError());
+ if (auto HandleOrErr =
+ BaseLayer.addObject(std::move(Buffer), std::move(Resolver))) {
+ BaseLayerHandles[Id] = std::move(*HandleOrErr);
+ return Id;
} else
- return teeLog(ObjectOrErr.takeError());
+ return teeLog(HandleOrErr.takeError());
}
Error removeObject(ObjHandleT H) {
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
index b01fbd44bacd..4c45cfd199dd 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
@@ -23,29 +23,36 @@ namespace orc {
class SymbolStringPtr;
-/// @brief String pool for symbol names used by the JIT.
+/// String pool for symbol names used by the JIT.
class SymbolStringPool {
friend class SymbolStringPtr;
public:
- /// @brief Create a symbol string pointer from the given string.
+ /// Destroy a SymbolStringPool.
+ ~SymbolStringPool();
+
+ /// Create a symbol string pointer from the given string.
SymbolStringPtr intern(StringRef S);
- /// @brief Remove from the pool any entries that are no longer referenced.
+ /// Remove from the pool any entries that are no longer referenced.
void clearDeadEntries();
- /// @brief Returns true if the pool is empty.
+ /// Returns true if the pool is empty.
bool empty() const;
private:
- using RefCountType = std::atomic<uint64_t>;
+ using RefCountType = std::atomic<size_t>;
using PoolMap = StringMap<RefCountType>;
using PoolMapEntry = StringMapEntry<RefCountType>;
mutable std::mutex PoolMutex;
PoolMap Pool;
};
-/// @brief Pointer to a pooled string representing a symbol name.
+/// Pointer to a pooled string representing a symbol name.
class SymbolStringPtr {
friend class SymbolStringPool;
+ friend bool operator==(const SymbolStringPtr &LHS,
+ const SymbolStringPtr &RHS);
+ friend bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS);
+
public:
SymbolStringPtr() = default;
SymbolStringPtr(const SymbolStringPtr &Other)
@@ -80,17 +87,7 @@ public:
--S->getValue();
}
- bool operator==(const SymbolStringPtr &Other) const {
- return S == Other.S;
- }
-
- bool operator!=(const SymbolStringPtr &Other) const {
- return !(*this == Other);
- }
-
- bool operator<(const SymbolStringPtr &Other) const {
- return S->getValue() < Other.S->getValue();
- }
+ StringRef operator*() const { return S->first(); }
private:
@@ -103,25 +100,39 @@ private:
SymbolStringPool::PoolMapEntry *S = nullptr;
};
+inline bool operator==(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
+ return LHS.S == RHS.S;
+}
+
+inline bool operator!=(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
+ return !(LHS == RHS);
+}
+
+inline bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
+ return LHS.S < RHS.S;
+}
+
+inline SymbolStringPool::~SymbolStringPool() {
+#ifndef NDEBUG
+ clearDeadEntries();
+ assert(Pool.empty() && "Dangling references at pool destruction time");
+#endif // NDEBUG
+}
+
inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
std::lock_guard<std::mutex> Lock(PoolMutex);
- auto I = Pool.find(S);
- if (I != Pool.end())
- return SymbolStringPtr(&*I);
-
+ PoolMap::iterator I;
bool Added;
std::tie(I, Added) = Pool.try_emplace(S, 0);
- assert(Added && "Insert should always succeed here");
return SymbolStringPtr(&*I);
}
inline void SymbolStringPool::clearDeadEntries() {
std::lock_guard<std::mutex> Lock(PoolMutex);
for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
- auto Tmp = std::next(I);
- if (I->second == 0)
- Pool.erase(I);
- I = Tmp;
+ auto Tmp = I++;
+ if (Tmp->second == 0)
+ Pool.erase(Tmp);
}
}
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
index 0c1862c5c3ea..23d651f6d1b6 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
@@ -47,6 +47,9 @@ public:
/// newly loaded object.
virtual void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
+
+private:
+ void anchor() override;
};
// RuntimeDyld clients often want to handle the memory management of
@@ -56,7 +59,7 @@ public:
// FIXME: As the RuntimeDyld fills out, additional routines will be needed
// for the varying types of objects to be allocated.
class RTDyldMemoryManager : public MCJITMemoryManager,
- public JITSymbolResolver {
+ public LegacyJITSymbolResolver {
public:
RTDyldMemoryManager() = default;
RTDyldMemoryManager(const RTDyldMemoryManager&) = delete;
@@ -142,6 +145,9 @@ protected:
};
typedef std::vector<EHFrame> EHFrameInfos;
EHFrameInfos EHFrames;
+
+private:
+ void anchor() override;
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h
index 56aa04ce694a..5dd5add1bb39 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -65,7 +65,7 @@ protected:
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
public:
- /// \brief Information about the loaded object.
+ /// Information about the loaded object.
class LoadedObjectInfo : public llvm::LoadedObjectInfo {
friend class RuntimeDyldImpl;
@@ -88,7 +88,7 @@ public:
ObjSectionToIDMap ObjSecToIDMap;
};
- /// \brief Memory Management.
+ /// Memory Management.
class MemoryManager {
friend class RuntimeDyld;
@@ -170,7 +170,7 @@ public:
bool FinalizationLocked = false;
};
- /// \brief Construct a RuntimeDyld instance.
+ /// Construct a RuntimeDyld instance.
RuntimeDyld(MemoryManager &MemMgr, JITSymbolResolver &Resolver);
RuntimeDyld(const RuntimeDyld &) = delete;
RuntimeDyld &operator=(const RuntimeDyld &) = delete;
@@ -189,6 +189,13 @@ public:
/// This address is the one used for relocation.
JITEvaluatedSymbol getSymbol(StringRef Name) const;
+ /// Returns a copy of the symbol table. This can be used by on-finalized
+ /// callbacks to extract the symbol table before throwing away the
+ /// RuntimeDyld instance. Because the map keys (StringRefs) are backed by
+ /// strings inside the RuntimeDyld instance, the map should be processed
+ /// before the RuntimeDyld instance is discarded.
+ std::map<StringRef, JITEvaluatedSymbol> getSymbolTable() const;
+
/// Resolve the relocations for all symbols we currently know about.
void resolveRelocations();
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index de89f405af4c..13fc5fd5a3e7 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -27,7 +27,7 @@ class RuntimeDyld;
class RuntimeDyldCheckerImpl;
class raw_ostream;
-/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has
+/// RuntimeDyld invariant checker for verifying that RuntimeDyld has
/// correctly applied relocations.
///
/// The RuntimeDyldChecker class evaluates expressions against an attached
@@ -74,22 +74,22 @@ public:
MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
~RuntimeDyldChecker();
- // \brief Get the associated RTDyld instance.
+ // Get the associated RTDyld instance.
RuntimeDyld& getRTDyld();
- // \brief Get the associated RTDyld instance.
+ // Get the associated RTDyld instance.
const RuntimeDyld& getRTDyld() const;
- /// \brief Check a single expression against the attached RuntimeDyld
+ /// Check a single expression against the attached RuntimeDyld
/// instance.
bool check(StringRef CheckExpr) const;
- /// \brief Scan the given memory buffer for lines beginning with the string
+ /// Scan the given memory buffer for lines beginning with the string
/// in RulePrefix. The remainder of the line is passed to the check
/// method to be evaluated as an expression.
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
- /// \brief Returns the address of the requested section (or an error message
+ /// Returns the address of the requested section (or an error message
/// in the second element of the pair if the address cannot be found).
///
/// if 'LocalAddress' is true, this returns the address of the section
@@ -99,7 +99,7 @@ public:
StringRef SectionName,
bool LocalAddress);
- /// \brief If there is a section at the given local address, return its load
+ /// If there is a section at the given local address, return its load
/// address, otherwise return none.
Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h
index d76e37113c66..3cf131c27778 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h
+++ b/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h
@@ -111,7 +111,7 @@ public:
void operator=(const SectionMemoryManager &) = delete;
~SectionMemoryManager() override;
- /// \brief Allocates a memory block of (at least) the given size suitable for
+ /// Allocates a memory block of (at least) the given size suitable for
/// executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is zero
@@ -120,7 +120,7 @@ public:
unsigned SectionID,
StringRef SectionName) override;
- /// \brief Allocates a memory block of (at least) the given size suitable for
+ /// Allocates a memory block of (at least) the given size suitable for
/// executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is zero
@@ -129,7 +129,7 @@ public:
unsigned SectionID, StringRef SectionName,
bool isReadOnly) override;
- /// \brief Update section-specific memory permissions and other attributes.
+ /// Update section-specific memory permissions and other attributes.
///
/// This method is called when object loading is complete and section page
/// permissions can be applied. It is up to the memory manager implementation
@@ -142,7 +142,7 @@ public:
/// \returns true if an error occurred, false otherwise.
bool finalizeMemory(std::string *ErrMsg = nullptr) override;
- /// \brief Invalidate instruction cache for code sections.
+ /// Invalidate instruction cache for code sections.
///
/// Some platforms with separate data cache and instruction cache require
/// explicit cache flush, otherwise JIT code manipulations (like resolved
@@ -182,6 +182,8 @@ private:
std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
unsigned Permissions);
+ void anchor() override;
+
MemoryGroup CodeMem;
MemoryGroup RWDataMem;
MemoryGroup RODataMem;
diff --git a/contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h b/contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h
index a775fdfb603e..3333e96db166 100644
--- a/contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h
+++ b/contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h
@@ -68,6 +68,12 @@ std::unique_ptr<Module> parseModule(const uint8_t *Data, size_t Size,
/// returns 0 and leaves Dest unchanged.
size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize);
+/// Try to parse module and verify it. May output verification errors to the
+/// errs().
+/// \return New module or nullptr in case of error.
+std::unique_ptr<Module> parseAndVerify(const uint8_t *Data, size_t Size,
+ LLVMContext &Context);
+
} // end llvm namespace
#endif // LLVM_FUZZMUTATE_FUZZER_CLI_H
diff --git a/contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h b/contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h
index e9f8bf09a79b..dd30fda99bea 100644
--- a/contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h
+++ b/contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include <functional>
@@ -128,7 +129,7 @@ static inline SourcePred anyFloatType() {
static inline SourcePred anyPtrType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
- return V->getType()->isPointerTy();
+ return V->getType()->isPointerTy() && !V->isSwiftError();
};
auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
std::vector<Constant *> Result;
@@ -142,6 +143,9 @@ static inline SourcePred anyPtrType() {
static inline SourcePred sizedPtrType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
+ if (V->isSwiftError())
+ return false;
+
if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
return PtrT->getElementType()->isSized();
return false;
diff --git a/contrib/llvm/include/llvm/IR/Attributes.h b/contrib/llvm/include/llvm/IR/Attributes.h
index a05a01073049..5aaaaf3c396b 100644
--- a/contrib/llvm/include/llvm/IR/Attributes.h
+++ b/contrib/llvm/include/llvm/IR/Attributes.h
@@ -6,11 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
-/// \brief This file contains the simple types necessary to represent the
+/// This file contains the simple types necessary to represent the
/// attributes associated with functions and their calls.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_ATTRIBUTES_H
@@ -22,6 +22,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <bitset>
#include <cassert>
@@ -35,7 +36,6 @@ namespace llvm {
class AttrBuilder;
class AttributeImpl;
class AttributeListImpl;
-class AttributeList;
class AttributeSetNode;
template<typename T> struct DenseMapInfo;
class Function;
@@ -44,7 +44,7 @@ class Type;
//===----------------------------------------------------------------------===//
/// \class
-/// \brief Functions, function parameters, and return types can have attributes
+/// Functions, function parameters, and return types can have attributes
/// to indicate how they should be treated by optimizations and code
/// generation. This class represents one of those attributes. It's light-weight
/// and should be passed around by-value.
@@ -71,7 +71,7 @@ public:
// IR-Level Attributes
None, ///< No attributes have been set
#define GET_ATTR_ENUM
- #include "llvm/IR/Attributes.gen"
+ #include "llvm/IR/Attributes.inc"
EndAttrKinds ///< Sentinal value useful for loops
};
@@ -87,12 +87,12 @@ public:
// Attribute Construction
//===--------------------------------------------------------------------===//
- /// \brief Return a uniquified Attribute object.
+ /// Return a uniquified Attribute object.
static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0);
static Attribute get(LLVMContext &Context, StringRef Kind,
StringRef Val = StringRef());
- /// \brief Return a uniquified Attribute object that has the specific
+ /// Return a uniquified Attribute object that has the specific
/// alignment set.
static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align);
static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align);
@@ -108,51 +108,51 @@ public:
// Attribute Accessors
//===--------------------------------------------------------------------===//
- /// \brief Return true if the attribute is an Attribute::AttrKind type.
+ /// Return true if the attribute is an Attribute::AttrKind type.
bool isEnumAttribute() const;
- /// \brief Return true if the attribute is an integer attribute.
+ /// Return true if the attribute is an integer attribute.
bool isIntAttribute() const;
- /// \brief Return true if the attribute is a string (target-dependent)
+ /// Return true if the attribute is a string (target-dependent)
/// attribute.
bool isStringAttribute() const;
- /// \brief Return true if the attribute is present.
+ /// Return true if the attribute is present.
bool hasAttribute(AttrKind Val) const;
- /// \brief Return true if the target-dependent attribute is present.
+ /// Return true if the target-dependent attribute is present.
bool hasAttribute(StringRef Val) const;
- /// \brief Return the attribute's kind as an enum (Attribute::AttrKind). This
+ /// Return the attribute's kind as an enum (Attribute::AttrKind). This
/// requires the attribute to be an enum or integer attribute.
Attribute::AttrKind getKindAsEnum() const;
- /// \brief Return the attribute's value as an integer. This requires that the
+ /// Return the attribute's value as an integer. This requires that the
/// attribute be an integer attribute.
uint64_t getValueAsInt() const;
- /// \brief Return the attribute's kind as a string. This requires the
+ /// Return the attribute's kind as a string. This requires the
/// attribute to be a string attribute.
StringRef getKindAsString() const;
- /// \brief Return the attribute's value as a string. This requires the
+ /// Return the attribute's value as a string. This requires the
/// attribute to be a string attribute.
StringRef getValueAsString() const;
- /// \brief Returns the alignment field of an attribute as a byte alignment
+ /// Returns the alignment field of an attribute as a byte alignment
/// value.
unsigned getAlignment() const;
- /// \brief Returns the stack alignment field of an attribute as a byte
+ /// Returns the stack alignment field of an attribute as a byte
/// alignment value.
unsigned getStackAlignment() const;
- /// \brief Returns the number of dereferenceable bytes from the
+ /// Returns the number of dereferenceable bytes from the
/// dereferenceable attribute.
uint64_t getDereferenceableBytes() const;
- /// \brief Returns the number of dereferenceable_or_null bytes from the
+ /// Returns the number of dereferenceable_or_null bytes from the
/// dereferenceable_or_null attribute.
uint64_t getDereferenceableOrNullBytes() const;
@@ -160,27 +160,27 @@ public:
/// if not known).
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
- /// \brief The Attribute is converted to a string of equivalent mnemonic. This
+ /// The Attribute is converted to a string of equivalent mnemonic. This
/// is, presumably, for writing out the mnemonics for the assembly writer.
std::string getAsString(bool InAttrGrp = false) const;
- /// \brief Equality and non-equality operators.
+ /// Equality and non-equality operators.
bool operator==(Attribute A) const { return pImpl == A.pImpl; }
bool operator!=(Attribute A) const { return pImpl != A.pImpl; }
- /// \brief Less-than operator. Useful for sorting the attributes list.
+ /// Less-than operator. Useful for sorting the attributes list.
bool operator<(Attribute A) const;
void Profile(FoldingSetNodeID &ID) const {
ID.AddPointer(pImpl);
}
- /// \brief Return a raw pointer that uniquely identifies this attribute.
+ /// Return a raw pointer that uniquely identifies this attribute.
void *getRawPointer() const {
return pImpl;
}
- /// \brief Get an attribute from a raw pointer created by getRawPointer.
+ /// Get an attribute from a raw pointer created by getRawPointer.
static Attribute fromRawPointer(void *RawPtr) {
return Attribute(reinterpret_cast<AttributeImpl*>(RawPtr));
}
@@ -203,6 +203,9 @@ inline Attribute unwrap(LLVMAttributeRef Attr) {
/// copy. Adding and removing enum attributes is intended to be fast, but adding
/// and removing string or integer attributes involves a FoldingSet lookup.
class AttributeSet {
+ friend AttributeListImpl;
+ template <typename Ty> friend struct DenseMapInfo;
+
// TODO: Extract AvailableAttrs from AttributeSetNode and store them here.
// This will allow an efficient implementation of addAttribute and
// removeAttribute for enum attrs.
@@ -210,9 +213,6 @@ class AttributeSet {
/// Private implementation pointer.
AttributeSetNode *SetNode = nullptr;
- friend AttributeListImpl;
- template <typename Ty> friend struct DenseMapInfo;
-
private:
explicit AttributeSet(AttributeSetNode *ASN) : SetNode(ASN) {}
@@ -290,16 +290,16 @@ public:
//===----------------------------------------------------------------------===//
/// \class
-/// \brief Provide DenseMapInfo for AttributeSet.
+/// Provide DenseMapInfo for AttributeSet.
template <> struct DenseMapInfo<AttributeSet> {
- static inline AttributeSet getEmptyKey() {
- uintptr_t Val = static_cast<uintptr_t>(-1);
+ static AttributeSet getEmptyKey() {
+ auto Val = static_cast<uintptr_t>(-1);
Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val));
}
- static inline AttributeSet getTombstoneKey() {
- uintptr_t Val = static_cast<uintptr_t>(-2);
+ static AttributeSet getTombstoneKey() {
+ auto Val = static_cast<uintptr_t>(-2);
Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val));
}
@@ -314,7 +314,7 @@ template <> struct DenseMapInfo<AttributeSet> {
//===----------------------------------------------------------------------===//
/// \class
-/// \brief This class holds the attributes for a function, its return value, and
+/// This class holds the attributes for a function, its return value, and
/// its parameters. You access the attributes for each of them via an index into
/// the AttributeList object. The function attributes are at index
/// `AttributeList::FunctionIndex', the return value is at index
@@ -333,21 +333,20 @@ private:
friend class AttributeListImpl;
friend class AttributeSet;
friend class AttributeSetNode;
-
template <typename Ty> friend struct DenseMapInfo;
- /// \brief The attributes that we are managing. This can be null to represent
+ /// The attributes that we are managing. This can be null to represent
/// the empty attributes list.
AttributeListImpl *pImpl = nullptr;
public:
- /// \brief Create an AttributeList with the specified parameters in it.
+ /// Create an AttributeList with the specified parameters in it.
static AttributeList get(LLVMContext &C,
ArrayRef<std::pair<unsigned, Attribute>> Attrs);
static AttributeList get(LLVMContext &C,
ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
- /// \brief Create an AttributeList from attribute sets for a function, its
+ /// Create an AttributeList from attribute sets for a function, its
/// return value, and all of its arguments.
static AttributeList get(LLVMContext &C, AttributeSet FnAttrs,
AttributeSet RetAttrs,
@@ -365,7 +364,7 @@ public:
// AttributeList Construction and Mutation
//===--------------------------------------------------------------------===//
- /// \brief Return an AttributeList with the specified parameters in it.
+ /// Return an AttributeList with the specified parameters in it.
static AttributeList get(LLVMContext &C, ArrayRef<AttributeList> Attrs);
static AttributeList get(LLVMContext &C, unsigned Index,
ArrayRef<Attribute::AttrKind> Kinds);
@@ -374,12 +373,12 @@ public:
static AttributeList get(LLVMContext &C, unsigned Index,
const AttrBuilder &B);
- /// \brief Add an attribute to the attribute set at the given index.
+ /// Add an attribute to the attribute set at the given index.
/// Returns a new list because attribute lists are immutable.
AttributeList addAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const;
- /// \brief Add an attribute to the attribute set at the given index.
+ /// Add an attribute to the attribute set at the given index.
/// Returns a new list because attribute lists are immutable.
AttributeList addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
StringRef Value = StringRef()) const;
@@ -388,7 +387,7 @@ public:
/// Returns a new list because attribute lists are immutable.
AttributeList addAttribute(LLVMContext &C, unsigned Index, Attribute A) const;
- /// \brief Add attributes to the attribute set at the given index.
+ /// Add attributes to the attribute set at the given index.
/// Returns a new list because attribute lists are immutable.
AttributeList addAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &B) const;
@@ -420,70 +419,70 @@ public:
return addAttributes(C, ArgNo + FirstArgIndex, B);
}
- /// \brief Remove the specified attribute at the specified index from this
+ /// Remove the specified attribute at the specified index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const;
- /// \brief Remove the specified attribute at the specified index from this
+ /// Remove the specified attribute at the specified index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttribute(LLVMContext &C, unsigned Index,
StringRef Kind) const;
- /// \brief Remove the specified attributes at the specified index from this
+ /// Remove the specified attributes at the specified index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &AttrsToRemove) const;
- /// \brief Remove all attributes at the specified index from this
+ /// Remove all attributes at the specified index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttributes(LLVMContext &C, unsigned Index) const;
- /// \brief Remove the specified attribute at the specified arg index from this
+ /// Remove the specified attribute at the specified arg index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo,
Attribute::AttrKind Kind) const {
return removeAttribute(C, ArgNo + FirstArgIndex, Kind);
}
- /// \brief Remove the specified attribute at the specified arg index from this
+ /// Remove the specified attribute at the specified arg index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo,
StringRef Kind) const {
return removeAttribute(C, ArgNo + FirstArgIndex, Kind);
}
- /// \brief Remove the specified attribute at the specified arg index from this
+ /// Remove the specified attribute at the specified arg index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo,
const AttrBuilder &AttrsToRemove) const {
return removeAttributes(C, ArgNo + FirstArgIndex, AttrsToRemove);
}
- /// \brief Remove all attributes at the specified arg index from this
+ /// Remove all attributes at the specified arg index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo) const {
return removeAttributes(C, ArgNo + FirstArgIndex);
}
- /// \Brief Add the dereferenceable attribute to the attribute set at the given
+ /// \brief Add the dereferenceable attribute to the attribute set at the given
/// index. Returns a new list because attribute lists are immutable.
AttributeList addDereferenceableAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const;
- /// \Brief Add the dereferenceable attribute to the attribute set at the given
+ /// \brief Add the dereferenceable attribute to the attribute set at the given
/// arg index. Returns a new list because attribute lists are immutable.
AttributeList addDereferenceableParamAttr(LLVMContext &C, unsigned ArgNo,
uint64_t Bytes) const {
return addDereferenceableAttr(C, ArgNo + FirstArgIndex, Bytes);
}
- /// \brief Add the dereferenceable_or_null attribute to the attribute set at
+ /// Add the dereferenceable_or_null attribute to the attribute set at
/// the given index. Returns a new list because attribute lists are immutable.
AttributeList addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const;
- /// \brief Add the dereferenceable_or_null attribute to the attribute set at
+ /// Add the dereferenceable_or_null attribute to the attribute set at
/// the given arg index. Returns a new list because attribute lists are
/// immutable.
AttributeList addDereferenceableOrNullParamAttr(LLVMContext &C,
@@ -510,102 +509,102 @@ public:
// AttributeList Accessors
//===--------------------------------------------------------------------===//
- /// \brief Retrieve the LLVM context.
+ /// Retrieve the LLVM context.
LLVMContext &getContext() const;
- /// \brief The attributes for the specified index are returned.
+ /// The attributes for the specified index are returned.
AttributeSet getAttributes(unsigned Index) const;
- /// \brief The attributes for the argument or parameter at the given index are
+ /// The attributes for the argument or parameter at the given index are
/// returned.
AttributeSet getParamAttributes(unsigned ArgNo) const;
- /// \brief The attributes for the ret value are returned.
+ /// The attributes for the ret value are returned.
AttributeSet getRetAttributes() const;
- /// \brief The function attributes are returned.
+ /// The function attributes are returned.
AttributeSet getFnAttributes() const;
- /// \brief Return true if the attribute exists at the given index.
+ /// Return true if the attribute exists at the given index.
bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const;
- /// \brief Return true if the attribute exists at the given index.
+ /// Return true if the attribute exists at the given index.
bool hasAttribute(unsigned Index, StringRef Kind) const;
- /// \brief Return true if attribute exists at the given index.
+ /// Return true if attribute exists at the given index.
bool hasAttributes(unsigned Index) const;
- /// \brief Return true if the attribute exists for the given argument
+ /// Return true if the attribute exists for the given argument
bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
return hasAttribute(ArgNo + FirstArgIndex, Kind);
}
- /// \brief Return true if the attribute exists for the given argument
+ /// Return true if the attribute exists for the given argument
bool hasParamAttr(unsigned ArgNo, StringRef Kind) const {
return hasAttribute(ArgNo + FirstArgIndex, Kind);
}
- /// \brief Return true if attributes exists for the given argument
+ /// Return true if attributes exists for the given argument
bool hasParamAttrs(unsigned ArgNo) const {
return hasAttributes(ArgNo + FirstArgIndex);
}
- /// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
+ /// Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
/// may be faster.
bool hasFnAttribute(Attribute::AttrKind Kind) const;
- /// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
+ /// Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
/// may be faster.
bool hasFnAttribute(StringRef Kind) const;
- /// \brief Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind).
+ /// Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind).
bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const;
- /// \brief Return true if the specified attribute is set for at least one
+ /// Return true if the specified attribute is set for at least one
/// parameter or for the return value. If Index is not nullptr, the index
/// of a parameter with the specified attribute is provided.
bool hasAttrSomewhere(Attribute::AttrKind Kind,
unsigned *Index = nullptr) const;
- /// \brief Return the attribute object that exists at the given index.
+ /// Return the attribute object that exists at the given index.
Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const;
- /// \brief Return the attribute object that exists at the given index.
+ /// Return the attribute object that exists at the given index.
Attribute getAttribute(unsigned Index, StringRef Kind) const;
- /// \brief Return the attribute object that exists at the arg index.
+ /// Return the attribute object that exists at the arg index.
Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
return getAttribute(ArgNo + FirstArgIndex, Kind);
}
- /// \brief Return the attribute object that exists at the given index.
+ /// Return the attribute object that exists at the given index.
Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const {
return getAttribute(ArgNo + FirstArgIndex, Kind);
}
- /// \brief Return the alignment of the return value.
+ /// Return the alignment of the return value.
unsigned getRetAlignment() const;
- /// \brief Return the alignment for the specified function parameter.
+ /// Return the alignment for the specified function parameter.
unsigned getParamAlignment(unsigned ArgNo) const;
- /// \brief Get the stack alignment.
+ /// Get the stack alignment.
unsigned getStackAlignment(unsigned Index) const;
- /// \brief Get the number of dereferenceable bytes (or zero if unknown).
+ /// Get the number of dereferenceable bytes (or zero if unknown).
uint64_t getDereferenceableBytes(unsigned Index) const;
- /// \brief Get the number of dereferenceable bytes (or zero if unknown) of an
+ /// Get the number of dereferenceable bytes (or zero if unknown) of an
/// arg.
uint64_t getParamDereferenceableBytes(unsigned ArgNo) const {
return getDereferenceableBytes(ArgNo + FirstArgIndex);
}
- /// \brief Get the number of dereferenceable_or_null bytes (or zero if
+ /// Get the number of dereferenceable_or_null bytes (or zero if
/// unknown).
uint64_t getDereferenceableOrNullBytes(unsigned Index) const;
- /// \brief Get the number of dereferenceable_or_null bytes (or zero if
+ /// Get the number of dereferenceable_or_null bytes (or zero if
/// unknown) of an arg.
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const {
return getDereferenceableOrNullBytes(ArgNo + FirstArgIndex);
@@ -615,7 +614,7 @@ public:
std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs(unsigned Index) const;
- /// \brief Return the attributes at the index as a string.
+ /// Return the attributes at the index as a string.
std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
//===--------------------------------------------------------------------===//
@@ -637,12 +636,12 @@ public:
bool operator==(const AttributeList &RHS) const { return pImpl == RHS.pImpl; }
bool operator!=(const AttributeList &RHS) const { return pImpl != RHS.pImpl; }
- /// \brief Return a raw pointer that uniquely identifies this attribute list.
+ /// Return a raw pointer that uniquely identifies this attribute list.
void *getRawPointer() const {
return pImpl;
}
- /// \brief Return true if there are no attributes.
+ /// Return true if there are no attributes.
bool isEmpty() const { return pImpl == nullptr; }
void dump() const;
@@ -650,16 +649,16 @@ public:
//===----------------------------------------------------------------------===//
/// \class
-/// \brief Provide DenseMapInfo for AttributeList.
+/// Provide DenseMapInfo for AttributeList.
template <> struct DenseMapInfo<AttributeList> {
- static inline AttributeList getEmptyKey() {
- uintptr_t Val = static_cast<uintptr_t>(-1);
+ static AttributeList getEmptyKey() {
+ auto Val = static_cast<uintptr_t>(-1);
Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
return AttributeList(reinterpret_cast<AttributeListImpl *>(Val));
}
- static inline AttributeList getTombstoneKey() {
- uintptr_t Val = static_cast<uintptr_t>(-2);
+ static AttributeList getTombstoneKey() {
+ auto Val = static_cast<uintptr_t>(-2);
Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
return AttributeList(reinterpret_cast<AttributeListImpl *>(Val));
}
@@ -676,7 +675,7 @@ template <> struct DenseMapInfo<AttributeList> {
//===----------------------------------------------------------------------===//
/// \class
-/// \brief This class is used in conjunction with the Attribute::get method to
+/// This class is used in conjunction with the Attribute::get method to
/// create an Attribute object. The object itself is uniquified. The Builder's
/// value, however, is not. So this can be used as a quick way to test for
/// equality, presence of attributes, etc.
@@ -691,73 +690,75 @@ class AttrBuilder {
public:
AttrBuilder() = default;
+
AttrBuilder(const Attribute &A) {
addAttribute(A);
}
+
AttrBuilder(AttributeList AS, unsigned Idx);
AttrBuilder(AttributeSet AS);
void clear();
- /// \brief Add an attribute to the builder.
+ /// Add an attribute to the builder.
AttrBuilder &addAttribute(Attribute::AttrKind Val);
- /// \brief Add the Attribute object to the builder.
+ /// Add the Attribute object to the builder.
AttrBuilder &addAttribute(Attribute A);
- /// \brief Add the target-dependent attribute to the builder.
+ /// Add the target-dependent attribute to the builder.
AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef());
- /// \brief Remove an attribute from the builder.
+ /// Remove an attribute from the builder.
AttrBuilder &removeAttribute(Attribute::AttrKind Val);
- /// \brief Remove the attributes from the builder.
+ /// Remove the attributes from the builder.
AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex);
- /// \brief Remove the target-dependent attribute to the builder.
+ /// Remove the target-dependent attribute to the builder.
AttrBuilder &removeAttribute(StringRef A);
- /// \brief Add the attributes from the builder.
+ /// Add the attributes from the builder.
AttrBuilder &merge(const AttrBuilder &B);
- /// \brief Remove the attributes from the builder.
+ /// Remove the attributes from the builder.
AttrBuilder &remove(const AttrBuilder &B);
- /// \brief Return true if the builder has any attribute that's in the
+ /// Return true if the builder has any attribute that's in the
/// specified builder.
bool overlaps(const AttrBuilder &B) const;
- /// \brief Return true if the builder has the specified attribute.
+ /// Return true if the builder has the specified attribute.
bool contains(Attribute::AttrKind A) const {
assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
return Attrs[A];
}
- /// \brief Return true if the builder has the specified target-dependent
+ /// Return true if the builder has the specified target-dependent
/// attribute.
bool contains(StringRef A) const;
- /// \brief Return true if the builder has IR-level attributes.
+ /// Return true if the builder has IR-level attributes.
bool hasAttributes() const;
- /// \brief Return true if the builder has any attribute that's in the
+ /// Return true if the builder has any attribute that's in the
/// specified attribute.
bool hasAttributes(AttributeList A, uint64_t Index) const;
- /// \brief Return true if the builder has an alignment attribute.
+ /// Return true if the builder has an alignment attribute.
bool hasAlignmentAttr() const;
- /// \brief Retrieve the alignment attribute, if it exists.
+ /// Retrieve the alignment attribute, if it exists.
uint64_t getAlignment() const { return Alignment; }
- /// \brief Retrieve the stack alignment attribute, if it exists.
+ /// Retrieve the stack alignment attribute, if it exists.
uint64_t getStackAlignment() const { return StackAlignment; }
- /// \brief Retrieve the number of dereferenceable bytes, if the
+ /// Retrieve the number of dereferenceable bytes, if the
/// dereferenceable attribute exists (zero is returned otherwise).
uint64_t getDereferenceableBytes() const { return DerefBytes; }
- /// \brief Retrieve the number of dereferenceable_or_null bytes, if the
+ /// Retrieve the number of dereferenceable_or_null bytes, if the
/// dereferenceable_or_null attribute exists (zero is returned otherwise).
uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; }
@@ -765,19 +766,19 @@ public:
/// doesn't exist, pair(0, 0) is returned.
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
- /// \brief This turns an int alignment (which must be a power of 2) into the
+ /// This turns an int alignment (which must be a power of 2) into the
/// form used internally in Attribute.
AttrBuilder &addAlignmentAttr(unsigned Align);
- /// \brief This turns an int stack alignment (which must be a power of 2) into
+ /// This turns an int stack alignment (which must be a power of 2) into
/// the form used internally in Attribute.
AttrBuilder &addStackAlignmentAttr(unsigned Align);
- /// \brief This turns the number of dereferenceable bytes into the form used
+ /// This turns the number of dereferenceable bytes into the form used
/// internally in Attribute.
AttrBuilder &addDereferenceableAttr(uint64_t Bytes);
- /// \brief This turns the number of dereferenceable_or_null bytes into the
+ /// This turns the number of dereferenceable_or_null bytes into the
/// form used internally in Attribute.
AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes);
@@ -789,7 +790,7 @@ public:
/// Attribute.getIntValue().
AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr);
- /// \brief Return true if the builder contains no target-independent
+ /// Return true if the builder contains no target-independent
/// attributes.
bool empty() const { return Attrs.none(); }
@@ -800,18 +801,19 @@ public:
using td_range = iterator_range<td_iterator>;
using td_const_range = iterator_range<td_const_iterator>;
- td_iterator td_begin() { return TargetDepAttrs.begin(); }
- td_iterator td_end() { return TargetDepAttrs.end(); }
+ td_iterator td_begin() { return TargetDepAttrs.begin(); }
+ td_iterator td_end() { return TargetDepAttrs.end(); }
td_const_iterator td_begin() const { return TargetDepAttrs.begin(); }
- td_const_iterator td_end() const { return TargetDepAttrs.end(); }
+ td_const_iterator td_end() const { return TargetDepAttrs.end(); }
td_range td_attrs() { return td_range(td_begin(), td_end()); }
+
td_const_range td_attrs() const {
return td_const_range(td_begin(), td_end());
}
- bool td_empty() const { return TargetDepAttrs.empty(); }
+ bool td_empty() const { return TargetDepAttrs.empty(); }
bool operator==(const AttrBuilder &B);
bool operator!=(const AttrBuilder &B) {
@@ -821,14 +823,14 @@ public:
namespace AttributeFuncs {
-/// \brief Which attributes cannot be applied to a type.
+/// Which attributes cannot be applied to a type.
AttrBuilder typeIncompatible(Type *Ty);
/// \returns Return true if the two functions have compatible target-independent
/// attributes for inlining purposes.
bool areInlineCompatible(const Function &Caller, const Function &Callee);
-/// \brief Merge caller's and callee's attributes.
+/// Merge caller's and callee's attributes.
void mergeAttributesForInlining(Function &Caller, const Function &Callee);
} // end namespace AttributeFuncs
diff --git a/contrib/llvm/include/llvm/IR/Attributes.td b/contrib/llvm/include/llvm/IR/Attributes.td
index ebe5c1985875..1019f867aab0 100644
--- a/contrib/llvm/include/llvm/IR/Attributes.td
+++ b/contrib/llvm/include/llvm/IR/Attributes.td
@@ -106,9 +106,15 @@ def NoRedZone : EnumAttr<"noredzone">;
/// Mark the function as not returning.
def NoReturn : EnumAttr<"noreturn">;
+/// Disable Indirect Branch Tracking.
+def NoCfCheck : EnumAttr<"nocf_check">;
+
/// Function doesn't unwind stack.
def NoUnwind : EnumAttr<"nounwind">;
+/// Select optimizations for best fuzzing signal.
+def OptForFuzzing : EnumAttr<"optforfuzzing">;
+
/// opt_size.
def OptimizeForSize : EnumAttr<"optsize">;
@@ -130,6 +136,9 @@ def ReturnsTwice : EnumAttr<"returns_twice">;
/// Safe Stack protection.
def SafeStack : EnumAttr<"safestack">;
+/// Shadow Call Stack protection.
+def ShadowCallStack : EnumAttr<"shadowcallstack">;
+
/// Sign extended before/after call.
def SExt : EnumAttr<"signext">;
@@ -205,6 +214,7 @@ def : CompatRule<"isEqual<SanitizeThreadAttr>">;
def : CompatRule<"isEqual<SanitizeMemoryAttr>">;
def : CompatRule<"isEqual<SanitizeHWAddressAttr>">;
def : CompatRule<"isEqual<SafeStackAttr>">;
+def : CompatRule<"isEqual<ShadowCallStackAttr>">;
class MergeRule<string F> {
// The name of the function called to merge the attributes of the caller and
@@ -225,3 +235,4 @@ def : MergeRule<"setOR<ProfileSampleAccurateAttr>">;
def : MergeRule<"adjustCallerSSPLevel">;
def : MergeRule<"adjustCallerStackProbes">;
def : MergeRule<"adjustCallerStackProbeSize">;
+def : MergeRule<"adjustMinLegalVectorWidth">;
diff --git a/contrib/llvm/include/llvm/IR/AutoUpgrade.h b/contrib/llvm/include/llvm/IR/AutoUpgrade.h
index 3f406f0cf196..8cf574c6a138 100644
--- a/contrib/llvm/include/llvm/IR/AutoUpgrade.h
+++ b/contrib/llvm/include/llvm/IR/AutoUpgrade.h
@@ -37,6 +37,10 @@ namespace llvm {
/// intrinsic function with a call to the specified new function.
void UpgradeIntrinsicCall(CallInst *CI, Function *NewFn);
+ // This upgrades the comment for objc retain release markers in inline asm
+ // calls
+ void UpgradeInlineAsmString(std::string *AsmStr);
+
/// This is an auto-upgrade hook for any old intrinsic function syntaxes
/// which need to have both the function updated as well as all calls updated
/// to the new function. This should only be run in a post-processing fashion
@@ -51,6 +55,10 @@ namespace llvm {
/// module is modified.
bool UpgradeModuleFlags(Module &M);
+ /// This checks for objc retain release marker which should be upgraded. It
+ /// returns true if module is modified.
+ bool UpgradeRetainReleaseMarker(Module &M);
+
void UpgradeSectionAttributes(Module &M);
/// If the given TBAA tag uses the scalar TBAA format, create a new node
diff --git a/contrib/llvm/include/llvm/IR/BasicBlock.h b/contrib/llvm/include/llvm/IR/BasicBlock.h
index 77cfc9776df0..1ee19975af75 100644
--- a/contrib/llvm/include/llvm/IR/BasicBlock.h
+++ b/contrib/llvm/include/llvm/IR/BasicBlock.h
@@ -41,7 +41,7 @@ class PHINode;
class TerminatorInst;
class ValueSymbolTable;
-/// \brief LLVM Basic Block Representation
+/// LLVM Basic Block Representation
///
/// This represents a single basic block in LLVM. A basic block is simply a
/// container of instructions that execute sequentially. Basic blocks are Values
@@ -70,7 +70,7 @@ private:
void setParent(Function *parent);
- /// \brief Constructor.
+ /// Constructor.
///
/// If the function parameter is specified, the basic block is automatically
/// inserted at either the end of the function (if InsertBefore is null), or
@@ -84,7 +84,7 @@ public:
BasicBlock &operator=(const BasicBlock &) = delete;
~BasicBlock();
- /// \brief Get the context in which this basic block lives.
+ /// Get the context in which this basic block lives.
LLVMContext &getContext() const;
/// Instruction iterators...
@@ -93,7 +93,7 @@ public:
using reverse_iterator = InstListType::reverse_iterator;
using const_reverse_iterator = InstListType::const_reverse_iterator;
- /// \brief Creates a new BasicBlock.
+ /// Creates a new BasicBlock.
///
/// If the Parent parameter is specified, the basic block is automatically
/// inserted at either the end of the function (if InsertBefore is 0), or
@@ -104,12 +104,12 @@ public:
return new BasicBlock(Context, Name, Parent, InsertBefore);
}
- /// \brief Return the enclosing method, or null if none.
+ /// Return the enclosing method, or null if none.
const Function *getParent() const { return Parent; }
Function *getParent() { return Parent; }
- /// \brief Return the module owning the function this basic block belongs to,
- /// or nullptr it the function does not have a module.
+ /// Return the module owning the function this basic block belongs to, or
+ /// nullptr if the function does not have a module.
///
/// Note: this is undefined behavior if the block does not have a parent.
const Module *getModule() const;
@@ -118,34 +118,34 @@ public:
static_cast<const BasicBlock *>(this)->getModule());
}
- /// \brief Returns the terminator instruction if the block is well formed or
- /// null if the block is not well formed.
+ /// Returns the terminator instruction if the block is well formed or null
+ /// if the block is not well formed.
const TerminatorInst *getTerminator() const LLVM_READONLY;
TerminatorInst *getTerminator() {
return const_cast<TerminatorInst *>(
static_cast<const BasicBlock *>(this)->getTerminator());
}
- /// \brief Returns the call instruction calling @llvm.experimental.deoptimize
- /// prior to the terminating return instruction of this basic block, if such a
- /// call is present. Otherwise, returns null.
+ /// Returns the call instruction calling \@llvm.experimental.deoptimize
+ /// prior to the terminating return instruction of this basic block, if such
+ /// a call is present. Otherwise, returns null.
const CallInst *getTerminatingDeoptimizeCall() const;
CallInst *getTerminatingDeoptimizeCall() {
return const_cast<CallInst *>(
static_cast<const BasicBlock *>(this)->getTerminatingDeoptimizeCall());
}
- /// \brief Returns the call instruction marked 'musttail' prior to the
- /// terminating return instruction of this basic block, if such a call is
- /// present. Otherwise, returns null.
+ /// Returns the call instruction marked 'musttail' prior to the terminating
+ /// return instruction of this basic block, if such a call is present.
+ /// Otherwise, returns null.
const CallInst *getTerminatingMustTailCall() const;
CallInst *getTerminatingMustTailCall() {
return const_cast<CallInst *>(
static_cast<const BasicBlock *>(this)->getTerminatingMustTailCall());
}
- /// \brief Returns a pointer to the first instruction in this block that is
- /// not a PHINode instruction.
+ /// Returns a pointer to the first instruction in this block that is not a
+ /// PHINode instruction.
///
/// When adding instructions to the beginning of the basic block, they should
/// be added before the returned value, not before the first instruction,
@@ -156,23 +156,23 @@ public:
static_cast<const BasicBlock *>(this)->getFirstNonPHI());
}
- /// \brief Returns a pointer to the first instruction in this block that is not
- /// a PHINode or a debug intrinsic.
+ /// Returns a pointer to the first instruction in this block that is not a
+ /// PHINode or a debug intrinsic.
const Instruction* getFirstNonPHIOrDbg() const;
Instruction* getFirstNonPHIOrDbg() {
return const_cast<Instruction *>(
static_cast<const BasicBlock *>(this)->getFirstNonPHIOrDbg());
}
- /// \brief Returns a pointer to the first instruction in this block that is not
- /// a PHINode, a debug intrinsic, or a lifetime intrinsic.
+ /// Returns a pointer to the first instruction in this block that is not a
+ /// PHINode, a debug intrinsic, or a lifetime intrinsic.
const Instruction* getFirstNonPHIOrDbgOrLifetime() const;
Instruction* getFirstNonPHIOrDbgOrLifetime() {
return const_cast<Instruction *>(
static_cast<const BasicBlock *>(this)->getFirstNonPHIOrDbgOrLifetime());
}
- /// \brief Returns an iterator to the first instruction in this block that is
+ /// Returns an iterator to the first instruction in this block that is
/// suitable for inserting a non-PHI instruction.
///
/// In particular, it skips all PHIs and LandingPad instructions.
@@ -182,23 +182,35 @@ public:
->getFirstInsertionPt().getNonConst();
}
- /// \brief Unlink 'this' from the containing function, but do not delete it.
+ /// Return a const iterator range over the instructions in the block, skipping
+ /// any debug instructions.
+ iterator_range<filter_iterator<BasicBlock::const_iterator,
+ std::function<bool(const Instruction &)>>>
+ instructionsWithoutDebug() const;
+
+ /// Return an iterator range over the instructions in the block, skipping any
+ /// debug instructions.
+ iterator_range<filter_iterator<BasicBlock::iterator,
+ std::function<bool(Instruction &)>>>
+ instructionsWithoutDebug();
+
+ /// Unlink 'this' from the containing function, but do not delete it.
void removeFromParent();
- /// \brief Unlink 'this' from the containing function and delete it.
+ /// Unlink 'this' from the containing function and delete it.
///
// \returns an iterator pointing to the element after the erased one.
SymbolTableList<BasicBlock>::iterator eraseFromParent();
- /// \brief Unlink this basic block from its current function and insert it
- /// into the function that \p MovePos lives in, right before \p MovePos.
+ /// Unlink this basic block from its current function and insert it into
+ /// the function that \p MovePos lives in, right before \p MovePos.
void moveBefore(BasicBlock *MovePos);
- /// \brief Unlink this basic block from its current function and insert it
+ /// Unlink this basic block from its current function and insert it
/// right after \p MovePos in the function \p MovePos lives in.
void moveAfter(BasicBlock *MovePos);
- /// \brief Insert unlinked basic block into a function.
+ /// Insert unlinked basic block into a function.
///
/// Inserts an unlinked basic block into \c Parent. If \c InsertBefore is
/// provided, inserts before that basic block, otherwise inserts at the end.
@@ -206,7 +218,7 @@ public:
/// \pre \a getParent() is \c nullptr.
void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr);
- /// \brief Return the predecessor of this block if it has a single predecessor
+ /// Return the predecessor of this block if it has a single predecessor
/// block. Otherwise return a null pointer.
const BasicBlock *getSinglePredecessor() const;
BasicBlock *getSinglePredecessor() {
@@ -214,7 +226,7 @@ public:
static_cast<const BasicBlock *>(this)->getSinglePredecessor());
}
- /// \brief Return the predecessor of this block if it has a unique predecessor
+ /// Return the predecessor of this block if it has a unique predecessor
/// block. Otherwise return a null pointer.
///
/// Note that unique predecessor doesn't mean single edge, there can be
@@ -226,7 +238,7 @@ public:
static_cast<const BasicBlock *>(this)->getUniquePredecessor());
}
- /// \brief Return the successor of this block if it has a single successor.
+ /// Return the successor of this block if it has a single successor.
/// Otherwise return a null pointer.
///
/// This method is analogous to getSinglePredecessor above.
@@ -236,7 +248,7 @@ public:
static_cast<const BasicBlock *>(this)->getSingleSuccessor());
}
- /// \brief Return the successor of this block if it has a unique successor.
+ /// Return the successor of this block if it has a unique successor.
/// Otherwise return a null pointer.
///
/// This method is analogous to getUniquePredecessor above.
@@ -310,28 +322,28 @@ public:
}
iterator_range<phi_iterator> phis();
- /// \brief Return the underlying instruction list container.
+ /// Return the underlying instruction list container.
///
/// Currently you need to access the underlying instruction list container
/// directly if you want to modify it.
const InstListType &getInstList() const { return InstList; }
InstListType &getInstList() { return InstList; }
- /// \brief Returns a pointer to a member of the instruction list.
+ /// Returns a pointer to a member of the instruction list.
static InstListType BasicBlock::*getSublistAccess(Instruction*) {
return &BasicBlock::InstList;
}
- /// \brief Returns a pointer to the symbol table if one exists.
+ /// Returns a pointer to the symbol table if one exists.
ValueSymbolTable *getValueSymbolTable();
- /// \brief Methods for support type inquiry through isa, cast, and dyn_cast.
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Value *V) {
return V->getValueID() == Value::BasicBlockVal;
}
- /// \brief Cause all subinstructions to "let go" of all the references that
- /// said subinstructions are maintaining.
+ /// Cause all subinstructions to "let go" of all the references that said
+ /// subinstructions are maintaining.
///
/// This allows one to 'delete' a whole class at a time, even though there may
/// be circular references... first all references are dropped, and all use
@@ -340,8 +352,8 @@ public:
/// except operator delete.
void dropAllReferences();
- /// \brief Notify the BasicBlock that the predecessor \p Pred is no longer
- /// able to reach it.
+ /// Notify the BasicBlock that the predecessor \p Pred is no longer able to
+ /// reach it.
///
/// This is actually not used to update the Predecessor list, but is actually
/// used to update the PHI nodes that reside in the block. Note that this
@@ -350,8 +362,7 @@ public:
bool canSplitPredecessors() const;
- /// \brief Split the basic block into two basic blocks at the specified
- /// instruction.
+ /// Split the basic block into two basic blocks at the specified instruction.
///
/// Note that all instructions BEFORE the specified iterator stay as part of
/// the original basic block, an unconditional branch is added to the original
@@ -371,37 +382,37 @@ public:
return splitBasicBlock(I->getIterator(), BBName);
}
- /// \brief Returns true if there are any uses of this basic block other than
+ /// Returns true if there are any uses of this basic block other than
/// direct branches, switches, etc. to it.
bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; }
- /// \brief Update all phi nodes in this basic block's successors to refer to
- /// basic block \p New instead of to it.
+ /// Update all phi nodes in this basic block's successors to refer to basic
+ /// block \p New instead of to it.
void replaceSuccessorsPhiUsesWith(BasicBlock *New);
- /// \brief Return true if this basic block is an exception handling block.
+ /// Return true if this basic block is an exception handling block.
bool isEHPad() const { return getFirstNonPHI()->isEHPad(); }
- /// \brief Return true if this basic block is a landing pad.
+ /// Return true if this basic block is a landing pad.
///
/// Being a ``landing pad'' means that the basic block is the destination of
/// the 'unwind' edge of an invoke instruction.
bool isLandingPad() const;
- /// \brief Return the landingpad instruction associated with the landing pad.
+ /// Return the landingpad instruction associated with the landing pad.
const LandingPadInst *getLandingPadInst() const;
LandingPadInst *getLandingPadInst() {
return const_cast<LandingPadInst *>(
static_cast<const BasicBlock *>(this)->getLandingPadInst());
}
- /// \brief Return true if it is legal to hoist instructions into this block.
+ /// Return true if it is legal to hoist instructions into this block.
bool isLegalToHoistInto() const;
Optional<uint64_t> getIrrLoopHeaderWeight() const;
private:
- /// \brief Increment the internal refcount of the number of BlockAddresses
+ /// Increment the internal refcount of the number of BlockAddresses
/// referencing this BasicBlock by \p Amt.
///
/// This is almost always 0, sometimes one possibly, but almost never 2, and
@@ -412,8 +423,8 @@ private:
"Refcount wrap-around");
}
- /// \brief Shadow Value::setValueSubclassData with a private forwarding method
- /// so that any future subclasses cannot accidentally use it.
+ /// 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);
}
@@ -422,6 +433,10 @@ private:
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef)
+/// Advance \p It while it points to a debug instruction and return the result.
+/// This assumes that \p It is not at the end of a block.
+BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It);
+
} // end namespace llvm
#endif // LLVM_IR_BASICBLOCK_H
diff --git a/contrib/llvm/include/llvm/IR/CFG.h b/contrib/llvm/include/llvm/IR/CFG.h
index e259e42e1ce4..f4988e7f1fec 100644
--- a/contrib/llvm/include/llvm/IR/CFG.h
+++ b/contrib/llvm/include/llvm/IR/CFG.h
@@ -107,6 +107,9 @@ inline const_pred_iterator pred_end(const BasicBlock *BB) {
inline bool pred_empty(const BasicBlock *BB) {
return pred_begin(BB) == pred_end(BB);
}
+inline unsigned pred_size(const BasicBlock *BB) {
+ return std::distance(pred_begin(BB), pred_end(BB));
+}
inline pred_range predecessors(BasicBlock *BB) {
return pred_range(pred_begin(BB), pred_end(BB));
}
@@ -140,6 +143,9 @@ inline succ_const_iterator succ_end(const BasicBlock *BB) {
inline bool succ_empty(const BasicBlock *BB) {
return succ_begin(BB) == succ_end(BB);
}
+inline unsigned succ_size(const BasicBlock *BB) {
+ return std::distance(succ_begin(BB), succ_end(BB));
+}
inline succ_range successors(BasicBlock *BB) {
return succ_range(succ_begin(BB), succ_end(BB));
}
diff --git a/contrib/llvm/include/llvm/IR/CallSite.h b/contrib/llvm/include/llvm/IR/CallSite.h
index 5b10da8f2aee..2162ccb982b0 100644
--- a/contrib/llvm/include/llvm/IR/CallSite.h
+++ b/contrib/llvm/include/llvm/IR/CallSite.h
@@ -637,7 +637,8 @@ public:
if (hasRetAttr(Attribute::NonNull))
return true;
else if (getDereferenceableBytes(AttributeList::ReturnIndex) > 0 &&
- getType()->getPointerAddressSpace() == 0)
+ !NullPointerIsDefined(getCaller(),
+ getType()->getPointerAddressSpace()))
return true;
return false;
diff --git a/contrib/llvm/include/llvm/IR/CallingConv.h b/contrib/llvm/include/llvm/IR/CallingConv.h
index 84fe836adc35..b9c02d7ed424 100644
--- a/contrib/llvm/include/llvm/IR/CallingConv.h
+++ b/contrib/llvm/include/llvm/IR/CallingConv.h
@@ -26,7 +26,7 @@ namespace CallingConv {
/// A set of enums which specify the assigned numeric values for known llvm
/// calling conventions.
- /// @brief LLVM Calling Convention Representation
+ /// LLVM Calling Convention Representation
enum {
/// C - The default llvm calling convention, compatible with C. This
/// convention is the only calling convention that supports varargs calls.
@@ -139,11 +139,11 @@ namespace CallingConv {
/// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins
Intel_OCL_BI = 77,
- /// \brief The C convention as specified in the x86-64 supplement to the
+ /// The C convention as specified in the x86-64 supplement to the
/// System V ABI, used on most non-Windows systems.
X86_64_SysV = 78,
- /// \brief The C convention as implemented on Windows/x86-64 and
+ /// The C convention as implemented on Windows/x86-64 and
/// AArch64. This convention differs from the more common
/// \c X86_64_SysV convention in a number of ways, most notably in
/// that XMM registers used to pass arguments are shadowed by GPRs,
@@ -153,17 +153,17 @@ namespace CallingConv {
/// registers to variadic functions.
Win64 = 79,
- /// \brief MSVC calling convention that passes vectors and vector aggregates
+ /// MSVC calling convention that passes vectors and vector aggregates
/// in SSE registers.
X86_VectorCall = 80,
- /// \brief Calling convention used by HipHop Virtual Machine (HHVM) to
+ /// Calling convention used by HipHop Virtual Machine (HHVM) to
/// perform calls to and from translation cache, and for calling PHP
/// functions.
/// HHVM calling convention supports tail/sibling call elimination.
HHVM = 81,
- /// \brief HHVM calling convention for invoking C/C++ helpers.
+ /// HHVM calling convention for invoking C/C++ helpers.
HHVM_C = 82,
/// X86_INTR - x86 hardware interrupt context. Callee may take one or two
diff --git a/contrib/llvm/include/llvm/IR/Comdat.h b/contrib/llvm/include/llvm/IR/Comdat.h
index fa87093ca50a..555121e928f7 100644
--- a/contrib/llvm/include/llvm/IR/Comdat.h
+++ b/contrib/llvm/include/llvm/IR/Comdat.h
@@ -16,6 +16,9 @@
#ifndef LLVM_IR_COMDAT_H
#define LLVM_IR_COMDAT_H
+#include "llvm-c/Types.h"
+#include "llvm/Support/CBindingWrapping.h"
+
namespace llvm {
class raw_ostream;
@@ -55,6 +58,9 @@ private:
SelectionKind SK = Any;
};
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Comdat, LLVMComdatRef)
+
inline raw_ostream &operator<<(raw_ostream &OS, const Comdat &C) {
C.print(OS);
return OS;
diff --git a/contrib/llvm/include/llvm/IR/Constant.h b/contrib/llvm/include/llvm/IR/Constant.h
index 0c94b58a3112..5fdf0ea00f00 100644
--- a/contrib/llvm/include/llvm/IR/Constant.h
+++ b/contrib/llvm/include/llvm/IR/Constant.h
@@ -38,7 +38,7 @@ class APInt;
/// structurally equivalent constants will always have the same address.
/// Constants are created on demand as needed and never deleted: thus clients
/// don't have to worry about the lifetime of the objects.
-/// @brief LLVM Constant Representation
+/// LLVM Constant Representation
class Constant : public User {
protected:
Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps)
@@ -71,6 +71,26 @@ public:
/// Return true if the value is the smallest signed value.
bool isMinSignedValue() const;
+ /// Return true if this is a finite and non-zero floating-point scalar
+ /// constant or a vector constant with all finite and non-zero elements.
+ bool isFiniteNonZeroFP() const;
+
+ /// Return true if this is a normal (as opposed to denormal) floating-point
+ /// scalar constant or a vector constant with all normal elements.
+ bool isNormalFP() const;
+
+ /// Return true if this scalar has an exact multiplicative inverse or this
+ /// vector has an exact multiplicative inverse for each element in the vector.
+ bool hasExactInverseFP() const;
+
+ /// Return true if this is a floating-point NaN constant or a vector
+ /// floating-point constant with all NaN elements.
+ bool isNaN() const;
+
+ /// Return true if this is a vector constant that includes any undefined
+ /// elements.
+ bool containsUndefElement() const;
+
/// Return true if evaluation of this constant could trap. This is true for
/// things like constant expressions that could divide by zero.
bool canTrap() const;
@@ -137,7 +157,7 @@ public:
/// @returns the value for an integer or vector of integer constant of the
/// given type that has all its bits set to true.
- /// @brief Get the all ones value
+ /// Get the all ones value
static Constant *getAllOnesValue(Type* Ty);
/// Return the value for an integer or pointer constant, or a vector thereof,
diff --git a/contrib/llvm/include/llvm/IR/ConstantRange.h b/contrib/llvm/include/llvm/IR/ConstantRange.h
index 6889e2658244..1adda3269abc 100644
--- a/contrib/llvm/include/llvm/IR/ConstantRange.h
+++ b/contrib/llvm/include/llvm/IR/ConstantRange.h
@@ -54,7 +54,7 @@ public:
/// Initialize a range to hold the single specified value.
ConstantRange(APInt Value);
- /// @brief Initialize a range of values explicitly. This will assert out if
+ /// Initialize a range of values explicitly. This will assert out if
/// Lower==Upper and Lower != Min or Max value for its type. It will also
/// assert out if the two APInt's are not the same bit width.
ConstantRange(APInt Lower, APInt Upper);
diff --git a/contrib/llvm/include/llvm/IR/Constants.h b/contrib/llvm/include/llvm/IR/Constants.h
index 0094fd54992a..f9d5ebc560c7 100644
--- a/contrib/llvm/include/llvm/IR/Constants.h
+++ b/contrib/llvm/include/llvm/IR/Constants.h
@@ -80,7 +80,7 @@ public:
//===----------------------------------------------------------------------===//
/// This is the shared class of boolean and integer constants. This class
/// represents both boolean and integral constants.
-/// @brief Class for constant integers.
+/// Class for constant integers.
class ConstantInt final : public ConstantData {
friend class Constant;
@@ -107,7 +107,7 @@ public:
/// to fit the type, unless isSigned is true, in which case the value will
/// be interpreted as a 64-bit signed integer and sign-extended to fit
/// the type.
- /// @brief Get a ConstantInt for a specific value.
+ /// Get a ConstantInt for a specific value.
static ConstantInt *get(IntegerType *Ty, uint64_t V,
bool isSigned = false);
@@ -115,7 +115,7 @@ public:
/// value V will be canonicalized to a an unsigned APInt. Accessing it with
/// either getSExtValue() or getZExtValue() will yield a correctly sized and
/// signed value for the type Ty.
- /// @brief Get a ConstantInt for a specific signed value.
+ /// Get a ConstantInt for a specific signed value.
static ConstantInt *getSigned(IntegerType *Ty, int64_t V);
static Constant *getSigned(Type *Ty, int64_t V);
@@ -134,7 +134,7 @@ public:
/// Return the constant as an APInt value reference. This allows clients to
/// obtain a full-precision copy of the value.
- /// @brief Return the constant's value.
+ /// Return the constant's value.
inline const APInt &getValue() const {
return Val;
}
@@ -145,7 +145,7 @@ public:
/// Return the constant as a 64-bit unsigned integer value after it
/// has been zero extended as appropriate for the type of this constant. Note
/// that this method can assert if the value does not fit in 64 bits.
- /// @brief Return the zero extended value.
+ /// Return the zero extended value.
inline uint64_t getZExtValue() const {
return Val.getZExtValue();
}
@@ -153,7 +153,7 @@ public:
/// Return the constant as a 64-bit integer value after it has been sign
/// extended as appropriate for the type of this constant. Note that
/// this method can assert if the value does not fit in 64 bits.
- /// @brief Return the sign extended value.
+ /// Return the sign extended value.
inline int64_t getSExtValue() const {
return Val.getSExtValue();
}
@@ -161,7 +161,7 @@ public:
/// A helper method that can be used to determine if the constant contained
/// within is equal to a constant. This only works for very small values,
/// because this is all that can be represented with all types.
- /// @brief Determine if this constant's value is same as an unsigned char.
+ /// Determine if this constant's value is same as an unsigned char.
bool equalsInt(uint64_t V) const {
return Val == V;
}
@@ -181,7 +181,7 @@ public:
/// the signed version avoids callers having to convert a signed quantity
/// to the appropriate unsigned type before calling the method.
/// @returns true if V is a valid value for type Ty
- /// @brief Determine if the value is in range for the given type.
+ /// Determine if the value is in range for the given type.
static bool isValueValidForType(Type *Ty, uint64_t V);
static bool isValueValidForType(Type *Ty, int64_t V);
@@ -197,7 +197,7 @@ public:
/// This is just a convenience method to make client code smaller for a
/// common case. It also correctly performs the comparison without the
/// potential for an assertion from getZExtValue().
- /// @brief Determine if the value is one.
+ /// Determine if the value is one.
bool isOne() const {
return Val.isOneValue();
}
@@ -205,7 +205,7 @@ public:
/// This function will return true iff every bit in this constant is set
/// to true.
/// @returns true iff this constant's bits are all set to true.
- /// @brief Determine if the value is all ones.
+ /// Determine if the value is all ones.
bool isMinusOne() const {
return Val.isAllOnesValue();
}
@@ -214,7 +214,7 @@ public:
/// value that may be represented by the constant's type.
/// @returns true iff this is the largest value that may be represented
/// by this type.
- /// @brief Determine if the value is maximal.
+ /// Determine if the value is maximal.
bool isMaxValue(bool isSigned) const {
if (isSigned)
return Val.isMaxSignedValue();
@@ -226,7 +226,7 @@ public:
/// value that may be represented by this constant's type.
/// @returns true if this is the smallest value that may be represented by
/// this type.
- /// @brief Determine if the value is minimal.
+ /// Determine if the value is minimal.
bool isMinValue(bool isSigned) const {
if (isSigned)
return Val.isMinSignedValue();
@@ -238,7 +238,7 @@ public:
/// active bits bigger than 64 bits or a value greater than the given uint64_t
/// value.
/// @returns true iff this constant is greater or equal to the given number.
- /// @brief Determine if the value is greater or equal to the given number.
+ /// Determine if the value is greater or equal to the given number.
bool uge(uint64_t Num) const {
return Val.uge(Num);
}
@@ -247,12 +247,12 @@ public:
/// return it, otherwise return the limit value. This causes the value
/// to saturate to the limit.
/// @returns the min of the value of the constant and the specified value
- /// @brief Get the constant's value with a saturation limit
+ /// Get the constant's value with a saturation limit
uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
return Val.getLimitedValue(Limit);
}
- /// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
+ /// Methods to support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Value *V) {
return V->getValueID() == ConstantIntVal;
}
@@ -283,6 +283,11 @@ public:
/// for simple constant values like 2.0/1.0 etc, that are known-valid both as
/// host double and as the target format.
static Constant *get(Type* Ty, double V);
+
+ /// If Ty is a vector type, return a Constant with a splat of the given
+ /// value. Otherwise return a ConstantFP for the given value.
+ static Constant *get(Type *Ty, const APFloat &V);
+
static Constant *get(Type* Ty, StringRef Str);
static ConstantFP *get(LLVMContext &Context, const APFloat &V);
static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0);
@@ -687,15 +692,33 @@ class ConstantDataArray final : public ConstantDataSequential {
public:
ConstantDataArray(const ConstantDataArray &) = delete;
- /// get() constructors - Return a constant with array type with an element
+ /// get() constructor - Return a constant with array type with an element
/// count and element type matching the ArrayRef passed in. Note that this
/// can return a ConstantAggregateZero object.
- static Constant *get(LLVMContext &Context, ArrayRef<uint8_t> Elts);
- static Constant *get(LLVMContext &Context, ArrayRef<uint16_t> Elts);
- static Constant *get(LLVMContext &Context, ArrayRef<uint32_t> Elts);
- static Constant *get(LLVMContext &Context, ArrayRef<uint64_t> Elts);
- static Constant *get(LLVMContext &Context, ArrayRef<float> Elts);
- static Constant *get(LLVMContext &Context, ArrayRef<double> Elts);
+ template <typename ElementTy>
+ static Constant *get(LLVMContext &Context, ArrayRef<ElementTy> Elts) {
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getRaw(StringRef(Data, Elts.size() * sizeof(ElementTy)), Elts.size(),
+ Type::getScalarTy<ElementTy>(Context));
+ }
+
+ /// get() constructor - ArrayTy needs to be compatible with
+ /// ArrayRef<ElementTy>. Calls get(LLVMContext, ArrayRef<ElementTy>).
+ template <typename ArrayTy>
+ static Constant *get(LLVMContext &Context, ArrayTy &Elts) {
+ return ConstantDataArray::get(Context, makeArrayRef(Elts));
+ }
+
+ /// get() constructor - Return a constant with array type with an element
+ /// count and element type matching the NumElements and ElementTy parameters
+ /// passed in. Note that this can return a ConstantAggregateZero object.
+ /// ElementTy needs to be one of i8/i16/i32/i64/float/double. Data is the
+ /// buffer containing the elements. Be careful to make sure Data uses the
+ /// right endianness, the buffer will be used as-is.
+ static Constant *getRaw(StringRef Data, uint64_t NumElements, Type *ElementTy) {
+ Type *Ty = ArrayType::get(ElementTy, NumElements);
+ return getImpl(Data, Ty);
+ }
/// getFP() constructors - Return a constant with array type with an element
/// count and element type of float with precision matching the number of
@@ -802,7 +825,7 @@ public:
/// Return the ConstantTokenNone.
static ConstantTokenNone *get(LLVMContext &Context);
- /// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
+ /// Methods to support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Value *V) {
return V->getValueID() == ConstantTokenNoneVal;
}
@@ -995,10 +1018,15 @@ public:
return getLShr(C1, C2, true);
}
- /// Return the identity for the given binary operation,
- /// i.e. a constant C such that X op C = X and C op X = X for every X. It
- /// returns null if the operator doesn't have an identity.
- static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty);
+ /// Return the identity constant for a binary opcode.
+ /// The identity constant C is defined as X op C = X and C op X = X for every
+ /// X when the binary operation is commutative. If the binop is not
+ /// commutative, callers can acquire the operand 1 identity constant by
+ /// setting AllowRHSConstant to true. For example, any shift has a zero
+ /// identity constant for operand 1: X shift 0 = X.
+ /// Return nullptr if the operator does not have an identity constant.
+ static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty,
+ bool AllowRHSConstant = false);
/// Return the absorbing element for the given binary
/// operation, i.e. a constant C such that X op C = C and C op X = C for
@@ -1009,7 +1037,7 @@ public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
- /// \brief Convenience function for getting a Cast operation.
+ /// Convenience function for getting a Cast operation.
///
/// \param ops The opcode for the conversion
/// \param C The constant to be converted
@@ -1018,62 +1046,62 @@ public:
static Constant *getCast(unsigned ops, Constant *C, Type *Ty,
bool OnlyIfReduced = false);
- // @brief Create a ZExt or BitCast cast constant expression
+ // Create a ZExt or BitCast cast constant expression
static Constant *getZExtOrBitCast(
Constant *C, ///< The constant to zext or bitcast
Type *Ty ///< The type to zext or bitcast C to
);
- // @brief Create a SExt or BitCast cast constant expression
+ // Create a SExt or BitCast cast constant expression
static Constant *getSExtOrBitCast(
Constant *C, ///< The constant to sext or bitcast
Type *Ty ///< The type to sext or bitcast C to
);
- // @brief Create a Trunc or BitCast cast constant expression
+ // Create a Trunc or BitCast cast constant expression
static Constant *getTruncOrBitCast(
Constant *C, ///< The constant to trunc or bitcast
Type *Ty ///< The type to trunc or bitcast C to
);
- /// @brief Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant
+ /// Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant
/// expression.
static Constant *getPointerCast(
Constant *C, ///< The pointer value to be casted (operand 0)
Type *Ty ///< The type to which cast should be made
);
- /// @brief Create a BitCast or AddrSpaceCast for a pointer type depending on
+ /// Create a BitCast or AddrSpaceCast for a pointer type depending on
/// the address space.
static Constant *getPointerBitCastOrAddrSpaceCast(
Constant *C, ///< The constant to addrspacecast or bitcast
Type *Ty ///< The type to bitcast or addrspacecast C to
);
- /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts
+ /// Create a ZExt, Bitcast or Trunc for integer -> integer casts
static Constant *getIntegerCast(
Constant *C, ///< The integer constant to be casted
Type *Ty, ///< The integer type to cast to
bool isSigned ///< Whether C should be treated as signed or not
);
- /// @brief Create a FPExt, Bitcast or FPTrunc for fp -> fp casts
+ /// Create a FPExt, Bitcast or FPTrunc for fp -> fp casts
static Constant *getFPCast(
Constant *C, ///< The integer constant to be casted
Type *Ty ///< The integer type to cast to
);
- /// @brief Return true if this is a convert constant expression
+ /// Return true if this is a convert constant expression
bool isCast() const;
- /// @brief Return true if this is a compare constant expression
+ /// Return true if this is a compare constant expression
bool isCompare() const;
- /// @brief Return true if this is an insertvalue or extractvalue expression,
+ /// Return true if this is an insertvalue or extractvalue expression,
/// and the getIndices() method may be used.
bool hasIndices() const;
- /// @brief Return true if this is a getelementptr expression and all
+ /// Return true if this is a getelementptr expression and all
/// the index operands are compile-time known integers within the
/// corresponding notional static array extents. Note that this is
/// not equivalant to, a subset of, or a superset of the "inbounds"
@@ -1093,7 +1121,7 @@ public:
static Constant *get(unsigned Opcode, Constant *C1, Constant *C2,
unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr);
- /// \brief Return an ICmp or FCmp comparison operator constant expression.
+ /// Return an ICmp or FCmp comparison operator constant expression.
///
/// \param OnlyIfReduced see \a getWithOperands() docs.
static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2,
diff --git a/contrib/llvm/include/llvm/IR/DIBuilder.h b/contrib/llvm/include/llvm/IR/DIBuilder.h
index 3c2074dfe788..06c9421ec1d6 100644
--- a/contrib/llvm/include/llvm/IR/DIBuilder.h
+++ b/contrib/llvm/include/llvm/IR/DIBuilder.h
@@ -18,7 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -46,6 +46,7 @@ namespace llvm {
DICompileUnit *CUNode; ///< The one compile unit created by this DIBuiler.
Function *DeclareFn; ///< llvm.dbg.declare
Function *ValueFn; ///< llvm.dbg.value
+ Function *LabelFn; ///< llvm.dbg.label
SmallVector<Metadata *, 4> AllEnumTypes;
/// Track the RetainTypes, since they can be updated later on.
@@ -69,6 +70,9 @@ namespace llvm {
/// copy.
DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> PreservedVariables;
+ /// Each subprogram's preserved labels.
+ DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> PreservedLabels;
+
/// Create a temporary.
///
/// Create an \a temporary node and track it in \a UnresolvedNodes.
@@ -79,6 +83,10 @@ namespace llvm {
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);
+ /// Internal helper for insertLabel.
+ Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
+ BasicBlock *InsertBB, Instruction *InsertBefore);
+
/// Internal helper for insertDbgValueIntrinsic.
Instruction *
insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo,
@@ -90,7 +98,10 @@ namespace llvm {
///
/// 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);
+ ///
+ /// If \p CU is given a value other than nullptr, then set \p CUNode to CU.
+ explicit DIBuilder(Module &M, bool AllowUnresolved = true,
+ DICompileUnit *CU = nullptr);
DIBuilder(const DIBuilder &) = delete;
DIBuilder &operator=(const DIBuilder &) = delete;
@@ -138,11 +149,13 @@ namespace llvm {
/// Create a file descriptor to hold debugging information for a file.
/// \param Filename File name.
/// \param Directory Directory.
- /// \param CSKind Checksum kind (e.g. CSK_None, CSK_MD5, CSK_SHA1, etc.).
- /// \param Checksum Checksum data.
- DIFile *createFile(StringRef Filename, StringRef Directory,
- DIFile::ChecksumKind CSKind = DIFile::CSK_None,
- StringRef Checksum = StringRef());
+ /// \param Checksum Optional checksum kind (e.g. CSK_MD5, CSK_SHA1, etc.)
+ /// and value.
+ /// \param Source Optional source text.
+ DIFile *
+ createFile(StringRef Filename, StringRef Directory,
+ Optional<DIFile::ChecksumInfo<StringRef>> Checksum = None,
+ Optional<StringRef> Source = None);
/// Create debugging information entry for a macro.
/// \param Parent Macro parent (could be nullptr).
@@ -163,7 +176,7 @@ namespace llvm {
DIFile *File);
/// Create a single enumerator value.
- DIEnumerator *createEnumerator(StringRef Name, int64_t Val);
+ DIEnumerator *createEnumerator(StringRef Name, int64_t Val, bool IsUnsigned = false);
/// Create a DWARF unspecified type.
DIBasicType *createUnspecifiedType(StringRef Name);
@@ -232,10 +245,11 @@ namespace llvm {
/// \param Ty Original type.
/// \param BaseTy Base type. Ty is inherits from base.
/// \param BaseOffset Base offset.
+ /// \param VBPtrOffset Virtual base pointer offset.
/// \param Flags Flags to describe inheritance attribute,
/// e.g. private
DIDerivedType *createInheritance(DIType *Ty, DIType *BaseTy,
- uint64_t BaseOffset,
+ uint64_t BaseOffset, uint32_t VBPtrOffset,
DINode::DIFlags Flags);
/// Create debugging information entry for a member.
@@ -255,6 +269,27 @@ namespace llvm {
uint64_t OffsetInBits,
DINode::DIFlags Flags, DIType *Ty);
+ /// Create debugging information entry for a variant. A variant
+ /// normally should be a member of a variant part.
+ /// \param Scope Member scope.
+ /// \param Name Member name.
+ /// \param File File where this member is defined.
+ /// \param LineNo Line number.
+ /// \param SizeInBits Member size.
+ /// \param AlignInBits Member alignment.
+ /// \param OffsetInBits Member offset.
+ /// \param Flags Flags to encode member attribute, e.g. private
+ /// \param Discriminant The discriminant for this branch; null for
+ /// the default branch
+ /// \param Ty Parent type.
+ DIDerivedType *createVariantMemberType(DIScope *Scope, StringRef Name,
+ DIFile *File, unsigned LineNo,
+ uint64_t SizeInBits,
+ uint32_t AlignInBits,
+ uint64_t OffsetInBits,
+ Constant *Discriminant,
+ DINode::DIFlags Flags, DIType *Ty);
+
/// Create debugging information entry for a bit field member.
/// \param Scope Member scope.
/// \param Name Member name.
@@ -376,6 +411,27 @@ namespace llvm {
unsigned RunTimeLang = 0,
StringRef UniqueIdentifier = "");
+ /// Create debugging information entry for a variant part. A
+ /// variant part normally has a discriminator (though this is not
+ /// required) and a number of variant children.
+ /// \param Scope Scope in which this union is defined.
+ /// \param Name Union name.
+ /// \param File File where this member is defined.
+ /// \param LineNumber Line number.
+ /// \param SizeInBits Member size.
+ /// \param AlignInBits Member alignment.
+ /// \param Flags Flags to encode member attribute, e.g. private
+ /// \param Discriminator Discriminant member
+ /// \param Elements Variant elements.
+ /// \param UniqueIdentifier A unique identifier for the union.
+ DICompositeType *createVariantPart(DIScope *Scope, StringRef Name,
+ DIFile *File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits,
+ DINode::DIFlags Flags,
+ DIDerivedType *Discriminator,
+ DINodeArray Elements,
+ StringRef UniqueIdentifier = "");
+
/// Create debugging information for template
/// type parameter.
/// \param Scope Scope in which this type is defined.
@@ -442,10 +498,11 @@ namespace llvm {
/// \param Elements Enumeration elements.
/// \param UnderlyingType Underlying type of a C++11/ObjC fixed enum.
/// \param UniqueIdentifier A unique identifier for the enum.
+ /// \param IsFixed Boolean flag indicate if this is C++11/ObjC fixed enum.
DICompositeType *createEnumerationType(
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements,
- DIType *UnderlyingType, StringRef UniqueIdentifier = "");
+ DIType *UnderlyingType, StringRef UniqueIdentifier = "", bool IsFixed = false);
/// Create subroutine type.
/// \param ParameterTypes An array of subroutine parameter types. This
@@ -458,12 +515,15 @@ namespace llvm {
DINode::DIFlags Flags = DINode::FlagZero,
unsigned CC = 0);
- /// Create a new DIType* with "artificial" flag set.
- DIType *createArtificialType(DIType *Ty);
+ /// Create a distinct clone of \p SP with FlagArtificial set.
+ static DISubprogram *createArtificialSubprogram(DISubprogram *SP);
+
+ /// Create a uniqued clone of \p Ty with FlagArtificial set.
+ static DIType *createArtificialType(DIType *Ty);
- /// Create a new DIType* with the "object pointer"
- /// flag set.
- DIType *createObjectPointerType(DIType *Ty);
+ /// Create a uniqued clone of \p Ty with FlagObjectPointer and
+ /// FlagArtificial set.
+ static DIType *createObjectPointerType(DIType *Ty);
/// Create a permanent forward-declared type.
DICompositeType *createForwardDecl(unsigned Tag, StringRef Name,
@@ -500,6 +560,7 @@ namespace llvm {
/// Create a descriptor for a value range. This
/// implicitly uniques the values returned.
DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count);
+ DISubrange *getOrCreateSubrange(int64_t Lo, Metadata *CountNode);
/// Create a new descriptor for the specified variable.
/// \param Context Variable scope.
@@ -542,6 +603,14 @@ namespace llvm {
DINode::DIFlags Flags = DINode::FlagZero,
uint32_t AlignInBits = 0);
+ /// Create a new descriptor for an label.
+ ///
+ /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually
+ /// leads to a \a DISubprogram.
+ DILabel *
+ createLabel(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo,
+ bool AlwaysPreserve = false);
+
/// Create a new descriptor for a parameter variable.
///
/// \c Scope must be a \a DILocalScope, and thus its scope chain eventually
@@ -733,6 +802,20 @@ namespace llvm {
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore);
+ /// Insert a new llvm.dbg.label intrinsic call.
+ /// \param LabelInfo Label's debug info descriptor.
+ /// \param DL Debug info location.
+ /// \param InsertBefore Location for the new intrinsic.
+ Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
+ Instruction *InsertBefore);
+
+ /// Insert a new llvm.dbg.label intrinsic call.
+ /// \param LabelInfo Label's debug info descriptor.
+ /// \param DL Debug info location.
+ /// \param InsertAtEnd Location for the new intrinsic.
+ Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
+ BasicBlock *InsertAtEnd);
+
/// Insert a new llvm.dbg.value intrinsic call.
/// \param Val llvm::Value of the variable
/// \param VarInfo Variable's debug info descriptor.
diff --git a/contrib/llvm/include/llvm/IR/DataLayout.h b/contrib/llvm/include/llvm/IR/DataLayout.h
index a6c71a5a2c3e..d796a65e6129 100644
--- a/contrib/llvm/include/llvm/IR/DataLayout.h
+++ b/contrib/llvm/include/llvm/IR/DataLayout.h
@@ -61,7 +61,7 @@ enum AlignTypeEnum {
// sunk down to an FTTI element that is queried rather than a global
// preference.
-/// \brief Layout alignment element.
+/// Layout alignment element.
///
/// Stores the alignment data associated with a given alignment type (integer,
/// vector, float) and type bit width.
@@ -69,7 +69,7 @@ enum AlignTypeEnum {
/// \note The unusual order of elements in the structure attempts to reduce
/// padding and make the structure slightly more cache friendly.
struct LayoutAlignElem {
- /// \brief Alignment type from \c AlignTypeEnum
+ /// Alignment type from \c AlignTypeEnum
unsigned AlignType : 8;
unsigned TypeBitWidth : 24;
unsigned ABIAlign : 16;
@@ -81,7 +81,7 @@ struct LayoutAlignElem {
bool operator==(const LayoutAlignElem &rhs) const;
};
-/// \brief Layout pointer alignment element.
+/// Layout pointer alignment element.
///
/// Stores the alignment data associated with a given pointer and address space.
///
@@ -92,15 +92,17 @@ struct PointerAlignElem {
unsigned PrefAlign;
uint32_t TypeByteWidth;
uint32_t AddressSpace;
+ uint32_t IndexWidth;
/// Initializer
static PointerAlignElem get(uint32_t AddressSpace, unsigned ABIAlign,
- unsigned PrefAlign, uint32_t TypeByteWidth);
+ unsigned PrefAlign, uint32_t TypeByteWidth,
+ uint32_t IndexWidth);
bool operator==(const PointerAlignElem &rhs) const;
};
-/// \brief A parsed version of the target data layout string in and methods for
+/// A parsed version of the target data layout string in and methods for
/// querying it.
///
/// The target data layout string is specified *by the target* - a frontend
@@ -113,6 +115,7 @@ private:
unsigned AllocaAddrSpace;
unsigned StackNaturalAlign;
+ unsigned ProgramAddrSpace;
enum ManglingModeT {
MM_None,
@@ -126,7 +129,7 @@ private:
SmallVector<unsigned char, 8> LegalIntWidths;
- /// \brief Primitive type alignment data. This is sorted by type and bit
+ /// Primitive type alignment data. This is sorted by type and bit
/// width during construction.
using AlignmentsTy = SmallVector<LayoutAlignElem, 16>;
AlignmentsTy Alignments;
@@ -140,7 +143,7 @@ private:
AlignmentsTy::iterator
findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth);
- /// \brief The string representation used to create this DataLayout
+ /// The string representation used to create this DataLayout
std::string StringRepresentation;
using PointersTy = SmallVector<PointerAlignElem, 8>;
@@ -165,7 +168,8 @@ private:
unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width,
bool ABIAlign, Type *Ty) const;
void setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
- unsigned PrefAlign, uint32_t TypeByteWidth);
+ unsigned PrefAlign, uint32_t TypeByteWidth,
+ uint32_t IndexWidth);
/// Internal helper method that returns requested alignment for type.
unsigned getAlignment(Type *Ty, bool abi_or_pref) const;
@@ -196,6 +200,7 @@ public:
BigEndian = DL.isBigEndian();
AllocaAddrSpace = DL.AllocaAddrSpace;
StackNaturalAlign = DL.StackNaturalAlign;
+ ProgramAddrSpace = DL.ProgramAddrSpace;
ManglingMode = DL.ManglingMode;
LegalIntWidths = DL.LegalIntWidths;
Alignments = DL.Alignments;
@@ -216,7 +221,7 @@ public:
bool isLittleEndian() const { return !BigEndian; }
bool isBigEndian() const { return BigEndian; }
- /// \brief Returns the string representation of the DataLayout.
+ /// Returns the string representation of the DataLayout.
///
/// This representation is in the same format accepted by the string
/// constructor above. This should not be used to compare two DataLayout as
@@ -225,10 +230,10 @@ public:
return StringRepresentation;
}
- /// \brief Test if the DataLayout was constructed from an empty string.
+ /// Test if the DataLayout was constructed from an empty string.
bool isDefault() const { return StringRepresentation.empty(); }
- /// \brief Returns true if the specified type is known to be a native integer
+ /// Returns true if the specified type is known to be a native integer
/// type supported by the CPU.
///
/// For example, i64 is not native on most 32-bit CPUs and i37 is not native
@@ -252,10 +257,18 @@ public:
unsigned getStackAlignment() const { return StackNaturalAlign; }
unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; }
+ unsigned getProgramAddressSpace() const { return ProgramAddrSpace; }
+
bool hasMicrosoftFastStdCallMangling() const {
return ManglingMode == MM_WinCOFFX86;
}
+ /// Returns true if symbols with leading question marks should not receive IR
+ /// mangling. True for Windows mangling modes.
+ bool doNotMangleLeadingQuestionMark() const {
+ return ManglingMode == MM_WinCOFF || ManglingMode == MM_WinCOFFX86;
+ }
+
bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; }
StringRef getLinkerPrivateGlobalPrefix() const {
@@ -296,7 +309,7 @@ public:
static const char *getManglingComponent(const Triple &T);
- /// \brief Returns true if the specified type fits in a native integer type
+ /// Returns true if the specified type fits in a native integer type
/// supported by the CPU.
///
/// For example, if the CPU only supports i32 as a native integer type, then
@@ -321,6 +334,9 @@ public:
/// the backends/clients are updated.
unsigned getPointerSize(unsigned AS = 0) const;
+ // Index size used for address calculation.
+ unsigned getIndexSize(unsigned AS) const;
+
/// Return the address spaces containing non-integral pointers. Pointers in
/// this address space don't have a well-defined bitwise representation.
ArrayRef<unsigned> getNonIntegralAddressSpaces() const {
@@ -345,6 +361,11 @@ public:
return getPointerSize(AS) * 8;
}
+ /// Size in bits of index used for address calculation in getelementptr.
+ unsigned getIndexSizeInBits(unsigned AS) const {
+ return getIndexSize(AS) * 8;
+ }
+
/// Layout pointer size, in bits, based on the type. If this function is
/// called with a pointer type, then the type size of the pointer is returned.
/// If this function is called with a vector of pointers, then the type size
@@ -352,6 +373,10 @@ public:
/// vector of pointers.
unsigned getPointerTypeSizeInBits(Type *) const;
+ /// Layout size of the index used in GEP calculation.
+ /// The function should be called with pointer or vector of pointers type.
+ unsigned getIndexTypeSizeInBits(Type *Ty) const;
+
unsigned getPointerTypeSize(Type *Ty) const {
return getPointerTypeSizeInBits(Ty) / 8;
}
@@ -373,13 +398,13 @@ public:
/// [*] The alloc size depends on the alignment, and thus on the target.
/// These values are for x86-32 linux.
- /// \brief Returns the number of bits necessary to hold the specified type.
+ /// Returns the number of bits necessary to hold the specified type.
///
/// For example, returns 36 for i36 and 80 for x86_fp80. The type passed must
/// have a size (Type::isSized() must return true).
uint64_t getTypeSizeInBits(Type *Ty) const;
- /// \brief Returns the maximum number of bytes that may be overwritten by
+ /// Returns the maximum number of bytes that may be overwritten by
/// storing the specified type.
///
/// For example, returns 5 for i36 and 10 for x86_fp80.
@@ -387,7 +412,7 @@ public:
return (getTypeSizeInBits(Ty) + 7) / 8;
}
- /// \brief Returns the maximum number of bits that may be overwritten by
+ /// Returns the maximum number of bits that may be overwritten by
/// storing the specified type; always a multiple of 8.
///
/// For example, returns 40 for i36 and 80 for x86_fp80.
@@ -395,7 +420,7 @@ public:
return 8 * getTypeStoreSize(Ty);
}
- /// \brief Returns the offset in bytes between successive objects of the
+ /// Returns the offset in bytes between successive objects of the
/// specified type, including alignment padding.
///
/// This is the amount that alloca reserves for this type. For example,
@@ -405,7 +430,7 @@ public:
return alignTo(getTypeStoreSize(Ty), getABITypeAlignment(Ty));
}
- /// \brief Returns the offset in bits between successive objects of the
+ /// Returns the offset in bits between successive objects of the
/// specified type, including alignment padding; always a multiple of 8.
///
/// This is the amount that alloca reserves for this type. For example,
@@ -414,64 +439,69 @@ public:
return 8 * getTypeAllocSize(Ty);
}
- /// \brief Returns the minimum ABI-required alignment for the specified type.
+ /// Returns the minimum ABI-required alignment for the specified type.
unsigned getABITypeAlignment(Type *Ty) const;
- /// \brief Returns the minimum ABI-required alignment for an integer type of
+ /// Returns the minimum ABI-required alignment for an integer type of
/// the specified bitwidth.
unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const;
- /// \brief Returns the preferred stack/global alignment for the specified
+ /// Returns the preferred stack/global alignment for the specified
/// type.
///
/// This is always at least as good as the ABI alignment.
unsigned getPrefTypeAlignment(Type *Ty) const;
- /// \brief Returns the preferred alignment for the specified type, returned as
+ /// Returns the preferred alignment for the specified type, returned as
/// log2 of the value (a shift amount).
unsigned getPreferredTypeAlignmentShift(Type *Ty) const;
- /// \brief Returns an integer type with size at least as big as that of a
+ /// Returns an integer type with size at least as big as that of a
/// pointer in the given address space.
IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const;
- /// \brief Returns an integer (vector of integer) type with size at least as
+ /// Returns an integer (vector of integer) type with size at least as
/// big as that of a pointer of the given pointer (vector of pointer) type.
Type *getIntPtrType(Type *) const;
- /// \brief Returns the smallest integer type with size at least as big as
+ /// Returns the smallest integer type with size at least as big as
/// Width bits.
Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const;
- /// \brief Returns the largest legal integer type, or null if none are set.
+ /// Returns the largest legal integer type, or null if none are set.
Type *getLargestLegalIntType(LLVMContext &C) const {
unsigned LargestSize = getLargestLegalIntTypeSizeInBits();
return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize);
}
- /// \brief Returns the size of largest legal integer type size, or 0 if none
+ /// Returns the size of largest legal integer type size, or 0 if none
/// are set.
unsigned getLargestLegalIntTypeSizeInBits() const;
- /// \brief Returns the offset from the beginning of the type for the specified
+ /// Returns the type of a GEP index.
+ /// If it was not specified explicitly, it will be the integer type of the
+ /// pointer width - IntPtrType.
+ Type *getIndexType(Type *PtrTy) const;
+
+ /// Returns the offset from the beginning of the type for the specified
/// indices.
///
/// Note that this takes the element type, not the pointer type.
/// This is used to implement getelementptr.
int64_t getIndexedOffsetInType(Type *ElemTy, ArrayRef<Value *> Indices) const;
- /// \brief Returns a StructLayout object, indicating the alignment of the
+ /// Returns a StructLayout object, indicating the alignment of the
/// struct, its size, and the offsets of its fields.
///
/// Note that this information is lazily cached.
const StructLayout *getStructLayout(StructType *Ty) const;
- /// \brief Returns the preferred alignment of the specified global.
+ /// Returns the preferred alignment of the specified global.
///
/// This includes an explicitly requested alignment (if the global has one).
unsigned getPreferredAlignment(const GlobalVariable *GV) const;
- /// \brief Returns the preferred alignment of the specified global, returned
+ /// Returns the preferred alignment of the specified global, returned
/// in log form.
///
/// This includes an explicitly requested alignment (if the global has one).
@@ -506,7 +536,7 @@ public:
/// NB: Padding in nested element is not taken into account.
bool hasPadding() const { return IsPadded; }
- /// \brief Given a valid byte offset into the structure, returns the structure
+ /// Given a valid byte offset into the structure, returns the structure
/// index that contains it.
unsigned getElementContainingOffset(uint64_t Offset) const;
diff --git a/contrib/llvm/include/llvm/IR/DebugInfo.h b/contrib/llvm/include/llvm/IR/DebugInfo.h
index 1d8e7e2855fd..01178af3c9ff 100644
--- a/contrib/llvm/include/llvm/IR/DebugInfo.h
+++ b/contrib/llvm/include/llvm/IR/DebugInfo.h
@@ -28,10 +28,10 @@ class DbgDeclareInst;
class DbgValueInst;
class Module;
-/// \brief Find subprogram that is enclosing this scope.
+/// Find subprogram that is enclosing this scope.
DISubprogram *getDISubprogram(const MDNode *Scope);
-/// \brief Strip debug info in the module if it exists.
+/// Strip debug info in the module if it exists.
///
/// To do this, we remove all calls to the debugger intrinsics and any named
/// metadata for debugging. We also remove debug locations for instructions.
@@ -51,10 +51,10 @@ bool stripDebugInfo(Function &F);
/// All debug type metadata nodes are unreachable and garbage collected.
bool stripNonLineTableDebugInfo(Module &M);
-/// \brief Return Debug Info Metadata Version by checking module flags.
+/// Return Debug Info Metadata Version by checking module flags.
unsigned getDebugMetadataVersionFromModule(const Module &M);
-/// \brief Utility to find all debug info in a module.
+/// Utility to find all debug info in a module.
///
/// DebugInfoFinder tries to list all debug info MDNodes used in a module. To
/// list debug info MDNodes used by an instruction, DebugInfoFinder uses
@@ -64,30 +64,33 @@ unsigned getDebugMetadataVersionFromModule(const Module &M);
/// used by the CUs.
class DebugInfoFinder {
public:
- /// \brief Process entire module and collect debug info anchors.
+ /// Process entire module and collect debug info anchors.
void processModule(const Module &M);
+ /// Process a single instruction and collect debug info anchors.
+ void processInstruction(const Module &M, const Instruction &I);
- /// \brief Process DbgDeclareInst.
+ /// Process DbgDeclareInst.
void processDeclare(const Module &M, const DbgDeclareInst *DDI);
- /// \brief Process DbgValueInst.
+ /// Process DbgValueInst.
void processValue(const Module &M, const DbgValueInst *DVI);
- /// \brief Process debug info location.
+ /// Process debug info location.
void processLocation(const Module &M, const DILocation *Loc);
- /// \brief Clear all lists.
+ /// Clear all lists.
void reset();
private:
void InitializeTypeMap(const Module &M);
- void processType(DIType *DT);
- void processSubprogram(DISubprogram *SP);
+ void processCompileUnit(DICompileUnit *CU);
void processScope(DIScope *Scope);
+ void processSubprogram(DISubprogram *SP);
+ void processType(DIType *DT);
bool addCompileUnit(DICompileUnit *CU);
bool addGlobalVariable(DIGlobalVariableExpression *DIG);
+ bool addScope(DIScope *Scope);
bool addSubprogram(DISubprogram *SP);
bool addType(DIType *DT);
- bool addScope(DIScope *Scope);
public:
using compile_unit_iterator =
diff --git a/contrib/llvm/include/llvm/IR/DebugInfoFlags.def b/contrib/llvm/include/llvm/IR/DebugInfoFlags.def
index 7ea6346998fe..b1f5fac64232 100644
--- a/contrib/llvm/include/llvm/IR/DebugInfoFlags.def
+++ b/contrib/llvm/include/llvm/IR/DebugInfoFlags.def
@@ -43,6 +43,11 @@ HANDLE_DI_FLAG((1 << 18), IntroducedVirtual)
HANDLE_DI_FLAG((1 << 19), BitField)
HANDLE_DI_FLAG((1 << 20), NoReturn)
HANDLE_DI_FLAG((1 << 21), MainSubprogram)
+HANDLE_DI_FLAG((1 << 22), TypePassByValue)
+HANDLE_DI_FLAG((1 << 23), TypePassByReference)
+HANDLE_DI_FLAG((1 << 24), FixedEnum)
+HANDLE_DI_FLAG((1 << 25), Thunk)
+HANDLE_DI_FLAG((1 << 26), Trivial)
// To avoid needing a dedicated value for IndirectVirtualBase, we use
// the bitwise or of Virtual and FwdDecl, which does not otherwise
@@ -52,7 +57,7 @@ HANDLE_DI_FLAG((1 << 2) | (1 << 5), IndirectVirtualBase)
#ifdef DI_FLAG_LARGEST_NEEDED
// intended to be used with ADT/BitmaskEnum.h
// NOTE: always must be equal to largest flag, check this when adding new flag
-HANDLE_DI_FLAG((1 << 21), Largest)
+HANDLE_DI_FLAG((1 << 26), Largest)
#undef DI_FLAG_LARGEST_NEEDED
#endif
diff --git a/contrib/llvm/include/llvm/IR/DebugInfoMetadata.h b/contrib/llvm/include/llvm/IR/DebugInfoMetadata.h
index 75b0c43b6512..820746851104 100644
--- a/contrib/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/contrib/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -18,11 +18,13 @@
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/Casting.h"
#include <cassert>
@@ -230,6 +232,7 @@ public:
case DITemplateValueParameterKind:
case DIGlobalVariableKind:
case DILocalVariableKind:
+ case DILabelKind:
case DIObjCPropertyKind:
case DIImportedEntityKind:
case DIModuleKind:
@@ -332,31 +335,53 @@ class DISubrange : public DINode {
friend class LLVMContextImpl;
friend class MDNode;
- int64_t Count;
int64_t LowerBound;
- DISubrange(LLVMContext &C, StorageType Storage, int64_t Count,
- int64_t LowerBound)
- : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None),
- Count(Count), LowerBound(LowerBound) {}
+ DISubrange(LLVMContext &C, StorageType Storage, Metadata *Node,
+ int64_t LowerBound, ArrayRef<Metadata *> Ops)
+ : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops),
+ LowerBound(LowerBound) {}
+
~DISubrange() = default;
static DISubrange *getImpl(LLVMContext &Context, int64_t Count,
int64_t LowerBound, StorageType Storage,
bool ShouldCreate = true);
+ static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode,
+ int64_t LowerBound, StorageType Storage,
+ bool ShouldCreate = true);
+
TempDISubrange cloneImpl() const {
- return getTemporary(getContext(), getCount(), getLowerBound());
+ return getTemporary(getContext(), getRawCountNode(), getLowerBound());
}
public:
DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0),
(Count, LowerBound))
+ DEFINE_MDNODE_GET(DISubrange, (Metadata *CountNode, int64_t LowerBound = 0),
+ (CountNode, LowerBound))
+
TempDISubrange clone() const { return cloneImpl(); }
int64_t getLowerBound() const { return LowerBound; }
- int64_t getCount() const { return Count; }
+
+ Metadata *getRawCountNode() const {
+ return getOperand(0).get();
+ }
+
+ typedef PointerUnion<ConstantInt*, DIVariable*> CountType;
+
+ CountType getCount() const {
+ if (auto *MD = dyn_cast<ConstantAsMetadata>(getRawCountNode()))
+ return CountType(cast<ConstantInt>(MD->getValue()));
+
+ if (auto *DV = dyn_cast<DIVariable>(getRawCountNode()))
+ return CountType(DV);
+
+ return CountType();
+ }
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DISubrangeKind;
@@ -372,36 +397,38 @@ class DIEnumerator : public DINode {
friend class MDNode;
int64_t Value;
-
DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value,
- ArrayRef<Metadata *> Ops)
+ bool IsUnsigned, ArrayRef<Metadata *> Ops)
: DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
- Value(Value) {}
+ Value(Value) {
+ SubclassData32 = IsUnsigned;
+ }
~DIEnumerator() = default;
static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value,
- StringRef Name, StorageType Storage,
- bool ShouldCreate = true) {
- return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage,
- ShouldCreate);
+ bool IsUnsigned, StringRef Name,
+ StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(Context, Value, IsUnsigned,
+ getCanonicalMDString(Context, Name), Storage, ShouldCreate);
}
static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value,
- MDString *Name, StorageType Storage,
- bool ShouldCreate = true);
+ bool IsUnsigned, MDString *Name,
+ StorageType Storage, bool ShouldCreate = true);
TempDIEnumerator cloneImpl() const {
- return getTemporary(getContext(), getValue(), getName());
+ return getTemporary(getContext(), getValue(), isUnsigned(), getName());
}
public:
- DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, StringRef Name),
- (Value, Name))
- DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, MDString *Name),
- (Value, Name))
+ DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, StringRef Name),
+ (Value, IsUnsigned, Name))
+ DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, MDString *Name),
+ (Value, IsUnsigned, Name))
TempDIEnumerator clone() const { return cloneImpl(); }
int64_t getValue() const { return Value; }
+ bool isUnsigned() const { return SubclassData32; }
StringRef getName() const { return getStringOperand(0); }
MDString *getRawName() const { return getOperandAs<MDString>(0); }
@@ -429,6 +456,7 @@ public:
inline StringRef getFilename() const;
inline StringRef getDirectory() const;
+ inline Optional<StringRef> getSource() const;
StringRef getName() const;
DIScopeRef getScope() const;
@@ -473,63 +501,103 @@ class DIFile : public DIScope {
friend class MDNode;
public:
- // These values must be explictly set, as they end up in the final object
- // file.
+ /// Which algorithm (e.g. MD5) a checksum was generated with.
+ ///
+ /// The encoding is explicit because it is used directly in Bitcode. The
+ /// value 0 is reserved to indicate the absence of a checksum in Bitcode.
enum ChecksumKind {
- CSK_None = 0,
+ // The first variant was originally CSK_None, encoded as 0. The new
+ // internal representation removes the need for this by wrapping the
+ // ChecksumInfo in an Optional, but to preserve Bitcode compatibility the 0
+ // encoding is reserved.
CSK_MD5 = 1,
CSK_SHA1 = 2,
CSK_Last = CSK_SHA1 // Should be last enumeration.
};
+ /// A single checksum, represented by a \a Kind and a \a Value (a string).
+ template <typename T>
+ struct ChecksumInfo {
+ /// The kind of checksum which \a Value encodes.
+ ChecksumKind Kind;
+ /// The string value of the checksum.
+ T Value;
+
+ ChecksumInfo(ChecksumKind Kind, T Value) : Kind(Kind), Value(Value) { }
+ ~ChecksumInfo() = default;
+ bool operator==(const ChecksumInfo<T> &X) const {
+ return Kind == X.Kind && Value == X.Value;
+ }
+ bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); }
+ StringRef getKindAsString() const { return getChecksumKindAsString(Kind); }
+ };
+
private:
- ChecksumKind CSKind;
+ Optional<ChecksumInfo<MDString *>> Checksum;
+ Optional<MDString *> Source;
- DIFile(LLVMContext &C, StorageType Storage, ChecksumKind CSK,
+ DIFile(LLVMContext &C, StorageType Storage,
+ Optional<ChecksumInfo<MDString *>> CS, Optional<MDString *> Src,
ArrayRef<Metadata *> Ops)
: DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops),
- CSKind(CSK) {}
+ Checksum(CS), Source(Src) {}
~DIFile() = default;
static DIFile *getImpl(LLVMContext &Context, StringRef Filename,
- StringRef Directory, ChecksumKind CSK, StringRef CS,
+ StringRef Directory,
+ Optional<ChecksumInfo<StringRef>> CS,
+ Optional<StringRef> Source,
StorageType Storage, bool ShouldCreate = true) {
+ Optional<ChecksumInfo<MDString *>> MDChecksum;
+ if (CS)
+ MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value));
return getImpl(Context, getCanonicalMDString(Context, Filename),
- getCanonicalMDString(Context, Directory), CSK,
- getCanonicalMDString(Context, CS), Storage, ShouldCreate);
+ getCanonicalMDString(Context, Directory), MDChecksum,
+ Source ? Optional<MDString *>(getCanonicalMDString(Context, *Source)) : None,
+ Storage, ShouldCreate);
}
static DIFile *getImpl(LLVMContext &Context, MDString *Filename,
- MDString *Directory, ChecksumKind CSK, MDString *CS,
- StorageType Storage, bool ShouldCreate = true);
+ MDString *Directory,
+ Optional<ChecksumInfo<MDString *>> CS,
+ Optional<MDString *> Source, StorageType Storage,
+ bool ShouldCreate = true);
TempDIFile cloneImpl() const {
return getTemporary(getContext(), getFilename(), getDirectory(),
- getChecksumKind(), getChecksum());
+ getChecksum(), getSource());
}
public:
DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory,
- ChecksumKind CSK = CSK_None,
- StringRef CS = StringRef()),
- (Filename, Directory, CSK, CS))
+ Optional<ChecksumInfo<StringRef>> CS = None,
+ Optional<StringRef> Source = None),
+ (Filename, Directory, CS, Source))
DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory,
- ChecksumKind CSK = CSK_None,
- MDString *CS = nullptr),
- (Filename, Directory, CSK, CS))
+ Optional<ChecksumInfo<MDString *>> CS = None,
+ Optional<MDString *> Source = None),
+ (Filename, Directory, CS, Source))
TempDIFile clone() const { return cloneImpl(); }
StringRef getFilename() const { return getStringOperand(0); }
StringRef getDirectory() const { return getStringOperand(1); }
- StringRef getChecksum() const { return getStringOperand(2); }
- ChecksumKind getChecksumKind() const { return CSKind; }
- StringRef getChecksumKindAsString() const;
+ Optional<ChecksumInfo<StringRef>> getChecksum() const {
+ Optional<ChecksumInfo<StringRef>> StringRefChecksum;
+ if (Checksum)
+ StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString());
+ return StringRefChecksum;
+ }
+ Optional<StringRef> getSource() const {
+ return Source ? Optional<StringRef>((*Source)->getString()) : None;
+ }
MDString *getRawFilename() const { return getOperandAs<MDString>(0); }
MDString *getRawDirectory() const { return getOperandAs<MDString>(1); }
- MDString *getRawChecksum() const { return getOperandAs<MDString>(2); }
+ Optional<ChecksumInfo<MDString *>> getRawChecksum() const { return Checksum; }
+ Optional<MDString *> getRawSource() const { return Source; }
- static ChecksumKind getChecksumKind(StringRef CSKindStr);
+ static StringRef getChecksumKindAsString(ChecksumKind CSKind);
+ static Optional<ChecksumKind> getChecksumKind(StringRef CSKindStr);
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIFileKind;
@@ -548,6 +616,12 @@ StringRef DIScope::getDirectory() const {
return "";
}
+Optional<StringRef> DIScope::getSource() const {
+ if (auto *F = getFile())
+ return F->getSource();
+ return None;
+}
+
/// Base class for types.
///
/// TODO: Remove the hardcoded name and context, since many types don't use
@@ -605,9 +679,11 @@ public:
Metadata *getRawScope() const { return getOperand(1); }
MDString *getRawName() const { return getOperandAs<MDString>(2); }
- void setFlags(DIFlags NewFlags) {
- assert(!isUniqued() && "Cannot set flags on uniqued nodes");
- Flags = NewFlags;
+ /// Returns a new temporary DIType with updated Flags
+ TempDIType cloneWithFlags(DIFlags NewFlags) const {
+ auto NewTy = clone();
+ NewTy->Flags = NewFlags;
+ return NewTy;
}
bool isPrivate() const {
@@ -633,6 +709,10 @@ public:
bool isStaticMember() const { return getFlags() & FlagStaticMember; }
bool isLValueReference() const { return getFlags() & FlagLValueReference; }
bool isRValueReference() const { return getFlags() & FlagRValueReference; }
+ bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; }
+ bool isTypePassByReference() const {
+ return getFlags() & FlagTypePassByReference;
+ }
static bool classof(const Metadata *MD) {
switch (MD->getMetadataID()) {
@@ -698,6 +778,12 @@ public:
unsigned getEncoding() const { return Encoding; }
+ enum class Signedness { Signed, Unsigned };
+
+ /// Return the signedness of this type, or None if this type is neither
+ /// signed nor unsigned.
+ Optional<Signedness> getSignedness() const;
+
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIBasicTypeKind;
}
@@ -713,7 +799,7 @@ class DIDerivedType : public DIType {
friend class LLVMContextImpl;
friend class MDNode;
- /// \brief The DWARF address space of the memory pointed to or referenced by a
+ /// The DWARF address space of the memory pointed to or referenced by a
/// pointer or reference type respectively.
Optional<unsigned> DWARFAddressSpace;
@@ -788,7 +874,8 @@ public:
/// 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.
+ /// global constant wrapper for static members, or virtual base pointer offset
+ /// for inheritance.
///
/// TODO: Separate out types that need this extra operand: pointer-to-member
/// types and member fields (static members and ivars).
@@ -806,6 +893,14 @@ public:
return dyn_cast_or_null<DIObjCProperty>(getExtraData());
}
+ uint32_t getVBPtrOffset() const {
+ assert(getTag() == dwarf::DW_TAG_inheritance);
+ if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData()))
+ if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue()))
+ return static_cast<uint32_t>(CI->getZExtValue());
+ return 0;
+ }
+
Constant *getStorageOffsetInBits() const {
assert(getTag() == dwarf::DW_TAG_member && isBitField());
if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
@@ -819,6 +914,12 @@ public:
return C->getValue();
return nullptr;
}
+ Constant *getDiscriminantValue() const {
+ assert(getTag() == dwarf::DW_TAG_member && !isStaticMember());
+ if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
+ return C->getValue();
+ return nullptr;
+ }
/// @}
static bool classof(const Metadata *MD) {
@@ -861,12 +962,13 @@ class DICompositeType : public DIType {
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang,
DITypeRef VTableHolder, DITemplateParameterArray TemplateParams,
- StringRef Identifier, StorageType Storage, bool ShouldCreate = true) {
+ StringRef Identifier, DIDerivedType *Discriminator,
+ StorageType Storage, bool ShouldCreate = true) {
return getImpl(
Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
RuntimeLang, VTableHolder, TemplateParams.get(),
- getCanonicalMDString(Context, Identifier), Storage, ShouldCreate);
+ getCanonicalMDString(Context, Identifier), Discriminator, Storage, ShouldCreate);
}
static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@@ -874,14 +976,15 @@ class DICompositeType : public DIType {
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams,
- MDString *Identifier, StorageType Storage, bool ShouldCreate = true);
+ MDString *Identifier, Metadata *Discriminator,
+ StorageType Storage, bool ShouldCreate = true);
TempDICompositeType cloneImpl() const {
return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
getScope(), getBaseType(), getSizeInBits(),
getAlignInBits(), getOffsetInBits(), getFlags(),
getElements(), getRuntimeLang(), getVTableHolder(),
- getTemplateParams(), getIdentifier());
+ getTemplateParams(), getIdentifier(), getDiscriminator());
}
public:
@@ -892,10 +995,10 @@ public:
DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang,
DITypeRef VTableHolder,
DITemplateParameterArray TemplateParams = nullptr,
- StringRef Identifier = ""),
+ StringRef Identifier = "", DIDerivedType *Discriminator = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier))
+ VTableHolder, TemplateParams, Identifier, Discriminator))
DEFINE_MDNODE_GET(DICompositeType,
(unsigned Tag, MDString *Name, Metadata *File,
unsigned Line, Metadata *Scope, Metadata *BaseType,
@@ -903,10 +1006,11 @@ public:
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams = nullptr,
- MDString *Identifier = nullptr),
+ MDString *Identifier = nullptr,
+ Metadata *Discriminator = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier))
+ VTableHolder, TemplateParams, Identifier, Discriminator))
TempDICompositeType clone() const { return cloneImpl(); }
@@ -923,7 +1027,7 @@ public:
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
- Metadata *TemplateParams);
+ Metadata *TemplateParams, Metadata *Discriminator);
static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
MDString &Identifier);
@@ -942,7 +1046,7 @@ public:
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
- Metadata *TemplateParams);
+ Metadata *TemplateParams, Metadata *Discriminator);
DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); }
DINodeArray getElements() const {
@@ -960,6 +1064,8 @@ public:
Metadata *getRawVTableHolder() const { return getOperand(5); }
Metadata *getRawTemplateParams() const { return getOperand(6); }
MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); }
+ Metadata *getRawDiscriminator() const { return getOperand(8); }
+ DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); }
/// Replace operands.
///
@@ -1060,7 +1166,7 @@ public:
};
static Optional<DebugEmissionKind> getEmissionKind(StringRef Str);
- static const char *EmissionKindString(DebugEmissionKind EK);
+ static const char *emissionKindString(DebugEmissionKind EK);
private:
unsigned SourceLanguage;
@@ -1337,6 +1443,7 @@ public:
DIFile *getFile() const { return getScope()->getFile(); }
StringRef getFilename() const { return getScope()->getFilename(); }
StringRef getDirectory() const { return getScope()->getDirectory(); }
+ Optional<StringRef> getSource() const { return getScope()->getSource(); }
/// Get the scope where this is inlined.
///
@@ -1380,7 +1487,7 @@ public:
///
/// The above 3 components are encoded into a 32bit unsigned integer in
/// order. If the lowest bit is 1, the current component is empty, and the
- /// next component will start in the next bit. Otherwise, the the current
+ /// next component will start in the next bit. Otherwise, the current
/// component is non-empty, and its content starts in the next bit. The
/// length of each components is either 5 bit or 12 bit: if the 7th bit
/// is 0, the bit 2~6 (5 bits) are used to represent the component; if the
@@ -1408,26 +1515,25 @@ public:
/// discriminator.
inline const DILocation *cloneWithDuplicationFactor(unsigned DF) const;
+ enum { NoGeneratedLocation = false, WithGeneratedLocation = true };
+
/// When two instructions are combined into a single instruction we also
/// need to combine the original locations into a single location.
///
/// When the locations are the same we can use either location. When they
- /// differ, we need a third location which is distinct from either. If
- /// they have the same file/line but have a different discriminator we
- /// could create a location with a new discriminator. If they are from
- /// different files/lines the location is ambiguous and can't be
- /// represented in a single line entry. In this case, no location
- /// should be set, unless the merged instruction is a call, which we will
- /// set the merged debug location as line 0 of the nearest common scope
- /// where 2 locations are inlined from. This only applies to Instruction;
- /// for MachineInstruction, as it is post-inline, we will treat the call
- /// instruction the same way as other instructions.
+ /// differ, we need a third location which is distinct from either. If they
+ /// have the same file/line but have a different discriminator we could
+ /// create a location with a new discriminator. If they are from different
+ /// files/lines the location is ambiguous and can't be represented in a line
+ /// entry. In this case, if \p GenerateLocation is true, we will set the
+ /// merged debug location as line 0 of the nearest common scope where the two
+ /// locations are inlined from.
///
- /// \p ForInst: The Instruction the merged DILocation is for. If the
- /// Instruction is unavailable or non-existent, use nullptr.
+ /// \p GenerateLocation: Whether the merged location can be generated when
+ /// \p LocA and \p LocB differ.
static const DILocation *
getMergedLocation(const DILocation *LocA, const DILocation *LocB,
- const Instruction *ForInst = nullptr);
+ bool GenerateLocation = NoGeneratedLocation);
/// Returns the base discriminator for a given encoded discriminator \p D.
static unsigned getBaseDiscriminatorFromDiscriminator(unsigned D) {
@@ -1521,13 +1627,13 @@ class DISubprogram : public DILocalScope {
unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags,
bool IsOptimized, DICompileUnit *Unit,
DITemplateParameterArray TemplateParams, DISubprogram *Declaration,
- DILocalVariableArray Variables, DITypeArray ThrownTypes,
+ DINodeArray RetainedNodes, DITypeArray ThrownTypes,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, LinkageName), File, Line, Type,
IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
- Unit, TemplateParams.get(), Declaration, Variables.get(),
+ Unit, TemplateParams.get(), Declaration, RetainedNodes.get(),
ThrownTypes.get(), Storage, ShouldCreate);
}
static DISubprogram *
@@ -1536,7 +1642,7 @@ class DISubprogram : public DILocalScope {
bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit,
- Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
+ Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes,
Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate = true);
TempDISubprogram cloneImpl() const {
@@ -1545,7 +1651,7 @@ class DISubprogram : public DILocalScope {
isDefinition(), getScopeLine(), getContainingType(),
getVirtuality(), getVirtualIndex(), getThisAdjustment(),
getFlags(), isOptimized(), getUnit(),
- getTemplateParams(), getDeclaration(), getVariables(),
+ getTemplateParams(), getDeclaration(), getRetainedNodes(),
getThrownTypes());
}
@@ -1559,12 +1665,12 @@ public:
bool IsOptimized, DICompileUnit *Unit,
DITemplateParameterArray TemplateParams = nullptr,
DISubprogram *Declaration = nullptr,
- DILocalVariableArray Variables = nullptr,
+ DINodeArray RetainedNodes = nullptr,
DITypeArray ThrownTypes = nullptr),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, ScopeLine, ContainingType, Virtuality,
VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit,
- TemplateParams, Declaration, Variables, ThrownTypes))
+ TemplateParams, Declaration, RetainedNodes, ThrownTypes))
DEFINE_MDNODE_GET(
DISubprogram,
(Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File,
@@ -1572,15 +1678,22 @@ public:
unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality,
unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags,
bool IsOptimized, Metadata *Unit, Metadata *TemplateParams = nullptr,
- Metadata *Declaration = nullptr, Metadata *Variables = nullptr,
+ Metadata *Declaration = nullptr, Metadata *RetainedNodes = nullptr,
Metadata *ThrownTypes = nullptr),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment,
- Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables,
+ Flags, IsOptimized, Unit, TemplateParams, Declaration, RetainedNodes,
ThrownTypes))
TempDISubprogram clone() const { return cloneImpl(); }
+ /// Returns a new temporary DISubprogram with updated Flags
+ TempDISubprogram cloneWithFlags(DIFlags NewFlags) const {
+ auto NewSP = clone();
+ NewSP->Flags = NewFlags;
+ return NewSP;
+ }
+
public:
unsigned getLine() const { return Line; }
unsigned getVirtuality() const { return Virtuality; }
@@ -1623,6 +1736,11 @@ public:
/// Return true if this subprogram is C++11 noreturn or C11 _Noreturn
bool isNoReturn() const { return getFlags() & FlagNoReturn; }
+ // Check if this routine is a compiler-generated thunk.
+ //
+ // Returns true if this subprogram is a thunk generated by the compiler.
+ bool isThunk() const { return getFlags() & FlagThunk; }
+
DIScopeRef getScope() const { return DIScopeRef(getRawScope()); }
StringRef getName() const { return getStringOperand(2); }
@@ -1645,8 +1763,8 @@ public:
DISubprogram *getDeclaration() const {
return cast_or_null<DISubprogram>(getRawDeclaration());
}
- DILocalVariableArray getVariables() const {
- return cast_or_null<MDTuple>(getRawVariables());
+ DINodeArray getRetainedNodes() const {
+ return cast_or_null<MDTuple>(getRawRetainedNodes());
}
DITypeArray getThrownTypes() const {
return cast_or_null<MDTuple>(getRawThrownTypes());
@@ -1658,7 +1776,7 @@ public:
Metadata *getRawType() const { return getOperand(4); }
Metadata *getRawUnit() const { return getOperand(5); }
Metadata *getRawDeclaration() const { return getOperand(6); }
- Metadata *getRawVariables() const { return getOperand(7); }
+ Metadata *getRawRetainedNodes() const { return getOperand(7); }
Metadata *getRawContainingType() const {
return getNumOperands() > 8 ? getOperandAs<Metadata>(8) : nullptr;
}
@@ -2094,6 +2212,14 @@ public:
/// Determines the size of the variable's type.
Optional<uint64_t> getSizeInBits() const;
+ /// Return the signedness of this variable's type, or None if this type is
+ /// neither signed nor unsigned.
+ Optional<DIBasicType::Signedness> getSignedness() const {
+ if (auto *BT = dyn_cast<DIBasicType>(getType().resolve()))
+ return BT->getSignedness();
+ return None;
+ }
+
StringRef getFilename() const {
if (auto *F = getFile())
return F->getFilename();
@@ -2106,6 +2232,12 @@ public:
return "";
}
+ Optional<StringRef> getSource() const {
+ if (auto *F = getFile())
+ return F->getSource();
+ return None;
+ }
+
Metadata *getRawScope() const { return getOperand(0); }
MDString *getRawName() const { return getOperandAs<MDString>(1); }
Metadata *getRawFile() const { return getOperand(2); }
@@ -2194,6 +2326,11 @@ public:
///
/// Return the number of elements in the operand (1 + args).
unsigned getSize() const;
+
+ /// Append the elements of this operand to \p V.
+ void appendToVector(SmallVectorImpl<uint64_t> &V) const {
+ V.append(get(), get() + getSize());
+ }
};
/// An iterator for expression operands.
@@ -2297,10 +2434,29 @@ public:
/// Prepend \p DIExpr with a deref and offset operation and optionally turn it
/// into a stack value.
- static DIExpression *prepend(const DIExpression *DIExpr, bool DerefBefore,
+ static DIExpression *prepend(const DIExpression *Expr, bool DerefBefore,
int64_t Offset = 0, bool DerefAfter = false,
bool StackValue = false);
+ /// Prepend \p DIExpr with the given opcodes and optionally turn it into a
+ /// stack value.
+ static DIExpression *prependOpcodes(const DIExpression *Expr,
+ SmallVectorImpl<uint64_t> &Ops,
+ bool StackValue = false);
+
+ /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the
+ /// returned expression is a stack value only if \p DIExpr is a stack value.
+ /// If \p DIExpr describes a fragment, the returned expression will describe
+ /// the same fragment.
+ static DIExpression *append(const DIExpression *Expr, ArrayRef<uint64_t> Ops);
+
+ /// Convert \p DIExpr into a stack value if it isn't one already by appending
+ /// DW_OP_deref if needed, and appending \p Ops to the resulting expression.
+ /// If \p DIExpr describes a fragment, the returned expression will describe
+ /// the same fragment.
+ static DIExpression *appendToStack(const DIExpression *Expr,
+ ArrayRef<uint64_t> Ops);
+
/// Create a DIExpression to describe one part of an aggregate variable that
/// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation
/// will be appended to the elements of \c Expr. If \c Expr already contains
@@ -2314,6 +2470,32 @@ public:
static Optional<DIExpression *>
createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits,
unsigned SizeInBits);
+
+ /// Determine the relative position of the fragments described by this
+ /// DIExpression and \p Other.
+ /// Returns -1 if this is entirely before Other, 0 if this and Other overlap,
+ /// 1 if this is entirely after Other.
+ int fragmentCmp(const DIExpression *Other) const {
+ auto Fragment1 = *getFragmentInfo();
+ auto Fragment2 = *Other->getFragmentInfo();
+ unsigned l1 = Fragment1.OffsetInBits;
+ unsigned l2 = Fragment2.OffsetInBits;
+ unsigned r1 = l1 + Fragment1.SizeInBits;
+ unsigned r2 = l2 + Fragment2.SizeInBits;
+ if (r1 <= l2)
+ return -1;
+ else if (r2 <= l1)
+ return 1;
+ else
+ return 0;
+ }
+
+ /// Check if fragments overlap between this DIExpression and \p Other.
+ bool fragmentsOverlap(const DIExpression *Other) const {
+ if (!isFragment() || !Other->isFragment())
+ return true;
+ return fragmentCmp(Other) == 0;
+ }
};
/// Global variables.
@@ -2476,6 +2658,76 @@ public:
}
};
+/// Label.
+///
+class DILabel : public DINode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Line;
+
+ DILabel(LLVMContext &C, StorageType Storage, unsigned Line,
+ ArrayRef<Metadata *> Ops)
+ : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {}
+ ~DILabel() = default;
+
+ static DILabel *getImpl(LLVMContext &Context, DIScope *Scope,
+ StringRef Name, DIFile *File, unsigned Line,
+ StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File,
+ Line, Storage, ShouldCreate);
+ }
+ static DILabel *getImpl(LLVMContext &Context, Metadata *Scope,
+ MDString *Name, Metadata *File, unsigned Line,
+ StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDILabel cloneImpl() const {
+ return getTemporary(getContext(), getScope(), getName(), getFile(),
+ getLine());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DILabel,
+ (DILocalScope * Scope, StringRef Name, DIFile *File,
+ unsigned Line),
+ (Scope, Name, File, Line))
+ DEFINE_MDNODE_GET(DILabel,
+ (Metadata * Scope, MDString *Name, Metadata *File,
+ unsigned Line),
+ (Scope, Name, File, Line))
+
+ TempDILabel clone() const { return cloneImpl(); }
+
+ /// Get the local scope for this label.
+ ///
+ /// Labels must be defined in a local scope.
+ DILocalScope *getScope() const {
+ return cast_or_null<DILocalScope>(getRawScope());
+ }
+ unsigned getLine() const { return Line; }
+ StringRef getName() const { return getStringOperand(1); }
+ DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
+
+ Metadata *getRawScope() const { return getOperand(0); }
+ MDString *getRawName() const { return getOperandAs<MDString>(1); }
+ Metadata *getRawFile() const { return getOperand(2); }
+
+ /// Check that a location is valid for this label.
+ ///
+ /// Check that \c DL exists, is in the same subprogram, and has the same
+ /// inlined-at location as \c this. (Otherwise, it's not a valid attachment
+ /// to a \a DbgInfoIntrinsic.)
+ bool isValidLocationForIntrinsic(const DILocation *DL) const {
+ return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram();
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DILabelKind;
+ }
+};
+
class DIObjCProperty : public DINode {
friend class LLVMContextImpl;
friend class MDNode;
@@ -2547,6 +2799,12 @@ public:
return "";
}
+ Optional<StringRef> getSource() const {
+ if (auto *F = getFile())
+ return F->getSource();
+ return None;
+ }
+
MDString *getRawName() const { return getOperandAs<MDString>(0); }
Metadata *getRawFile() const { return getOperand(1); }
MDString *getRawGetterName() const { return getOperandAs<MDString>(2); }
diff --git a/contrib/llvm/include/llvm/IR/DebugLoc.h b/contrib/llvm/include/llvm/IR/DebugLoc.h
index eef1212abc4b..9f619ffc5c4d 100644
--- a/contrib/llvm/include/llvm/IR/DebugLoc.h
+++ b/contrib/llvm/include/llvm/IR/DebugLoc.h
@@ -24,7 +24,7 @@ namespace llvm {
class raw_ostream;
class DILocation;
- /// \brief A debug info location.
+ /// A debug info location.
///
/// This class is a wrapper around a tracking reference to an \a DILocation
/// pointer.
@@ -37,10 +37,10 @@ namespace llvm {
public:
DebugLoc() = default;
- /// \brief Construct from an \a DILocation.
+ /// Construct from an \a DILocation.
DebugLoc(const DILocation *L);
- /// \brief Construct from an \a MDNode.
+ /// Construct from an \a MDNode.
///
/// Note: if \c N is not an \a DILocation, a verifier check will fail, and
/// accessors will crash. However, construction from other nodes is
@@ -48,7 +48,7 @@ namespace llvm {
/// IR.
explicit DebugLoc(const MDNode *N);
- /// \brief Get the underlying \a DILocation.
+ /// Get the underlying \a DILocation.
///
/// \pre !*this or \c isa<DILocation>(getAsMDNode()).
/// @{
@@ -58,7 +58,7 @@ namespace llvm {
DILocation &operator*() const { return *get(); }
/// @}
- /// \brief Check for null.
+ /// Check for null.
///
/// Check for null in a way that is safe with broken debug info. Unlike
/// the conversion to \c DILocation, this doesn't require that \c Loc is of
@@ -66,10 +66,10 @@ namespace llvm {
/// \a Instruction::hasMetadata().
explicit operator bool() const { return Loc; }
- /// \brief Check whether this has a trivial destructor.
+ /// Check whether this has a trivial destructor.
bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); }
- /// \brief Create a new DebugLoc.
+ /// Create a new DebugLoc.
///
/// Create a new DebugLoc at the specified line/col and scope/inline. This
/// forwards to \a DILocation::get().
@@ -95,12 +95,12 @@ namespace llvm {
MDNode *getScope() const;
DILocation *getInlinedAt() const;
- /// \brief Get the fully inlined-at scope for a DebugLoc.
+ /// Get the fully inlined-at scope for a DebugLoc.
///
/// Gets the inlined-at scope for a DebugLoc.
MDNode *getInlinedAtScope() const;
- /// \brief Find the debug info location for the start of the function.
+ /// Find the debug info location for the start of the function.
///
/// Walk up the scope chain of given debug loc and find line number info
/// for the function.
@@ -109,7 +109,7 @@ namespace llvm {
/// find the subprogram, and then DILocation::get().
DebugLoc getFnDebugLoc() const;
- /// \brief Return \c this as a bar \a MDNode.
+ /// Return \c this as a bar \a MDNode.
MDNode *getAsMDNode() const { return Loc; }
bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; }
@@ -117,7 +117,7 @@ namespace llvm {
void dump() const;
- /// \brief prints source location /path/to/file.exe:line:col @[inlined at]
+ /// prints source location /path/to/file.exe:line:col @[inlined at]
void print(raw_ostream &OS) const;
};
diff --git a/contrib/llvm/include/llvm/IR/DerivedTypes.h b/contrib/llvm/include/llvm/IR/DerivedTypes.h
index 6e5e085873ab..9526d6287d2f 100644
--- a/contrib/llvm/include/llvm/IR/DerivedTypes.h
+++ b/contrib/llvm/include/llvm/IR/DerivedTypes.h
@@ -36,7 +36,7 @@ class LLVMContext;
/// Class to represent integer types. Note that this class is also used to
/// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and
/// Int64Ty.
-/// @brief Integer representation type
+/// Integer representation type
class IntegerType : public Type {
friend class LLVMContextImpl;
@@ -59,10 +59,10 @@ public:
/// If an IntegerType with the same NumBits value was previously instantiated,
/// that instance will be returned. Otherwise a new one will be created. Only
/// one instance with a given NumBits value is ever created.
- /// @brief Get or create an IntegerType instance.
+ /// Get or create an IntegerType instance.
static IntegerType *get(LLVMContext &C, unsigned NumBits);
- /// @brief Get the number of bits in this IntegerType
+ /// Get the number of bits in this IntegerType
unsigned getBitWidth() const { return getSubclassData(); }
/// Return a bitmask with ones set for all of the bits that can be set by an
@@ -79,13 +79,13 @@ public:
/// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc.
/// @returns a bit mask with ones set for all the bits of this type.
- /// @brief Get a bit mask for this type.
+ /// Get a bit mask for this type.
APInt getMask() const;
/// This method determines if the width of this IntegerType is a power-of-2
/// in terms of 8 bit bytes.
/// @returns true if this is a power-of-2 byte width.
- /// @brief Is this a power-of-2 byte-width IntegerType ?
+ /// Is this a power-of-2 byte-width IntegerType ?
bool isPowerOf2ByteWidth() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
@@ -193,7 +193,7 @@ public:
/// StructType::create() forms.
///
/// Independent of what kind of struct you have, the body of a struct type are
-/// laid out in memory consequtively with the elements directly one after the
+/// laid out in memory consecutively with the elements directly one after the
/// other (if the struct is packed) or (if not packed) with padding between the
/// elements as defined by DataLayout (which is required to match what the code
/// generator for a target expects).
diff --git a/contrib/llvm/include/llvm/IR/DiagnosticHandler.h b/contrib/llvm/include/llvm/IR/DiagnosticHandler.h
index 9256d4850df1..51873bea3d41 100644
--- a/contrib/llvm/include/llvm/IR/DiagnosticHandler.h
+++ b/contrib/llvm/include/llvm/IR/DiagnosticHandler.h
@@ -18,7 +18,7 @@
namespace llvm {
class DiagnosticInfo;
-/// \brief This is the base class for diagnostic handling in LLVM.
+/// This is the base class for diagnostic handling in LLVM.
/// The handleDiagnostics method must be overriden by the subclasses to handle
/// diagnostic. The *RemarkEnabled methods can be overriden to control
/// which remarks are enabled.
diff --git a/contrib/llvm/include/llvm/IR/DiagnosticInfo.h b/contrib/llvm/include/llvm/IR/DiagnosticInfo.h
index 020b67d6b711..81d4ae84bf01 100644
--- a/contrib/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/contrib/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -39,7 +39,7 @@ class LLVMContext;
class Module;
class SMDiagnostic;
-/// \brief Defines the different supported severity of a diagnostic.
+/// Defines the different supported severity of a diagnostic.
enum DiagnosticSeverity : char {
DS_Error,
DS_Warning,
@@ -49,7 +49,7 @@ enum DiagnosticSeverity : char {
DS_Note
};
-/// \brief Defines the different supported kind of a diagnostic.
+/// 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_InlineAsm,
@@ -79,7 +79,7 @@ enum DiagnosticKind {
DK_FirstPluginKind
};
-/// \brief Get the next available kind ID for a plugin diagnostic.
+/// Get the next available kind ID for a plugin diagnostic.
/// Each time this function is called, it returns a different number.
/// Therefore, a plugin that wants to "identify" its own classes
/// with a dynamic identifier, just have to use this method to get a new ID
@@ -89,7 +89,7 @@ enum DiagnosticKind {
/// DiagnosticKind values.
int getNextAvailablePluginDiagnosticKind();
-/// \brief This is the base abstract class for diagnostic reporting in
+/// This is the base abstract class for diagnostic reporting in
/// the backend.
/// The print method must be overloaded by the subclasses to print a
/// user-friendly message in the client of the backend (let us call it a
@@ -389,20 +389,20 @@ private:
DiagnosticLocation Loc;
};
-/// \brief Common features for diagnostics dealing with optimization remarks
+/// Common features for diagnostics dealing with optimization remarks
/// that are used by both IR and MIR passes.
class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
public:
- /// \brief Used to set IsVerbose via the stream interface.
+ /// Used to set IsVerbose via the stream interface.
struct setIsVerbose {};
- /// \brief When an instance of this is inserted into the stream, the arguments
+ /// When an instance of this is inserted into the stream, the arguments
/// following will not appear in the remark printed in the compiler output
/// (-Rpass) but only in the optimization record file
/// (-fsave-optimization-record).
struct setExtraArgs {};
- /// \brief Used in the streaming interface as the general argument type. It
+ /// Used in the streaming interface as the general argument type. It
/// internally converts everything into a key-value pair.
struct Argument {
std::string Key;
@@ -415,6 +415,7 @@ public:
Argument(StringRef Key, const Type *T);
Argument(StringRef Key, StringRef S);
Argument(StringRef Key, int N);
+ Argument(StringRef Key, float N);
Argument(StringRef Key, long N);
Argument(StringRef Key, long long N);
Argument(StringRef Key, unsigned N);
@@ -503,7 +504,7 @@ protected:
/// The remark is expected to be noisy.
bool IsVerbose = false;
- /// \brief If positive, the index of the first argument that only appear in
+ /// If positive, the index of the first argument that only appear in
/// the optimization records and not in the remark printed in the compiler
/// output.
int FirstExtraArgIndex = -1;
@@ -586,7 +587,7 @@ operator<<(RemarkT &R,
return R;
}
-/// \brief Common features for diagnostics dealing with optimization remarks
+/// Common features for diagnostics dealing with optimization remarks
/// that are used by IR passes.
class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
public:
@@ -608,7 +609,7 @@ public:
Loc),
CodeRegion(CodeRegion) {}
- /// \brief This is ctor variant allows a pass to build an optimization remark
+ /// This is ctor variant allows a pass to build an optimization remark
/// from an existing remark.
///
/// This is useful when a transformation pass (e.g LV) wants to emit a remark
@@ -711,7 +712,7 @@ public:
const DiagnosticLocation &Loc,
const Value *CodeRegion);
- /// \brief Same as above but \p Inst is used to derive code region and debug
+ /// Same as above but \p Inst is used to derive code region and debug
/// location.
OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
const Instruction *Inst);
@@ -752,7 +753,7 @@ public:
const DiagnosticLocation &Loc,
const Value *CodeRegion);
- /// \brief This is ctor variant allows a pass to build an optimization remark
+ /// This is ctor variant allows a pass to build an optimization remark
/// from an existing remark.
///
/// This is useful when a transformation pass (e.g LV) wants to emit a remark
@@ -763,7 +764,7 @@ public:
const OptimizationRemarkAnalysis &Orig)
: DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
- /// \brief Same as above but \p Inst is used to derive code region and debug
+ /// Same as above but \p Inst is used to derive code region and debug
/// location.
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
const Instruction *Inst);
diff --git a/contrib/llvm/include/llvm/IR/DiagnosticPrinter.h b/contrib/llvm/include/llvm/IR/DiagnosticPrinter.h
index 59c83291affa..25c47cdd1a12 100644
--- a/contrib/llvm/include/llvm/IR/DiagnosticPrinter.h
+++ b/contrib/llvm/include/llvm/IR/DiagnosticPrinter.h
@@ -28,7 +28,7 @@ class StringRef;
class Twine;
class Value;
-/// \brief Interface for custom diagnostic printing.
+/// Interface for custom diagnostic printing.
class DiagnosticPrinter {
public:
virtual ~DiagnosticPrinter() = default;
@@ -58,7 +58,7 @@ public:
virtual DiagnosticPrinter &operator<<(const SMDiagnostic &Diag) = 0;
};
-/// \brief Basic diagnostic printer that uses an underlying raw_ostream.
+/// Basic diagnostic printer that uses an underlying raw_ostream.
class DiagnosticPrinterRawOStream : public DiagnosticPrinter {
protected:
raw_ostream &Stream;
diff --git a/contrib/llvm/include/llvm/IR/DomTreeUpdater.h b/contrib/llvm/include/llvm/IR/DomTreeUpdater.h
new file mode 100644
index 000000000000..81ba670ac0f5
--- /dev/null
+++ b/contrib/llvm/include/llvm/IR/DomTreeUpdater.h
@@ -0,0 +1,259 @@
+//===- DomTreeUpdater.h - DomTree/Post DomTree Updater ----------*- 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 DomTreeUpdater class, which provides a uniform way to
+// update dominator tree related data structures.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DOMTREEUPDATER_H
+#define LLVM_DOMTREEUPDATER_H
+
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Support/GenericDomTree.h"
+#include <functional>
+#include <vector>
+
+namespace llvm {
+class DomTreeUpdater {
+public:
+ enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 };
+
+ explicit DomTreeUpdater(UpdateStrategy Strategy_) : Strategy(Strategy_) {}
+ DomTreeUpdater(DominatorTree &DT_, UpdateStrategy Strategy_)
+ : DT(&DT_), Strategy(Strategy_) {}
+ DomTreeUpdater(DominatorTree *DT_, UpdateStrategy Strategy_)
+ : DT(DT_), Strategy(Strategy_) {}
+ DomTreeUpdater(PostDominatorTree &PDT_, UpdateStrategy Strategy_)
+ : PDT(&PDT_), Strategy(Strategy_) {}
+ DomTreeUpdater(PostDominatorTree *PDT_, UpdateStrategy Strategy_)
+ : PDT(PDT_), Strategy(Strategy_) {}
+ DomTreeUpdater(DominatorTree &DT_, PostDominatorTree &PDT_,
+ UpdateStrategy Strategy_)
+ : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {}
+ DomTreeUpdater(DominatorTree *DT_, PostDominatorTree *PDT_,
+ UpdateStrategy Strategy_)
+ : DT(DT_), PDT(PDT_), Strategy(Strategy_) {}
+
+ ~DomTreeUpdater() { flush(); }
+
+ /// Returns true if the current strategy is Lazy.
+ bool isLazy() const { return Strategy == UpdateStrategy::Lazy; };
+
+ /// Returns true if the current strategy is Eager.
+ bool isEager() const { return Strategy == UpdateStrategy::Eager; };
+
+ /// Returns true if it holds a DominatorTree.
+ bool hasDomTree() const { return DT != nullptr; }
+
+ /// Returns true if it holds a PostDominatorTree.
+ bool hasPostDomTree() const { return PDT != nullptr; }
+
+ /// Returns true if there is BasicBlock awaiting deletion.
+ /// The deletion will only happen until a flush event and
+ /// all available trees are up-to-date.
+ /// Returns false under Eager UpdateStrategy.
+ bool hasPendingDeletedBB() const { return !DeletedBBs.empty(); }
+
+ /// Returns true if DelBB is awaiting deletion.
+ /// Returns false under Eager UpdateStrategy.
+ bool isBBPendingDeletion(BasicBlock *DelBB) const;
+
+ /// Returns true if either of DT or PDT is valid and the tree has at
+ /// least one update pending. If DT or PDT is nullptr it is treated
+ /// as having no pending updates. This function does not check
+ /// whether there is BasicBlock awaiting deletion.
+ /// Returns false under Eager UpdateStrategy.
+ bool hasPendingUpdates() const;
+
+ /// Returns true if there are DominatorTree updates queued.
+ /// Returns false under Eager UpdateStrategy or DT is nullptr.
+ bool hasPendingDomTreeUpdates() const;
+
+ /// Returns true if there are PostDominatorTree updates queued.
+ /// Returns false under Eager UpdateStrategy or PDT is nullptr.
+ bool hasPendingPostDomTreeUpdates() const;
+
+ /// Apply updates on all available trees. Under Eager UpdateStrategy with
+ /// ForceRemoveDuplicates enabled or under Lazy UpdateStrategy, it will
+ /// discard duplicated updates and self-dominance updates. If both DT and PDT
+ /// are nullptrs, this function discards all updates. The Eager Strategy
+ /// applies the updates immediately while the Lazy Strategy queues the
+ /// updates. It is required for the state of the LLVM IR to be updated
+ /// *before* applying the Updates because the internal update routine will
+ /// analyze the current state of the relationship between a pair of (From, To)
+ /// BasicBlocks to determine whether a single update needs to be discarded.
+ void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates,
+ bool ForceRemoveDuplicates = false);
+
+ /// Notify all available trees on an edge insertion. If both DT and PDT are
+ /// nullptrs, this function discards the update. Under either Strategy,
+ /// self-dominance update will be removed. The Eager Strategy applies
+ /// the update immediately while the Lazy Strategy queues the update.
+ /// It is recommended to only use this method when you have exactly one
+ /// insertion (and no deletions). It is recommended to use applyUpdates() in
+ /// all other cases. This function has to be called *after* making the update
+ /// on the actual CFG. An internal functions checks if the edge exists in the
+ /// CFG in DEBUG mode.
+ void insertEdge(BasicBlock *From, BasicBlock *To);
+
+ /// Notify all available trees on an edge insertion.
+ /// Under either Strategy, the following updates will be discard silently
+ /// 1. Invalid - Inserting an edge that does not exist in the CFG.
+ /// 2. Self-dominance update.
+ /// 3. Both DT and PDT are nullptrs.
+ /// The Eager Strategy applies the update immediately while the Lazy Strategy
+ /// queues the update. It is recommended to only use this method when you have
+ /// exactly one insertion (and no deletions) and want to discard an invalid
+ /// update.
+ void insertEdgeRelaxed(BasicBlock *From, BasicBlock *To);
+
+ /// Notify all available trees on an edge deletion. If both DT and PDT are
+ /// nullptrs, this function discards the update. Under either Strategy,
+ /// self-dominance update will be removed. The Eager Strategy applies
+ /// the update immediately while the Lazy Strategy queues the update.
+ /// It is recommended to only use this method when you have exactly one
+ /// deletion (and no insertions). It is recommended to use applyUpdates() in
+ /// all other cases. This function has to be called *after* making the update
+ /// on the actual CFG. An internal functions checks if the edge doesn't exist
+ /// in the CFG in DEBUG mode.
+ void deleteEdge(BasicBlock *From, BasicBlock *To);
+
+ /// Notify all available trees on an edge deletion.
+ /// Under either Strategy, the following updates will be discard silently
+ /// 1. Invalid - Deleting an edge that still exists in the CFG.
+ /// 2. Self-dominance update.
+ /// 3. Both DT and PDT are nullptrs.
+ /// The Eager Strategy applies the update immediately while the Lazy Strategy
+ /// queues the update. It is recommended to only use this method when you have
+ /// exactly one deletion (and no insertions) and want to discard an invalid
+ /// update.
+ void deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To);
+
+ /// Delete DelBB. DelBB will be removed from its Parent and
+ /// erased from available trees if it exists and finally get deleted.
+ /// Under Eager UpdateStrategy, DelBB will be processed immediately.
+ /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
+ /// all available trees are up-to-date. Assert if any instruction of DelBB is
+ /// modified while awaiting deletion. When both DT and PDT are nullptrs, DelBB
+ /// will be queued until flush() is called.
+ void deleteBB(BasicBlock *DelBB);
+
+ /// Delete DelBB. DelBB will be removed from its Parent and
+ /// erased from available trees if it exists. Then the callback will
+ /// be called. Finally, DelBB will be deleted.
+ /// Under Eager UpdateStrategy, DelBB will be processed immediately.
+ /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
+ /// all available trees are up-to-date. Assert if any instruction of DelBB is
+ /// modified while awaiting deletion. Multiple callbacks can be queued for one
+ /// DelBB under Lazy UpdateStrategy.
+ void callbackDeleteBB(BasicBlock *DelBB,
+ std::function<void(BasicBlock *)> Callback);
+
+ /// Recalculate all available trees.
+ /// Under Lazy Strategy, available trees will only be recalculated if there
+ /// are pending updates or there is BasicBlock awaiting deletion. Returns true
+ /// if at least one tree is recalculated.
+ bool recalculate(Function &F);
+
+ /// Flush DomTree updates and return DomTree.
+ /// It also flush out of date updates applied by all available trees
+ /// and flush Deleted BBs if both trees are up-to-date.
+ /// It must only be called when it has a DomTree.
+ DominatorTree &getDomTree();
+
+ /// Flush PostDomTree updates and return PostDomTree.
+ /// It also flush out of date updates applied by all available trees
+ /// and flush Deleted BBs if both trees are up-to-date.
+ /// It must only be called when it has a PostDomTree.
+ PostDominatorTree &getPostDomTree();
+
+ /// Apply all pending updates to available trees and flush all BasicBlocks
+ /// awaiting deletion.
+ /// Does nothing under Eager UpdateStrategy.
+ void flush();
+
+ /// Debug method to help view the internal state of this class.
+ LLVM_DUMP_METHOD void dump() const;
+
+private:
+ class CallBackOnDeletion final : public CallbackVH {
+ public:
+ CallBackOnDeletion(BasicBlock *V,
+ std::function<void(BasicBlock *)> Callback)
+ : CallbackVH(V), DelBB(V), Callback_(Callback) {}
+
+ private:
+ BasicBlock *DelBB = nullptr;
+ std::function<void(BasicBlock *)> Callback_;
+
+ void deleted() override {
+ Callback_(DelBB);
+ CallbackVH::deleted();
+ }
+ };
+
+ SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
+ size_t PendDTUpdateIndex = 0;
+ size_t PendPDTUpdateIndex = 0;
+ DominatorTree *DT = nullptr;
+ PostDominatorTree *PDT = nullptr;
+ const UpdateStrategy Strategy;
+ SmallPtrSet<BasicBlock *, 8> DeletedBBs;
+ std::vector<CallBackOnDeletion> Callbacks;
+ bool IsRecalculatingDomTree = false;
+ bool IsRecalculatingPostDomTree = false;
+
+ /// First remove all the instructions of DelBB and then make sure DelBB has a
+ /// valid terminator instruction which is necessary to have when DelBB still
+ /// has to be inside of its parent Function while awaiting deletion under Lazy
+ /// UpdateStrategy to prevent other routines from asserting the state of the
+ /// IR is inconsistent. Assert if DelBB is nullptr or has predecessors.
+ void validateDeleteBB(BasicBlock *DelBB);
+
+ /// Returns true if at least one BasicBlock is deleted.
+ bool forceFlushDeletedBB();
+
+ /// Deduplicate and remove unnecessary updates (no-ops) when using Lazy
+ /// UpdateStrategy. Returns true if the update is queued for update.
+ bool applyLazyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
+ BasicBlock *To);
+
+ /// Helper function to apply all pending DomTree updates.
+ void applyDomTreeUpdates();
+
+ /// Helper function to apply all pending PostDomTree updates.
+ void applyPostDomTreeUpdates();
+
+ /// Helper function to flush deleted BasicBlocks if all available
+ /// trees are up-to-date.
+ void tryFlushDeletedBB();
+
+ /// Drop all updates applied by all available trees and delete BasicBlocks if
+ /// all available trees are up-to-date.
+ void dropOutOfDateUpdates();
+
+ /// Erase Basic Block node that has been unlinked from Function
+ /// in the DomTree and PostDomTree.
+ void eraseDelBBNode(BasicBlock *DelBB);
+
+ /// Returns true if the update appears in the LLVM IR.
+ /// It is used to check whether an update is valid in
+ /// insertEdge/deleteEdge or is unnecessary in the batch update.
+ bool isUpdateValid(DominatorTree::UpdateType Update) const;
+
+ /// Returns true if the update is self dominance.
+ bool isSelfDominance(DominatorTree::UpdateType Update) const;
+};
+} // namespace llvm
+
+#endif // LLVM_DOMTREEUPDATER_H
diff --git a/contrib/llvm/include/llvm/IR/Dominators.h b/contrib/llvm/include/llvm/IR/Dominators.h
index 6ad99e516fba..f9e992b0ef0c 100644
--- a/contrib/llvm/include/llvm/IR/Dominators.h
+++ b/contrib/llvm/include/llvm/IR/Dominators.h
@@ -63,8 +63,10 @@ extern template void DeleteEdge<BBPostDomTree>(BBPostDomTree &DT,
extern template void ApplyUpdates<BBDomTree>(BBDomTree &DT, BBUpdates);
extern template void ApplyUpdates<BBPostDomTree>(BBPostDomTree &DT, BBUpdates);
-extern template bool Verify<BBDomTree>(const BBDomTree &DT);
-extern template bool Verify<BBPostDomTree>(const BBPostDomTree &DT);
+extern template bool Verify<BBDomTree>(const BBDomTree &DT,
+ BBDomTree::VerificationLevel VL);
+extern template bool Verify<BBPostDomTree>(const BBPostDomTree &DT,
+ BBPostDomTree::VerificationLevel VL);
} // namespace DomTreeBuilder
using DomTreeNode = DomTreeNodeBase<BasicBlock>;
@@ -119,7 +121,7 @@ template <> struct DenseMapInfo<BasicBlockEdge> {
}
};
-/// \brief Concrete subclass of DominatorTreeBase that is used to compute a
+/// Concrete subclass of DominatorTreeBase that is used to compute a
/// normal dominator tree.
///
/// Definition: A block is said to be forward statically reachable if there is
@@ -148,19 +150,10 @@ class DominatorTree : public DominatorTreeBase<BasicBlock, false> {
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
- /// \brief Returns *false* if the other dominator tree matches this dominator
- /// tree.
- inline bool compare(const DominatorTree &Other) const {
- const DomTreeNode *R = getRootNode();
- const DomTreeNode *OtherR = Other.getRootNode();
- return !R || !OtherR || R->getBlock() != OtherR->getBlock() ||
- Base::compare(Other);
- }
-
// Ensure base-class overloads are visible.
using Base::dominates;
- /// \brief Return true if Def dominates a use in User.
+ /// Return true if Def dominates a use in User.
///
/// This performs the special checks necessary if Def and User are in the same
/// basic block. Note that Def doesn't dominate a use in Def itself!
@@ -178,15 +171,9 @@ class DominatorTree : public DominatorTreeBase<BasicBlock, false> {
// Ensure base class overloads are visible.
using Base::isReachableFromEntry;
- /// \brief Provide an overload for a Use.
+ /// Provide an overload for a Use.
bool isReachableFromEntry(const Use &U) const;
- /// \brief Verify the correctness of the domtree by re-computing it.
- ///
- /// This should only be used for debugging as it aborts the program if the
- /// verification fails.
- void verifyDomTree() const;
-
// Pop up a GraphViz/gv window with the Dominator Tree rendered using `dot`.
void viewGraph(const Twine &Name, const Twine &Title);
void viewGraph();
@@ -234,20 +221,20 @@ template <> struct GraphTraits<DominatorTree*>
}
};
-/// \brief Analysis pass which computes a \c DominatorTree.
+/// Analysis pass which computes a \c DominatorTree.
class DominatorTreeAnalysis : public AnalysisInfoMixin<DominatorTreeAnalysis> {
friend AnalysisInfoMixin<DominatorTreeAnalysis>;
static AnalysisKey Key;
public:
- /// \brief Provide the result typedef for this analysis pass.
+ /// Provide the result typedef for this analysis pass.
using Result = DominatorTree;
- /// \brief Run the analysis pass over a function and produce a dominator tree.
+ /// Run the analysis pass over a function and produce a dominator tree.
DominatorTree run(Function &F, FunctionAnalysisManager &);
};
-/// \brief Printer pass for the \c DominatorTree.
+/// Printer pass for the \c DominatorTree.
class DominatorTreePrinterPass
: public PassInfoMixin<DominatorTreePrinterPass> {
raw_ostream &OS;
@@ -258,12 +245,12 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Verifier pass for the \c DominatorTree.
+/// Verifier pass for the \c DominatorTree.
struct DominatorTreeVerifierPass : PassInfoMixin<DominatorTreeVerifierPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Legacy analysis pass which computes a \c DominatorTree.
+/// Legacy analysis pass which computes a \c DominatorTree.
class DominatorTreeWrapperPass : public FunctionPass {
DominatorTree DT;
@@ -290,6 +277,93 @@ public:
void print(raw_ostream &OS, const Module *M = nullptr) const override;
};
+//===-------------------------------------
+/// Class to defer updates to a DominatorTree.
+///
+/// Definition: Applying updates to every edge insertion and deletion is
+/// expensive and not necessary. When one needs the DominatorTree for analysis
+/// they can request a flush() to perform a larger batch update. This has the
+/// advantage of the DominatorTree inspecting the set of updates to find
+/// duplicates or unnecessary subtree updates.
+///
+/// The scope of DeferredDominance operates at a Function level.
+///
+/// It is not necessary for the user to scrub the updates for duplicates or
+/// updates that point to the same block (Delete, BB_A, BB_A). Performance
+/// can be gained if the caller attempts to batch updates before submitting
+/// to applyUpdates(ArrayRef) in cases where duplicate edge requests will
+/// occur.
+///
+/// It is required for the state of the LLVM IR to be applied *before*
+/// submitting updates. The update routines must analyze the current state
+/// between a pair of (From, To) basic blocks to determine if the update
+/// needs to be queued.
+/// Example (good):
+/// TerminatorInstructionBB->removeFromParent();
+/// DDT->deleteEdge(BB, Successor);
+/// Example (bad):
+/// DDT->deleteEdge(BB, Successor);
+/// TerminatorInstructionBB->removeFromParent();
+class DeferredDominance {
+public:
+ DeferredDominance(DominatorTree &DT_) : DT(DT_) {}
+
+ /// Queues multiple updates and discards duplicates.
+ void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates);
+
+ /// Helper method for a single edge insertion. It's almost always
+ /// better to batch updates and call applyUpdates to quickly remove duplicate
+ /// edges. This is best used when there is only a single insertion needed to
+ /// update Dominators.
+ void insertEdge(BasicBlock *From, BasicBlock *To);
+
+ /// Helper method for a single edge deletion. It's almost always better
+ /// to batch updates and call applyUpdates to quickly remove duplicate edges.
+ /// This is best used when there is only a single deletion needed to update
+ /// Dominators.
+ void deleteEdge(BasicBlock *From, BasicBlock *To);
+
+ /// Delays the deletion of a basic block until a flush() event.
+ void deleteBB(BasicBlock *DelBB);
+
+ /// Returns true if DelBB is awaiting deletion at a flush() event.
+ bool pendingDeletedBB(BasicBlock *DelBB);
+
+ /// Returns true if pending DT updates are queued for a flush() event.
+ bool pending();
+
+ /// Flushes all pending updates and block deletions. Returns a
+ /// correct DominatorTree reference to be used by the caller for analysis.
+ DominatorTree &flush();
+
+ /// Drops all internal state and forces a (slow) recalculation of the
+ /// DominatorTree based on the current state of the LLVM IR in F. This should
+ /// only be used in corner cases such as the Entry block of F being deleted.
+ void recalculate(Function &F);
+
+ /// Debug method to help view the state of pending updates.
+ LLVM_DUMP_METHOD void dump() const;
+
+private:
+ DominatorTree &DT;
+ SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
+ SmallPtrSet<BasicBlock *, 8> DeletedBBs;
+
+ /// Apply an update (Kind, From, To) to the internal queued updates. The
+ /// update is only added when determined to be necessary. Checks for
+ /// self-domination, unnecessary updates, duplicate requests, and balanced
+ /// pairs of requests are all performed. Returns true if the update is
+ /// queued and false if it is discarded.
+ bool applyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
+ BasicBlock *To);
+
+ /// Performs all pending basic block deletions. We have to defer the deletion
+ /// of these blocks until after the DominatorTree updates are applied. The
+ /// internal workings of the DominatorTree code expect every update's From
+ /// and To blocks to exist and to be a member of the same Function.
+ bool flushDelBB();
+};
+
} // end namespace llvm
#endif // LLVM_IR_DOMINATORS_H
diff --git a/contrib/llvm/include/llvm/IR/Function.h b/contrib/llvm/include/llvm/IR/Function.h
index def842f5fcee..c8d6b0776fbf 100644
--- a/contrib/llvm/include/llvm/IR/Function.h
+++ b/contrib/llvm/include/llvm/IR/Function.h
@@ -141,6 +141,11 @@ public:
// Provide fast operand accessors.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+ /// Returns the number of non-debug IR instructions in this function.
+ /// This is equivalent to the sum of the sizes of each basic block contained
+ /// within this function.
+ unsigned getInstructionCount();
+
/// Returns the FunctionType for me.
FunctionType *getFunctionType() const {
return cast<FunctionType>(getValueType());
@@ -181,7 +186,7 @@ public:
static Intrinsic::ID lookupIntrinsicID(StringRef Name);
- /// \brief Recalculate the ID for this function if it is an Intrinsic defined
+ /// Recalculate the ID for this function if it is an Intrinsic defined
/// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic
/// if the name of this function does not match an intrinsic in that header.
/// Note, this method does not need to be called directly, as it is called
@@ -201,53 +206,86 @@ public:
setValueSubclassData((getSubclassDataFromValue() & 0xc00f) | (ID << 4));
}
- /// @brief Return the attribute list for this Function.
+ /// Return the attribute list for this Function.
AttributeList getAttributes() const { return AttributeSets; }
- /// @brief Set the attribute list for this Function.
+ /// Set the attribute list for this Function.
void setAttributes(AttributeList Attrs) { AttributeSets = Attrs; }
- /// @brief Add function attributes to this function.
+ /// Add function attributes to this function.
void addFnAttr(Attribute::AttrKind Kind) {
addAttribute(AttributeList::FunctionIndex, Kind);
}
- /// @brief Add function attributes to this function.
+ /// Add function attributes to this function.
void addFnAttr(StringRef Kind, StringRef Val = StringRef()) {
addAttribute(AttributeList::FunctionIndex,
Attribute::get(getContext(), Kind, Val));
}
- /// @brief Add function attributes to this function.
+ /// Add function attributes to this function.
void addFnAttr(Attribute Attr) {
addAttribute(AttributeList::FunctionIndex, Attr);
}
- /// @brief Remove function attributes from this function.
+ /// Remove function attributes from this function.
void removeFnAttr(Attribute::AttrKind Kind) {
removeAttribute(AttributeList::FunctionIndex, Kind);
}
- /// @brief Remove function attribute from this function.
+ /// Remove function attribute from this function.
void removeFnAttr(StringRef Kind) {
setAttributes(getAttributes().removeAttribute(
getContext(), AttributeList::FunctionIndex, Kind));
}
- /// \brief Set the entry count for this function.
+ enum ProfileCountType { PCT_Invalid, PCT_Real, PCT_Synthetic };
+
+ /// Class to represent profile counts.
+ ///
+ /// This class represents both real and synthetic profile counts.
+ class ProfileCount {
+ private:
+ uint64_t Count;
+ ProfileCountType PCT;
+ static ProfileCount Invalid;
+
+ public:
+ ProfileCount() : Count(-1), PCT(PCT_Invalid) {}
+ ProfileCount(uint64_t Count, ProfileCountType PCT)
+ : Count(Count), PCT(PCT) {}
+ bool hasValue() const { return PCT != PCT_Invalid; }
+ uint64_t getCount() const { return Count; }
+ ProfileCountType getType() const { return PCT; }
+ bool isSynthetic() const { return PCT == PCT_Synthetic; }
+ explicit operator bool() { return hasValue(); }
+ bool operator!() const { return !hasValue(); }
+ // Update the count retaining the same profile count type.
+ ProfileCount &setCount(uint64_t C) {
+ Count = C;
+ return *this;
+ }
+ static ProfileCount getInvalid() { return ProfileCount(-1, PCT_Invalid); }
+ };
+
+ /// Set the entry count for this function.
///
/// Entry count is the number of times this function was executed based on
- /// pgo data. \p Imports points to a set of GUIDs that needs to be imported
- /// by the function for sample PGO, to enable the same inlines as the
- /// profiled optimized binary.
- void setEntryCount(uint64_t Count,
+ /// pgo data. \p Imports points to a set of GUIDs that needs to
+ /// be imported by the function for sample PGO, to enable the same inlines as
+ /// the profiled optimized binary.
+ void setEntryCount(ProfileCount Count,
const DenseSet<GlobalValue::GUID> *Imports = nullptr);
- /// \brief Get the entry count for this function.
+ /// A convenience wrapper for setting entry count
+ void setEntryCount(uint64_t Count, ProfileCountType Type = PCT_Real,
+ const DenseSet<GlobalValue::GUID> *Imports = nullptr);
+
+ /// Get the entry count for this function.
///
/// Entry count is the number of times the function was executed based on
/// pgo data.
- Optional<uint64_t> getEntryCount() const;
+ ProfileCount getEntryCount() const;
/// Return true if the function is annotated with profile data.
///
@@ -265,27 +303,27 @@ public:
/// Get the section prefix for this function.
Optional<StringRef> getSectionPrefix() const;
- /// @brief Return true if the function has the attribute.
+ /// Return true if the function has the attribute.
bool hasFnAttribute(Attribute::AttrKind Kind) const {
return AttributeSets.hasFnAttribute(Kind);
}
- /// @brief Return true if the function has the attribute.
+ /// Return true if the function has the attribute.
bool hasFnAttribute(StringRef Kind) const {
return AttributeSets.hasFnAttribute(Kind);
}
- /// @brief Return the attribute for the given attribute kind.
+ /// Return the attribute for the given attribute kind.
Attribute getFnAttribute(Attribute::AttrKind Kind) const {
return getAttribute(AttributeList::FunctionIndex, Kind);
}
- /// @brief Return the attribute for the given attribute kind.
+ /// Return the attribute for the given attribute kind.
Attribute getFnAttribute(StringRef Kind) const {
return getAttribute(AttributeList::FunctionIndex, Kind);
}
- /// \brief Return the stack alignment for the function.
+ /// Return the stack alignment for the function.
unsigned getFnStackAlignment() const {
if (!hasFnAttribute(Attribute::StackAlignment))
return 0;
@@ -301,110 +339,110 @@ public:
void setGC(std::string Str);
void clearGC();
- /// @brief adds the attribute to the list of attributes.
+ /// adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute::AttrKind Kind);
- /// @brief adds the attribute to the list of attributes.
+ /// adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute Attr);
- /// @brief adds the attributes to the list of attributes.
+ /// adds the attributes to the list of attributes.
void addAttributes(unsigned i, const AttrBuilder &Attrs);
- /// @brief adds the attribute to the list of attributes for the given arg.
+ /// adds the attribute to the list of attributes for the given arg.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
- /// @brief adds the attribute to the list of attributes for the given arg.
+ /// adds the attribute to the list of attributes for the given arg.
void addParamAttr(unsigned ArgNo, Attribute Attr);
- /// @brief adds the attributes to the list of attributes for the given arg.
+ /// adds the attributes to the list of attributes for the given arg.
void addParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs);
- /// @brief removes the attribute from the list of attributes.
+ /// removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
- /// @brief removes the attribute from the list of attributes.
+ /// removes the attribute from the list of attributes.
void removeAttribute(unsigned i, StringRef Kind);
- /// @brief removes the attributes from the list of attributes.
+ /// removes the attributes from the list of attributes.
void removeAttributes(unsigned i, const AttrBuilder &Attrs);
- /// @brief removes the attribute from the list of attributes.
+ /// removes the attribute from the list of attributes.
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
- /// @brief removes the attribute from the list of attributes.
+ /// removes the attribute from the list of attributes.
void removeParamAttr(unsigned ArgNo, StringRef Kind);
- /// @brief removes the attribute from the list of attributes.
+ /// removes the attribute from the list of attributes.
void removeParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs);
- /// @brief check if an attributes is in the list of attributes.
+ /// check if an attributes is in the list of attributes.
bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const {
return getAttributes().hasAttribute(i, Kind);
}
- /// @brief check if an attributes is in the list of attributes.
+ /// check if an attributes is in the list of attributes.
bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const {
return getAttributes().hasParamAttribute(ArgNo, Kind);
}
- /// @brief gets the attribute from the list of attributes.
+ /// gets the attribute from the list of attributes.
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
return AttributeSets.getAttribute(i, Kind);
}
- /// @brief gets the attribute from the list of attributes.
+ /// gets the attribute from the list of attributes.
Attribute getAttribute(unsigned i, StringRef Kind) const {
return AttributeSets.getAttribute(i, Kind);
}
- /// @brief adds the dereferenceable attribute to the list of attributes.
+ /// adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
- /// @brief adds the dereferenceable attribute to the list of attributes for
+ /// adds the dereferenceable attribute to the list of attributes for
/// the given arg.
void addDereferenceableParamAttr(unsigned ArgNo, uint64_t Bytes);
- /// @brief adds the dereferenceable_or_null attribute to the list of
+ /// adds the dereferenceable_or_null attribute to the list of
/// attributes.
void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
- /// @brief adds the dereferenceable_or_null attribute to the list of
+ /// adds the dereferenceable_or_null attribute to the list of
/// attributes for the given arg.
void addDereferenceableOrNullParamAttr(unsigned ArgNo, uint64_t Bytes);
- /// @brief Extract the alignment for a call or parameter (0=unknown).
+ /// Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned ArgNo) const {
return AttributeSets.getParamAlignment(ArgNo);
}
- /// @brief Extract the number of dereferenceable bytes for a call or
+ /// Extract the number of dereferenceable bytes for a call or
/// parameter (0=unknown).
/// @param i AttributeList index, referring to a return value or argument.
uint64_t getDereferenceableBytes(unsigned i) const {
return AttributeSets.getDereferenceableBytes(i);
}
- /// @brief Extract the number of dereferenceable bytes for a parameter.
+ /// Extract the number of dereferenceable bytes for a parameter.
/// @param ArgNo Index of an argument, with 0 being the first function arg.
uint64_t getParamDereferenceableBytes(unsigned ArgNo) const {
return AttributeSets.getParamDereferenceableBytes(ArgNo);
}
- /// @brief Extract the number of dereferenceable_or_null bytes for a call or
+ /// Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
/// @param i AttributeList index, referring to a return value or argument.
uint64_t getDereferenceableOrNullBytes(unsigned i) const {
return AttributeSets.getDereferenceableOrNullBytes(i);
}
- /// @brief Extract the number of dereferenceable_or_null bytes for a
+ /// Extract the number of dereferenceable_or_null bytes for a
/// parameter.
/// @param ArgNo AttributeList ArgNo, referring to an argument.
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const {
return AttributeSets.getParamDereferenceableOrNullBytes(ArgNo);
}
- /// @brief Determine if the function does not access memory.
+ /// Determine if the function does not access memory.
bool doesNotAccessMemory() const {
return hasFnAttribute(Attribute::ReadNone);
}
@@ -412,7 +450,7 @@ public:
addFnAttr(Attribute::ReadNone);
}
- /// @brief Determine if the function does not access or only reads memory.
+ /// Determine if the function does not access or only reads memory.
bool onlyReadsMemory() const {
return doesNotAccessMemory() || hasFnAttribute(Attribute::ReadOnly);
}
@@ -420,7 +458,7 @@ public:
addFnAttr(Attribute::ReadOnly);
}
- /// @brief Determine if the function does not access or only writes memory.
+ /// Determine if the function does not access or only writes memory.
bool doesNotReadMemory() const {
return doesNotAccessMemory() || hasFnAttribute(Attribute::WriteOnly);
}
@@ -428,14 +466,14 @@ public:
addFnAttr(Attribute::WriteOnly);
}
- /// @brief Determine if the call can access memmory only using pointers based
+ /// Determine if the call can access memmory only using pointers based
/// on its arguments.
bool onlyAccessesArgMemory() const {
return hasFnAttribute(Attribute::ArgMemOnly);
}
void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); }
- /// @brief Determine if the function may only access memory that is
+ /// Determine if the function may only access memory that is
/// inaccessible from the IR.
bool onlyAccessesInaccessibleMemory() const {
return hasFnAttribute(Attribute::InaccessibleMemOnly);
@@ -444,7 +482,7 @@ public:
addFnAttr(Attribute::InaccessibleMemOnly);
}
- /// @brief Determine if the function may only access memory that is
+ /// Determine if the function may only access memory that is
/// either inaccessible from the IR or pointed to by its arguments.
bool onlyAccessesInaccessibleMemOrArgMem() const {
return hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly);
@@ -453,7 +491,7 @@ public:
addFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
}
- /// @brief Determine if the function cannot return.
+ /// Determine if the function cannot return.
bool doesNotReturn() const {
return hasFnAttribute(Attribute::NoReturn);
}
@@ -461,7 +499,10 @@ public:
addFnAttr(Attribute::NoReturn);
}
- /// @brief Determine if the function cannot unwind.
+ /// Determine if the function should not perform indirect branch tracking.
+ bool doesNoCfCheck() const { return hasFnAttribute(Attribute::NoCfCheck); }
+
+ /// Determine if the function cannot unwind.
bool doesNotThrow() const {
return hasFnAttribute(Attribute::NoUnwind);
}
@@ -469,7 +510,7 @@ public:
addFnAttr(Attribute::NoUnwind);
}
- /// @brief Determine if the call cannot be duplicated.
+ /// Determine if the call cannot be duplicated.
bool cannotDuplicate() const {
return hasFnAttribute(Attribute::NoDuplicate);
}
@@ -477,7 +518,7 @@ public:
addFnAttr(Attribute::NoDuplicate);
}
- /// @brief Determine if the call is convergent.
+ /// Determine if the call is convergent.
bool isConvergent() const {
return hasFnAttribute(Attribute::Convergent);
}
@@ -488,7 +529,7 @@ public:
removeFnAttr(Attribute::Convergent);
}
- /// @brief Determine if the call has sideeffects.
+ /// Determine if the call has sideeffects.
bool isSpeculatable() const {
return hasFnAttribute(Attribute::Speculatable);
}
@@ -505,7 +546,7 @@ public:
addFnAttr(Attribute::NoRecurse);
}
- /// @brief True if the ABI mandates (or the user requested) that this
+ /// True if the ABI mandates (or the user requested) that this
/// function be in a unwind table.
bool hasUWTable() const {
return hasFnAttribute(Attribute::UWTable);
@@ -514,19 +555,19 @@ public:
addFnAttr(Attribute::UWTable);
}
- /// @brief True if this function needs an unwind table.
+ /// True if this function needs an unwind table.
bool needsUnwindTableEntry() const {
return hasUWTable() || !doesNotThrow();
}
- /// @brief Determine if the function returns a structure through first
+ /// Determine if the function returns a structure through first
/// or second pointer argument.
bool hasStructRetAttr() const {
return AttributeSets.hasParamAttribute(0, Attribute::StructRet) ||
AttributeSets.hasParamAttribute(1, Attribute::StructRet);
}
- /// @brief Determine if the parameter or return value is marked with NoAlias
+ /// Determine if the parameter or return value is marked with NoAlias
/// attribute.
bool returnDoesNotAlias() const {
return AttributeSets.hasAttribute(AttributeList::ReturnIndex,
@@ -643,30 +684,30 @@ public:
size_t arg_size() const { return NumArgs; }
bool arg_empty() const { return arg_size() == 0; }
- /// \brief Check whether this function has a personality function.
+ /// Check whether this function has a personality function.
bool hasPersonalityFn() const {
return getSubclassDataFromValue() & (1<<3);
}
- /// \brief Get the personality function associated with this function.
+ /// Get the personality function associated with this function.
Constant *getPersonalityFn() const;
void setPersonalityFn(Constant *Fn);
- /// \brief Check whether this function has prefix data.
+ /// Check whether this function has prefix data.
bool hasPrefixData() const {
return getSubclassDataFromValue() & (1<<1);
}
- /// \brief Get the prefix data associated with this function.
+ /// Get the prefix data associated with this function.
Constant *getPrefixData() const;
void setPrefixData(Constant *PrefixData);
- /// \brief Check whether this function has prologue data.
+ /// Check whether this function has prologue data.
bool hasPrologueData() const {
return getSubclassDataFromValue() & (1<<2);
}
- /// \brief Get the prologue data associated with this function.
+ /// Get the prologue data associated with this function.
Constant *getPrologueData() const;
void setPrologueData(Constant *PrologueData);
@@ -726,12 +767,12 @@ public:
/// setjmp or other function that gcc recognizes as "returning twice".
bool callsFunctionThatReturnsTwice() const;
- /// \brief Set the attached subprogram.
+ /// Set the attached subprogram.
///
/// Calls \a setMetadata() with \a LLVMContext::MD_dbg.
void setSubprogram(DISubprogram *SP);
- /// \brief Get the attached subprogram.
+ /// Get the attached subprogram.
///
/// Calls \a getMetadata() with \a LLVMContext::MD_dbg and casts the result
/// to \a DISubprogram.
@@ -740,6 +781,12 @@ public:
/// Returns true if we should emit debug info for profiling.
bool isDebugInfoForProfiling() const;
+ /// Check if null pointer dereferencing is considered undefined behavior for
+ /// the function.
+ /// Return value: false => null pointer dereference is undefined.
+ /// Return value: true => null pointer dereference is not undefined.
+ bool nullPointerIsDefined() const;
+
private:
void allocHungoffUselist();
template<int Idx> void setHungoffOperand(Constant *C);
@@ -752,6 +799,13 @@ private:
void setValueSubclassDataBit(unsigned Bit, bool On);
};
+/// Check whether null pointer dereferencing is considered undefined behavior
+/// for a given function or an address space.
+/// Null pointer access in non-zero address space is not considered undefined.
+/// Return value: false => null pointer dereference is undefined.
+/// Return value: true => null pointer dereference is not undefined.
+bool NullPointerIsDefined(const Function *F, unsigned AS = 0);
+
template <>
struct OperandTraits<Function> : public HungoffOperandTraits<3> {};
diff --git a/contrib/llvm/include/llvm/IR/GlobalObject.h b/contrib/llvm/include/llvm/IR/GlobalObject.h
index 278b193567f1..1fd3568100c2 100644
--- a/contrib/llvm/include/llvm/IR/GlobalObject.h
+++ b/contrib/llvm/include/llvm/IR/GlobalObject.h
@@ -105,6 +105,14 @@ public:
/// Check if this has any metadata.
bool hasMetadata() const { return hasMetadataHashEntry(); }
+ /// Check if this has any metadata of the given kind.
+ bool hasMetadata(unsigned KindID) const {
+ return getMetadata(KindID) != nullptr;
+ }
+ bool hasMetadata(StringRef Kind) const {
+ return getMetadata(Kind) != nullptr;
+ }
+
/// Get the current metadata attachments for the given kind, if any.
///
/// These functions require that the function have at most a single attachment
@@ -143,7 +151,9 @@ public:
getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
/// Erase all metadata attachments with the given kind.
- void eraseMetadata(unsigned KindID);
+ ///
+ /// \returns true if any metadata was removed.
+ bool eraseMetadata(unsigned KindID);
/// Copy metadata from Src, adjusting offsets by Offset.
void copyMetadata(const GlobalObject *Src, unsigned Offset);
diff --git a/contrib/llvm/include/llvm/IR/GlobalValue.h b/contrib/llvm/include/llvm/IR/GlobalValue.h
index 1793de7887fc..9d9f4f65a6b5 100644
--- a/contrib/llvm/include/llvm/IR/GlobalValue.h
+++ b/contrib/llvm/include/llvm/IR/GlobalValue.h
@@ -44,7 +44,7 @@ namespace Intrinsic {
class GlobalValue : public Constant {
public:
- /// @brief An enumeration for the kinds of linkage for global values.
+ /// An enumeration for the kinds of linkage for global values.
enum LinkageTypes {
ExternalLinkage = 0,///< Externally visible function
AvailableExternallyLinkage, ///< Available for inspection, not emission.
@@ -59,14 +59,14 @@ public:
CommonLinkage ///< Tentative definitions.
};
- /// @brief An enumeration for the kinds of visibility of global values.
+ /// An enumeration for the kinds of visibility of global values.
enum VisibilityTypes {
DefaultVisibility = 0, ///< The GV is visible
HiddenVisibility, ///< The GV is hidden
ProtectedVisibility ///< The GV is protected
};
- /// @brief Storage classes of global values for PE targets.
+ /// Storage classes of global values for PE targets.
enum DLLStorageClassTypes {
DefaultStorageClass = 0,
DLLImportStorageClass = 1, ///< Function to be imported from DLL
@@ -77,11 +77,12 @@ protected:
GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace)
: Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps),
- ValueType(Ty), Linkage(Linkage), Visibility(DefaultVisibility),
+ ValueType(Ty), Visibility(DefaultVisibility),
UnnamedAddrVal(unsigned(UnnamedAddr::None)),
DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal),
- HasLLVMReservedName(false), IsDSOLocal(false),
- IntID((Intrinsic::ID)0U), Parent(nullptr) {
+ HasLLVMReservedName(false), IsDSOLocal(false), IntID((Intrinsic::ID)0U),
+ Parent(nullptr) {
+ setLinkage(Linkage);
setName(Name);
}
@@ -109,12 +110,12 @@ protected:
unsigned IsDSOLocal : 1;
private:
- friend class Constant;
-
// Give subclasses access to what otherwise would be wasted padding.
// (17 + 4 + 2 + 2 + 2 + 3 + 1 + 1) == 32.
unsigned SubClassData : GlobalValueSubClassDataBits;
+ friend class Constant;
+
void destroyConstantImpl();
Value *handleOperandChangeImpl(Value *From, Value *To);
@@ -142,8 +143,14 @@ private:
llvm_unreachable("Fully covered switch above!");
}
+ void maybeSetDsoLocal() {
+ if (hasLocalLinkage() ||
+ (!hasDefaultVisibility() && !hasExternalWeakLinkage()))
+ setDSOLocal(true);
+ }
+
protected:
- /// \brief The intrinsic ID for this subclass (which must be a Function).
+ /// The intrinsic ID for this subclass (which must be a Function).
///
/// This member is defined by this class, but not used for anything.
/// Subclasses can use it to store their intrinsic ID, if they have one.
@@ -232,6 +239,7 @@ public:
assert((!hasLocalLinkage() || V == DefaultVisibility) &&
"local linkage requires default visibility");
Visibility = V;
+ maybeSetDsoLocal();
}
/// If the value is "Thread Local", its value isn't shared by the threads.
@@ -437,6 +445,7 @@ public:
if (isLocalLinkage(LT))
Visibility = DefaultVisibility;
Linkage = LT;
+ maybeSetDsoLocal();
}
LinkageTypes getLinkage() const { return LinkageTypes(Linkage); }
@@ -563,6 +572,13 @@ public:
V->getValueID() == Value::GlobalAliasVal ||
V->getValueID() == Value::GlobalIFuncVal;
}
+
+ /// True if GV can be left out of the object symbol table. This is the case
+ /// for linkonce_odr values whose address is not significant. While legal, it
+ /// is not normally profitable to omit them from the .o symbol table. Using
+ /// this analysis makes sense when the information can be passed down to the
+ /// linker or we are in LTO.
+ bool canBeOmittedFromSymbolTable() const;
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/IR/GlobalVariable.h b/contrib/llvm/include/llvm/IR/GlobalVariable.h
index 34ace6f2b4f4..03b9ec46ebb4 100644
--- a/contrib/llvm/include/llvm/IR/GlobalVariable.h
+++ b/contrib/llvm/include/llvm/IR/GlobalVariable.h
@@ -68,9 +68,6 @@ public:
~GlobalVariable() {
dropAllReferences();
-
- // FIXME: needed by operator delete
- setGlobalVariableNumOperands(1);
}
// allocate space for exactly one operand
@@ -78,6 +75,16 @@ public:
return User::operator new(s, 1);
}
+ // delete space for exactly one operand as created in the corresponding new operator
+ void operator delete(void *ptr){
+ assert(ptr != nullptr && "must not be nullptr");
+ User *Obj = static_cast<User *>(ptr);
+ // Number of operands can be set to 0 after construction and initialization. Make sure
+ // that number of operands is reset to 1, as this is needed in User::operator delete
+ Obj->setGlobalVariableNumOperands(1);
+ User::operator delete(Obj);
+ }
+
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
diff --git a/contrib/llvm/include/llvm/IR/IRBuilder.h b/contrib/llvm/include/llvm/IR/IRBuilder.h
index e687ca689d46..70641ba25d2e 100644
--- a/contrib/llvm/include/llvm/IR/IRBuilder.h
+++ b/contrib/llvm/include/llvm/IR/IRBuilder.h
@@ -1,4 +1,4 @@
-//===---- llvm/IRBuilder.h - Builder for LLVM Instructions ------*- C++ -*-===//
+//===- llvm/IRBuilder.h - Builder for LLVM Instructions ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -42,20 +42,19 @@
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Casting.h"
-#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <functional>
+#include <utility>
namespace llvm {
class APInt;
class MDNode;
-class Module;
class Use;
-/// \brief This provides the default implementation of the IRBuilder
+/// This provides the default implementation of the IRBuilder
/// 'InsertHelper' method that is called whenever an instruction is created by
/// IRBuilder and needs to be inserted.
///
@@ -86,7 +85,7 @@ protected:
}
};
-/// \brief Common base class shared among various IRBuilders.
+/// Common base class shared among various IRBuilders.
class IRBuilderBase {
DebugLoc CurDbgLocation;
@@ -112,7 +111,7 @@ public:
// Builder configuration methods
//===--------------------------------------------------------------------===//
- /// \brief Clear the insertion point: created instructions will not be
+ /// Clear the insertion point: created instructions will not be
/// inserted into a block.
void ClearInsertionPoint() {
BB = nullptr;
@@ -123,14 +122,14 @@ public:
BasicBlock::iterator GetInsertPoint() const { return InsertPt; }
LLVMContext &getContext() const { return Context; }
- /// \brief This specifies that created instructions should be appended to the
+ /// This specifies that created instructions should be appended to the
/// end of the specified block.
void SetInsertPoint(BasicBlock *TheBB) {
BB = TheBB;
InsertPt = BB->end();
}
- /// \brief This specifies that created instructions should be inserted before
+ /// This specifies that created instructions should be inserted before
/// the specified instruction.
void SetInsertPoint(Instruction *I) {
BB = I->getParent();
@@ -139,7 +138,7 @@ public:
SetCurrentDebugLocation(I->getDebugLoc());
}
- /// \brief This specifies that created instructions should be inserted at the
+ /// This specifies that created instructions should be inserted at the
/// specified point.
void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) {
BB = TheBB;
@@ -148,20 +147,20 @@ public:
SetCurrentDebugLocation(IP->getDebugLoc());
}
- /// \brief Set location information used by debugging information.
+ /// Set location information used by debugging information.
void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); }
- /// \brief Get location information used by debugging information.
+ /// Get location information used by debugging information.
const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; }
- /// \brief If this builder has a current debug location, set it on the
+ /// If this builder has a current debug location, set it on the
/// specified instruction.
void SetInstDebugLocation(Instruction *I) const {
if (CurDbgLocation)
I->setDebugLoc(CurDbgLocation);
}
- /// \brief Get the return type of the current function that we're emitting
+ /// Get the return type of the current function that we're emitting
/// into.
Type *getCurrentFunctionReturnType() const;
@@ -171,33 +170,33 @@ public:
BasicBlock::iterator Point;
public:
- /// \brief Creates a new insertion point which doesn't point to anything.
+ /// Creates a new insertion point which doesn't point to anything.
InsertPoint() = default;
- /// \brief Creates a new insertion point at the given location.
+ /// Creates a new insertion point at the given location.
InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint)
- : Block(InsertBlock), Point(InsertPoint) {}
+ : Block(InsertBlock), Point(InsertPoint) {}
- /// \brief Returns true if this insert point is set.
+ /// Returns true if this insert point is set.
bool isSet() const { return (Block != nullptr); }
BasicBlock *getBlock() const { return Block; }
BasicBlock::iterator getPoint() const { return Point; }
};
- /// \brief Returns the current insert point.
+ /// Returns the current insert point.
InsertPoint saveIP() const {
return InsertPoint(GetInsertBlock(), GetInsertPoint());
}
- /// \brief Returns the current insert point, clearing it in the process.
+ /// Returns the current insert point, clearing it in the process.
InsertPoint saveAndClearIP() {
InsertPoint IP(GetInsertBlock(), GetInsertPoint());
ClearInsertionPoint();
return IP;
}
- /// \brief Sets the current insert point to a previously-saved location.
+ /// Sets the current insert point to a previously-saved location.
void restoreIP(InsertPoint IP) {
if (IP.isSet())
SetInsertPoint(IP.getBlock(), IP.getPoint());
@@ -205,26 +204,26 @@ public:
ClearInsertionPoint();
}
- /// \brief Get the floating point math metadata being used.
+ /// Get the floating point math metadata being used.
MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; }
- /// \brief Get the flags to be applied to created floating point ops
+ /// Get the flags to be applied to created floating point ops
FastMathFlags getFastMathFlags() const { return FMF; }
- /// \brief Clear the fast-math flags.
+ /// Clear the fast-math flags.
void clearFastMathFlags() { FMF.clear(); }
- /// \brief Set the floating point math metadata to be used.
+ /// Set the floating point math metadata to be used.
void setDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; }
- /// \brief Set the fast-math flags to be used with generated fp-math operators
+ /// Set the fast-math flags to be used with generated fp-math operators
void setFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; }
//===--------------------------------------------------------------------===//
// RAII helpers.
//===--------------------------------------------------------------------===//
- // \brief RAII object that stores the current insertion point and restores it
+ // RAII object that stores the current insertion point and restores it
// when the object is destroyed. This includes the debug location.
class InsertPointGuard {
IRBuilderBase &Builder;
@@ -246,7 +245,7 @@ public:
}
};
- // \brief RAII object that stores the current fast math settings and restores
+ // RAII object that stores the current fast math settings and restores
// them when the object is destroyed.
class FastMathFlagGuard {
IRBuilderBase &Builder;
@@ -270,7 +269,7 @@ public:
// Miscellaneous creation methods.
//===--------------------------------------------------------------------===//
- /// \brief Make a new global variable with initializer type i8*
+ /// Make a new global variable with initializer type i8*
///
/// Make a new global variable with an initializer that has array of i8 type
/// filled in with the null terminated string value specified. The new global
@@ -279,48 +278,48 @@ public:
GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = "",
unsigned AddressSpace = 0);
- /// \brief Get a constant value representing either true or false.
+ /// Get a constant value representing either true or false.
ConstantInt *getInt1(bool V) {
return ConstantInt::get(getInt1Ty(), V);
}
- /// \brief Get the constant value for i1 true.
+ /// Get the constant value for i1 true.
ConstantInt *getTrue() {
return ConstantInt::getTrue(Context);
}
- /// \brief Get the constant value for i1 false.
+ /// Get the constant value for i1 false.
ConstantInt *getFalse() {
return ConstantInt::getFalse(Context);
}
- /// \brief Get a constant 8-bit value.
+ /// Get a constant 8-bit value.
ConstantInt *getInt8(uint8_t C) {
return ConstantInt::get(getInt8Ty(), C);
}
- /// \brief Get a constant 16-bit value.
+ /// Get a constant 16-bit value.
ConstantInt *getInt16(uint16_t C) {
return ConstantInt::get(getInt16Ty(), C);
}
- /// \brief Get a constant 32-bit value.
+ /// Get a constant 32-bit value.
ConstantInt *getInt32(uint32_t C) {
return ConstantInt::get(getInt32Ty(), C);
}
- /// \brief Get a constant 64-bit value.
+ /// Get a constant 64-bit value.
ConstantInt *getInt64(uint64_t C) {
return ConstantInt::get(getInt64Ty(), C);
}
- /// \brief Get a constant N-bit value, zero extended or truncated from
+ /// Get a constant N-bit value, zero extended or truncated from
/// a 64-bit value.
ConstantInt *getIntN(unsigned N, uint64_t C) {
return ConstantInt::get(getIntNTy(N), C);
}
- /// \brief Get a constant integer value.
+ /// Get a constant integer value.
ConstantInt *getInt(const APInt &AI) {
return ConstantInt::get(Context, AI);
}
@@ -329,65 +328,65 @@ public:
// Type creation methods
//===--------------------------------------------------------------------===//
- /// \brief Fetch the type representing a single bit
+ /// Fetch the type representing a single bit
IntegerType *getInt1Ty() {
return Type::getInt1Ty(Context);
}
- /// \brief Fetch the type representing an 8-bit integer.
+ /// Fetch the type representing an 8-bit integer.
IntegerType *getInt8Ty() {
return Type::getInt8Ty(Context);
}
- /// \brief Fetch the type representing a 16-bit integer.
+ /// Fetch the type representing a 16-bit integer.
IntegerType *getInt16Ty() {
return Type::getInt16Ty(Context);
}
- /// \brief Fetch the type representing a 32-bit integer.
+ /// Fetch the type representing a 32-bit integer.
IntegerType *getInt32Ty() {
return Type::getInt32Ty(Context);
}
- /// \brief Fetch the type representing a 64-bit integer.
+ /// Fetch the type representing a 64-bit integer.
IntegerType *getInt64Ty() {
return Type::getInt64Ty(Context);
}
- /// \brief Fetch the type representing a 128-bit integer.
+ /// Fetch the type representing a 128-bit integer.
IntegerType *getInt128Ty() { return Type::getInt128Ty(Context); }
- /// \brief Fetch the type representing an N-bit integer.
+ /// Fetch the type representing an N-bit integer.
IntegerType *getIntNTy(unsigned N) {
return Type::getIntNTy(Context, N);
}
- /// \brief Fetch the type representing a 16-bit floating point value.
+ /// Fetch the type representing a 16-bit floating point value.
Type *getHalfTy() {
return Type::getHalfTy(Context);
}
- /// \brief Fetch the type representing a 32-bit floating point value.
+ /// Fetch the type representing a 32-bit floating point value.
Type *getFloatTy() {
return Type::getFloatTy(Context);
}
- /// \brief Fetch the type representing a 64-bit floating point value.
+ /// Fetch the type representing a 64-bit floating point value.
Type *getDoubleTy() {
return Type::getDoubleTy(Context);
}
- /// \brief Fetch the type representing void.
+ /// Fetch the type representing void.
Type *getVoidTy() {
return Type::getVoidTy(Context);
}
- /// \brief Fetch the type representing a pointer to an 8-bit integer value.
+ /// Fetch the type representing a pointer to an 8-bit integer value.
PointerType *getInt8PtrTy(unsigned AddrSpace = 0) {
return Type::getInt8PtrTy(Context, AddrSpace);
}
- /// \brief Fetch the type representing a pointer to an integer value.
+ /// Fetch the type representing a pointer to an integer value.
IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) {
return DL.getIntPtrType(Context, AddrSpace);
}
@@ -396,7 +395,7 @@ public:
// Intrinsic creation methods
//===--------------------------------------------------------------------===//
- /// \brief Create and insert a memset to the specified pointer and the
+ /// Create and insert a memset to the specified pointer and the
/// specified value.
///
/// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
@@ -415,27 +414,54 @@ public:
MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr);
- /// \brief Create and insert a memcpy between the specified pointers.
+ /// Create and insert an element unordered-atomic memset of the region of
+ /// memory starting at the given pointer to the given value.
+ ///
+ /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
+ /// specified, it will be added to the instruction. Likewise with alias.scope
+ /// and noalias tags.
+ CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val,
+ uint64_t Size, unsigned Align,
+ uint32_t ElementSize,
+ MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
+ return CreateElementUnorderedAtomicMemSet(Ptr, Val, getInt64(Size), Align,
+ ElementSize, TBAATag, ScopeTag,
+ NoAliasTag);
+ }
+
+ CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val,
+ Value *Size, unsigned Align,
+ uint32_t ElementSize,
+ MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
+
+ /// Create and insert a memcpy between the specified pointers.
///
/// If the pointers aren't i8*, they will be converted. If a TBAA tag is
/// specified, it will be added to the instruction. Likewise with alias.scope
/// and noalias tags.
- CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align,
+ CallInst *CreateMemCpy(Value *Dst, unsigned DstAlign, Value *Src,
+ unsigned SrcAlign, uint64_t Size,
bool isVolatile = false, MDNode *TBAATag = nullptr,
MDNode *TBAAStructTag = nullptr,
MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr) {
- return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag,
- TBAAStructTag, ScopeTag, NoAliasTag);
+ return CreateMemCpy(Dst, DstAlign, Src, SrcAlign, getInt64(Size),
+ isVolatile, TBAATag, TBAAStructTag, ScopeTag,
+ NoAliasTag);
}
- CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
+ CallInst *CreateMemCpy(Value *Dst, unsigned DstAlign, Value *Src,
+ unsigned SrcAlign, Value *Size,
bool isVolatile = false, MDNode *TBAATag = nullptr,
MDNode *TBAAStructTag = nullptr,
MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr);
- /// \brief Create and insert an element unordered-atomic memcpy between the
+ /// Create and insert an element unordered-atomic memcpy between the
/// specified pointers.
///
/// DstAlign/SrcAlign are the alignments of the Dst/Src pointers, respectively.
@@ -459,70 +485,95 @@ public:
MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr);
- /// \brief Create and insert a memmove between the specified
+ /// Create and insert a memmove between the specified
/// pointers.
///
/// If the pointers aren't i8*, they will be converted. If a TBAA tag is
/// specified, it will be added to the instruction. Likewise with alias.scope
/// and noalias tags.
- CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr,
- MDNode *ScopeTag = nullptr,
+ CallInst *CreateMemMove(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign,
+ uint64_t Size, bool isVolatile = false,
+ MDNode *TBAATag = nullptr, MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr) {
- return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile,
+ return CreateMemMove(Dst, DstAlign, Src, SrcAlign, getInt64(Size), isVolatile,
TBAATag, ScopeTag, NoAliasTag);
}
- CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr,
+ CallInst *CreateMemMove(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign,
+ Value *Size, bool isVolatile = false, MDNode *TBAATag = nullptr,
MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr);
- /// \brief Create a vector fadd reduction intrinsic of the source vector.
+ /// \brief Create and insert an element unordered-atomic memmove between the
+ /// specified pointers.
+ ///
+ /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers,
+ /// respectively.
+ ///
+ /// If the pointers aren't i8*, they will be converted. If a TBAA tag is
+ /// specified, it will be added to the instruction. Likewise with alias.scope
+ /// and noalias tags.
+ CallInst *CreateElementUnorderedAtomicMemMove(
+ Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign,
+ uint64_t Size, uint32_t ElementSize, MDNode *TBAATag = nullptr,
+ MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
+ return CreateElementUnorderedAtomicMemMove(
+ Dst, DstAlign, Src, SrcAlign, getInt64(Size), ElementSize, TBAATag,
+ TBAAStructTag, ScopeTag, NoAliasTag);
+ }
+
+ CallInst *CreateElementUnorderedAtomicMemMove(
+ Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, Value *Size,
+ uint32_t ElementSize, MDNode *TBAATag = nullptr,
+ MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
+
+ /// Create a vector fadd reduction intrinsic of the source vector.
/// The first parameter is a scalar accumulator value for ordered reductions.
CallInst *CreateFAddReduce(Value *Acc, Value *Src);
- /// \brief Create a vector fmul reduction intrinsic of the source vector.
+ /// Create a vector fmul reduction intrinsic of the source vector.
/// The first parameter is a scalar accumulator value for ordered reductions.
CallInst *CreateFMulReduce(Value *Acc, Value *Src);
- /// \brief Create a vector int add reduction intrinsic of the source vector.
+ /// Create a vector int add reduction intrinsic of the source vector.
CallInst *CreateAddReduce(Value *Src);
- /// \brief Create a vector int mul reduction intrinsic of the source vector.
+ /// Create a vector int mul reduction intrinsic of the source vector.
CallInst *CreateMulReduce(Value *Src);
- /// \brief Create a vector int AND reduction intrinsic of the source vector.
+ /// Create a vector int AND reduction intrinsic of the source vector.
CallInst *CreateAndReduce(Value *Src);
- /// \brief Create a vector int OR reduction intrinsic of the source vector.
+ /// Create a vector int OR reduction intrinsic of the source vector.
CallInst *CreateOrReduce(Value *Src);
- /// \brief Create a vector int XOR reduction intrinsic of the source vector.
+ /// Create a vector int XOR reduction intrinsic of the source vector.
CallInst *CreateXorReduce(Value *Src);
- /// \brief Create a vector integer max reduction intrinsic of the source
+ /// Create a vector integer max reduction intrinsic of the source
/// vector.
CallInst *CreateIntMaxReduce(Value *Src, bool IsSigned = false);
- /// \brief Create a vector integer min reduction intrinsic of the source
+ /// Create a vector integer min reduction intrinsic of the source
/// vector.
CallInst *CreateIntMinReduce(Value *Src, bool IsSigned = false);
- /// \brief Create a vector float max reduction intrinsic of the source
+ /// Create a vector float max reduction intrinsic of the source
/// vector.
CallInst *CreateFPMaxReduce(Value *Src, bool NoNaN = false);
- /// \brief Create a vector float min reduction intrinsic of the source
+ /// Create a vector float min reduction intrinsic of the source
/// vector.
CallInst *CreateFPMinReduce(Value *Src, bool NoNaN = false);
- /// \brief Create a lifetime.start intrinsic.
+ /// Create a lifetime.start intrinsic.
///
/// If the pointer isn't i8* it will be converted.
CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = nullptr);
- /// \brief Create a lifetime.end intrinsic.
+ /// Create a lifetime.end intrinsic.
///
/// If the pointer isn't i8* it will be converted.
CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr);
@@ -532,29 +583,29 @@ public:
/// If the pointer isn't i8* it will be converted.
CallInst *CreateInvariantStart(Value *Ptr, ConstantInt *Size = nullptr);
- /// \brief Create a call to Masked Load intrinsic
+ /// Create a call to Masked Load intrinsic
CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask,
Value *PassThru = nullptr, const Twine &Name = "");
- /// \brief Create a call to Masked Store intrinsic
+ /// Create a call to Masked Store intrinsic
CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align,
Value *Mask);
- /// \brief Create a call to Masked Gather intrinsic
+ /// Create a call to Masked Gather intrinsic
CallInst *CreateMaskedGather(Value *Ptrs, unsigned Align,
Value *Mask = nullptr,
Value *PassThru = nullptr,
const Twine& Name = "");
- /// \brief Create a call to Masked Scatter intrinsic
+ /// Create a call to Masked Scatter intrinsic
CallInst *CreateMaskedScatter(Value *Val, Value *Ptrs, unsigned Align,
Value *Mask = nullptr);
- /// \brief Create an assume intrinsic call that allows the optimizer to
+ /// 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
+ /// Create a call to the experimental.gc.statepoint intrinsic to
/// start a new statepoint sequence.
CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
Value *ActualCallee,
@@ -563,7 +614,7 @@ public:
ArrayRef<Value *> GCArgs,
const Twine &Name = "");
- /// \brief Create a call to the experimental.gc.statepoint intrinsic to
+ /// Create a call to the experimental.gc.statepoint intrinsic to
/// start a new statepoint sequence.
CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
Value *ActualCallee, uint32_t Flags,
@@ -573,16 +624,16 @@ public:
ArrayRef<Value *> GCArgs,
const Twine &Name = "");
- // \brief Conveninence function for the common case when CallArgs are filled
- // in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be
- // .get()'ed to get the Value pointer.
+ /// Conveninence function for the common case when CallArgs are filled
+ /// in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be
+ /// .get()'ed to get the Value pointer.
CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
Value *ActualCallee, ArrayRef<Use> CallArgs,
ArrayRef<Value *> DeoptArgs,
ArrayRef<Value *> GCArgs,
const Twine &Name = "");
- /// brief Create an invoke to the experimental.gc.statepoint intrinsic to
+ /// Create an invoke to the experimental.gc.statepoint intrinsic to
/// start a new statepoint sequence.
InvokeInst *
CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes,
@@ -591,7 +642,7 @@ public:
ArrayRef<Value *> DeoptArgs,
ArrayRef<Value *> GCArgs, const Twine &Name = "");
- /// brief Create an invoke to the experimental.gc.statepoint intrinsic to
+ /// Create an invoke to the experimental.gc.statepoint intrinsic to
/// start a new statepoint sequence.
InvokeInst *CreateGCStatepointInvoke(
uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee,
@@ -610,13 +661,13 @@ public:
ArrayRef<Value *> DeoptArgs,
ArrayRef<Value *> GCArgs, const Twine &Name = "");
- /// \brief Create a call to the experimental.gc.result intrinsic to extract
+ /// 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
+ /// 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,
@@ -630,6 +681,18 @@ public:
Value *LHS, Value *RHS,
const Twine &Name = "");
+ /// Create a call to intrinsic \p ID with no operands.
+ CallInst *CreateIntrinsic(Intrinsic::ID ID,
+ Instruction *FMFSource = nullptr,
+ const Twine &Name = "");
+
+ /// Create a call to intrinsic \p ID with 1 or more operands assuming the
+ /// intrinsic and all operands have the same type. If \p FMFSource is
+ /// provided, copy fast-math-flags from that instruction to the intrinsic.
+ CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef<Value *> Args,
+ Instruction *FMFSource = nullptr,
+ const Twine &Name = "");
+
/// Create call to the minnum intrinsic.
CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name);
@@ -637,11 +700,11 @@ public:
/// Create call to the maxnum intrinsic.
CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name);
+ return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, Name);
}
private:
- /// \brief Create a call to a masked intrinsic with given Id.
+ /// Create a call to a masked intrinsic with given Id.
CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops,
ArrayRef<Type *> OverloadedTypes,
const Twine &Name = "");
@@ -649,7 +712,7 @@ private:
Value *getCastedInt8PtrValue(Value *Ptr);
};
-/// \brief This provides a uniform API for creating instructions and inserting
+/// This provides a uniform API for creating instructions and inserting
/// them into a basic block: either at the end of a BasicBlock, or at a specific
/// iterator location in a block.
///
@@ -677,7 +740,7 @@ public:
explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None)
- : IRBuilderBase(C, FPMathTag, OpBundles), Folder() {}
+ : IRBuilderBase(C, FPMathTag, OpBundles) {}
explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None)
@@ -687,13 +750,13 @@ public:
explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None)
- : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles), Folder() {
+ : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles) {
SetInsertPoint(TheBB);
}
explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None)
- : IRBuilderBase(IP->getContext(), FPMathTag, OpBundles), Folder() {
+ : IRBuilderBase(IP->getContext(), FPMathTag, OpBundles) {
SetInsertPoint(IP);
}
@@ -707,14 +770,14 @@ public:
IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP,
MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None)
- : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles), Folder() {
+ : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles) {
SetInsertPoint(TheBB, IP);
}
- /// \brief Get the constant folder being used.
+ /// Get the constant folder being used.
const T &getFolder() { return Folder; }
- /// \brief Insert and return the specified instruction.
+ /// Insert and return the specified instruction.
template<typename InstTy>
InstTy *Insert(InstTy *I, const Twine &Name = "") const {
this->InsertHelper(I, Name, BB, InsertPt);
@@ -722,7 +785,7 @@ public:
return I;
}
- /// \brief No-op overload to handle constants.
+ /// No-op overload to handle constants.
Constant *Insert(Constant *C, const Twine& = "") const {
return C;
}
@@ -732,7 +795,7 @@ public:
//===--------------------------------------------------------------------===//
private:
- /// \brief Helper to add branch weight and unpredictable metadata onto an
+ /// Helper to add branch weight and unpredictable metadata onto an
/// instruction.
/// \returns The annotated instruction.
template <typename InstTy>
@@ -745,17 +808,17 @@ private:
}
public:
- /// \brief Create a 'ret void' instruction.
+ /// Create a 'ret void' instruction.
ReturnInst *CreateRetVoid() {
return Insert(ReturnInst::Create(Context));
}
- /// \brief Create a 'ret <val>' instruction.
+ /// Create a 'ret <val>' instruction.
ReturnInst *CreateRet(Value *V) {
return Insert(ReturnInst::Create(Context, V));
}
- /// \brief Create a sequence of N insertvalue instructions,
+ /// Create a sequence of N insertvalue instructions,
/// with one Value from the retVals array each, that build a aggregate
/// return value one value at a time, and a ret instruction to return
/// the resulting aggregate value.
@@ -769,12 +832,12 @@ public:
return Insert(ReturnInst::Create(Context, V));
}
- /// \brief Create an unconditional 'br label X' instruction.
+ /// Create an unconditional 'br label X' instruction.
BranchInst *CreateBr(BasicBlock *Dest) {
return Insert(BranchInst::Create(Dest));
}
- /// \brief Create a conditional 'br Cond, TrueDest, FalseDest'
+ /// Create a conditional 'br Cond, TrueDest, FalseDest'
/// instruction.
BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
MDNode *BranchWeights = nullptr,
@@ -783,7 +846,7 @@ public:
BranchWeights, Unpredictable));
}
- /// \brief Create a conditional 'br Cond, TrueDest, FalseDest'
+ /// Create a conditional 'br Cond, TrueDest, FalseDest'
/// instruction. Copy branch meta data if available.
BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
Instruction *MDSrc) {
@@ -796,7 +859,7 @@ public:
return Insert(Br);
}
- /// \brief Create a switch instruction with the specified value, default dest,
+ /// Create a switch instruction with the specified value, default dest,
/// and with a hint for the number of cases that will be added (for efficient
/// allocation).
SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10,
@@ -806,14 +869,14 @@ public:
BranchWeights, Unpredictable));
}
- /// \brief Create an indirect branch instruction with the specified address
+ /// Create an indirect branch instruction with the specified address
/// operand, with an optional hint for the number of destinations that will be
/// added (for efficient allocation).
IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) {
return Insert(IndirectBrInst::Create(Addr, NumDests));
}
- /// \brief Create an invoke instruction.
+ /// Create an invoke instruction.
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
BasicBlock *UnwindDest,
ArrayRef<Value *> Args = None,
@@ -878,150 +941,128 @@ private:
return BO;
}
- Instruction *AddFPMathAttributes(Instruction *I,
- MDNode *FPMathTag,
- FastMathFlags FMF) const {
- if (!FPMathTag)
- FPMathTag = DefaultFPMathTag;
- if (FPMathTag)
- I->setMetadata(LLVMContext::MD_fpmath, FPMathTag);
+ Instruction *setFPAttrs(Instruction *I, MDNode *FPMD,
+ FastMathFlags FMF) const {
+ if (!FPMD)
+ FPMD = DefaultFPMathTag;
+ if (FPMD)
+ I->setMetadata(LLVMContext::MD_fpmath, FPMD);
I->setFastMathFlags(FMF);
return I;
}
+ Value *foldConstant(Instruction::BinaryOps Opc, Value *L,
+ Value *R, const Twine &Name = nullptr) const {
+ auto *LC = dyn_cast<Constant>(L);
+ auto *RC = dyn_cast<Constant>(R);
+ return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr;
+ }
+
public:
Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name);
return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name,
HasNUW, HasNSW);
}
+
Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateAdd(LHS, RHS, Name, false, true);
}
+
Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateAdd(LHS, RHS, Name, true, false);
}
- Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFAdd(LC, RC), Name);
- return Insert(AddFPMathAttributes(BinaryOperator::CreateFAdd(LHS, RHS),
- FPMathTag, FMF), Name);
- }
+
Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateSub(LC, RC, HasNUW, HasNSW), Name);
return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name,
HasNUW, HasNSW);
}
+
Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateSub(LHS, RHS, Name, false, true);
}
+
Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateSub(LHS, RHS, Name, true, false);
}
- Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFSub(LC, RC), Name);
- return Insert(AddFPMathAttributes(BinaryOperator::CreateFSub(LHS, RHS),
- FPMathTag, FMF), Name);
- }
+
Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateMul(LC, RC, HasNUW, HasNSW), Name);
return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name,
HasNUW, HasNSW);
}
+
Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateMul(LHS, RHS, Name, false, true);
}
+
Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateMul(LHS, RHS, Name, true, false);
}
- Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFMul(LC, RC), Name);
- return Insert(AddFPMathAttributes(BinaryOperator::CreateFMul(LHS, RHS),
- FPMathTag, FMF), Name);
- }
+
Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "",
bool isExact = false) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateUDiv(LC, RC, isExact), Name);
if (!isExact)
return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name);
return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name);
}
+
Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateUDiv(LHS, RHS, Name, true);
}
+
Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "",
bool isExact = false) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateSDiv(LC, RC, isExact), Name);
if (!isExact)
return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name);
return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name);
}
+
Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateSDiv(LHS, RHS, Name, true);
}
- Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFDiv(LC, RC), Name);
- return Insert(AddFPMathAttributes(BinaryOperator::CreateFDiv(LHS, RHS),
- FPMathTag, FMF), Name);
- }
+
Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateURem(LC, RC), Name);
+ if (Value *V = foldConstant(Instruction::URem, LHS, RHS, Name)) return V;
return Insert(BinaryOperator::CreateURem(LHS, RHS), Name);
}
+
Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateSRem(LC, RC), Name);
+ if (Value *V = foldConstant(Instruction::SRem, LHS, RHS, Name)) return V;
return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name);
}
- Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateFRem(LC, RC), Name);
- return Insert(AddFPMathAttributes(BinaryOperator::CreateFRem(LHS, RHS),
- FPMathTag, FMF), Name);
- }
Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name);
return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name,
HasNUW, HasNSW);
}
+
Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name,
HasNUW, HasNSW);
}
+
Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name,
@@ -1030,17 +1071,19 @@ public:
Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "",
bool isExact = false) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateLShr(LC, RC, isExact), Name);
if (!isExact)
return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name);
return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name);
}
+
Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
bool isExact = false) {
return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
}
+
Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
bool isExact = false) {
return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
@@ -1048,103 +1091,196 @@ public:
Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "",
bool isExact = false) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateAShr(LC, RC, isExact), Name);
if (!isExact)
return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name);
return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name);
}
+
Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
bool isExact = false) {
return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
}
+
Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
bool isExact = false) {
return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
}
Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") {
- if (Constant *RC = dyn_cast<Constant>(RHS)) {
+ if (auto *RC = dyn_cast<Constant>(RHS)) {
if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isMinusOne())
return LHS; // LHS & -1 -> LHS
- if (Constant *LC = dyn_cast<Constant>(LHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
return Insert(Folder.CreateAnd(LC, RC), Name);
}
return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name);
}
+
Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") {
return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
}
+
Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") {
return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
}
Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") {
- if (Constant *RC = dyn_cast<Constant>(RHS)) {
+ if (auto *RC = dyn_cast<Constant>(RHS)) {
if (RC->isNullValue())
return LHS; // LHS | 0 -> LHS
- if (Constant *LC = dyn_cast<Constant>(LHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
return Insert(Folder.CreateOr(LC, RC), Name);
}
return Insert(BinaryOperator::CreateOr(LHS, RHS), Name);
}
+
Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") {
return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
}
+
Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
}
Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateXor(LC, RC), Name);
+ if (Value *V = foldConstant(Instruction::Xor, LHS, RHS, Name)) return V;
return Insert(BinaryOperator::CreateXor(LHS, RHS), Name);
}
+
Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") {
return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
}
+
Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") {
return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
}
+ Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "",
+ MDNode *FPMD = nullptr) {
+ if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF);
+ return Insert(I, Name);
+ }
+
+ /// Copy fast-math-flags from an instruction rather than using the builder's
+ /// default FMF.
+ Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource,
+ const Twine &Name = "") {
+ if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr,
+ FMFSource->getFastMathFlags());
+ return Insert(I, Name);
+ }
+
+ Value *CreateFSub(Value *L, Value *R, const Twine &Name = "",
+ MDNode *FPMD = nullptr) {
+ if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF);
+ return Insert(I, Name);
+ }
+
+ /// Copy fast-math-flags from an instruction rather than using the builder's
+ /// default FMF.
+ Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource,
+ const Twine &Name = "") {
+ if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr,
+ FMFSource->getFastMathFlags());
+ return Insert(I, Name);
+ }
+
+ Value *CreateFMul(Value *L, Value *R, const Twine &Name = "",
+ MDNode *FPMD = nullptr) {
+ if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF);
+ return Insert(I, Name);
+ }
+
+ /// Copy fast-math-flags from an instruction rather than using the builder's
+ /// default FMF.
+ Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource,
+ const Twine &Name = "") {
+ if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr,
+ FMFSource->getFastMathFlags());
+ return Insert(I, Name);
+ }
+
+ Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "",
+ MDNode *FPMD = nullptr) {
+ if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF);
+ return Insert(I, Name);
+ }
+
+ /// Copy fast-math-flags from an instruction rather than using the builder's
+ /// default FMF.
+ Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource,
+ const Twine &Name = "") {
+ if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr,
+ FMFSource->getFastMathFlags());
+ return Insert(I, Name);
+ }
+
+ Value *CreateFRem(Value *L, Value *R, const Twine &Name = "",
+ MDNode *FPMD = nullptr) {
+ if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF);
+ return Insert(I, Name);
+ }
+
+ /// Copy fast-math-flags from an instruction rather than using the builder's
+ /// default FMF.
+ Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource,
+ const Twine &Name = "") {
+ if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V;
+ Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr,
+ FMFSource->getFastMathFlags());
+ return Insert(I, Name);
+ }
+
Value *CreateBinOp(Instruction::BinaryOps Opc,
Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateBinOp(Opc, LC, RC), Name);
+ if (Value *V = foldConstant(Opc, LHS, RHS, Name)) return V;
Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS);
if (isa<FPMathOperator>(BinOp))
- BinOp = AddFPMathAttributes(BinOp, FPMathTag, FMF);
+ BinOp = setFPAttrs(BinOp, FPMathTag, FMF);
return Insert(BinOp, Name);
}
Value *CreateNeg(Value *V, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name);
BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name);
if (HasNUW) BO->setHasNoUnsignedWrap();
if (HasNSW) BO->setHasNoSignedWrap();
return BO;
}
+
Value *CreateNSWNeg(Value *V, const Twine &Name = "") {
return CreateNeg(V, Name, false, true);
}
+
Value *CreateNUWNeg(Value *V, const Twine &Name = "") {
return CreateNeg(V, Name, true, false);
}
+
Value *CreateFNeg(Value *V, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateFNeg(VC), Name);
- return Insert(AddFPMathAttributes(BinaryOperator::CreateFNeg(V),
- FPMathTag, FMF), Name);
+ return Insert(setFPAttrs(BinaryOperator::CreateFNeg(V), FPMathTag, FMF),
+ Name);
}
+
Value *CreateNot(Value *V, const Twine &Name = "") {
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateNot(VC), Name);
return Insert(BinaryOperator::CreateNot(V), Name);
}
@@ -1163,26 +1299,32 @@ public:
const DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
return Insert(new AllocaInst(Ty, DL.getAllocaAddrSpace(), ArraySize), Name);
}
- // \brief Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of
- // converting the string to 'bool' for the isVolatile parameter.
+
+ /// Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of
+ /// converting the string to 'bool' for the isVolatile parameter.
LoadInst *CreateLoad(Value *Ptr, const char *Name) {
return Insert(new LoadInst(Ptr), Name);
}
+
LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") {
return Insert(new LoadInst(Ptr), Name);
}
+
LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") {
return Insert(new LoadInst(Ty, Ptr), Name);
}
+
LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") {
return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name);
}
+
StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) {
return Insert(new StoreInst(Val, Ptr, isVolatile));
}
- // \brief Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")'
- // correctly, instead of converting the string to 'bool' for the isVolatile
- // parameter.
+
+ /// Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")'
+ /// correctly, instead of converting the string to 'bool' for the isVolatile
+ /// parameter.
LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, const char *Name) {
LoadInst *LI = CreateLoad(Ptr, Name);
LI->setAlignment(Align);
@@ -1200,17 +1342,20 @@ public:
LI->setAlignment(Align);
return LI;
}
+
StoreInst *CreateAlignedStore(Value *Val, Value *Ptr, unsigned Align,
bool isVolatile = false) {
StoreInst *SI = CreateStore(Val, Ptr, isVolatile);
SI->setAlignment(Align);
return SI;
}
+
FenceInst *CreateFence(AtomicOrdering Ordering,
SyncScope::ID SSID = SyncScope::System,
const Twine &Name = "") {
return Insert(new FenceInst(Context, Ordering, SSID), Name);
}
+
AtomicCmpXchgInst *
CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New,
AtomicOrdering SuccessOrdering,
@@ -1219,18 +1364,21 @@ public:
return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering,
FailureOrdering, SSID));
}
+
AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val,
AtomicOrdering Ordering,
SyncScope::ID SSID = SyncScope::System) {
return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SSID));
}
+
Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
return CreateGEP(nullptr, Ptr, IdxList, Name);
}
+
Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
- if (Constant *PC = dyn_cast<Constant>(Ptr)) {
+ if (auto *PC = dyn_cast<Constant>(Ptr)) {
// Every index must be constant.
size_t i, e;
for (i = 0, e = IdxList.size(); i != e; ++i)
@@ -1241,13 +1389,15 @@ public:
}
return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name);
}
+
Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
return CreateInBoundsGEP(nullptr, Ptr, IdxList, Name);
}
+
Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
- if (Constant *PC = dyn_cast<Constant>(Ptr)) {
+ if (auto *PC = dyn_cast<Constant>(Ptr)) {
// Every index must be constant.
size_t i, e;
for (i = 0, e = IdxList.size(); i != e; ++i)
@@ -1259,43 +1409,50 @@ public:
}
return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name);
}
+
Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") {
return CreateGEP(nullptr, Ptr, Idx, Name);
}
+
Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") {
- if (Constant *PC = dyn_cast<Constant>(Ptr))
- if (Constant *IC = dyn_cast<Constant>(Idx))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
+ if (auto *IC = dyn_cast<Constant>(Idx))
return Insert(Folder.CreateGetElementPtr(Ty, PC, IC), Name);
return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name);
}
+
Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx,
const Twine &Name = "") {
- if (Constant *PC = dyn_cast<Constant>(Ptr))
- if (Constant *IC = dyn_cast<Constant>(Idx))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
+ if (auto *IC = dyn_cast<Constant>(Idx))
return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IC), Name);
return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name);
}
+
Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") {
return CreateConstGEP1_32(nullptr, Ptr, Idx0, Name);
}
+
Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,
const Twine &Name = "") {
Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0);
- if (Constant *PC = dyn_cast<Constant>(Ptr))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
return Insert(Folder.CreateGetElementPtr(Ty, PC, Idx), Name);
return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name);
}
+
Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,
const Twine &Name = "") {
Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0);
- if (Constant *PC = dyn_cast<Constant>(Ptr))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idx), Name);
return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name);
}
+
Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1,
const Twine &Name = "") {
Value *Idxs[] = {
@@ -1303,11 +1460,12 @@ public:
ConstantInt::get(Type::getInt32Ty(Context), Idx1)
};
- if (Constant *PC = dyn_cast<Constant>(Ptr))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
return Insert(Folder.CreateGetElementPtr(Ty, PC, Idxs), Name);
return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name);
}
+
Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0,
unsigned Idx1, const Twine &Name = "") {
Value *Idxs[] = {
@@ -1315,28 +1473,31 @@ public:
ConstantInt::get(Type::getInt32Ty(Context), Idx1)
};
- if (Constant *PC = dyn_cast<Constant>(Ptr))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idxs), Name);
return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name);
}
+
Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") {
Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0);
- if (Constant *PC = dyn_cast<Constant>(Ptr))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idx), Name);
return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name);
}
+
Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0,
const Twine &Name = "") {
Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0);
- if (Constant *PC = dyn_cast<Constant>(Ptr))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idx), Name);
return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name);
}
+
Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1,
const Twine &Name = "") {
Value *Idxs[] = {
@@ -1344,11 +1505,12 @@ public:
ConstantInt::get(Type::getInt64Ty(Context), Idx1)
};
- if (Constant *PC = dyn_cast<Constant>(Ptr))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idxs), Name);
return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name);
}
+
Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1,
const Twine &Name = "") {
Value *Idxs[] = {
@@ -1356,25 +1518,31 @@ public:
ConstantInt::get(Type::getInt64Ty(Context), Idx1)
};
- if (Constant *PC = dyn_cast<Constant>(Ptr))
+ if (auto *PC = dyn_cast<Constant>(Ptr))
return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idxs),
Name);
return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name);
}
+
Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx,
const Twine &Name = "") {
return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name);
}
- /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type
+ Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") {
+ return CreateConstInBoundsGEP2_32(nullptr, Ptr, 0, Idx, Name);
+ }
+
+ /// Same as CreateGlobalString, but return a pointer with "i8*" type
/// instead of a pointer to array of i8.
- Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "",
- unsigned AddressSpace = 0) {
- GlobalVariable *gv = CreateGlobalString(Str, Name, AddressSpace);
- Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0);
- Value *Args[] = { zero, zero };
- return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name);
+ Constant *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "",
+ unsigned AddressSpace = 0) {
+ GlobalVariable *GV = CreateGlobalString(Str, Name, AddressSpace);
+ Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0);
+ Constant *Indices[] = {Zero, Zero};
+ return ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV,
+ Indices);
}
//===--------------------------------------------------------------------===//
@@ -1384,13 +1552,16 @@ public:
Value *CreateTrunc(Value *V, Type *DestTy, const Twine &Name = "") {
return CreateCast(Instruction::Trunc, V, DestTy, Name);
}
+
Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "") {
return CreateCast(Instruction::ZExt, V, DestTy, Name);
}
+
Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") {
return CreateCast(Instruction::SExt, V, DestTy, Name);
}
- /// \brief Create a ZExt or Trunc from the integer value V to DestTy. Return
+
+ /// Create a ZExt or Trunc from the integer value V to DestTy. Return
/// the value untouched if the type of V is already DestTy.
Value *CreateZExtOrTrunc(Value *V, Type *DestTy,
const Twine &Name = "") {
@@ -1404,7 +1575,8 @@ public:
return CreateTrunc(V, DestTy, Name);
return V;
}
- /// \brief Create a SExt or Trunc from the integer value V to DestTy. Return
+
+ /// Create a SExt or Trunc from the integer value V to DestTy. Return
/// the value untouched if the type of V is already DestTy.
Value *CreateSExtOrTrunc(Value *V, Type *DestTy,
const Twine &Name = "") {
@@ -1418,78 +1590,93 @@ public:
return CreateTrunc(V, DestTy, Name);
return V;
}
+
Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = ""){
return CreateCast(Instruction::FPToUI, V, DestTy, Name);
}
+
Value *CreateFPToSI(Value *V, Type *DestTy, const Twine &Name = ""){
return CreateCast(Instruction::FPToSI, V, DestTy, Name);
}
+
Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
return CreateCast(Instruction::UIToFP, V, DestTy, Name);
}
+
Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
return CreateCast(Instruction::SIToFP, V, DestTy, Name);
}
+
Value *CreateFPTrunc(Value *V, Type *DestTy,
const Twine &Name = "") {
return CreateCast(Instruction::FPTrunc, V, DestTy, Name);
}
+
Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") {
return CreateCast(Instruction::FPExt, V, DestTy, Name);
}
+
Value *CreatePtrToInt(Value *V, Type *DestTy,
const Twine &Name = "") {
return CreateCast(Instruction::PtrToInt, V, DestTy, Name);
}
+
Value *CreateIntToPtr(Value *V, Type *DestTy,
const Twine &Name = "") {
return CreateCast(Instruction::IntToPtr, V, DestTy, Name);
}
+
Value *CreateBitCast(Value *V, Type *DestTy,
const Twine &Name = "") {
return CreateCast(Instruction::BitCast, V, DestTy, Name);
}
+
Value *CreateAddrSpaceCast(Value *V, Type *DestTy,
const Twine &Name = "") {
return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name);
}
+
Value *CreateZExtOrBitCast(Value *V, Type *DestTy,
const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name);
return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name);
}
+
Value *CreateSExtOrBitCast(Value *V, Type *DestTy,
const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name);
return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name);
}
+
Value *CreateTruncOrBitCast(Value *V, Type *DestTy,
const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name);
return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name);
}
+
Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy,
const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateCast(Op, VC, DestTy), Name);
return Insert(CastInst::Create(Op, V, DestTy), Name);
}
+
Value *CreatePointerCast(Value *V, Type *DestTy,
const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreatePointerCast(VC, DestTy), Name);
return Insert(CastInst::CreatePointerCast(V, DestTy), Name);
}
@@ -1499,7 +1686,7 @@ public:
if (V->getType() == DestTy)
return V;
- if (Constant *VC = dyn_cast<Constant>(V)) {
+ if (auto *VC = dyn_cast<Constant>(V)) {
return Insert(Folder.CreatePointerBitCastOrAddrSpaceCast(VC, DestTy),
Name);
}
@@ -1512,7 +1699,7 @@ public:
const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name);
return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name);
}
@@ -1529,16 +1716,15 @@ public:
return CreateBitCast(V, DestTy, Name);
}
-public:
Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
- if (Constant *VC = dyn_cast<Constant>(V))
+ if (auto *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateFPCast(VC, DestTy), Name);
return Insert(CastInst::CreateFPCast(V, DestTy), Name);
}
- // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
+ // 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 *) = delete;
@@ -1550,30 +1736,39 @@ public:
Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name);
}
+
Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name);
}
+
Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name);
}
+
Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name);
}
+
Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name);
}
+
Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name);
}
+
Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name);
}
+
Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name);
}
+
Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name);
}
+
Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") {
return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name);
}
@@ -1582,54 +1777,67 @@ public:
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag);
}
+
Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag);
@@ -1637,18 +1845,18 @@ public:
Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS,
const Twine &Name = "") {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateICmp(P, LC, RC), Name);
return Insert(new ICmpInst(P, LHS, RHS), Name);
}
+
Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS,
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
- if (Constant *LC = dyn_cast<Constant>(LHS))
- if (Constant *RC = dyn_cast<Constant>(RHS))
+ if (auto *LC = dyn_cast<Constant>(LHS))
+ if (auto *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateFCmp(P, LC, RC), Name);
- return Insert(AddFPMathAttributes(new FCmpInst(P, LHS, RHS),
- FPMathTag, FMF), Name);
+ return Insert(setFPAttrs(new FCmpInst(P, LHS, RHS), FPMathTag, FMF), Name);
}
//===--------------------------------------------------------------------===//
@@ -1662,8 +1870,8 @@ public:
CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args = None,
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
- PointerType *PTy = cast<PointerType>(Callee->getType());
- FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ auto *PTy = cast<PointerType>(Callee->getType());
+ auto *FTy = cast<FunctionType>(PTy->getElementType());
return CreateCall(FTy, Callee, Args, Name, FPMathTag);
}
@@ -1672,7 +1880,7 @@ public:
MDNode *FPMathTag = nullptr) {
CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
if (isa<FPMathOperator>(CI))
- CI = cast<CallInst>(AddFPMathAttributes(CI, FPMathTag, FMF));
+ CI = cast<CallInst>(setFPAttrs(CI, FPMathTag, FMF));
return Insert(CI, Name);
}
@@ -1681,7 +1889,7 @@ public:
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
CallInst *CI = CallInst::Create(Callee, Args, OpBundles);
if (isa<FPMathOperator>(CI))
- CI = cast<CallInst>(AddFPMathAttributes(CI, FPMathTag, FMF));
+ CI = cast<CallInst>(setFPAttrs(CI, FPMathTag, FMF));
return Insert(CI, Name);
}
@@ -1692,9 +1900,9 @@ public:
Value *CreateSelect(Value *C, Value *True, Value *False,
const Twine &Name = "", Instruction *MDFrom = nullptr) {
- if (Constant *CC = dyn_cast<Constant>(C))
- if (Constant *TC = dyn_cast<Constant>(True))
- if (Constant *FC = dyn_cast<Constant>(False))
+ if (auto *CC = dyn_cast<Constant>(C))
+ if (auto *TC = dyn_cast<Constant>(True))
+ if (auto *FC = dyn_cast<Constant>(False))
return Insert(Folder.CreateSelect(CC, TC, FC), Name);
SelectInst *Sel = SelectInst::Create(C, True, False);
@@ -1712,8 +1920,8 @@ public:
Value *CreateExtractElement(Value *Vec, Value *Idx,
const Twine &Name = "") {
- if (Constant *VC = dyn_cast<Constant>(Vec))
- if (Constant *IC = dyn_cast<Constant>(Idx))
+ if (auto *VC = dyn_cast<Constant>(Vec))
+ if (auto *IC = dyn_cast<Constant>(Idx))
return Insert(Folder.CreateExtractElement(VC, IC), Name);
return Insert(ExtractElementInst::Create(Vec, Idx), Name);
}
@@ -1725,9 +1933,9 @@ public:
Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx,
const Twine &Name = "") {
- if (Constant *VC = dyn_cast<Constant>(Vec))
- if (Constant *NC = dyn_cast<Constant>(NewElt))
- if (Constant *IC = dyn_cast<Constant>(Idx))
+ if (auto *VC = dyn_cast<Constant>(Vec))
+ if (auto *NC = dyn_cast<Constant>(NewElt))
+ if (auto *IC = dyn_cast<Constant>(Idx))
return Insert(Folder.CreateInsertElement(VC, NC, IC), Name);
return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name);
}
@@ -1739,9 +1947,9 @@ public:
Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask,
const Twine &Name = "") {
- if (Constant *V1C = dyn_cast<Constant>(V1))
- if (Constant *V2C = dyn_cast<Constant>(V2))
- if (Constant *MC = dyn_cast<Constant>(Mask))
+ if (auto *V1C = dyn_cast<Constant>(V1))
+ if (auto *V2C = dyn_cast<Constant>(V2))
+ if (auto *MC = dyn_cast<Constant>(Mask))
return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name);
return Insert(new ShuffleVectorInst(V1, V2, Mask), Name);
}
@@ -1755,7 +1963,7 @@ public:
Value *CreateExtractValue(Value *Agg,
ArrayRef<unsigned> Idxs,
const Twine &Name = "") {
- if (Constant *AggC = dyn_cast<Constant>(Agg))
+ if (auto *AggC = dyn_cast<Constant>(Agg))
return Insert(Folder.CreateExtractValue(AggC, Idxs), Name);
return Insert(ExtractValueInst::Create(Agg, Idxs), Name);
}
@@ -1763,8 +1971,8 @@ public:
Value *CreateInsertValue(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs,
const Twine &Name = "") {
- if (Constant *AggC = dyn_cast<Constant>(Agg))
- if (Constant *ValC = dyn_cast<Constant>(Val))
+ if (auto *AggC = dyn_cast<Constant>(Agg))
+ if (auto *ValC = dyn_cast<Constant>(Val))
return Insert(Folder.CreateInsertValue(AggC, ValC, Idxs), Name);
return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name);
}
@@ -1778,19 +1986,19 @@ public:
// Utility creation methods
//===--------------------------------------------------------------------===//
- /// \brief Return an i1 value testing if \p Arg is null.
+ /// Return an i1 value testing if \p Arg is null.
Value *CreateIsNull(Value *Arg, const Twine &Name = "") {
return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()),
Name);
}
- /// \brief Return an i1 value testing if \p Arg is not null.
+ /// Return an i1 value testing if \p Arg is not null.
Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") {
return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()),
Name);
}
- /// \brief Return the i64 difference between two pointer values, dividing out
+ /// Return the i64 difference between two pointer values, dividing out
/// the size of the pointed-to objects.
///
/// This is intended to implement C-style pointer subtraction. As such, the
@@ -1799,7 +2007,7 @@ public:
Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") {
assert(LHS->getType() == RHS->getType() &&
"Pointer subtraction operand types must match!");
- PointerType *ArgType = cast<PointerType>(LHS->getType());
+ auto *ArgType = cast<PointerType>(LHS->getType());
Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context));
Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context));
Value *Difference = CreateSub(LHS_int, RHS_int);
@@ -1808,35 +2016,62 @@ public:
Name);
}
- /// \brief Create an invariant.group.barrier intrinsic call, that stops
- /// optimizer to propagate equality using invariant.group metadata.
- /// If Ptr type is different from pointer to i8, it's casted to pointer to i8
- /// in the same address space before call and casted back to Ptr type after
- /// call.
- Value *CreateInvariantGroupBarrier(Value *Ptr) {
+ /// Create a launder.invariant.group intrinsic call. If Ptr type is
+ /// different from pointer to i8, it's casted to pointer to i8 in the same
+ /// address space before call and casted back to Ptr type after call.
+ Value *CreateLaunderInvariantGroup(Value *Ptr) {
assert(isa<PointerType>(Ptr->getType()) &&
- "invariant.group.barrier only applies to pointers.");
+ "launder.invariant.group only applies to pointers.");
+ // FIXME: we could potentially avoid casts to/from i8*.
auto *PtrType = Ptr->getType();
auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace());
if (PtrType != Int8PtrTy)
Ptr = CreateBitCast(Ptr, Int8PtrTy);
Module *M = BB->getParent()->getParent();
- Function *FnInvariantGroupBarrier = Intrinsic::getDeclaration(
- M, Intrinsic::invariant_group_barrier, {Int8PtrTy});
+ Function *FnLaunderInvariantGroup = Intrinsic::getDeclaration(
+ M, Intrinsic::launder_invariant_group, {Int8PtrTy});
- assert(FnInvariantGroupBarrier->getReturnType() == Int8PtrTy &&
- FnInvariantGroupBarrier->getFunctionType()->getParamType(0) ==
+ assert(FnLaunderInvariantGroup->getReturnType() == Int8PtrTy &&
+ FnLaunderInvariantGroup->getFunctionType()->getParamType(0) ==
Int8PtrTy &&
- "InvariantGroupBarrier should take and return the same type");
+ "LaunderInvariantGroup should take and return the same type");
- CallInst *Fn = CreateCall(FnInvariantGroupBarrier, {Ptr});
+ CallInst *Fn = CreateCall(FnLaunderInvariantGroup, {Ptr});
if (PtrType != Int8PtrTy)
return CreateBitCast(Fn, PtrType);
return Fn;
}
- /// \brief Return a vector value that contains \arg V broadcasted to \p
+ /// \brief Create a strip.invariant.group intrinsic call. If Ptr type is
+ /// different from pointer to i8, it's casted to pointer to i8 in the same
+ /// address space before call and casted back to Ptr type after call.
+ Value *CreateStripInvariantGroup(Value *Ptr) {
+ assert(isa<PointerType>(Ptr->getType()) &&
+ "strip.invariant.group only applies to pointers.");
+
+ // FIXME: we could potentially avoid casts to/from i8*.
+ auto *PtrType = Ptr->getType();
+ auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace());
+ if (PtrType != Int8PtrTy)
+ Ptr = CreateBitCast(Ptr, Int8PtrTy);
+ Module *M = BB->getParent()->getParent();
+ Function *FnStripInvariantGroup = Intrinsic::getDeclaration(
+ M, Intrinsic::strip_invariant_group, {Int8PtrTy});
+
+ assert(FnStripInvariantGroup->getReturnType() == Int8PtrTy &&
+ FnStripInvariantGroup->getFunctionType()->getParamType(0) ==
+ Int8PtrTy &&
+ "StripInvariantGroup should take and return the same type");
+
+ CallInst *Fn = CreateCall(FnStripInvariantGroup, {Ptr});
+
+ if (PtrType != Int8PtrTy)
+ return CreateBitCast(Fn, PtrType);
+ return Fn;
+ }
+
+ /// Return a vector value that contains \arg V broadcasted to \p
/// NumElts elements.
Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "") {
assert(NumElts > 0 && "Cannot splat to an empty vector!");
@@ -1852,11 +2087,11 @@ public:
return CreateShuffleVector(V, Undef, Zeros, Name + ".splat");
}
- /// \brief Return a value that has been extracted from a larger integer type.
+ /// Return a value that has been extracted from a larger integer type.
Value *CreateExtractInteger(const DataLayout &DL, Value *From,
IntegerType *ExtractedTy, uint64_t Offset,
const Twine &Name) {
- IntegerType *IntTy = cast<IntegerType>(From->getType());
+ auto *IntTy = cast<IntegerType>(From->getType());
assert(DL.getTypeStoreSize(ExtractedTy) + Offset <=
DL.getTypeStoreSize(IntTy) &&
"Element extends past full value");
@@ -1877,7 +2112,7 @@ public:
}
private:
- /// \brief Helper function that creates an assume intrinsic call that
+ /// Helper function that creates an assume intrinsic call that
/// represents an alignment assumption on the provided Ptr, Mask, Type
/// and Offset.
CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL,
@@ -1888,7 +2123,7 @@ private:
if (OffsetValue) {
bool IsOffsetZero = false;
- if (ConstantInt *CI = dyn_cast<ConstantInt>(OffsetValue))
+ if (const auto *CI = dyn_cast<ConstantInt>(OffsetValue))
IsOffsetZero = CI->isZero();
if (!IsOffsetZero) {
@@ -1906,7 +2141,7 @@ private:
}
public:
- /// \brief Create an assume intrinsic call that represents an alignment
+ /// Create an assume intrinsic call that represents an alignment
/// assumption on the provided pointer.
///
/// An optional offset can be provided, and if it is provided, the offset
@@ -1917,15 +2152,15 @@ public:
Value *OffsetValue = nullptr) {
assert(isa<PointerType>(PtrValue->getType()) &&
"trying to create an alignment assumption on a non-pointer?");
- PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
+ auto *PtrTy = cast<PointerType>(PtrValue->getType());
Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
Value *Mask = ConstantInt::get(IntPtrTy, Alignment > 0 ? Alignment - 1 : 0);
return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy,
OffsetValue);
}
- //
- /// \brief Create an assume intrinsic call that represents an alignment
+
+ /// Create an assume intrinsic call that represents an alignment
/// assumption on the provided pointer.
///
/// An optional offset can be provided, and if it is provided, the offset
@@ -1939,7 +2174,7 @@ public:
Value *OffsetValue = nullptr) {
assert(isa<PointerType>(PtrValue->getType()) &&
"trying to create an alignment assumption on a non-pointer?");
- PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
+ auto *PtrTy = cast<PointerType>(PtrValue->getType());
Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
if (Alignment->getType() != IntPtrTy)
diff --git a/contrib/llvm/include/llvm/IR/IRPrintingPasses.h b/contrib/llvm/include/llvm/IR/IRPrintingPasses.h
index 0825e0696cac..e4ac5d4d88a3 100644
--- a/contrib/llvm/include/llvm/IR/IRPrintingPasses.h
+++ b/contrib/llvm/include/llvm/IR/IRPrintingPasses.h
@@ -23,6 +23,7 @@
#include <string>
namespace llvm {
+class Pass;
class BasicBlockPass;
class Function;
class FunctionPass;
@@ -32,18 +33,18 @@ class PreservedAnalyses;
class raw_ostream;
template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
-/// \brief Create and return a pass that writes the module to the specified
+/// Create and return a pass that writes the module to the specified
/// \c raw_ostream.
ModulePass *createPrintModulePass(raw_ostream &OS,
const std::string &Banner = "",
bool ShouldPreserveUseListOrder = false);
-/// \brief Create and return a pass that prints functions to the specified
+/// Create and return a pass that prints functions to the specified
/// \c raw_ostream as they are processed.
FunctionPass *createPrintFunctionPass(raw_ostream &OS,
const std::string &Banner = "");
-/// \brief Create and return a pass that writes the BB to the specified
+/// Create and return a pass that writes the BB to the specified
/// \c raw_ostream.
BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS,
const std::string &Banner = "");
@@ -54,7 +55,10 @@ BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS,
/// non-printable characters in it.
void printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name);
-/// \brief Pass for printing a Module as LLVM's text IR assembly.
+/// Return true if a pass is for IR printing.
+bool isIRPrintingPass(Pass *P);
+
+/// Pass for printing a Module as LLVM's text IR assembly.
///
/// Note: This pass is for use with the new pass manager. Use the create...Pass
/// functions above to create passes for use with the legacy pass manager.
@@ -73,7 +77,7 @@ public:
static StringRef name() { return "PrintModulePass"; }
};
-/// \brief Pass for printing a Function as LLVM's text IR assembly.
+/// Pass for printing a Function as LLVM's text IR assembly.
///
/// Note: This pass is for use with the new pass manager. Use the create...Pass
/// functions above to create passes for use with the legacy pass manager.
diff --git a/contrib/llvm/include/llvm/IR/InstVisitor.h b/contrib/llvm/include/llvm/IR/InstVisitor.h
index 55579819fd34..65074025a083 100644
--- a/contrib/llvm/include/llvm/IR/InstVisitor.h
+++ b/contrib/llvm/include/llvm/IR/InstVisitor.h
@@ -32,7 +32,7 @@ namespace llvm {
visit##CLASS_TO_VISIT(static_cast<CLASS_TO_VISIT&>(I))
-/// @brief Base class for instruction visitors
+/// Base class for instruction visitors
///
/// Instruction visitors are used when you want to perform different actions
/// for different kinds of instructions without having to use lots of casts
@@ -213,6 +213,7 @@ public:
// Handle the special instrinsic instruction classes.
RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);}
RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgInfoIntrinsic);}
+ RetTy visitDbgLabelInst(DbgLabelInst &I) { DELEGATE(DbgInfoIntrinsic);}
RetTy visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { DELEGATE(IntrinsicInst); }
RetTy visitMemSetInst(MemSetInst &I) { DELEGATE(MemIntrinsic); }
RetTy visitMemCpyInst(MemCpyInst &I) { DELEGATE(MemTransferInst); }
@@ -272,6 +273,7 @@ private:
default: DELEGATE(IntrinsicInst);
case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst);
case Intrinsic::dbg_value: DELEGATE(DbgValueInst);
+ case Intrinsic::dbg_label: DELEGATE(DbgLabelInst);
case Intrinsic::memcpy: DELEGATE(MemCpyInst);
case Intrinsic::memmove: DELEGATE(MemMoveInst);
case Intrinsic::memset: DELEGATE(MemSetInst);
diff --git a/contrib/llvm/include/llvm/IR/InstrTypes.h b/contrib/llvm/include/llvm/IR/InstrTypes.h
index 871f702f95f2..ad0012048ac9 100644
--- a/contrib/llvm/include/llvm/IR/InstrTypes.h
+++ b/contrib/llvm/include/llvm/IR/InstrTypes.h
@@ -25,6 +25,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
@@ -80,7 +81,7 @@ public:
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
- // \brief Returns true if this terminator relates to exception handling.
+ // Returns true if this terminator relates to exception handling.
bool isExceptional() const {
switch (getOpcode()) {
case Instruction::CatchSwitch:
@@ -117,7 +118,7 @@ public:
return idx < TermInst->getNumSuccessors();
}
- /// \brief Proxy object to allow write access in operator[]
+ /// Proxy object to allow write access in operator[]
class SuccessorProxy {
Self it;
@@ -391,6 +392,37 @@ public:
return BO;
}
+ static BinaryOperator *CreateFAddFMF(Value *V1, Value *V2,
+ BinaryOperator *FMFSource,
+ const Twine &Name = "") {
+ return CreateWithCopiedFlags(Instruction::FAdd, V1, V2, FMFSource, Name);
+ }
+ static BinaryOperator *CreateFSubFMF(Value *V1, Value *V2,
+ BinaryOperator *FMFSource,
+ const Twine &Name = "") {
+ return CreateWithCopiedFlags(Instruction::FSub, V1, V2, FMFSource, Name);
+ }
+ static BinaryOperator *CreateFMulFMF(Value *V1, Value *V2,
+ BinaryOperator *FMFSource,
+ const Twine &Name = "") {
+ return CreateWithCopiedFlags(Instruction::FMul, V1, V2, FMFSource, Name);
+ }
+ static BinaryOperator *CreateFDivFMF(Value *V1, Value *V2,
+ BinaryOperator *FMFSource,
+ const Twine &Name = "") {
+ return CreateWithCopiedFlags(Instruction::FDiv, V1, V2, FMFSource, Name);
+ }
+ static BinaryOperator *CreateFRemFMF(Value *V1, Value *V2,
+ BinaryOperator *FMFSource,
+ const Twine &Name = "") {
+ return CreateWithCopiedFlags(Instruction::FRem, V1, V2, FMFSource, Name);
+ }
+ static BinaryOperator *CreateFNegFMF(Value *Op, BinaryOperator *FMFSource,
+ const Twine &Name = "") {
+ Value *Zero = ConstantFP::getNegativeZero(Op->getType());
+ return CreateWithCopiedFlags(Instruction::FSub, Zero, Op, FMFSource);
+ }
+
static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2,
const Twine &Name = "") {
BinaryOperator *BO = Create(Opc, V1, V2, Name);
@@ -556,16 +588,16 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value)
/// can be performed with code like:
///
/// if (isa<CastInst>(Instr)) { ... }
-/// @brief Base class of casting instructions.
+/// Base class of casting instructions.
class CastInst : public UnaryInstruction {
protected:
- /// @brief Constructor with insert-before-instruction semantics for subclasses
+ /// Constructor with insert-before-instruction semantics for subclasses
CastInst(Type *Ty, unsigned iType, Value *S,
const Twine &NameStr = "", Instruction *InsertBefore = nullptr)
: UnaryInstruction(Ty, iType, S, InsertBefore) {
setName(NameStr);
}
- /// @brief Constructor with insert-at-end-of-block semantics for subclasses
+ /// Constructor with insert-at-end-of-block semantics for subclasses
CastInst(Type *Ty, unsigned iType, Value *S,
const Twine &NameStr, BasicBlock *InsertAtEnd)
: UnaryInstruction(Ty, iType, S, InsertAtEnd) {
@@ -578,7 +610,7 @@ public:
/// CastOps category (Instruction::isCast(opcode) returns true). This
/// constructor has insert-before-instruction semantics to automatically
/// insert the new CastInst before InsertBefore (if it is non-null).
- /// @brief Construct any of the CastInst subclasses
+ /// Construct any of the CastInst subclasses
static CastInst *Create(
Instruction::CastOps, ///< The opcode of the cast instruction
Value *S, ///< The value to be casted (operand 0)
@@ -591,7 +623,7 @@ public:
/// CastOps category. This constructor has insert-at-end-of-block semantics
/// to automatically insert the new CastInst at the end of InsertAtEnd (if
/// its non-null).
- /// @brief Construct any of the CastInst subclasses
+ /// Construct any of the CastInst subclasses
static CastInst *Create(
Instruction::CastOps, ///< The opcode for the cast instruction
Value *S, ///< The value to be casted (operand 0)
@@ -600,7 +632,7 @@ public:
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
- /// @brief Create a ZExt or BitCast cast instruction
+ /// Create a ZExt or BitCast cast instruction
static CastInst *CreateZExtOrBitCast(
Value *S, ///< The value to be casted (operand 0)
Type *Ty, ///< The type to which cast should be made
@@ -608,7 +640,7 @@ public:
Instruction *InsertBefore = nullptr ///< Place to insert the instruction
);
- /// @brief Create a ZExt or BitCast cast instruction
+ /// Create a ZExt or BitCast cast instruction
static CastInst *CreateZExtOrBitCast(
Value *S, ///< The value to be casted (operand 0)
Type *Ty, ///< The type to which operand is casted
@@ -616,7 +648,7 @@ public:
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
- /// @brief Create a SExt or BitCast cast instruction
+ /// Create a SExt or BitCast cast instruction
static CastInst *CreateSExtOrBitCast(
Value *S, ///< The value to be casted (operand 0)
Type *Ty, ///< The type to which cast should be made
@@ -624,7 +656,7 @@ public:
Instruction *InsertBefore = nullptr ///< Place to insert the instruction
);
- /// @brief Create a SExt or BitCast cast instruction
+ /// Create a SExt or BitCast cast instruction
static CastInst *CreateSExtOrBitCast(
Value *S, ///< The value to be casted (operand 0)
Type *Ty, ///< The type to which operand is casted
@@ -632,7 +664,7 @@ public:
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
- /// @brief Create a BitCast AddrSpaceCast, or a PtrToInt cast instruction.
+ /// Create a BitCast AddrSpaceCast, or a PtrToInt cast instruction.
static CastInst *CreatePointerCast(
Value *S, ///< The pointer value to be casted (operand 0)
Type *Ty, ///< The type to which operand is casted
@@ -640,7 +672,7 @@ public:
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
- /// @brief Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
+ /// Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
static CastInst *CreatePointerCast(
Value *S, ///< The pointer value to be casted (operand 0)
Type *Ty, ///< The type to which cast should be made
@@ -648,7 +680,7 @@ public:
Instruction *InsertBefore = nullptr ///< Place to insert the instruction
);
- /// @brief Create a BitCast or an AddrSpaceCast cast instruction.
+ /// Create a BitCast or an AddrSpaceCast cast instruction.
static CastInst *CreatePointerBitCastOrAddrSpaceCast(
Value *S, ///< The pointer value to be casted (operand 0)
Type *Ty, ///< The type to which operand is casted
@@ -656,7 +688,7 @@ public:
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
- /// @brief Create a BitCast or an AddrSpaceCast cast instruction.
+ /// Create a BitCast or an AddrSpaceCast cast instruction.
static CastInst *CreatePointerBitCastOrAddrSpaceCast(
Value *S, ///< The pointer value to be casted (operand 0)
Type *Ty, ///< The type to which cast should be made
@@ -664,7 +696,7 @@ public:
Instruction *InsertBefore = nullptr ///< Place to insert the instruction
);
- /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction.
+ /// 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
@@ -677,7 +709,7 @@ public:
Instruction *InsertBefore = nullptr ///< Place to insert the instruction
);
- /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts.
+ /// Create a ZExt, BitCast, or Trunc for int -> int casts.
static CastInst *CreateIntegerCast(
Value *S, ///< The pointer value to be casted (operand 0)
Type *Ty, ///< The type to which cast should be made
@@ -686,7 +718,7 @@ public:
Instruction *InsertBefore = nullptr ///< Place to insert the instruction
);
- /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts.
+ /// Create a ZExt, BitCast, or Trunc for int -> int casts.
static CastInst *CreateIntegerCast(
Value *S, ///< The integer value to be casted (operand 0)
Type *Ty, ///< The integer type to which operand is casted
@@ -695,7 +727,7 @@ public:
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
- /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts
+ /// Create an FPExt, BitCast, or FPTrunc for fp -> fp casts
static CastInst *CreateFPCast(
Value *S, ///< The floating point value to be casted
Type *Ty, ///< The floating point type to cast to
@@ -703,7 +735,7 @@ public:
Instruction *InsertBefore = nullptr ///< Place to insert the instruction
);
- /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts
+ /// Create an FPExt, BitCast, or FPTrunc for fp -> fp casts
static CastInst *CreateFPCast(
Value *S, ///< The floating point value to be casted
Type *Ty, ///< The floating point type to cast to
@@ -711,7 +743,7 @@ public:
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
- /// @brief Create a Trunc or BitCast cast instruction
+ /// Create a Trunc or BitCast cast instruction
static CastInst *CreateTruncOrBitCast(
Value *S, ///< The value to be casted (operand 0)
Type *Ty, ///< The type to which cast should be made
@@ -719,7 +751,7 @@ public:
Instruction *InsertBefore = nullptr ///< Place to insert the instruction
);
- /// @brief Create a Trunc or BitCast cast instruction
+ /// Create a Trunc or BitCast cast instruction
static CastInst *CreateTruncOrBitCast(
Value *S, ///< The value to be casted (operand 0)
Type *Ty, ///< The type to which operand is casted
@@ -727,19 +759,19 @@ public:
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
- /// @brief Check whether it is valid to call getCastOpcode for these types.
+ /// Check whether it is valid to call getCastOpcode for these types.
static bool isCastable(
Type *SrcTy, ///< The Type from which the value should be cast.
Type *DestTy ///< The Type to which the value should be cast.
);
- /// @brief Check whether a bitcast between these types is valid
+ /// Check whether a bitcast between these types is valid
static bool isBitCastable(
Type *SrcTy, ///< The Type from which the value should be cast.
Type *DestTy ///< The Type to which the value should be cast.
);
- /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these
+ /// 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
@@ -751,7 +783,7 @@ public:
/// Returns the opcode necessary to cast Val into Ty using usual casting
/// rules.
- /// @brief Infer the opcode for cast operand and type
+ /// Infer the opcode for cast operand and type
static Instruction::CastOps getCastOpcode(
const Value *Val, ///< The value to cast
bool SrcIsSigned, ///< Whether to treat the source as signed
@@ -763,14 +795,14 @@ public:
/// only deals with integer source and destination types. To simplify that
/// logic, this method is provided.
/// @returns true iff the cast has only integral typed operand and dest type.
- /// @brief Determine if this is an integer-only cast.
+ /// Determine if this is an integer-only cast.
bool isIntegerCast() const;
/// A lossless cast is one that does not alter the basic value. It implies
/// a no-op cast but is more stringent, preventing things like int->float,
/// long->double, or int->ptr.
/// @returns true iff the cast is lossless.
- /// @brief Determine if this is a lossless cast.
+ /// Determine if this is a lossless cast.
bool isLosslessCast() const;
/// A no-op cast is one that can be effected without changing any bits.
@@ -779,7 +811,7 @@ public:
/// involving Integer and Pointer types. They are no-op casts if the integer
/// is the same size as the pointer. However, pointer size varies with
/// platform.
- /// @brief Determine if the described cast is a no-op cast.
+ /// Determine if the described cast is a no-op cast.
static bool isNoopCast(
Instruction::CastOps Opcode, ///< Opcode of cast
Type *SrcTy, ///< SrcTy of cast
@@ -787,7 +819,7 @@ public:
const DataLayout &DL ///< DataLayout to get the Int Ptr type from.
);
- /// @brief Determine if this cast is a no-op cast.
+ /// Determine if this cast is a no-op cast.
///
/// \param DL is the DataLayout to determine pointer size.
bool isNoopCast(const DataLayout &DL) const;
@@ -797,7 +829,7 @@ public:
/// @returns 0 if the CastInst pair can't be eliminated, otherwise
/// returns Instruction::CastOps value for a cast that can replace
/// the pair, casting SrcTy to DstTy.
- /// @brief Determine if a cast pair is eliminable
+ /// Determine if a cast pair is eliminable
static unsigned isEliminableCastPair(
Instruction::CastOps firstOpcode, ///< Opcode of first cast
Instruction::CastOps secondOpcode, ///< Opcode of second cast
@@ -809,23 +841,23 @@ public:
Type *DstIntPtrTy ///< Integer type corresponding to Ptr DstTy, or null
);
- /// @brief Return the opcode of this CastInst
+ /// Return the opcode of this CastInst
Instruction::CastOps getOpcode() const {
return Instruction::CastOps(Instruction::getOpcode());
}
- /// @brief Return the source type, as a convenience
+ /// Return the source type, as a convenience
Type* getSrcTy() const { return getOperand(0)->getType(); }
- /// @brief Return the destination type, as a convenience
+ /// Return the destination type, as a convenience
Type* getDestTy() const { return getType(); }
/// This method can be used to determine if a cast from S to DstTy using
/// Opcode op is valid or not.
/// @returns true iff the proposed cast is valid.
- /// @brief Determine if a cast is valid without creating one.
+ /// Determine if a cast is valid without creating one.
static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy);
- /// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Instruction *I) {
return I->isCast();
}
@@ -839,7 +871,7 @@ public:
//===----------------------------------------------------------------------===//
/// This class is the base class for the comparison instructions.
-/// @brief Abstract base class of comparison instructions.
+/// Abstract base class of comparison instructions.
class CmpInst : public Instruction {
public:
/// This enumeration lists the possible predicates for CmpInst subclasses.
@@ -905,7 +937,7 @@ public:
/// the two operands. Optionally (if InstBefore is specified) insert the
/// instruction into a BasicBlock right before the specified instruction.
/// The specified Instruction is allowed to be a dereferenced end iterator.
- /// @brief Create a CmpInst
+ /// Create a CmpInst
static CmpInst *Create(OtherOps Op,
Predicate predicate, Value *S1,
Value *S2, const Twine &Name = "",
@@ -914,21 +946,21 @@ public:
/// Construct a compare instruction, given the opcode, the predicate and the
/// two operands. Also automatically insert this instruction to the end of
/// the BasicBlock specified.
- /// @brief Create a CmpInst
+ /// Create a CmpInst
static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1,
Value *S2, const Twine &Name, BasicBlock *InsertAtEnd);
- /// @brief Get the opcode casted to the right type
+ /// Get the opcode casted to the right type
OtherOps getOpcode() const {
return static_cast<OtherOps>(Instruction::getOpcode());
}
- /// @brief Return the predicate for this instruction.
+ /// Return the predicate for this instruction.
Predicate getPredicate() const {
return Predicate(getSubclassDataFromInstruction());
}
- /// @brief Set the predicate for this instruction to the specified value.
+ /// Set the predicate for this instruction to the specified value.
void setPredicate(Predicate P) { setInstructionSubclassData(P); }
static bool isFPPredicate(Predicate P) {
@@ -947,7 +979,7 @@ public:
/// For example, EQ -> NE, UGT -> ULE, SLT -> SGE,
/// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc.
/// @returns the inverse predicate for the instruction's current predicate.
- /// @brief Return the inverse of the instruction's predicate.
+ /// Return the inverse of the instruction's predicate.
Predicate getInversePredicate() const {
return getInversePredicate(getPredicate());
}
@@ -955,7 +987,7 @@ public:
/// For example, EQ -> NE, UGT -> ULE, SLT -> SGE,
/// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc.
/// @returns the inverse predicate for predicate provided in \p pred.
- /// @brief Return the inverse of a given predicate
+ /// Return the inverse of a given predicate
static Predicate getInversePredicate(Predicate pred);
/// For example, EQ->EQ, SLE->SGE, ULT->UGT,
@@ -963,81 +995,109 @@ public:
/// @returns the predicate that would be the result of exchanging the two
/// operands of the CmpInst instruction without changing the result
/// produced.
- /// @brief Return the predicate as if the operands were swapped
+ /// Return the predicate as if the operands were swapped
Predicate getSwappedPredicate() const {
return getSwappedPredicate(getPredicate());
}
/// This is a static version that you can use without an instruction
/// available.
- /// @brief Return the predicate as if the operands were swapped.
+ /// Return the predicate as if the operands were swapped.
static Predicate getSwappedPredicate(Predicate pred);
- /// @brief Provide more efficient getOperand methods.
+ /// For predicate of kind "is X or equal to 0" returns the predicate "is X".
+ /// For predicate of kind "is X" returns the predicate "is X or equal to 0".
+ /// does not support other kind of predicates.
+ /// @returns the predicate that does not contains is equal to zero if
+ /// it had and vice versa.
+ /// Return the flipped strictness of predicate
+ Predicate getFlippedStrictnessPredicate() const {
+ return getFlippedStrictnessPredicate(getPredicate());
+ }
+
+ /// This is a static version that you can use without an instruction
+ /// available.
+ /// Return the flipped strictness of predicate
+ static Predicate getFlippedStrictnessPredicate(Predicate pred);
+
+ /// For example, SGT -> SGE, SLT -> SLE, ULT -> ULE, UGT -> UGE.
+ /// Returns the non-strict version of strict comparisons.
+ Predicate getNonStrictPredicate() const {
+ return getNonStrictPredicate(getPredicate());
+ }
+
+ /// This is a static version that you can use without an instruction
+ /// available.
+ /// @returns the non-strict version of comparison provided in \p pred.
+ /// If \p pred is not a strict comparison predicate, returns \p pred.
+ /// Returns the non-strict version of strict comparisons.
+ static Predicate getNonStrictPredicate(Predicate pred);
+
+ /// Provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// This is just a convenience that dispatches to the subclasses.
- /// @brief Swap the operands and adjust predicate accordingly to retain
+ /// Swap the operands and adjust predicate accordingly to retain
/// the same comparison.
void swapOperands();
/// This is just a convenience that dispatches to the subclasses.
- /// @brief Determine if this CmpInst is commutative.
+ /// Determine if this CmpInst is commutative.
bool isCommutative() const;
/// This is just a convenience that dispatches to the subclasses.
- /// @brief Determine if this is an equals/not equals predicate.
+ /// Determine if this is an equals/not equals predicate.
bool isEquality() const;
/// @returns true if the comparison is signed, false otherwise.
- /// @brief Determine if this instruction is using a signed comparison.
+ /// Determine if this instruction is using a signed comparison.
bool isSigned() const {
return isSigned(getPredicate());
}
/// @returns true if the comparison is unsigned, false otherwise.
- /// @brief Determine if this instruction is using an unsigned comparison.
+ /// Determine if this instruction is using an unsigned comparison.
bool isUnsigned() const {
return isUnsigned(getPredicate());
}
/// For example, ULT->SLT, ULE->SLE, UGT->SGT, UGE->SGE, SLT->Failed assert
/// @returns the signed version of the unsigned predicate pred.
- /// @brief return the signed version of a predicate
+ /// return the signed version of a predicate
static Predicate getSignedPredicate(Predicate pred);
/// For example, ULT->SLT, ULE->SLE, UGT->SGT, UGE->SGE, SLT->Failed assert
/// @returns the signed version of the predicate for this instruction (which
/// has to be an unsigned predicate).
- /// @brief return the signed version of a predicate
+ /// return the signed version of a predicate
Predicate getSignedPredicate() {
return getSignedPredicate(getPredicate());
}
/// This is just a convenience.
- /// @brief Determine if this is true when both operands are the same.
+ /// Determine if this is true when both operands are the same.
bool isTrueWhenEqual() const {
return isTrueWhenEqual(getPredicate());
}
/// This is just a convenience.
- /// @brief Determine if this is false when both operands are the same.
+ /// Determine if this is false when both operands are the same.
bool isFalseWhenEqual() const {
return isFalseWhenEqual(getPredicate());
}
/// @returns true if the predicate is unsigned, false otherwise.
- /// @brief Determine if the predicate is an unsigned operation.
+ /// Determine if the predicate is an unsigned operation.
static bool isUnsigned(Predicate predicate);
/// @returns true if the predicate is signed, false otherwise.
- /// @brief Determine if the predicate is an signed operation.
+ /// Determine if the predicate is an signed operation.
static bool isSigned(Predicate predicate);
- /// @brief Determine if the predicate is an ordered operation.
+ /// Determine if the predicate is an ordered operation.
static bool isOrdered(Predicate predicate);
- /// @brief Determine if the predicate is an unordered operation.
+ /// Determine if the predicate is an unordered operation.
static bool isUnordered(Predicate predicate);
/// Determine if the predicate is true when comparing a value with itself.
@@ -1054,7 +1114,7 @@ public:
/// operands.
static bool isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2);
- /// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::ICmp ||
I->getOpcode() == Instruction::FCmp;
@@ -1063,7 +1123,7 @@ public:
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
- /// @brief Create a result type for fcmp/icmp
+ /// Create a result type for fcmp/icmp
static Type* makeCmpResultType(Type* opnd_type) {
if (VectorType* vt = dyn_cast<VectorType>(opnd_type)) {
return VectorType::get(Type::getInt1Ty(opnd_type->getContext()),
@@ -1121,7 +1181,7 @@ public:
/// Convenience accessors
- /// \brief Return the outer EH-pad this funclet is nested within.
+ /// Return the outer EH-pad this funclet is nested within.
///
/// Note: This returns the associated CatchSwitchInst if this FuncletPadInst
/// is a CatchPadInst.
@@ -1157,7 +1217,7 @@ struct OperandTraits<FuncletPadInst>
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(FuncletPadInst, Value)
-/// \brief A lightweight accessor for an operand bundle meant to be passed
+/// A lightweight accessor for an operand bundle meant to be passed
/// around by value.
struct OperandBundleUse {
ArrayRef<Use> Inputs;
@@ -1166,7 +1226,7 @@ struct OperandBundleUse {
explicit OperandBundleUse(StringMapEntry<uint32_t> *Tag, ArrayRef<Use> Inputs)
: Inputs(Inputs), Tag(Tag) {}
- /// \brief Return true if the operand at index \p Idx in this operand bundle
+ /// Return true if the operand at index \p Idx in this operand bundle
/// has the attribute A.
bool operandHasAttr(unsigned Idx, Attribute::AttrKind A) const {
if (isDeoptOperandBundle())
@@ -1177,12 +1237,12 @@ struct OperandBundleUse {
return false;
}
- /// \brief Return the tag of this operand bundle as a string.
+ /// Return the tag of this operand bundle as a string.
StringRef getTagName() const {
return Tag->getKey();
}
- /// \brief Return the tag of this operand bundle as an integer.
+ /// Return the tag of this operand bundle as an integer.
///
/// Operand bundle tags are interned by LLVMContextImpl::getOrInsertBundleTag,
/// and this function returns the unique integer getOrInsertBundleTag
@@ -1191,22 +1251,22 @@ struct OperandBundleUse {
return Tag->getValue();
}
- /// \brief Return true if this is a "deopt" operand bundle.
+ /// Return true if this is a "deopt" operand bundle.
bool isDeoptOperandBundle() const {
return getTagID() == LLVMContext::OB_deopt;
}
- /// \brief Return true if this is a "funclet" operand bundle.
+ /// Return true if this is a "funclet" operand bundle.
bool isFuncletOperandBundle() const {
return getTagID() == LLVMContext::OB_funclet;
}
private:
- /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag.
+ /// Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag.
StringMapEntry<uint32_t> *Tag;
};
-/// \brief A container for an operand bundle being viewed as a set of values
+/// A container for an operand bundle being viewed as a set of values
/// rather than a set of uses.
///
/// Unlike OperandBundleUse, OperandBundleDefT owns the memory it carries, and
@@ -1241,7 +1301,7 @@ public:
using OperandBundleDef = OperandBundleDefT<Value *>;
using ConstOperandBundleDef = OperandBundleDefT<const Value *>;
-/// \brief A mixin to add operand bundle functionality to llvm instruction
+/// A mixin to add operand bundle functionality to llvm instruction
/// classes.
///
/// OperandBundleUser uses the descriptor area co-allocated with the host User
@@ -1289,21 +1349,21 @@ using ConstOperandBundleDef = OperandBundleDefT<const Value *>;
/// Currently operand bundle users with hung-off operands are not supported.
template <typename InstrTy, typename OpIteratorTy> class OperandBundleUser {
public:
- /// \brief Return the number of operand bundles associated with this User.
+ /// Return the number of operand bundles associated with this User.
unsigned getNumOperandBundles() const {
return std::distance(bundle_op_info_begin(), bundle_op_info_end());
}
- /// \brief Return true if this User has any operand bundles.
+ /// Return true if this User has any operand bundles.
bool hasOperandBundles() const { return getNumOperandBundles() != 0; }
- /// \brief Return the index of the first bundle operand in the Use array.
+ /// Return the index of the first bundle operand in the Use array.
unsigned getBundleOperandsStartIndex() const {
assert(hasOperandBundles() && "Don't call otherwise!");
return bundle_op_info_begin()->Begin;
}
- /// \brief Return the index of the last bundle operand in the Use array.
+ /// Return the index of the last bundle operand in the Use array.
unsigned getBundleOperandsEndIndex() const {
assert(hasOperandBundles() && "Don't call otherwise!");
return bundle_op_info_end()[-1].End;
@@ -1315,7 +1375,7 @@ public:
Idx < getBundleOperandsEndIndex();
}
- /// \brief Return the total number operands (not operand bundles) used by
+ /// Return the total number operands (not operand bundles) used by
/// every operand bundle in this OperandBundleUser.
unsigned getNumTotalBundleOperands() const {
if (!hasOperandBundles())
@@ -1328,13 +1388,13 @@ public:
return End - Begin;
}
- /// \brief Return the operand bundle at a specific index.
+ /// Return the operand bundle at a specific index.
OperandBundleUse getOperandBundleAt(unsigned Index) const {
assert(Index < getNumOperandBundles() && "Index out of bounds!");
return operandBundleFromBundleOpInfo(*(bundle_op_info_begin() + Index));
}
- /// \brief Return the number of operand bundles with the tag Name attached to
+ /// Return the number of operand bundles with the tag Name attached to
/// this instruction.
unsigned countOperandBundlesOfType(StringRef Name) const {
unsigned Count = 0;
@@ -1345,7 +1405,7 @@ public:
return Count;
}
- /// \brief Return the number of operand bundles with the tag ID attached to
+ /// Return the number of operand bundles with the tag ID attached to
/// this instruction.
unsigned countOperandBundlesOfType(uint32_t ID) const {
unsigned Count = 0;
@@ -1356,7 +1416,7 @@ public:
return Count;
}
- /// \brief Return an operand bundle by name, if present.
+ /// Return an operand bundle by name, if present.
///
/// It is an error to call this for operand bundle types that may have
/// multiple instances of them on the same instruction.
@@ -1372,7 +1432,7 @@ public:
return None;
}
- /// \brief Return an operand bundle by tag ID, if present.
+ /// Return an operand bundle by tag ID, if present.
///
/// It is an error to call this for operand bundle types that may have
/// multiple instances of them on the same instruction.
@@ -1388,7 +1448,7 @@ public:
return None;
}
- /// \brief Return the list of operand bundles attached to this instruction as
+ /// Return the list of operand bundles attached to this instruction as
/// a vector of OperandBundleDefs.
///
/// This function copies the OperandBundeUse instances associated with this
@@ -1400,7 +1460,7 @@ public:
Defs.emplace_back(getOperandBundleAt(i));
}
- /// \brief Return the operand bundle for the operand at index OpIdx.
+ /// Return the operand bundle for the operand at index OpIdx.
///
/// It is an error to call this with an OpIdx that does not correspond to an
/// bundle operand.
@@ -1408,7 +1468,7 @@ public:
return operandBundleFromBundleOpInfo(getBundleOpInfoForOperand(OpIdx));
}
- /// \brief Return true if this operand bundle user has operand bundles that
+ /// Return true if this operand bundle user has operand bundles that
/// may read from the heap.
bool hasReadingOperandBundles() const {
// Implementation note: this is a conservative implementation of operand
@@ -1417,7 +1477,7 @@ public:
return hasOperandBundles();
}
- /// \brief Return true if this operand bundle user has operand bundles that
+ /// Return true if this operand bundle user has operand bundles that
/// may write to the heap.
bool hasClobberingOperandBundles() const {
for (auto &BOI : bundle_op_infos()) {
@@ -1433,7 +1493,7 @@ public:
return false;
}
- /// \brief Return true if the bundle operand at index \p OpIdx has the
+ /// Return true if the bundle operand at index \p OpIdx has the
/// attribute \p A.
bool bundleOperandHasAttr(unsigned OpIdx, Attribute::AttrKind A) const {
auto &BOI = getBundleOpInfoForOperand(OpIdx);
@@ -1441,7 +1501,7 @@ public:
return OBU.operandHasAttr(OpIdx - BOI.Begin, A);
}
- /// \brief Return true if \p Other has the same sequence of operand bundle
+ /// Return true if \p Other has the same sequence of operand bundle
/// tags with the same number of operands on each one of them as this
/// OperandBundleUser.
bool hasIdenticalOperandBundleSchema(
@@ -1453,7 +1513,7 @@ public:
Other.bundle_op_info_begin());
}
- /// \brief Return true if this operand bundle user contains operand bundles
+ /// Return true if this operand bundle user contains operand bundles
/// with tags other than those specified in \p IDs.
bool hasOperandBundlesOtherThan(ArrayRef<uint32_t> IDs) const {
for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) {
@@ -1465,7 +1525,7 @@ public:
}
protected:
- /// \brief Is the function attribute S disallowed by some operand bundle on
+ /// Is the function attribute S disallowed by some operand bundle on
/// this operand bundle user?
bool isFnAttrDisallowedByOpBundle(StringRef S) const {
// Operand bundles only possibly disallow readnone, readonly and argmenonly
@@ -1473,7 +1533,7 @@ protected:
return false;
}
- /// \brief Is the function attribute A disallowed by some operand bundle on
+ /// Is the function attribute A disallowed by some operand bundle on
/// this operand bundle user?
bool isFnAttrDisallowedByOpBundle(Attribute::AttrKind A) const {
switch (A) {
@@ -1499,18 +1559,18 @@ protected:
llvm_unreachable("switch has a default case!");
}
- /// \brief Used to keep track of an operand bundle. See the main comment on
+ /// Used to keep track of an operand bundle. See the main comment on
/// OperandBundleUser above.
struct BundleOpInfo {
- /// \brief The operand bundle tag, interned by
+ /// The operand bundle tag, interned by
/// LLVMContextImpl::getOrInsertBundleTag.
StringMapEntry<uint32_t> *Tag;
- /// \brief The index in the Use& vector where operands for this operand
+ /// The index in the Use& vector where operands for this operand
/// bundle starts.
uint32_t Begin;
- /// \brief The index in the Use& vector where operands for this operand
+ /// The index in the Use& vector where operands for this operand
/// bundle ends.
uint32_t End;
@@ -1519,7 +1579,7 @@ protected:
}
};
- /// \brief Simple helper function to map a BundleOpInfo to an
+ /// Simple helper function to map a BundleOpInfo to an
/// OperandBundleUse.
OperandBundleUse
operandBundleFromBundleOpInfo(const BundleOpInfo &BOI) const {
@@ -1531,7 +1591,7 @@ protected:
using bundle_op_iterator = BundleOpInfo *;
using const_bundle_op_iterator = const BundleOpInfo *;
- /// \brief Return the start of the list of BundleOpInfo instances associated
+ /// Return the start of the list of BundleOpInfo instances associated
/// with this OperandBundleUser.
bundle_op_iterator bundle_op_info_begin() {
if (!static_cast<InstrTy *>(this)->hasDescriptor())
@@ -1541,7 +1601,7 @@ protected:
return reinterpret_cast<bundle_op_iterator>(BytesBegin);
}
- /// \brief Return the start of the list of BundleOpInfo instances associated
+ /// Return the start of the list of BundleOpInfo instances associated
/// with this OperandBundleUser.
const_bundle_op_iterator bundle_op_info_begin() const {
auto *NonConstThis =
@@ -1549,7 +1609,7 @@ protected:
return NonConstThis->bundle_op_info_begin();
}
- /// \brief Return the end of the list of BundleOpInfo instances associated
+ /// Return the end of the list of BundleOpInfo instances associated
/// with this OperandBundleUser.
bundle_op_iterator bundle_op_info_end() {
if (!static_cast<InstrTy *>(this)->hasDescriptor())
@@ -1559,7 +1619,7 @@ protected:
return reinterpret_cast<bundle_op_iterator>(BytesEnd);
}
- /// \brief Return the end of the list of BundleOpInfo instances associated
+ /// Return the end of the list of BundleOpInfo instances associated
/// with this OperandBundleUser.
const_bundle_op_iterator bundle_op_info_end() const {
auto *NonConstThis =
@@ -1567,17 +1627,17 @@ protected:
return NonConstThis->bundle_op_info_end();
}
- /// \brief Return the range [\p bundle_op_info_begin, \p bundle_op_info_end).
+ /// Return the range [\p bundle_op_info_begin, \p bundle_op_info_end).
iterator_range<bundle_op_iterator> bundle_op_infos() {
return make_range(bundle_op_info_begin(), bundle_op_info_end());
}
- /// \brief Return the range [\p bundle_op_info_begin, \p bundle_op_info_end).
+ /// Return the range [\p bundle_op_info_begin, \p bundle_op_info_end).
iterator_range<const_bundle_op_iterator> bundle_op_infos() const {
return make_range(bundle_op_info_begin(), bundle_op_info_end());
}
- /// \brief Populate the BundleOpInfo instances and the Use& vector from \p
+ /// Populate the BundleOpInfo instances and the Use& vector from \p
/// Bundles. Return the op_iterator pointing to the Use& one past the last
/// last bundle operand use.
///
@@ -1608,7 +1668,7 @@ protected:
return It;
}
- /// \brief Return the BundleOpInfo for the operand at index OpIdx.
+ /// Return the BundleOpInfo for the operand at index OpIdx.
///
/// It is an error to call this with an OpIdx that does not correspond to an
/// bundle operand.
@@ -1620,7 +1680,7 @@ protected:
llvm_unreachable("Did not find operand bundle for operand!");
}
- /// \brief Return the total number of values used in \p Bundles.
+ /// Return the total number of values used in \p Bundles.
static unsigned CountBundleInputs(ArrayRef<OperandBundleDef> Bundles) {
unsigned Total = 0;
for (auto &B : Bundles)
diff --git a/contrib/llvm/include/llvm/IR/Instruction.h b/contrib/llvm/include/llvm/IR/Instruction.h
index 6af9cbfae5de..a3bf25056ee5 100644
--- a/contrib/llvm/include/llvm/IR/Instruction.h
+++ b/contrib/llvm/include/llvm/IR/Instruction.h
@@ -128,6 +128,7 @@ public:
const char *getOpcodeName() const { return getOpcodeName(getOpcode()); }
bool isTerminator() const { return isTerminator(getOpcode()); }
bool isBinaryOp() const { return isBinaryOp(getOpcode()); }
+ bool isIntDivRem() const { return isIntDivRem(getOpcode()); }
bool isShift() { return isShift(getOpcode()); }
bool isCast() const { return isCast(getOpcode()); }
bool isFuncletPad() const { return isFuncletPad(getOpcode()); }
@@ -142,6 +143,10 @@ public:
return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd;
}
+ static inline bool isIntDivRem(unsigned Opcode) {
+ return Opcode == UDiv || Opcode == SDiv || Opcode == URem || Opcode == SRem;
+ }
+
/// Determine if the Opcode is one of the shift instructions.
static inline bool isShift(unsigned Opcode) {
return Opcode >= Shl && Opcode <= AShr;
@@ -284,7 +289,7 @@ public:
/// Return the debug location for this node as a DebugLoc.
const DebugLoc &getDebugLoc() const { return DbgLoc; }
- /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// Set or clear the nuw flag on this instruction, which must be an operator
/// which supports this flag. See LangRef.html for the meaning of this flag.
void setHasNoUnsignedWrap(bool b = true);
@@ -535,6 +540,14 @@ public:
/// matters, isSafeToSpeculativelyExecute may be more appropriate.
bool mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow(); }
+ /// Return true if the instruction can be removed if the result is unused.
+ ///
+ /// When constant folding some instructions cannot be removed even if their
+ /// results are unused. Specifically terminator instructions and calls that
+ /// may have side effects cannot be removed without semantically changing the
+ /// generated program.
+ bool isSafeToRemove() const;
+
/// Return true if the instruction is a variety of EH-block.
bool isEHPad() const {
switch (getOpcode()) {
@@ -548,6 +561,14 @@ public:
}
}
+ /// Return a pointer to the next non-debug instruction in the same basic
+ /// block as 'this', or nullptr if no such instruction exists.
+ const Instruction *getNextNonDebugInstruction() const;
+ Instruction *getNextNonDebugInstruction() {
+ return const_cast<Instruction *>(
+ static_cast<const Instruction *>(this)->getNextNonDebugInstruction());
+ }
+
/// Create a copy of 'this' instruction that is identical in all ways except
/// the following:
/// * The instruction has no parent
@@ -582,7 +603,7 @@ public:
/// be identical.
/// @returns true if the specified instruction is the same operation as
/// the current one.
- /// @brief Determine if one instruction is the same operation as another.
+ /// Determine if one instruction is the same operation as another.
bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const;
/// Return true if there are any uses of this instruction in blocks other than
diff --git a/contrib/llvm/include/llvm/IR/Instructions.h b/contrib/llvm/include/llvm/IR/Instructions.h
index c1122d137f24..a2cb84a071f2 100644
--- a/contrib/llvm/include/llvm/IR/Instructions.h
+++ b/contrib/llvm/include/llvm/IR/Instructions.h
@@ -98,6 +98,10 @@ public:
return cast<PointerType>(Instruction::getType());
}
+ /// Get allocation size in bits. Returns None if size can't be determined,
+ /// e.g. in case of a VLA.
+ Optional<uint64_t> getAllocationSizeInBits(const DataLayout &DL) const;
+
/// Return the type that is being allocated by the instruction.
Type *getAllocatedType() const { return AllocatedType; }
/// for use only in special circumstances that need to generically
@@ -1346,224 +1350,71 @@ public:
}
};
-//===----------------------------------------------------------------------===//
-/// This class represents a function call, abstracting a target
-/// machine's calling convention. This class uses low bit of the SubClassData
-/// field to indicate whether or not this is a tail call. The rest of the bits
-/// hold the calling convention of the call.
-///
-class CallInst : public Instruction,
- public OperandBundleUser<CallInst, User::op_iterator> {
- friend class OperandBundleUser<CallInst, User::op_iterator>;
+class CallInst;
+class InvokeInst;
- AttributeList Attrs; ///< parameter attributes for call
- FunctionType *FTy;
+template <class T> struct CallBaseParent { using type = Instruction; };
- CallInst(const CallInst &CI);
-
- /// Construct a CallInst given a range of arguments.
- /// Construct a CallInst from a range of arguments
- inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
- Instruction *InsertBefore);
-
- inline CallInst(Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
- Instruction *InsertBefore)
- : CallInst(cast<FunctionType>(
- cast<PointerType>(Func->getType())->getElementType()),
- Func, Args, Bundles, NameStr, InsertBefore) {}
-
- inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr,
- Instruction *InsertBefore)
- : CallInst(Func, Args, None, NameStr, InsertBefore) {}
-
- /// Construct a CallInst given a range of arguments.
- /// Construct a CallInst from a range of arguments
- inline CallInst(Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
- BasicBlock *InsertAtEnd);
-
- explicit CallInst(Value *F, const Twine &NameStr,
- Instruction *InsertBefore);
-
- CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd);
-
- void init(Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
- init(cast<FunctionType>(
- cast<PointerType>(Func->getType())->getElementType()),
- Func, Args, Bundles, NameStr);
- }
- void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr);
- void init(Value *Func, const Twine &NameStr);
-
- bool hasDescriptor() const { return HasDescriptor; }
+template <> struct CallBaseParent<InvokeInst> { using type = TerminatorInst; };
+//===----------------------------------------------------------------------===//
+/// Base class for all callable instructions (InvokeInst and CallInst)
+/// Holds everything related to calling a function, abstracting from the base
+/// type @p BaseInstTy and the concrete instruction @p InstTy
+///
+template <class InstTy>
+class CallBase : public CallBaseParent<InstTy>::type,
+ public OperandBundleUser<InstTy, User::op_iterator> {
protected:
- // Note: Instruction needs to be a friend here to call cloneImpl.
- friend class Instruction;
-
- CallInst *cloneImpl() const;
-
-public:
- static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles = None,
- const Twine &NameStr = "",
- Instruction *InsertBefore = nullptr) {
- return Create(cast<FunctionType>(
- cast<PointerType>(Func->getType())->getElementType()),
- Func, Args, Bundles, NameStr, InsertBefore);
- }
-
- static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
- const Twine &NameStr,
- Instruction *InsertBefore = nullptr) {
- return Create(cast<FunctionType>(
- cast<PointerType>(Func->getType())->getElementType()),
- Func, Args, None, NameStr, InsertBefore);
- }
-
- static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
- const Twine &NameStr,
- Instruction *InsertBefore = nullptr) {
- return new (unsigned(Args.size() + 1))
- CallInst(Ty, Func, Args, None, NameStr, InsertBefore);
- }
-
- static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles = None,
- const Twine &NameStr = "",
- Instruction *InsertBefore = nullptr) {
- const unsigned TotalOps =
- unsigned(Args.size()) + CountBundleInputs(Bundles) + 1;
- const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo);
-
- return new (TotalOps, DescriptorBytes)
- CallInst(Ty, Func, Args, Bundles, NameStr, InsertBefore);
- }
+ AttributeList Attrs; ///< parameter attributes for callable
+ FunctionType *FTy;
+ using BaseInstTy = typename CallBaseParent<InstTy>::type;
- static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
- ArrayRef<OperandBundleDef> Bundles,
- const Twine &NameStr, BasicBlock *InsertAtEnd) {
- const unsigned TotalOps =
- unsigned(Args.size()) + CountBundleInputs(Bundles) + 1;
- const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo);
+ template <class... ArgsTy>
+ CallBase(AttributeList const &A, FunctionType *FT, ArgsTy &&... Args)
+ : BaseInstTy(std::forward<ArgsTy>(Args)...), Attrs(A), FTy(FT) {}
+ bool hasDescriptor() const { return Value::HasDescriptor; }
- return new (TotalOps, DescriptorBytes)
- CallInst(Func, Args, Bundles, NameStr, InsertAtEnd);
- }
+ using BaseInstTy::BaseInstTy;
- static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
- const Twine &NameStr, BasicBlock *InsertAtEnd) {
- return new (unsigned(Args.size() + 1))
- CallInst(Func, Args, None, NameStr, InsertAtEnd);
- }
+ using OperandBundleUser<InstTy,
+ User::op_iterator>::isFnAttrDisallowedByOpBundle;
+ using OperandBundleUser<InstTy, User::op_iterator>::getNumTotalBundleOperands;
+ using OperandBundleUser<InstTy, User::op_iterator>::bundleOperandHasAttr;
+ using Instruction::getSubclassDataFromInstruction;
+ using Instruction::setInstructionSubclassData;
- static CallInst *Create(Value *F, const Twine &NameStr = "",
- Instruction *InsertBefore = nullptr) {
- return new(1) CallInst(F, NameStr, InsertBefore);
- }
+public:
+ using Instruction::getContext;
+ using OperandBundleUser<InstTy, User::op_iterator>::hasOperandBundles;
+ using OperandBundleUser<InstTy,
+ User::op_iterator>::getBundleOperandsStartIndex;
- static CallInst *Create(Value *F, const Twine &NameStr,
- BasicBlock *InsertAtEnd) {
- return new(1) CallInst(F, NameStr, InsertAtEnd);
+ static bool classof(const Instruction *I) {
+ llvm_unreachable(
+ "CallBase is not meant to be used as part of the classof hierarchy");
}
- /// Create a clone of \p CI with a different set of operand bundles and
- /// insert it before \p InsertPt.
+public:
+ /// Return the parameter attributes for this call.
///
- /// The returned call instruction is identical \p CI in every way except that
- /// the operand bundles for the new instruction are set to the operand bundles
- /// in \p Bundles.
- static CallInst *Create(CallInst *CI, ArrayRef<OperandBundleDef> Bundles,
- Instruction *InsertPt = nullptr);
+ AttributeList getAttributes() const { return Attrs; }
- /// Generate the IR for a call to malloc:
- /// 1. Compute the malloc call's argument as the specified type's size,
- /// possibly multiplied by the array size if the array size is not
- /// constant 1.
- /// 2. Call malloc with that argument.
- /// 3. Bitcast the result of the malloc call to the specified type.
- static Instruction *CreateMalloc(Instruction *InsertBefore,
- Type *IntPtrTy, Type *AllocTy,
- Value *AllocSize, Value *ArraySize = nullptr,
- Function* MallocF = nullptr,
- const Twine &Name = "");
- static Instruction *CreateMalloc(BasicBlock *InsertAtEnd,
- Type *IntPtrTy, Type *AllocTy,
- Value *AllocSize, Value *ArraySize = nullptr,
- Function* MallocF = nullptr,
- const Twine &Name = "");
- static Instruction *CreateMalloc(Instruction *InsertBefore,
- Type *IntPtrTy, Type *AllocTy,
- Value *AllocSize, Value *ArraySize = nullptr,
- ArrayRef<OperandBundleDef> Bundles = None,
- Function* MallocF = nullptr,
- const Twine &Name = "");
- static Instruction *CreateMalloc(BasicBlock *InsertAtEnd,
- Type *IntPtrTy, Type *AllocTy,
- Value *AllocSize, Value *ArraySize = nullptr,
- ArrayRef<OperandBundleDef> Bundles = None,
- Function* MallocF = nullptr,
- const Twine &Name = "");
- /// Generate the IR for a call to the builtin free function.
- static Instruction *CreateFree(Value *Source,
- Instruction *InsertBefore);
- static Instruction *CreateFree(Value *Source,
- BasicBlock *InsertAtEnd);
- static Instruction *CreateFree(Value *Source,
- ArrayRef<OperandBundleDef> Bundles,
- Instruction *InsertBefore);
- static Instruction *CreateFree(Value *Source,
- ArrayRef<OperandBundleDef> Bundles,
- BasicBlock *InsertAtEnd);
+ /// Set the parameter attributes for this call.
+ ///
+ void setAttributes(AttributeList A) { Attrs = A; }
FunctionType *getFunctionType() const { return FTy; }
void mutateFunctionType(FunctionType *FTy) {
- mutateType(FTy->getReturnType());
+ Value::mutateType(FTy->getReturnType());
this->FTy = FTy;
}
- // Note that 'musttail' implies 'tail'.
- enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2,
- TCK_NoTail = 3 };
- TailCallKind getTailCallKind() const {
- return TailCallKind(getSubclassDataFromInstruction() & 3);
- }
-
- bool isTailCall() const {
- unsigned Kind = getSubclassDataFromInstruction() & 3;
- return Kind == TCK_Tail || Kind == TCK_MustTail;
- }
-
- bool isMustTailCall() const {
- return (getSubclassDataFromInstruction() & 3) == TCK_MustTail;
- }
-
- bool isNoTailCall() const {
- return (getSubclassDataFromInstruction() & 3) == TCK_NoTail;
- }
-
- void setTailCall(bool isTC = true) {
- setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) |
- unsigned(isTC ? TCK_Tail : TCK_None));
- }
-
- void setTailCallKind(TailCallKind TCK) {
- setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) |
- unsigned(TCK));
- }
-
- /// Provide fast operand accessors
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
-
/// Return the number of call arguments.
///
unsigned getNumArgOperands() const {
- return getNumOperands() - getNumTotalBundleOperands() - 1;
+ return getNumOperands() - getNumTotalBundleOperands() - InstTy::ArgOffset;
}
/// getArgOperand/setArgOperand - Return/set the i-th call argument.
@@ -1578,46 +1429,112 @@ public:
}
/// Return the iterator pointing to the beginning of the argument list.
- op_iterator arg_begin() { return op_begin(); }
+ User::op_iterator arg_begin() { return op_begin(); }
/// Return the iterator pointing to the end of the argument list.
- op_iterator arg_end() {
+ User::op_iterator arg_end() {
// [ call args ], [ operand bundles ], callee
- return op_end() - getNumTotalBundleOperands() - 1;
+ return op_end() - getNumTotalBundleOperands() - InstTy::ArgOffset;
}
/// Iteration adapter for range-for loops.
- iterator_range<op_iterator> arg_operands() {
+ iterator_range<User::op_iterator> arg_operands() {
return make_range(arg_begin(), arg_end());
}
/// Return the iterator pointing to the beginning of the argument list.
- const_op_iterator arg_begin() const { return op_begin(); }
+ User::const_op_iterator arg_begin() const { return op_begin(); }
/// Return the iterator pointing to the end of the argument list.
- const_op_iterator arg_end() const {
+ User::const_op_iterator arg_end() const {
// [ call args ], [ operand bundles ], callee
- return op_end() - getNumTotalBundleOperands() - 1;
+ return op_end() - getNumTotalBundleOperands() - InstTy::ArgOffset;
}
/// Iteration adapter for range-for loops.
- iterator_range<const_op_iterator> arg_operands() const {
+ iterator_range<User::const_op_iterator> arg_operands() const {
return make_range(arg_begin(), arg_end());
}
/// Wrappers for getting the \c Use of a call argument.
const Use &getArgOperandUse(unsigned i) const {
assert(i < getNumArgOperands() && "Out of bounds!");
- return getOperandUse(i);
+ return User::getOperandUse(i);
}
Use &getArgOperandUse(unsigned i) {
assert(i < getNumArgOperands() && "Out of bounds!");
- return getOperandUse(i);
+ return User::getOperandUse(i);
}
/// If one of the arguments has the 'returned' attribute, return its
/// operand value. Otherwise, return nullptr.
- Value *getReturnedArgOperand() const;
+ Value *getReturnedArgOperand() const {
+ unsigned Index;
+
+ if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
+ return getArgOperand(Index - AttributeList::FirstArgIndex);
+ if (const Function *F = getCalledFunction())
+ if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
+ Index)
+ return getArgOperand(Index - AttributeList::FirstArgIndex);
+
+ return nullptr;
+ }
+
+ User::op_iterator op_begin() {
+ return OperandTraits<CallBase>::op_begin(this);
+ }
+
+ User::const_op_iterator op_begin() const {
+ return OperandTraits<CallBase>::op_begin(const_cast<CallBase *>(this));
+ }
+
+ User::op_iterator op_end() { return OperandTraits<CallBase>::op_end(this); }
+
+ User::const_op_iterator op_end() const {
+ return OperandTraits<CallBase>::op_end(const_cast<CallBase *>(this));
+ }
+
+ Value *getOperand(unsigned i_nocapture) const {
+ assert(i_nocapture < OperandTraits<CallBase>::operands(this) &&
+ "getOperand() out of range!");
+ return cast_or_null<Value>(OperandTraits<CallBase>::op_begin(
+ const_cast<CallBase *>(this))[i_nocapture]
+ .get());
+ }
+
+ void setOperand(unsigned i_nocapture, Value *Val_nocapture) {
+ assert(i_nocapture < OperandTraits<CallBase>::operands(this) &&
+ "setOperand() out of range!");
+ OperandTraits<CallBase>::op_begin(this)[i_nocapture] = Val_nocapture;
+ }
+
+ unsigned getNumOperands() const {
+ return OperandTraits<CallBase>::operands(this);
+ }
+ template <int Idx_nocapture> Use &Op() {
+ return User::OpFrom<Idx_nocapture>(this);
+ }
+ template <int Idx_nocapture> const Use &Op() const {
+ return User::OpFrom<Idx_nocapture>(this);
+ }
+
+ /// Return the function called, or null if this is an
+ /// indirect function invocation.
+ ///
+ Function *getCalledFunction() const {
+ return dyn_cast<Function>(Op<-InstTy::ArgOffset>());
+ }
+
+ /// Determine whether this call has the given attribute.
+ bool hasFnAttr(Attribute::AttrKind Kind) const {
+ assert(Kind != Attribute::NoBuiltin &&
+ "Use CallBase::isNoBuiltin() to check for Attribute::NoBuiltin");
+ return hasFnAttrImpl(Kind);
+ }
+
+ /// Determine whether this call has the given attribute.
+ bool hasFnAttr(StringRef Kind) const { return hasFnAttrImpl(Kind); }
/// getCallingConv/setCallingConv - Get or set the calling convention of this
/// function call.
@@ -1631,62 +1548,103 @@ public:
(ID << 2));
}
- /// Return the parameter attributes for this call.
- ///
- AttributeList getAttributes() const { return Attrs; }
-
- /// Set the parameter attributes for this call.
- ///
- void setAttributes(AttributeList A) { Attrs = A; }
/// adds the attribute to the list of attributes.
- void addAttribute(unsigned i, Attribute::AttrKind Kind);
+ void addAttribute(unsigned i, Attribute::AttrKind Kind) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addAttribute(getContext(), i, Kind);
+ setAttributes(PAL);
+ }
/// adds the attribute to the list of attributes.
- void addAttribute(unsigned i, Attribute Attr);
+ void addAttribute(unsigned i, Attribute Attr) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addAttribute(getContext(), i, Attr);
+ setAttributes(PAL);
+ }
/// Adds the attribute to the indicated argument
- void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
+ void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
+ }
/// Adds the attribute to the indicated argument
- void addParamAttr(unsigned ArgNo, Attribute Attr);
+ void addParamAttr(unsigned ArgNo, Attribute Attr) {
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr);
+ setAttributes(PAL);
+ }
/// removes the attribute from the list of attributes.
- void removeAttribute(unsigned i, Attribute::AttrKind Kind);
+ void removeAttribute(unsigned i, Attribute::AttrKind Kind) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeAttribute(getContext(), i, Kind);
+ setAttributes(PAL);
+ }
/// removes the attribute from the list of attributes.
- void removeAttribute(unsigned i, StringRef Kind);
+ void removeAttribute(unsigned i, StringRef Kind) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeAttribute(getContext(), i, Kind);
+ setAttributes(PAL);
+ }
/// Removes the attribute from the given argument
- void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
+ void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
+ }
/// Removes the attribute from the given argument
- void removeParamAttr(unsigned ArgNo, StringRef Kind);
+ void removeParamAttr(unsigned ArgNo, StringRef Kind) {
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
+ }
/// adds the dereferenceable attribute to the list of attributes.
- void addDereferenceableAttr(unsigned i, uint64_t Bytes);
+ void addDereferenceableAttr(unsigned i, uint64_t Bytes) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
+ setAttributes(PAL);
+ }
/// adds the dereferenceable_or_null attribute to the list of
/// attributes.
- void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
-
- /// Determine whether this call has the given attribute.
- bool hasFnAttr(Attribute::AttrKind Kind) const {
- assert(Kind != Attribute::NoBuiltin &&
- "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin");
- return hasFnAttrImpl(Kind);
- }
-
- /// Determine whether this call has the given attribute.
- bool hasFnAttr(StringRef Kind) const {
- return hasFnAttrImpl(Kind);
+ void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes);
+ setAttributes(PAL);
}
/// Determine whether the return value has the given attribute.
- bool hasRetAttr(Attribute::AttrKind Kind) const;
+ bool hasRetAttr(Attribute::AttrKind Kind) const {
+ if (Attrs.hasAttribute(AttributeList::ReturnIndex, Kind))
+ return true;
+
+ // Look at the callee, if available.
+ if (const Function *F = getCalledFunction())
+ return F->getAttributes().hasAttribute(AttributeList::ReturnIndex, Kind);
+ return false;
+ }
/// Determine whether the argument or parameter has the given attribute.
- bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
+ bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
+ assert(ArgNo < getNumArgOperands() && "Param index out of bounds!");
+
+ if (Attrs.hasParamAttribute(ArgNo, Kind))
+ return true;
+ if (const Function *F = getCalledFunction())
+ return F->getAttributes().hasParamAttribute(ArgNo, Kind);
+ return false;
+ }
/// Get the attribute of a given kind at a position.
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
@@ -1709,7 +1667,6 @@ public:
assert(ArgNo < getNumArgOperands() && "Out of bounds");
return getAttributes().getParamAttr(ArgNo, Kind);
}
-
/// Return true if the data operand at index \p i has the attribute \p
/// A.
///
@@ -1723,7 +1680,28 @@ public:
/// \p i in [1, arg_size + 1) -> argument number (\p i - 1)
/// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index
/// (\p i - 1) in the operand list.
- bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const;
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const {
+ // There are getNumOperands() - (InstTy::ArgOffset - 1) data operands.
+ // The last operand is the callee.
+ assert(i < (getNumOperands() - InstTy::ArgOffset + 1) &&
+ "Data operand index out of bounds!");
+
+ // The attribute A can either be directly specified, if the operand in
+ // question is a call argument; or be indirectly implied by the kind of its
+ // containing operand bundle, if the operand is a bundle operand.
+
+ if (i == AttributeList::ReturnIndex)
+ return hasRetAttr(Kind);
+
+ // FIXME: Avoid these i - 1 calculations and update the API to use
+ // zero-based indices.
+ if (i < (getNumArgOperands() + 1))
+ return paramHasAttr(i - 1, Kind);
+
+ assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
+ "Must be either a call argument or an operand bundle!");
+ return bundleOperandHasAttr(i - 1, Kind);
+ }
/// Extract the alignment of the return value.
unsigned getRetAlignment() const { return Attrs.getRetAlignment(); }
@@ -1745,7 +1723,7 @@ public:
return Attrs.getDereferenceableOrNullBytes(i);
}
- /// @brief Determine if the return value is marked with NoAlias attribute.
+ /// Determine if the return value is marked with NoAlias attribute.
bool returnDoesNotAlias() const {
return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
}
@@ -1765,15 +1743,6 @@ public:
void setIsNoInline() {
addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);
}
-
- /// Return true if the call can return twice
- bool canReturnTwice() const {
- return hasFnAttr(Attribute::ReturnsTwice);
- }
- void setCanReturnTwice() {
- addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice);
- }
-
/// Determine if the call does not access memory.
bool doesNotAccessMemory() const {
return hasFnAttr(Attribute::ReadNone);
@@ -1798,7 +1767,7 @@ public:
addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly);
}
- /// @brief Determine if the call can access memmory only using pointers based
+ /// Determine if the call can access memmory only using pointers based
/// on its arguments.
bool onlyAccessesArgMemory() const {
return hasFnAttr(Attribute::ArgMemOnly);
@@ -1807,7 +1776,7 @@ public:
addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
}
- /// @brief Determine if the function may only access memory that is
+ /// Determine if the function may only access memory that is
/// inaccessible from the IR.
bool onlyAccessesInaccessibleMemory() const {
return hasFnAttr(Attribute::InaccessibleMemOnly);
@@ -1816,7 +1785,7 @@ public:
addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly);
}
- /// @brief Determine if the function may only access memory that is
+ /// Determine if the function may only access memory that is
/// either inaccessible from the IR or pointed to by its arguments.
bool onlyAccessesInaccessibleMemOrArgMem() const {
return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
@@ -1824,26 +1793,28 @@ public:
void setOnlyAccessesInaccessibleMemOrArgMem() {
addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly);
}
-
/// Determine if the call cannot return.
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
void setDoesNotReturn() {
addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
}
+ /// Determine if the call should not perform indirect branch tracking.
+ bool doesNoCfCheck() const { return hasFnAttr(Attribute::NoCfCheck); }
+
/// Determine if the call cannot unwind.
bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); }
void setDoesNotThrow() {
addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
}
- /// Determine if the call cannot be duplicated.
+ /// Determine if the invoke cannot be duplicated.
bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); }
void setCannotDuplicate() {
addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate);
}
- /// Determine if the call is convergent
+ /// Determine if the invoke is convergent
bool isConvergent() const { return hasFnAttr(Attribute::Convergent); }
void setConvergent() {
addAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
@@ -1866,18 +1837,10 @@ public:
bool hasByValArgument() const {
return Attrs.hasAttrSomewhere(Attribute::ByVal);
}
-
- /// Return the function called, or null if this is an
- /// indirect function invocation.
- ///
- Function *getCalledFunction() const {
- return dyn_cast<Function>(Op<-1>());
- }
-
/// Get a pointer to the function that is invoked by this
/// instruction.
- const Value *getCalledValue() const { return Op<-1>(); }
- Value *getCalledValue() { return Op<-1>(); }
+ const Value *getCalledValue() const { return Op<-InstTy::ArgOffset>(); }
+ Value *getCalledValue() { return Op<-InstTy::ArgOffset>(); }
/// Set the function called.
void setCalledFunction(Value* Fn) {
@@ -1889,23 +1852,10 @@ public:
this->FTy = FTy;
assert(FTy == cast<FunctionType>(
cast<PointerType>(Fn->getType())->getElementType()));
- Op<-1>() = Fn;
- }
-
- /// Check if this call is an inline asm statement.
- bool isInlineAsm() const {
- return isa<InlineAsm>(Op<-1>());
+ Op<-InstTy::ArgOffset>() = Fn;
}
- // Methods for support type inquiry through isa, cast, and dyn_cast:
- static bool classof(const Instruction *I) {
- return I->getOpcode() == Instruction::Call;
- }
- static bool classof(const Value *V) {
- return isa<Instruction>(V) && classof(cast<Instruction>(V));
- }
-
-private:
+protected:
template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const {
if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind))
return true;
@@ -1920,7 +1870,227 @@ private:
Kind);
return false;
}
+};
+
+//===----------------------------------------------------------------------===//
+/// This class represents a function call, abstracting a target
+/// machine's calling convention. This class uses low bit of the SubClassData
+/// field to indicate whether or not this is a tail call. The rest of the bits
+/// hold the calling convention of the call.
+///
+class CallInst : public CallBase<CallInst> {
+ friend class OperandBundleUser<CallInst, User::op_iterator>;
+
+ CallInst(const CallInst &CI);
+
+ /// Construct a CallInst given a range of arguments.
+ /// Construct a CallInst from a range of arguments
+ inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
+ Instruction *InsertBefore);
+
+ inline CallInst(Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : CallInst(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, Bundles, NameStr, InsertBefore) {}
+
+ inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : CallInst(Func, Args, None, NameStr, InsertBefore) {}
+
+ /// Construct a CallInst given a range of arguments.
+ /// Construct a CallInst from a range of arguments
+ inline CallInst(Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
+ BasicBlock *InsertAtEnd);
+
+ explicit CallInst(Value *F, const Twine &NameStr, Instruction *InsertBefore);
+
+ CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd);
+
+ void init(Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
+ init(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, Bundles, NameStr);
+ }
+ void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr);
+ void init(Value *Func, const Twine &NameStr);
+
+protected:
+ // Note: Instruction needs to be a friend here to call cloneImpl.
+ friend class Instruction;
+
+ CallInst *cloneImpl() const;
+
+public:
+ static constexpr int ArgOffset = 1;
+
+ static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles = None,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
+ return Create(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, Bundles, NameStr, InsertBefore);
+ }
+
+ static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
+ const Twine &NameStr,
+ Instruction *InsertBefore = nullptr) {
+ return Create(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, None, NameStr, InsertBefore);
+ }
+
+ static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
+ const Twine &NameStr,
+ Instruction *InsertBefore = nullptr) {
+ return new (unsigned(Args.size() + 1))
+ CallInst(Ty, Func, Args, None, NameStr, InsertBefore);
+ }
+
+ static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles = None,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
+ const unsigned TotalOps =
+ unsigned(Args.size()) + CountBundleInputs(Bundles) + 1;
+ const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo);
+
+ return new (TotalOps, DescriptorBytes)
+ CallInst(Ty, Func, Args, Bundles, NameStr, InsertBefore);
+ }
+
+ static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles,
+ const Twine &NameStr, BasicBlock *InsertAtEnd) {
+ const unsigned TotalOps =
+ unsigned(Args.size()) + CountBundleInputs(Bundles) + 1;
+ const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo);
+
+ return new (TotalOps, DescriptorBytes)
+ CallInst(Func, Args, Bundles, NameStr, InsertAtEnd);
+ }
+ static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
+ const Twine &NameStr, BasicBlock *InsertAtEnd) {
+ return new (unsigned(Args.size() + 1))
+ CallInst(Func, Args, None, NameStr, InsertAtEnd);
+ }
+
+ static CallInst *Create(Value *F, const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
+ return new (1) CallInst(F, NameStr, InsertBefore);
+ }
+
+ static CallInst *Create(Value *F, const Twine &NameStr,
+ BasicBlock *InsertAtEnd) {
+ return new (1) CallInst(F, NameStr, InsertAtEnd);
+ }
+
+ /// Create a clone of \p CI with a different set of operand bundles and
+ /// insert it before \p InsertPt.
+ ///
+ /// The returned call instruction is identical \p CI in every way except that
+ /// the operand bundles for the new instruction are set to the operand bundles
+ /// in \p Bundles.
+ static CallInst *Create(CallInst *CI, ArrayRef<OperandBundleDef> Bundles,
+ Instruction *InsertPt = nullptr);
+
+ /// Generate the IR for a call to malloc:
+ /// 1. Compute the malloc call's argument as the specified type's size,
+ /// possibly multiplied by the array size if the array size is not
+ /// constant 1.
+ /// 2. Call malloc with that argument.
+ /// 3. Bitcast the result of the malloc call to the specified type.
+ static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy,
+ Type *AllocTy, Value *AllocSize,
+ Value *ArraySize = nullptr,
+ Function *MallocF = nullptr,
+ const Twine &Name = "");
+ static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy,
+ Type *AllocTy, Value *AllocSize,
+ Value *ArraySize = nullptr,
+ Function *MallocF = nullptr,
+ const Twine &Name = "");
+ static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy,
+ Type *AllocTy, Value *AllocSize,
+ Value *ArraySize = nullptr,
+ ArrayRef<OperandBundleDef> Bundles = None,
+ Function *MallocF = nullptr,
+ const Twine &Name = "");
+ static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy,
+ Type *AllocTy, Value *AllocSize,
+ Value *ArraySize = nullptr,
+ ArrayRef<OperandBundleDef> Bundles = None,
+ Function *MallocF = nullptr,
+ const Twine &Name = "");
+ /// Generate the IR for a call to the builtin free function.
+ static Instruction *CreateFree(Value *Source, Instruction *InsertBefore);
+ static Instruction *CreateFree(Value *Source, BasicBlock *InsertAtEnd);
+ static Instruction *CreateFree(Value *Source,
+ ArrayRef<OperandBundleDef> Bundles,
+ Instruction *InsertBefore);
+ static Instruction *CreateFree(Value *Source,
+ ArrayRef<OperandBundleDef> Bundles,
+ BasicBlock *InsertAtEnd);
+
+ // Note that 'musttail' implies 'tail'.
+ enum TailCallKind {
+ TCK_None = 0,
+ TCK_Tail = 1,
+ TCK_MustTail = 2,
+ TCK_NoTail = 3
+ };
+ TailCallKind getTailCallKind() const {
+ return TailCallKind(getSubclassDataFromInstruction() & 3);
+ }
+
+ bool isTailCall() const {
+ unsigned Kind = getSubclassDataFromInstruction() & 3;
+ return Kind == TCK_Tail || Kind == TCK_MustTail;
+ }
+
+ bool isMustTailCall() const {
+ return (getSubclassDataFromInstruction() & 3) == TCK_MustTail;
+ }
+
+ bool isNoTailCall() const {
+ return (getSubclassDataFromInstruction() & 3) == TCK_NoTail;
+ }
+
+ void setTailCall(bool isTC = true) {
+ setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) |
+ unsigned(isTC ? TCK_Tail : TCK_None));
+ }
+
+ void setTailCallKind(TailCallKind TCK) {
+ setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) |
+ unsigned(TCK));
+ }
+
+ /// Return true if the call can return twice
+ bool canReturnTwice() const { return hasFnAttr(Attribute::ReturnsTwice); }
+ void setCanReturnTwice() {
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice);
+ }
+
+ /// Check if this call is an inline asm statement.
+ bool isInlineAsm() const { return isa<InlineAsm>(Op<-1>()); }
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static bool classof(const Instruction *I) {
+ return I->getOpcode() == Instruction::Call;
+ }
+ static bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+
+private:
// Shadow Instruction::setInstructionSubclassData with a private forwarding
// method so that subclasses cannot accidentally use it.
void setInstructionSubclassData(unsigned short D) {
@@ -1929,17 +2099,19 @@ private:
};
template <>
-struct OperandTraits<CallInst> : public VariadicOperandTraits<CallInst, 1> {
-};
+struct OperandTraits<CallBase<CallInst>>
+ : public VariadicOperandTraits<CallBase<CallInst>, 1> {};
CallInst::CallInst(Value *Func, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
BasicBlock *InsertAtEnd)
- : Instruction(
- cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call, OperandTraits<CallInst>::op_end(this) -
- (Args.size() + CountBundleInputs(Bundles) + 1),
+ : CallBase<CallInst>(
+ cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType())
+ ->getReturnType(),
+ Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::op_end(this) -
+ (Args.size() + CountBundleInputs(Bundles) + 1),
unsigned(Args.size() + CountBundleInputs(Bundles) + 1), InsertAtEnd) {
init(Func, Args, Bundles, NameStr);
}
@@ -1947,19 +2119,14 @@ CallInst::CallInst(Value *Func, ArrayRef<Value *> Args,
CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr,
Instruction *InsertBefore)
- : Instruction(Ty->getReturnType(), Instruction::Call,
- OperandTraits<CallInst>::op_end(this) -
- (Args.size() + CountBundleInputs(Bundles) + 1),
- unsigned(Args.size() + CountBundleInputs(Bundles) + 1),
- InsertBefore) {
+ : CallBase<CallInst>(Ty->getReturnType(), Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::op_end(this) -
+ (Args.size() + CountBundleInputs(Bundles) + 1),
+ unsigned(Args.size() + CountBundleInputs(Bundles) + 1),
+ InsertBefore) {
init(Ty, Func, Args, Bundles, NameStr);
}
-// Note: if you get compile errors about private methods then
-// please update your code to use the high-level operand
-// interfaces. See line 943 above.
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallInst, Value)
-
//===----------------------------------------------------------------------===//
// SelectInst Class
//===----------------------------------------------------------------------===//
@@ -2263,7 +2430,7 @@ public:
/// Return the shuffle mask value for the specified element of the mask.
/// Return -1 if the element is undef.
- static int getMaskValue(Constant *Mask, unsigned Elt);
+ static int getMaskValue(const Constant *Mask, unsigned Elt);
/// Return the shuffle mask value of this instruction for the given element
/// index. Return -1 if the element is undef.
@@ -2273,7 +2440,8 @@ public:
/// Convert the input shuffle mask operand to a vector of integers. Undefined
/// elements of the mask are returned as -1.
- static void getShuffleMask(Constant *Mask, SmallVectorImpl<int> &Result);
+ static void getShuffleMask(const Constant *Mask,
+ SmallVectorImpl<int> &Result);
/// Return the mask for this instruction as a vector of integers. Undefined
/// elements of the mask are returned as -1.
@@ -2287,6 +2455,176 @@ public:
return Mask;
}
+ /// Return true if this shuffle returns a vector with a different number of
+ /// elements than its source elements.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2>
+ bool changesLength() const {
+ unsigned NumSourceElts = Op<0>()->getType()->getVectorNumElements();
+ unsigned NumMaskElts = getMask()->getType()->getVectorNumElements();
+ return NumSourceElts != NumMaskElts;
+ }
+
+ /// Return true if this shuffle mask chooses elements from exactly one source
+ /// vector.
+ /// Example: <7,5,undef,7>
+ /// This assumes that vector operands are the same length as the mask.
+ static bool isSingleSourceMask(ArrayRef<int> Mask);
+ static bool isSingleSourceMask(const Constant *Mask) {
+ assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant.");
+ SmallVector<int, 16> MaskAsInts;
+ getShuffleMask(Mask, MaskAsInts);
+ return isSingleSourceMask(MaskAsInts);
+ }
+
+ /// Return true if this shuffle chooses elements from exactly one source
+ /// vector without changing the length of that vector.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <3,0,undef,3>
+ /// TODO: Optionally allow length-changing shuffles.
+ bool isSingleSource() const {
+ return !changesLength() && isSingleSourceMask(getMask());
+ }
+
+ /// Return true if this shuffle mask chooses elements from exactly one source
+ /// vector without lane crossings. A shuffle using this mask is not
+ /// necessarily a no-op because it may change the number of elements from its
+ /// input vectors or it may provide demanded bits knowledge via undef lanes.
+ /// Example: <undef,undef,2,3>
+ static bool isIdentityMask(ArrayRef<int> Mask);
+ static bool isIdentityMask(const Constant *Mask) {
+ assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant.");
+ SmallVector<int, 16> MaskAsInts;
+ getShuffleMask(Mask, MaskAsInts);
+ return isIdentityMask(MaskAsInts);
+ }
+
+ /// Return true if this shuffle mask chooses elements from exactly one source
+ /// vector without lane crossings and does not change the number of elements
+ /// from its input vectors.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef>
+ /// TODO: Optionally allow length-changing shuffles.
+ bool isIdentity() const {
+ return !changesLength() && isIdentityMask(getShuffleMask());
+ }
+
+ /// Return true if this shuffle mask chooses elements from its source vectors
+ /// without lane crossings. A shuffle using this mask would be
+ /// equivalent to a vector select with a constant condition operand.
+ /// Example: <4,1,6,undef>
+ /// This returns false if the mask does not choose from both input vectors.
+ /// In that case, the shuffle is better classified as an identity shuffle.
+ /// This assumes that vector operands are the same length as the mask
+ /// (a length-changing shuffle can never be equivalent to a vector select).
+ static bool isSelectMask(ArrayRef<int> Mask);
+ static bool isSelectMask(const Constant *Mask) {
+ assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant.");
+ SmallVector<int, 16> MaskAsInts;
+ getShuffleMask(Mask, MaskAsInts);
+ return isSelectMask(MaskAsInts);
+ }
+
+ /// Return true if this shuffle chooses elements from its source vectors
+ /// without lane crossings and all operands have the same number of elements.
+ /// In other words, this shuffle is equivalent to a vector select with a
+ /// constant condition operand.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,1,6,3>
+ /// This returns false if the mask does not choose from both input vectors.
+ /// In that case, the shuffle is better classified as an identity shuffle.
+ /// TODO: Optionally allow length-changing shuffles.
+ bool isSelect() const {
+ return !changesLength() && isSelectMask(getMask());
+ }
+
+ /// Return true if this shuffle mask swaps the order of elements from exactly
+ /// one source vector.
+ /// Example: <7,6,undef,4>
+ /// This assumes that vector operands are the same length as the mask.
+ static bool isReverseMask(ArrayRef<int> Mask);
+ static bool isReverseMask(const Constant *Mask) {
+ assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant.");
+ SmallVector<int, 16> MaskAsInts;
+ getShuffleMask(Mask, MaskAsInts);
+ return isReverseMask(MaskAsInts);
+ }
+
+ /// Return true if this shuffle swaps the order of elements from exactly
+ /// one source vector.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <3,undef,1,undef>
+ /// TODO: Optionally allow length-changing shuffles.
+ bool isReverse() const {
+ return !changesLength() && isReverseMask(getMask());
+ }
+
+ /// Return true if this shuffle mask chooses all elements with the same value
+ /// as the first element of exactly one source vector.
+ /// Example: <4,undef,undef,4>
+ /// This assumes that vector operands are the same length as the mask.
+ static bool isZeroEltSplatMask(ArrayRef<int> Mask);
+ static bool isZeroEltSplatMask(const Constant *Mask) {
+ assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant.");
+ SmallVector<int, 16> MaskAsInts;
+ getShuffleMask(Mask, MaskAsInts);
+ return isZeroEltSplatMask(MaskAsInts);
+ }
+
+ /// Return true if all elements of this shuffle are the same value as the
+ /// first element of exactly one source vector without changing the length
+ /// of that vector.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,0,undef,0>
+ /// TODO: Optionally allow length-changing shuffles.
+ /// TODO: Optionally allow splats from other elements.
+ bool isZeroEltSplat() const {
+ return !changesLength() && isZeroEltSplatMask(getMask());
+ }
+
+ /// Return true if this shuffle mask is a transpose mask.
+ /// Transpose vector masks transpose a 2xn matrix. They read corresponding
+ /// even- or odd-numbered vector elements from two n-dimensional source
+ /// vectors and write each result into consecutive elements of an
+ /// n-dimensional destination vector. Two shuffles are necessary to complete
+ /// the transpose, one for the even elements and another for the odd elements.
+ /// This description closely follows how the TRN1 and TRN2 AArch64
+ /// instructions operate.
+ ///
+ /// For example, a simple 2x2 matrix can be transposed with:
+ ///
+ /// ; Original matrix
+ /// m0 = < a, b >
+ /// m1 = < c, d >
+ ///
+ /// ; Transposed matrix
+ /// t0 = < a, c > = shufflevector m0, m1, < 0, 2 >
+ /// t1 = < b, d > = shufflevector m0, m1, < 1, 3 >
+ ///
+ /// For matrices having greater than n columns, the resulting nx2 transposed
+ /// matrix is stored in two result vectors such that one vector contains
+ /// interleaved elements from all the even-numbered rows and the other vector
+ /// contains interleaved elements from all the odd-numbered rows. For example,
+ /// a 2x4 matrix can be transposed with:
+ ///
+ /// ; Original matrix
+ /// m0 = < a, b, c, d >
+ /// m1 = < e, f, g, h >
+ ///
+ /// ; Transposed matrix
+ /// t0 = < a, e, c, g > = shufflevector m0, m1 < 0, 4, 2, 6 >
+ /// t1 = < b, f, d, h > = shufflevector m0, m1 < 1, 5, 3, 7 >
+ static bool isTransposeMask(ArrayRef<int> Mask);
+ static bool isTransposeMask(const Constant *Mask) {
+ assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant.");
+ SmallVector<int, 16> MaskAsInts;
+ getShuffleMask(Mask, MaskAsInts);
+ return isTransposeMask(MaskAsInts);
+ }
+
+ /// Return true if this shuffle transposes the elements of its inputs without
+ /// changing the length of the vectors. This operation may also be known as a
+ /// merge or interleave. See the description for isTransposeMask() for the
+ /// exact specification.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <0,4,2,6>
+ bool isTranspose() const {
+ return !changesLength() && isTransposeMask(getMask());
+ }
+
/// Change values in a shuffle permute mask assuming the two vector operands
/// of length InVecNumElts have swapped position.
static void commuteShuffleMask(MutableArrayRef<int> Mask,
@@ -3547,13 +3885,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value)
/// Invoke instruction. The SubclassData field is used to hold the
/// calling convention of the call.
///
-class InvokeInst : public TerminatorInst,
- public OperandBundleUser<InvokeInst, User::op_iterator> {
+class InvokeInst : public CallBase<InvokeInst> {
friend class OperandBundleUser<InvokeInst, User::op_iterator>;
- AttributeList Attrs;
- FunctionType *FTy;
-
InvokeInst(const InvokeInst &BI);
/// Construct an InvokeInst given a range of arguments.
@@ -3580,7 +3914,6 @@ class InvokeInst : public TerminatorInst,
unsigned Values, const Twine &NameStr,
BasicBlock *InsertAtEnd);
- bool hasDescriptor() const { return HasDescriptor; }
void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles,
@@ -3601,6 +3934,7 @@ protected:
InvokeInst *cloneImpl() const;
public:
+ static constexpr int ArgOffset = 3;
static InvokeInst *Create(Value *Func, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
const Twine &NameStr,
@@ -3674,299 +4008,15 @@ public:
static InvokeInst *Create(InvokeInst *II, ArrayRef<OperandBundleDef> Bundles,
Instruction *InsertPt = nullptr);
- /// Provide fast operand accessors
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
-
- FunctionType *getFunctionType() const { return FTy; }
-
- void mutateFunctionType(FunctionType *FTy) {
- mutateType(FTy->getReturnType());
- this->FTy = FTy;
- }
-
- /// Return the number of invoke arguments.
- ///
- unsigned getNumArgOperands() const {
- return getNumOperands() - getNumTotalBundleOperands() - 3;
- }
-
- /// getArgOperand/setArgOperand - Return/set the i-th invoke argument.
- ///
- Value *getArgOperand(unsigned i) const {
- assert(i < getNumArgOperands() && "Out of bounds!");
- return getOperand(i);
- }
- void setArgOperand(unsigned i, Value *v) {
- assert(i < getNumArgOperands() && "Out of bounds!");
- setOperand(i, v);
- }
-
- /// Return the iterator pointing to the beginning of the argument list.
- op_iterator arg_begin() { return op_begin(); }
-
- /// Return the iterator pointing to the end of the argument list.
- op_iterator arg_end() {
- // [ invoke args ], [ operand bundles ], normal dest, unwind dest, callee
- return op_end() - getNumTotalBundleOperands() - 3;
- }
-
- /// Iteration adapter for range-for loops.
- iterator_range<op_iterator> arg_operands() {
- return make_range(arg_begin(), arg_end());
- }
-
- /// Return the iterator pointing to the beginning of the argument list.
- const_op_iterator arg_begin() const { return op_begin(); }
-
- /// Return the iterator pointing to the end of the argument list.
- const_op_iterator arg_end() const {
- // [ invoke args ], [ operand bundles ], normal dest, unwind dest, callee
- return op_end() - getNumTotalBundleOperands() - 3;
- }
-
- /// Iteration adapter for range-for loops.
- iterator_range<const_op_iterator> arg_operands() const {
- return make_range(arg_begin(), arg_end());
- }
-
- /// Wrappers for getting the \c Use of a invoke argument.
- const Use &getArgOperandUse(unsigned i) const {
- assert(i < getNumArgOperands() && "Out of bounds!");
- return getOperandUse(i);
- }
- Use &getArgOperandUse(unsigned i) {
- assert(i < getNumArgOperands() && "Out of bounds!");
- return getOperandUse(i);
- }
-
- /// If one of the arguments has the 'returned' attribute, return its
- /// operand value. Otherwise, return nullptr.
- Value *getReturnedArgOperand() const;
-
- /// getCallingConv/setCallingConv - Get or set the calling convention of this
- /// function call.
- CallingConv::ID getCallingConv() const {
- return static_cast<CallingConv::ID>(getSubclassDataFromInstruction());
- }
- void setCallingConv(CallingConv::ID CC) {
- auto ID = static_cast<unsigned>(CC);
- assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention");
- setInstructionSubclassData(ID);
- }
-
- /// Return the parameter attributes for this invoke.
- ///
- AttributeList getAttributes() const { return Attrs; }
-
- /// Set the parameter attributes for this invoke.
- ///
- void setAttributes(AttributeList A) { Attrs = A; }
-
- /// adds the attribute to the list of attributes.
- void addAttribute(unsigned i, Attribute::AttrKind Kind);
-
- /// adds the attribute to the list of attributes.
- void addAttribute(unsigned i, Attribute Attr);
-
- /// Adds the attribute to the indicated argument
- void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
-
- /// removes the attribute from the list of attributes.
- void removeAttribute(unsigned i, Attribute::AttrKind Kind);
-
- /// removes the attribute from the list of attributes.
- void removeAttribute(unsigned i, StringRef Kind);
-
- /// Removes the attribute from the given argument
- void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
-
- /// adds the dereferenceable attribute to the list of attributes.
- void addDereferenceableAttr(unsigned i, uint64_t Bytes);
-
- /// adds the dereferenceable_or_null attribute to the list of
- /// attributes.
- void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
-
- /// Determine whether this call has the given attribute.
- bool hasFnAttr(Attribute::AttrKind Kind) const {
- assert(Kind != Attribute::NoBuiltin &&
- "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin");
- return hasFnAttrImpl(Kind);
- }
-
- /// Determine whether this call has the given attribute.
- bool hasFnAttr(StringRef Kind) const {
- return hasFnAttrImpl(Kind);
- }
-
- /// Determine whether the return value has the given attribute.
- bool hasRetAttr(Attribute::AttrKind Kind) const;
-
- /// Determine whether the argument or parameter has the given attribute.
- bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
-
- /// Get the attribute of a given kind at a position.
- Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
- return getAttributes().getAttribute(i, Kind);
- }
-
- /// Get the attribute of a given kind at a position.
- Attribute getAttribute(unsigned i, StringRef Kind) const {
- return getAttributes().getAttribute(i, Kind);
- }
-
- /// Return true if the data operand at index \p i has the attribute \p
- /// A.
- ///
- /// Data operands include invoke arguments and values used in operand bundles,
- /// but does not include the invokee operand, or the two successor blocks.
- /// This routine dispatches to the underlying AttributeList or the
- /// OperandBundleUser as appropriate.
- ///
- /// The index \p i is interpreted as
- ///
- /// \p i == Attribute::ReturnIndex -> the return value
- /// \p i in [1, arg_size + 1) -> argument number (\p i - 1)
- /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index
- /// (\p i - 1) in the operand list.
- bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const;
-
- /// Extract the alignment of the return value.
- unsigned getRetAlignment() const { return Attrs.getRetAlignment(); }
-
- /// Extract the alignment for a call or parameter (0=unknown).
- unsigned getParamAlignment(unsigned ArgNo) const {
- return Attrs.getParamAlignment(ArgNo);
- }
-
- /// Extract the number of dereferenceable bytes for a call or
- /// parameter (0=unknown).
- uint64_t getDereferenceableBytes(unsigned i) const {
- return Attrs.getDereferenceableBytes(i);
- }
-
- /// Extract the number of dereferenceable_or_null bytes for a call or
- /// parameter (0=unknown).
- uint64_t getDereferenceableOrNullBytes(unsigned i) const {
- return Attrs.getDereferenceableOrNullBytes(i);
- }
-
- /// @brief Determine if the return value is marked with NoAlias attribute.
- bool returnDoesNotAlias() const {
- return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
- }
-
- /// Return true if the call should not be treated as a call to a
- /// builtin.
- bool isNoBuiltin() const {
- // We assert in hasFnAttr if one passes in Attribute::NoBuiltin, so we have
- // to check it by hand.
- return hasFnAttrImpl(Attribute::NoBuiltin) &&
- !hasFnAttrImpl(Attribute::Builtin);
- }
-
- /// Determine if the call requires strict floating point semantics.
- bool isStrictFP() const { return hasFnAttr(Attribute::StrictFP); }
-
- /// Return true if the call should not be inlined.
- bool isNoInline() const { return hasFnAttr(Attribute::NoInline); }
- void setIsNoInline() {
- addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);
- }
-
- /// Determine if the call does not access memory.
- bool doesNotAccessMemory() const {
- return hasFnAttr(Attribute::ReadNone);
- }
- void setDoesNotAccessMemory() {
- addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
- }
-
- /// Determine if the call does not access or only reads memory.
- bool onlyReadsMemory() const {
- return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly);
- }
- void setOnlyReadsMemory() {
- addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly);
- }
-
- /// Determine if the call does not access or only writes memory.
- bool doesNotReadMemory() const {
- return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
- }
- void setDoesNotReadMemory() {
- addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly);
- }
-
- /// @brief Determine if the call access memmory only using it's pointer
- /// arguments.
- bool onlyAccessesArgMemory() const {
- return hasFnAttr(Attribute::ArgMemOnly);
- }
- void setOnlyAccessesArgMemory() {
- addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
- }
-
- /// @brief Determine if the function may only access memory that is
- /// inaccessible from the IR.
- bool onlyAccessesInaccessibleMemory() const {
- return hasFnAttr(Attribute::InaccessibleMemOnly);
- }
- void setOnlyAccessesInaccessibleMemory() {
- addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly);
- }
-
- /// @brief Determine if the function may only access memory that is
- /// either inaccessible from the IR or pointed to by its arguments.
- bool onlyAccessesInaccessibleMemOrArgMem() const {
- return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
- }
- void setOnlyAccessesInaccessibleMemOrArgMem() {
- addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly);
- }
-
- /// Determine if the call cannot return.
- bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
- void setDoesNotReturn() {
- addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
- }
+ /// Determine if the call should not perform indirect branch tracking.
+ bool doesNoCfCheck() const { return hasFnAttr(Attribute::NoCfCheck); }
/// Determine if the call cannot unwind.
bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); }
void setDoesNotThrow() {
addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
}
-
- /// Determine if the invoke cannot be duplicated.
- bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); }
- void setCannotDuplicate() {
- addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate);
- }
-
- /// Determine if the invoke is convergent
- bool isConvergent() const { return hasFnAttr(Attribute::Convergent); }
- void setConvergent() {
- addAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
- }
- void setNotConvergent() {
- removeAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
- }
-
- /// Determine if the call returns a structure through first
- /// pointer argument.
- bool hasStructRetAttr() const {
- if (getNumArgOperands() == 0)
- return false;
-
- // Be friendly and also check the callee.
- return paramHasAttr(0, Attribute::StructRet);
- }
-
- /// Determine if any call argument is an aggregate passed by value.
- bool hasByValArgument() const {
- return Attrs.hasAttrSomewhere(Attribute::ByVal);
- }
-
+
/// Return the function called, or null if this is an
/// indirect function invocation.
///
@@ -4031,20 +4081,6 @@ public:
}
private:
- template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const {
- if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind))
- return true;
-
- // Operand bundles override attributes on the called function, but don't
- // override attributes directly present on the invoke instruction.
- if (isFnAttrDisallowedByOpBundle(Kind))
- return false;
-
- if (const Function *F = getCalledFunction())
- return F->getAttributes().hasAttribute(AttributeList::FunctionIndex,
- Kind);
- return false;
- }
// Shadow Instruction::setInstructionSubclassData with a private forwarding
// method so that subclasses cannot accidentally use it.
@@ -4054,16 +4090,17 @@ private:
};
template <>
-struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> {
-};
+struct OperandTraits<CallBase<InvokeInst>>
+ : public VariadicOperandTraits<CallBase<InvokeInst>, 3> {};
InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, unsigned Values,
const Twine &NameStr, Instruction *InsertBefore)
- : TerminatorInst(Ty->getReturnType(), Instruction::Invoke,
- OperandTraits<InvokeInst>::op_end(this) - Values, Values,
- InsertBefore) {
+ : CallBase<InvokeInst>(Ty->getReturnType(), Instruction::Invoke,
+ OperandTraits<CallBase<InvokeInst>>::op_end(this) -
+ Values,
+ Values, InsertBefore) {
init(Ty, Func, IfNormal, IfException, Args, Bundles, NameStr);
}
@@ -4071,15 +4108,16 @@ InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, unsigned Values,
const Twine &NameStr, BasicBlock *InsertAtEnd)
- : TerminatorInst(
- cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Invoke, OperandTraits<InvokeInst>::op_end(this) - Values,
- Values, InsertAtEnd) {
+ : CallBase<InvokeInst>(
+ cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType())
+ ->getReturnType(),
+ Instruction::Invoke,
+ OperandTraits<CallBase<InvokeInst>>::op_end(this) - Values, Values,
+ InsertAtEnd) {
init(Func, IfNormal, IfException, Args, Bundles, NameStr);
}
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value)
//===----------------------------------------------------------------------===//
// ResumeInst Class
@@ -5190,6 +5228,26 @@ public:
}
};
+/// A helper function that returns the pointer operand of a load or store
+/// instruction. Returns nullptr if not load or store.
+inline Value *getLoadStorePointerOperand(Value *V) {
+ if (auto *Load = dyn_cast<LoadInst>(V))
+ return Load->getPointerOperand();
+ if (auto *Store = dyn_cast<StoreInst>(V))
+ return Store->getPointerOperand();
+ return nullptr;
+}
+
+/// A helper function that returns the pointer operand of a load, store
+/// or GEP instruction. Returns nullptr if not load, store, or GEP.
+inline Value *getPointerOperand(Value *V) {
+ if (auto *Ptr = getLoadStorePointerOperand(V))
+ return Ptr;
+ if (auto *Gep = dyn_cast<GetElementPtrInst>(V))
+ return Gep->getPointerOperand();
+ return nullptr;
+}
+
} // end namespace llvm
#endif // LLVM_IR_INSTRUCTIONS_H
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicInst.h b/contrib/llvm/include/llvm/IR/IntrinsicInst.h
index 2ca0a24cbae1..6650afcca7fb 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicInst.h
+++ b/contrib/llvm/include/llvm/IR/IntrinsicInst.h
@@ -93,6 +93,10 @@ namespace llvm {
return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
}
+ /// Get the size (in bits) of the variable, or fragment of the variable that
+ /// is described.
+ Optional<uint64_t> getFragmentSizeInBits() const;
+
/// \name Casting methods
/// @{
static bool classof(const IntrinsicInst *I) {
@@ -100,6 +104,7 @@ namespace llvm {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
case Intrinsic::dbg_addr:
+ case Intrinsic::dbg_label:
return true;
default: return false;
}
@@ -159,6 +164,32 @@ namespace llvm {
/// @}
};
+ /// This represents the llvm.dbg.label instruction.
+ class DbgLabelInst : public DbgInfoIntrinsic {
+ public:
+ DILabel *getLabel() const {
+ return cast<DILabel>(getRawVariable());
+ }
+
+ Metadata *getRawVariable() const {
+ return cast<MetadataAsValue>(getArgOperand(0))->getMetadata();
+ }
+
+ Metadata *getRawExpression() const {
+ return nullptr;
+ }
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// @{
+ static bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::dbg_label;
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ /// @}
+ };
+
/// This is the common base class for constrained floating point intrinsics.
class ConstrainedFPIntrinsic : public IntrinsicInst {
public:
@@ -243,6 +274,8 @@ namespace llvm {
return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
}
+ unsigned getDestAlignment() const { return getParamAlignment(ARG_DEST); }
+
/// Set the specified arguments of the instruction.
void setDest(Value *Ptr) {
assert(getRawDest()->getType() == Ptr->getType() &&
@@ -250,6 +283,13 @@ namespace llvm {
setArgOperand(ARG_DEST, Ptr);
}
+ void setDestAlignment(unsigned Align) {
+ removeParamAttr(ARG_DEST, Attribute::Alignment);
+ if (Align > 0)
+ addParamAttr(ARG_DEST,
+ Attribute::getWithAlignment(getContext(), Align));
+ }
+
void setLength(Value *L) {
assert(getLength()->getType() == L->getType() &&
"setLength called with value of wrong type!");
@@ -257,6 +297,71 @@ namespace llvm {
}
};
+ /// Common base class for all memory transfer intrinsics. Simply provides
+ /// common methods.
+ template <class BaseCL> class MemTransferBase : public BaseCL {
+ private:
+ enum { ARG_SOURCE = 1 };
+
+ public:
+ /// Return the arguments to the instruction.
+ Value *getRawSource() const {
+ return const_cast<Value *>(BaseCL::getArgOperand(ARG_SOURCE));
+ }
+ const Use &getRawSourceUse() const {
+ return BaseCL::getArgOperandUse(ARG_SOURCE);
+ }
+ Use &getRawSourceUse() { return BaseCL::getArgOperandUse(ARG_SOURCE); }
+
+ /// This is just like getRawSource, but it strips off any cast
+ /// instructions that feed it, giving the original input. The returned
+ /// value is guaranteed to be a pointer.
+ Value *getSource() const { return getRawSource()->stripPointerCasts(); }
+
+ unsigned getSourceAddressSpace() const {
+ return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
+ }
+
+ unsigned getSourceAlignment() const {
+ return BaseCL::getParamAlignment(ARG_SOURCE);
+ }
+
+ void setSource(Value *Ptr) {
+ assert(getRawSource()->getType() == Ptr->getType() &&
+ "setSource called with pointer of wrong type!");
+ BaseCL::setArgOperand(ARG_SOURCE, Ptr);
+ }
+
+ void setSourceAlignment(unsigned Align) {
+ BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment);
+ if (Align > 0)
+ BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment(
+ BaseCL::getContext(), Align));
+ }
+ };
+
+ /// Common base class for all memset intrinsics. Simply provides
+ /// common methods.
+ template <class BaseCL> class MemSetBase : public BaseCL {
+ private:
+ enum { ARG_VALUE = 1 };
+
+ public:
+ Value *getValue() const {
+ return const_cast<Value *>(BaseCL::getArgOperand(ARG_VALUE));
+ }
+ const Use &getValueUse() const {
+ return BaseCL::getArgOperandUse(ARG_VALUE);
+ }
+ Use &getValueUse() { return BaseCL::getArgOperandUse(ARG_VALUE); }
+
+ void setValue(Value *Val) {
+ assert(getValue()->getType() == Val->getType() &&
+ "setValue called with value of wrong type!");
+ BaseCL::setArgOperand(ARG_VALUE, Val);
+ }
+ };
+
// The common base class for the atomic memset/memmove/memcpy intrinsics
// i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> {
@@ -299,23 +404,8 @@ namespace llvm {
/// This class represents atomic memset intrinsic
// i.e. llvm.element.unordered.atomic.memset
- class AtomicMemSetInst : public AtomicMemIntrinsic {
- private:
- enum { ARG_VALUE = 1 };
-
+ class AtomicMemSetInst : public MemSetBase<AtomicMemIntrinsic> {
public:
- Value *getValue() const {
- return const_cast<Value *>(getArgOperand(ARG_VALUE));
- }
- const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); }
- Use &getValueUse() { return getArgOperandUse(ARG_VALUE); }
-
- void setValue(Value *Val) {
- assert(getValue()->getType() == Val->getType() &&
- "setValue called with value of wrong type!");
- setArgOperand(ARG_VALUE, Val);
- }
-
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic;
}
@@ -326,33 +416,8 @@ namespace llvm {
// This class wraps the atomic memcpy/memmove intrinsics
// i.e. llvm.element.unordered.atomic.memcpy/memmove
- class AtomicMemTransferInst : public AtomicMemIntrinsic {
- private:
- enum { ARG_SOURCE = 1 };
-
+ class AtomicMemTransferInst : public MemTransferBase<AtomicMemIntrinsic> {
public:
- /// Return the arguments to the instruction.
- Value *getRawSource() const {
- return const_cast<Value *>(getArgOperand(ARG_SOURCE));
- }
- const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
- Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
-
- /// This is just like getRawSource, but it strips off any cast
- /// instructions that feed it, giving the original input. The returned
- /// value is guaranteed to be a pointer.
- Value *getSource() const { return getRawSource()->stripPointerCasts(); }
-
- unsigned getSourceAddressSpace() const {
- return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
- }
-
- void setSource(Value *Ptr) {
- assert(getRawSource()->getType() == Ptr->getType() &&
- "setSource called with pointer of wrong type!");
- setArgOperand(ARG_SOURCE, Ptr);
- }
-
static bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
case Intrinsic::memcpy_element_unordered_atomic:
@@ -394,17 +459,9 @@ namespace llvm {
/// This is the common base class for memset/memcpy/memmove.
class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> {
private:
- enum { ARG_ALIGN = 3, ARG_VOLATILE = 4 };
+ enum { ARG_VOLATILE = 3 };
public:
- ConstantInt *getAlignmentCst() const {
- return cast<ConstantInt>(const_cast<Value *>(getArgOperand(ARG_ALIGN)));
- }
-
- unsigned getAlignment() const {
- return getAlignmentCst()->getZExtValue();
- }
-
ConstantInt *getVolatileCst() const {
return cast<ConstantInt>(
const_cast<Value *>(getArgOperand(ARG_VOLATILE)));
@@ -414,14 +471,8 @@ namespace llvm {
return !getVolatileCst()->isZero();
}
- void setAlignment(Constant *A) { setArgOperand(ARG_ALIGN, A); }
-
void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); }
- Type *getAlignmentType() const {
- return getArgOperand(ARG_ALIGN)->getType();
- }
-
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
@@ -438,19 +489,8 @@ namespace llvm {
};
/// This class wraps the llvm.memset intrinsic.
- class MemSetInst : public MemIntrinsic {
+ class MemSetInst : public MemSetBase<MemIntrinsic> {
public:
- /// Return the arguments to the instruction.
- Value *getValue() const { return const_cast<Value*>(getArgOperand(1)); }
- const Use &getValueUse() const { return getArgOperandUse(1); }
- Use &getValueUse() { return getArgOperandUse(1); }
-
- void setValue(Value *Val) {
- assert(getValue()->getType() == Val->getType() &&
- "setValue called with value of wrong type!");
- setArgOperand(1, Val);
- }
-
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::memset;
@@ -461,28 +501,8 @@ namespace llvm {
};
/// This class wraps the llvm.memcpy/memmove intrinsics.
- class MemTransferInst : public MemIntrinsic {
+ class MemTransferInst : public MemTransferBase<MemIntrinsic> {
public:
- /// Return the arguments to the instruction.
- Value *getRawSource() const { return const_cast<Value*>(getArgOperand(1)); }
- const Use &getRawSourceUse() const { return getArgOperandUse(1); }
- Use &getRawSourceUse() { return getArgOperandUse(1); }
-
- /// This is just like getRawSource, but it strips off any cast
- /// instructions that feed it, giving the original input. The returned
- /// value is guaranteed to be a pointer.
- Value *getSource() const { return getRawSource()->stripPointerCasts(); }
-
- unsigned getSourceAddressSpace() const {
- return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
- }
-
- void setSource(Value *Ptr) {
- assert(getRawSource()->getType() == Ptr->getType() &&
- "setSource called with pointer of wrong type!");
- setArgOperand(1, Ptr);
- }
-
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::memcpy ||
@@ -551,23 +571,8 @@ namespace llvm {
/// This class represents any memset intrinsic
// i.e. llvm.element.unordered.atomic.memset
// and llvm.memset
- class AnyMemSetInst : public AnyMemIntrinsic {
- private:
- enum { ARG_VALUE = 1 };
-
+ class AnyMemSetInst : public MemSetBase<AnyMemIntrinsic> {
public:
- Value *getValue() const {
- return const_cast<Value *>(getArgOperand(ARG_VALUE));
- }
- const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); }
- Use &getValueUse() { return getArgOperandUse(ARG_VALUE); }
-
- void setValue(Value *Val) {
- assert(getValue()->getType() == Val->getType() &&
- "setValue called with value of wrong type!");
- setArgOperand(ARG_VALUE, Val);
- }
-
static bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
case Intrinsic::memset:
@@ -585,33 +590,8 @@ namespace llvm {
// This class wraps any memcpy/memmove intrinsics
// i.e. llvm.element.unordered.atomic.memcpy/memmove
// and llvm.memcpy/memmove
- class AnyMemTransferInst : public AnyMemIntrinsic {
- private:
- enum { ARG_SOURCE = 1 };
-
+ class AnyMemTransferInst : public MemTransferBase<AnyMemIntrinsic> {
public:
- /// Return the arguments to the instruction.
- Value *getRawSource() const {
- return const_cast<Value *>(getArgOperand(ARG_SOURCE));
- }
- const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
- Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
-
- /// This is just like getRawSource, but it strips off any cast
- /// instructions that feed it, giving the original input. The returned
- /// value is guaranteed to be a pointer.
- Value *getSource() const { return getRawSource()->stripPointerCasts(); }
-
- unsigned getSourceAddressSpace() const {
- return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
- }
-
- void setSource(Value *Ptr) {
- assert(getRawSource()->getType() == Ptr->getType() &&
- "setSource called with pointer of wrong type!");
- setArgOperand(ARG_SOURCE, Ptr);
- }
-
static bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
case Intrinsic::memcpy:
diff --git a/contrib/llvm/include/llvm/IR/Intrinsics.h b/contrib/llvm/include/llvm/IR/Intrinsics.h
index fc79da7ae0e6..e1e17f983ff8 100644
--- a/contrib/llvm/include/llvm/IR/Intrinsics.h
+++ b/contrib/llvm/include/llvm/IR/Intrinsics.h
@@ -39,7 +39,7 @@ namespace Intrinsic {
// Get the intrinsic enums generated from Intrinsics.td
#define GET_INTRINSIC_ENUM_VALUES
-#include "llvm/IR/Intrinsics.gen"
+#include "llvm/IR/IntrinsicEnums.inc"
#undef GET_INTRINSIC_ENUM_VALUES
, num_intrinsics
};
@@ -97,7 +97,7 @@ namespace Intrinsic {
/// intrinsic. This is returned by getIntrinsicInfoTableEntries.
struct IITDescriptor {
enum IITDescriptorKind {
- Void, VarArg, MMX, Token, Metadata, Half, Float, Double,
+ Void, VarArg, MMX, Token, Metadata, Half, Float, Double, Quad,
Integer, Vector, Pointer, Struct,
Argument, ExtendArgument, TruncArgument, HalfVecArgument,
SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfAnyPtrsToElt
diff --git a/contrib/llvm/include/llvm/IR/Intrinsics.td b/contrib/llvm/include/llvm/IR/Intrinsics.td
index a2a1f26292ce..64455573ff19 100644
--- a/contrib/llvm/include/llvm/IR/Intrinsics.td
+++ b/contrib/llvm/include/llvm/IR/Intrinsics.td
@@ -117,6 +117,7 @@ def IntrHasSideEffects : IntrinsicProperty;
class LLVMType<ValueType vt> {
ValueType VT = vt;
+ int isAny = 0;
}
class LLVMQualPointerType<LLVMType elty, int addrspace>
@@ -131,6 +132,8 @@ class LLVMPointerType<LLVMType elty>
class LLVMAnyPointerType<LLVMType elty>
: LLVMType<iPTRAny>{
LLVMType ElTy = elty;
+
+ let isAny = 1;
}
// Match the type of another intrinsic parameter. Number is an index into the
@@ -163,10 +166,12 @@ class LLVMVectorOfAnyPointersToElt<int num> : LLVMMatchType<num>;
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>;
+let isAny = 1 in {
+ def llvm_any_ty : LLVMType<Any>;
+ def llvm_anyint_ty : LLVMType<iAny>;
+ def llvm_anyfloat_ty : LLVMType<fAny>;
+ def llvm_anyvector_ty : LLVMType<vAny>;
+}
def llvm_i1_ty : LLVMType<i1>;
def llvm_i8_ty : LLVMType<i8>;
def llvm_i16_ty : LLVMType<i16>;
@@ -249,7 +254,6 @@ def llvm_v8f64_ty : LLVMType<v8f64>; // 8 x double
def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here
-
//===----------------------------------------------------------------------===//
// Intrinsic Definitions.
//===----------------------------------------------------------------------===//
@@ -390,17 +394,17 @@ def int_instrprof_value_profile : Intrinsic<[],
def int_memcpy : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty,
- llvm_i32_ty, llvm_i1_ty],
+ llvm_i1_ty],
[IntrArgMemOnly, NoCapture<0>, NoCapture<1>,
WriteOnly<0>, ReadOnly<1>]>;
def int_memmove : Intrinsic<[],
[llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty,
- llvm_i32_ty, llvm_i1_ty],
+ llvm_i1_ty],
[IntrArgMemOnly, NoCapture<0>, NoCapture<1>,
ReadOnly<1>]>;
def int_memset : Intrinsic<[],
[llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty,
- llvm_i32_ty, llvm_i1_ty],
+ llvm_i1_ty],
[IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>;
// FIXME: Add version of these floating point intrinsics which allow non-default
@@ -573,6 +577,10 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>;
def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>;
def int_bitreverse : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>;
+ def int_fshl : Intrinsic<[llvm_anyint_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
+ def int_fshr : Intrinsic<[llvm_anyint_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
}
//===------------------------ Debugger Intrinsics -------------------------===//
@@ -595,6 +603,8 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
[llvm_metadata_ty,
llvm_metadata_ty,
llvm_metadata_ty]>;
+ def int_dbg_label : Intrinsic<[],
+ [llvm_metadata_ty]>;
}
//===------------------ Exception Handling Intrinsics----------------------===//
@@ -706,16 +716,26 @@ def int_invariant_end : Intrinsic<[],
llvm_anyptr_ty],
[IntrArgMemOnly, NoCapture<2>]>;
-// invariant.group.barrier can't be marked with 'readnone' (IntrNoMem),
+// launder.invariant.group can't be marked with 'readnone' (IntrNoMem),
// because it would cause CSE of two barriers with the same argument.
-// Readonly and argmemonly says that barrier only reads its argument and
-// it can be CSE only if memory didn't change between 2 barriers call,
-// which is valid.
+// Inaccessiblememonly says that the barrier doesn't read the argument,
+// but it changes state not accessible to this module. This way
+// we can DSE through the barrier because it doesn't read the value
+// after store. Although the barrier doesn't modify any memory it
+// can't be marked as readonly, because it would be possible to
+// CSE 2 barriers with store in between.
// The argument also can't be marked with 'returned' attribute, because
// it would remove barrier.
-def int_invariant_group_barrier : Intrinsic<[llvm_anyptr_ty],
+// Note that it is still experimental, which means that its semantics
+// might change in the future.
+def int_launder_invariant_group : Intrinsic<[llvm_anyptr_ty],
[LLVMMatchType<0>],
- [IntrReadMem, IntrArgMemOnly]>;
+ [IntrInaccessibleMemOnly, IntrSpeculatable]>;
+
+
+def int_strip_invariant_group : Intrinsic<[llvm_anyptr_ty],
+ [LLVMMatchType<0>],
+ [IntrSpeculatable, IntrNoMem]>;
//===------------------------ Stackmap Intrinsics -------------------------===//
//
@@ -768,6 +788,7 @@ def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
def int_coro_end : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_i1_ty], []>;
def int_coro_frame : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
+def int_coro_noop : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
def int_coro_size : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>;
def int_coro_save : Intrinsic<[llvm_token_ty], [llvm_ptr_ty], []>;
@@ -874,6 +895,10 @@ def int_type_checked_load : Intrinsic<[llvm_ptr_ty, llvm_i1_ty],
[llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty],
[IntrNoMem]>;
+// Create a branch funnel that implements an indirect call to a limited set of
+// callees. This needs to be a musttail call.
+def int_icall_branch_funnel : Intrinsic<[], [llvm_vararg_ty], []>;
+
def int_load_relative: Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty],
[IntrReadMem, IntrArgMemOnly]>;
@@ -883,6 +908,10 @@ def int_load_relative: Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty],
// Takes a pointer to a string and the length of the string.
def int_xray_customevent : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty],
[NoCapture<0>, ReadOnly<0>, IntrWriteMem]>;
+// Typed event logging for x-ray.
+// Takes a numeric type tag, a pointer to a string and the length of the string.
+def int_xray_typedevent : Intrinsic<[], [llvm_i16_ty, llvm_ptr_ty, llvm_i32_ty],
+ [NoCapture<1>, ReadOnly<1>, IntrWriteMem]>;
//===----------------------------------------------------------------------===//
//===------ Memory intrinsics with element-wise atomicity guarantees ------===//
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td b/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 65c9aaab975d..688e863c1afe 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td
+++ b/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td
@@ -146,6 +146,14 @@ let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.".
class AdvSIMD_CvtFPToFx_Intrinsic
: Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty],
[IntrNoMem]>;
+
+ class AdvSIMD_1Arg_Intrinsic
+ : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+
+ class AdvSIMD_Dot_Intrinsic
+ : Intrinsic<[llvm_anyvector_ty],
+ [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>],
+ [IntrNoMem]>;
}
// Arithmetic ops
@@ -244,7 +252,7 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in {
// Vector Max
def int_aarch64_neon_smax : AdvSIMD_2VectorArg_Intrinsic;
def int_aarch64_neon_umax : AdvSIMD_2VectorArg_Intrinsic;
- def int_aarch64_neon_fmax : AdvSIMD_2VectorArg_Intrinsic;
+ def int_aarch64_neon_fmax : AdvSIMD_2FloatArg_Intrinsic;
def int_aarch64_neon_fmaxnmp : AdvSIMD_2VectorArg_Intrinsic;
// Vector Max Across Lanes
@@ -256,7 +264,7 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in {
// Vector Min
def int_aarch64_neon_smin : AdvSIMD_2VectorArg_Intrinsic;
def int_aarch64_neon_umin : AdvSIMD_2VectorArg_Intrinsic;
- def int_aarch64_neon_fmin : AdvSIMD_2VectorArg_Intrinsic;
+ def int_aarch64_neon_fmin : AdvSIMD_2FloatArg_Intrinsic;
def int_aarch64_neon_fminnmp : AdvSIMD_2VectorArg_Intrinsic;
// Vector Min/Max Number
@@ -354,7 +362,7 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in {
def int_aarch64_neon_sqxtun : AdvSIMD_1VectorArg_Narrow_Intrinsic;
// Vector Absolute Value
- def int_aarch64_neon_abs : AdvSIMD_1IntArg_Intrinsic;
+ def int_aarch64_neon_abs : AdvSIMD_1Arg_Intrinsic;
// Vector Saturating Absolute Value
def int_aarch64_neon_sqabs : AdvSIMD_1IntArg_Intrinsic;
@@ -412,6 +420,10 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in {
// Scalar FP Inexact Narrowing
def int_aarch64_sisd_fcvtxn : Intrinsic<[llvm_float_ty], [llvm_double_ty],
[IntrNoMem]>;
+
+ // v8.2-A Dot Product
+ def int_aarch64_neon_udot : AdvSIMD_Dot_Intrinsic;
+ def int_aarch64_neon_sdot : AdvSIMD_Dot_Intrinsic;
}
let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.".
@@ -572,6 +584,14 @@ def int_aarch64_neon_tbx3 : AdvSIMD_Tbx3_Intrinsic;
def int_aarch64_neon_tbx4 : AdvSIMD_Tbx4_Intrinsic;
let TargetPrefix = "aarch64" in {
+ class FPCR_Get_Intrinsic
+ : Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>;
+}
+
+// FPCR
+def int_aarch64_get_fpcr : FPCR_Get_Intrinsic;
+
+let TargetPrefix = "aarch64" in {
class Crypto_AES_DataKey_Intrinsic
: Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>;
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
index 3397fa41db1b..8555db01645f 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -17,6 +17,13 @@ class AMDGPUReadPreloadRegisterIntrinsic
class AMDGPUReadPreloadRegisterIntrinsicNamed<string name>
: Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable]>, GCCBuiltin<name>;
+// Used to tag image and resource intrinsics with information used to generate
+// mem operands.
+class AMDGPURsrcIntrinsic<int rsrcarg, bit isimage = 0> {
+ int RsrcArg = rsrcarg;
+ bit IsImage = isimage;
+}
+
let TargetPrefix = "r600" in {
multiclass AMDGPUReadPreloadRegisterIntrinsic_xyz {
@@ -69,6 +76,59 @@ def int_r600_cube : Intrinsic<
[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem, IntrSpeculatable]
>;
+def int_r600_store_stream_output : Intrinsic<
+ [], [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []
+>;
+
+class TextureIntrinsicFloatInput : Intrinsic<[llvm_v4f32_ty], [
+ llvm_v4f32_ty, // Coord
+ llvm_i32_ty, // offset_x
+ llvm_i32_ty, // offset_y,
+ llvm_i32_ty, // offset_z,
+ llvm_i32_ty, // resource_id
+ llvm_i32_ty, // samplerid
+ llvm_i32_ty, // coord_type_x
+ llvm_i32_ty, // coord_type_y
+ llvm_i32_ty, // coord_type_z
+ llvm_i32_ty], // coord_type_w
+ [IntrNoMem]
+>;
+
+class TextureIntrinsicInt32Input : Intrinsic<[llvm_v4i32_ty], [
+ llvm_v4i32_ty, // Coord
+ llvm_i32_ty, // offset_x
+ llvm_i32_ty, // offset_y,
+ llvm_i32_ty, // offset_z,
+ llvm_i32_ty, // resource_id
+ llvm_i32_ty, // samplerid
+ llvm_i32_ty, // coord_type_x
+ llvm_i32_ty, // coord_type_y
+ llvm_i32_ty, // coord_type_z
+ llvm_i32_ty], // coord_type_w
+ [IntrNoMem]
+>;
+
+def int_r600_store_swizzle :
+ Intrinsic<[], [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], []
+>;
+
+def int_r600_tex : TextureIntrinsicFloatInput;
+def int_r600_texc : TextureIntrinsicFloatInput;
+def int_r600_txl : TextureIntrinsicFloatInput;
+def int_r600_txlc : TextureIntrinsicFloatInput;
+def int_r600_txb : TextureIntrinsicFloatInput;
+def int_r600_txbc : TextureIntrinsicFloatInput;
+def int_r600_txf : TextureIntrinsicInt32Input;
+def int_r600_txq : TextureIntrinsicInt32Input;
+def int_r600_ddx : TextureIntrinsicFloatInput;
+def int_r600_ddy : TextureIntrinsicFloatInput;
+
+def int_r600_dot4 : Intrinsic<[llvm_float_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem, IntrSpeculatable]
+>;
+
+def int_r600_kill : Intrinsic<[], [llvm_float_ty], []>;
+
} // End TargetPrefix = "r600"
let TargetPrefix = "amdgcn" in {
@@ -83,22 +143,22 @@ defm int_amdgcn_workgroup_id : AMDGPUReadPreloadRegisterIntrinsic_xyz_named
def int_amdgcn_dispatch_ptr :
GCCBuiltin<"__builtin_amdgcn_dispatch_ptr">,
- Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [],
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [],
[IntrNoMem, IntrSpeculatable]>;
def int_amdgcn_queue_ptr :
GCCBuiltin<"__builtin_amdgcn_queue_ptr">,
- Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [],
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [],
[IntrNoMem, IntrSpeculatable]>;
def int_amdgcn_kernarg_segment_ptr :
GCCBuiltin<"__builtin_amdgcn_kernarg_segment_ptr">,
- Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [],
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [],
[IntrNoMem, IntrSpeculatable]>;
def int_amdgcn_implicitarg_ptr :
GCCBuiltin<"__builtin_amdgcn_implicitarg_ptr">,
- Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [],
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [],
[IntrNoMem, IntrSpeculatable]>;
def int_amdgcn_groupstaticsize :
@@ -111,7 +171,7 @@ def int_amdgcn_dispatch_id :
def int_amdgcn_implicit_buffer_ptr :
GCCBuiltin<"__builtin_amdgcn_implicit_buffer_ptr">,
- Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [],
+ Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [],
[IntrNoMem, IntrSpeculatable]>;
// Set EXEC to the 64-bit value given.
@@ -300,6 +360,12 @@ def int_amdgcn_sffbh :
[IntrNoMem, IntrSpeculatable]
>;
+// v_mad_f32|f16/v_mac_f32|f16, selected regardless of denorm support.
+def int_amdgcn_fmad_ftz :
+ Intrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
+ [IntrNoMem, IntrSpeculatable]
+>;
// Fields should mirror atomicrmw
class AMDGPUAtomicIncIntrin : Intrinsic<[llvm_anyint_ty],
@@ -315,165 +381,414 @@ class AMDGPUAtomicIncIntrin : Intrinsic<[llvm_anyint_ty],
def int_amdgcn_atomic_inc : AMDGPUAtomicIncIntrin;
def int_amdgcn_atomic_dec : AMDGPUAtomicIncIntrin;
-class AMDGPUImageLoad<bit NoMem = 0> : Intrinsic <
- [llvm_anyfloat_ty], // vdata(VGPR)
- [llvm_anyint_ty, // vaddr(VGPR)
- llvm_anyint_ty, // rsrc(SGPR)
- llvm_i32_ty, // dmask(imm)
- llvm_i1_ty, // glc(imm)
- llvm_i1_ty, // slc(imm)
- llvm_i1_ty, // lwe(imm)
- llvm_i1_ty], // da(imm)
- !if(NoMem, [IntrNoMem], [IntrReadMem]), "",
- !if(NoMem, [], [SDNPMemOperand])>;
+class AMDGPULDSF32Intrin<string clang_builtin> :
+ GCCBuiltin<clang_builtin>,
+ Intrinsic<[llvm_float_ty],
+ [LLVMQualPointerType<llvm_float_ty, 3>,
+ llvm_float_ty,
+ llvm_i32_ty, // ordering
+ llvm_i32_ty, // scope
+ llvm_i1_ty], // isVolatile
+ [IntrArgMemOnly, NoCapture<0>]
+>;
-def int_amdgcn_image_load : AMDGPUImageLoad;
-def int_amdgcn_image_load_mip : AMDGPUImageLoad;
-def int_amdgcn_image_getresinfo : AMDGPUImageLoad<1>;
+def int_amdgcn_ds_fadd : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_faddf">;
+def int_amdgcn_ds_fmin : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_fminf">;
+def int_amdgcn_ds_fmax : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_fmaxf">;
-class AMDGPUImageStore : Intrinsic <
- [],
- [llvm_anyfloat_ty, // vdata(VGPR)
- llvm_anyint_ty, // vaddr(VGPR)
- llvm_anyint_ty, // rsrc(SGPR)
- llvm_i32_ty, // dmask(imm)
- llvm_i1_ty, // glc(imm)
- llvm_i1_ty, // slc(imm)
- llvm_i1_ty, // lwe(imm)
- llvm_i1_ty], // da(imm)
- [IntrWriteMem], "", [SDNPMemOperand]>;
+} // TargetPrefix = "amdgcn"
+
+// New-style image intrinsics
+
+//////////////////////////////////////////////////////////////////////////
+// Dimension-aware image intrinsics framework
+//////////////////////////////////////////////////////////////////////////
+
+// Helper class to represent (type, name) combinations of arguments. The
+// argument names are explanatory and used as DAG operand names for codegen
+// pattern matching.
+class AMDGPUArg<LLVMType ty, string name> {
+ LLVMType Type = ty;
+ string Name = name;
+}
+
+// Return [AMDGPUArg<basety, names[0]>, AMDGPUArg<LLVMMatchType<0>, names[1]>, ...]
+class makeArgList<list<string> names, LLVMType basety> {
+ list<AMDGPUArg> ret =
+ !listconcat([AMDGPUArg<basety, names[0]>],
+ !foreach(name, !tail(names), AMDGPUArg<LLVMMatchType<0>, name>));
+}
+
+// Return arglist, with LLVMMatchType's references shifted by 'shift'.
+class arglistmatchshift<list<AMDGPUArg> arglist, int shift> {
+ list<AMDGPUArg> ret =
+ !foreach(arg, arglist,
+ !if(!isa<LLVMMatchType>(arg.Type),
+ AMDGPUArg<LLVMMatchType<!add(!cast<LLVMMatchType>(arg.Type).Number, shift)>,
+ arg.Name>,
+ arg));
+}
-def int_amdgcn_image_store : AMDGPUImageStore;
-def int_amdgcn_image_store_mip : AMDGPUImageStore;
+// Return the concatenation of the given arglists. LLVMMatchType's are adjusted
+// accordingly, and shifted by an additional 'shift'.
+class arglistconcat<list<list<AMDGPUArg>> arglists, int shift = 0> {
+ list<AMDGPUArg> ret =
+ !foldl([]<AMDGPUArg>, arglists, lhs, rhs,
+ !listconcat(
+ lhs,
+ arglistmatchshift<rhs,
+ !add(shift, !foldl(0, lhs, a, b,
+ !add(a, b.Type.isAny)))>.ret));
+}
-class AMDGPUImageSample<bit NoMem = 0> : Intrinsic <
- [llvm_anyfloat_ty], // vdata(VGPR)
- [llvm_anyfloat_ty, // vaddr(VGPR)
- llvm_anyint_ty, // rsrc(SGPR)
- llvm_v4i32_ty, // sampler(SGPR)
- llvm_i32_ty, // dmask(imm)
- llvm_i1_ty, // unorm(imm)
- llvm_i1_ty, // glc(imm)
- llvm_i1_ty, // slc(imm)
- llvm_i1_ty, // lwe(imm)
- llvm_i1_ty], // da(imm)
- !if(NoMem, [IntrNoMem], [IntrReadMem]), "",
- !if(NoMem, [], [SDNPMemOperand])>;
+// Represent texture/image types / dimensionality.
+class AMDGPUDimProps<string name, list<string> coord_names, list<string> slice_names> {
+ AMDGPUDimProps Dim = !cast<AMDGPUDimProps>(NAME);
+ string Name = name; // e.g. "2darraymsaa"
+ bit DA = 0; // DA bit in MIMG encoding
-// Basic sample
-def int_amdgcn_image_sample : AMDGPUImageSample;
-def int_amdgcn_image_sample_cl : AMDGPUImageSample;
-def int_amdgcn_image_sample_d : AMDGPUImageSample;
-def int_amdgcn_image_sample_d_cl : AMDGPUImageSample;
-def int_amdgcn_image_sample_l : AMDGPUImageSample;
-def int_amdgcn_image_sample_b : AMDGPUImageSample;
-def int_amdgcn_image_sample_b_cl : AMDGPUImageSample;
-def int_amdgcn_image_sample_lz : AMDGPUImageSample;
-def int_amdgcn_image_sample_cd : AMDGPUImageSample;
-def int_amdgcn_image_sample_cd_cl : AMDGPUImageSample;
+ list<AMDGPUArg> CoordSliceArgs =
+ makeArgList<!listconcat(coord_names, slice_names), llvm_anyfloat_ty>.ret;
+ list<AMDGPUArg> CoordSliceIntArgs =
+ makeArgList<!listconcat(coord_names, slice_names), llvm_anyint_ty>.ret;
+ list<AMDGPUArg> GradientArgs =
+ makeArgList<!listconcat(!foreach(name, coord_names, "d" # name # "dh"),
+ !foreach(name, coord_names, "d" # name # "dv")),
+ llvm_anyfloat_ty>.ret;
-// Sample with comparison
-def int_amdgcn_image_sample_c : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_cl : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_d : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_d_cl : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_l : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_b : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_b_cl : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_lz : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_cd : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_cd_cl : AMDGPUImageSample;
+ bits<8> NumCoords = !size(CoordSliceArgs);
+ bits<8> NumGradients = !size(GradientArgs);
+}
-// Sample with offsets
-def int_amdgcn_image_sample_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_d_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_d_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_l_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_b_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_b_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_lz_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_cd_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_cd_cl_o : AMDGPUImageSample;
+def AMDGPUDim1D : AMDGPUDimProps<"1d", ["s"], []>;
+def AMDGPUDim2D : AMDGPUDimProps<"2d", ["s", "t"], []>;
+def AMDGPUDim3D : AMDGPUDimProps<"3d", ["s", "t", "r"], []>;
+let DA = 1 in {
+ def AMDGPUDimCube : AMDGPUDimProps<"cube", ["s", "t"], ["face"]>;
+ def AMDGPUDim1DArray : AMDGPUDimProps<"1darray", ["s"], ["slice"]>;
+ def AMDGPUDim2DArray : AMDGPUDimProps<"2darray", ["s", "t"], ["slice"]>;
+}
+def AMDGPUDim2DMsaa : AMDGPUDimProps<"2dmsaa", ["s", "t"], ["fragid"]>;
+let DA = 1 in {
+ def AMDGPUDim2DArrayMsaa : AMDGPUDimProps<"2darraymsaa", ["s", "t"], ["slice", "fragid"]>;
+}
-// Sample with comparison and offsets
-def int_amdgcn_image_sample_c_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_d_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_d_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_l_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_b_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_b_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_lz_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_cd_o : AMDGPUImageSample;
-def int_amdgcn_image_sample_c_cd_cl_o : AMDGPUImageSample;
+def AMDGPUDims {
+ list<AMDGPUDimProps> NoMsaa = [AMDGPUDim1D, AMDGPUDim2D, AMDGPUDim3D,
+ AMDGPUDimCube, AMDGPUDim1DArray,
+ AMDGPUDim2DArray];
+ list<AMDGPUDimProps> Msaa = [AMDGPUDim2DMsaa, AMDGPUDim2DArrayMsaa];
+ list<AMDGPUDimProps> All = !listconcat(NoMsaa, Msaa);
+}
-// Basic gather4
-def int_amdgcn_image_gather4 : AMDGPUImageSample;
-def int_amdgcn_image_gather4_cl : AMDGPUImageSample;
-def int_amdgcn_image_gather4_l : AMDGPUImageSample;
-def int_amdgcn_image_gather4_b : AMDGPUImageSample;
-def int_amdgcn_image_gather4_b_cl : AMDGPUImageSample;
-def int_amdgcn_image_gather4_lz : AMDGPUImageSample;
+// Represent sample variants, i.e. _C, _O, _B, ... and combinations thereof.
+class AMDGPUSampleVariant<string ucmod, string lcmod, list<AMDGPUArg> extra_addr> {
+ string UpperCaseMod = ucmod;
+ string LowerCaseMod = lcmod;
-// Gather4 with comparison
-def int_amdgcn_image_gather4_c : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_cl : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_l : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_b : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_b_cl : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_lz : AMDGPUImageSample;
+ // {offset} {bias} {z-compare}
+ list<AMDGPUArg> ExtraAddrArgs = extra_addr;
+ bit Gradients = 0;
-// Gather4 with offsets
-def int_amdgcn_image_gather4_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_l_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_b_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_b_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_lz_o : AMDGPUImageSample;
+ // Name of the {lod} or {clamp} argument that is appended to the coordinates,
+ // if any.
+ string LodOrClamp = "";
+}
-// Gather4 with comparison and offsets
-def int_amdgcn_image_gather4_c_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_l_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_b_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_b_cl_o : AMDGPUImageSample;
-def int_amdgcn_image_gather4_c_lz_o : AMDGPUImageSample;
+// AMDGPUSampleVariants: all variants supported by IMAGE_SAMPLE
+// AMDGPUSampleVariantsNoGradients: variants supported by IMAGE_GATHER4
+defset list<AMDGPUSampleVariant> AMDGPUSampleVariants = {
+ multiclass AMDGPUSampleHelper_Offset<string ucmod, string lcmod,
+ list<AMDGPUArg> extra_addr> {
+ def NAME#lcmod : AMDGPUSampleVariant<ucmod, lcmod, extra_addr>;
+ def NAME#lcmod#_o : AMDGPUSampleVariant<
+ ucmod#"_O", lcmod#"_o", !listconcat([AMDGPUArg<llvm_i32_ty, "offset">], extra_addr)>;
+ }
-def int_amdgcn_image_getlod : AMDGPUImageSample<1>;
+ multiclass AMDGPUSampleHelper_Compare<string ucmod, string lcmod,
+ list<AMDGPUArg> extra_addr> {
+ defm NAME : AMDGPUSampleHelper_Offset<ucmod, lcmod, extra_addr>;
+ defm NAME : AMDGPUSampleHelper_Offset<
+ "_C"#ucmod, "_c"#lcmod, !listconcat(extra_addr, [AMDGPUArg<llvm_float_ty, "zcompare">])>;
+ }
-class AMDGPUImageAtomic : Intrinsic <
- [llvm_i32_ty],
- [llvm_i32_ty, // vdata(VGPR)
- llvm_anyint_ty, // vaddr(VGPR)
- llvm_v8i32_ty, // rsrc(SGPR)
- llvm_i1_ty, // r128(imm)
- llvm_i1_ty, // da(imm)
- llvm_i1_ty], // slc(imm)
- [], "", [SDNPMemOperand]>;
+ multiclass AMDGPUSampleHelper_Clamp<string ucmod, string lcmod,
+ list<AMDGPUArg> extra_addr> {
+ defm NAME : AMDGPUSampleHelper_Compare<ucmod, lcmod, extra_addr>;
+ let LodOrClamp = "clamp" in
+ defm NAME : AMDGPUSampleHelper_Compare<ucmod#"_CL", lcmod#"_cl", extra_addr>;
+ }
-def int_amdgcn_image_atomic_swap : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_add : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_sub : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_smin : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_umin : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_smax : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_umax : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_and : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_or : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_xor : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_inc : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_dec : AMDGPUImageAtomic;
-def int_amdgcn_image_atomic_cmpswap : Intrinsic <
- [llvm_i32_ty],
- [llvm_i32_ty, // src(VGPR)
- llvm_i32_ty, // cmp(VGPR)
- llvm_anyint_ty, // vaddr(VGPR)
- llvm_v8i32_ty, // rsrc(SGPR)
- llvm_i1_ty, // r128(imm)
- llvm_i1_ty, // da(imm)
- llvm_i1_ty], // slc(imm)
- [], "", [SDNPMemOperand]>;
+ defset list<AMDGPUSampleVariant> AMDGPUSampleVariantsNoGradients = {
+ defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"", "", []>;
+ defm AMDGPUSample : AMDGPUSampleHelper_Clamp<
+ "_B", "_b", [AMDGPUArg<llvm_anyfloat_ty, "bias">]>;
+ let LodOrClamp = "lod" in
+ defm AMDGPUSample : AMDGPUSampleHelper_Compare<"_L", "_l", []>;
+ defm AMDGPUSample : AMDGPUSampleHelper_Compare<"_LZ", "_lz", []>;
+ }
+
+ let Gradients = 1 in {
+ defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"_D", "_d", []>;
+ defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"_CD", "_cd", []>;
+ }
+}
+
+// Helper class to capture the profile of a dimension-aware image intrinsic.
+// This information is used to generate the intrinsic's type and to inform
+// codegen pattern matching.
+class AMDGPUDimProfile<string opmod,
+ AMDGPUDimProps dim> {
+ AMDGPUDimProps Dim = dim;
+ string OpMod = opmod; // the corresponding instruction is named IMAGE_OpMod
+
+ // These are entended to be overwritten by subclasses
+ bit IsSample = 0;
+ bit IsAtomic = 0;
+ list<LLVMType> RetTypes = [];
+ list<AMDGPUArg> DataArgs = [];
+ list<AMDGPUArg> ExtraAddrArgs = [];
+ bit Gradients = 0;
+ string LodClampMip = "";
+
+ int NumRetAndDataAnyTypes =
+ !foldl(0, !listconcat(RetTypes, !foreach(arg, DataArgs, arg.Type)), a, b,
+ !add(a, b.isAny));
+
+ list<AMDGPUArg> AddrArgs =
+ arglistconcat<[ExtraAddrArgs,
+ !if(Gradients, dim.GradientArgs, []),
+ !listconcat(!if(IsSample, dim.CoordSliceArgs, dim.CoordSliceIntArgs),
+ !if(!eq(LodClampMip, ""),
+ []<AMDGPUArg>,
+ [AMDGPUArg<LLVMMatchType<0>, LodClampMip>]))],
+ NumRetAndDataAnyTypes>.ret;
+ list<LLVMType> AddrTypes = !foreach(arg, AddrArgs, arg.Type);
+ list<AMDGPUArg> AddrDefaultArgs =
+ !foreach(arg, AddrArgs,
+ AMDGPUArg<!if(!or(arg.Type.isAny, !isa<LLVMMatchType>(arg.Type)),
+ !if(IsSample, llvm_float_ty, llvm_i32_ty), arg.Type),
+ arg.Name>);
+ list<AMDGPUArg> AddrA16Args =
+ !foreach(arg, AddrArgs,
+ AMDGPUArg<!if(!or(arg.Type.isAny, !isa<LLVMMatchType>(arg.Type)),
+ !if(IsSample, llvm_half_ty, llvm_i16_ty), arg.Type),
+ arg.Name>);
+}
+
+class AMDGPUDimProfileCopy<AMDGPUDimProfile base> : AMDGPUDimProfile<base.OpMod, base.Dim> {
+ let IsSample = base.IsSample;
+ let IsAtomic = base.IsAtomic;
+ let RetTypes = base.RetTypes;
+ let DataArgs = base.DataArgs;
+ let ExtraAddrArgs = base.ExtraAddrArgs;
+ let Gradients = base.Gradients;
+ let LodClampMip = base.LodClampMip;
+}
+
+class AMDGPUDimSampleProfile<string opmod,
+ AMDGPUDimProps dim,
+ AMDGPUSampleVariant sample> : AMDGPUDimProfile<opmod, dim> {
+ let IsSample = 1;
+ let RetTypes = [llvm_anyfloat_ty];
+ let ExtraAddrArgs = sample.ExtraAddrArgs;
+ let Gradients = sample.Gradients;
+ let LodClampMip = sample.LodOrClamp;
+}
+
+class AMDGPUDimNoSampleProfile<string opmod,
+ AMDGPUDimProps dim,
+ list<LLVMType> retty,
+ list<AMDGPUArg> dataargs,
+ bit Mip = 0> : AMDGPUDimProfile<opmod, dim> {
+ let RetTypes = retty;
+ let DataArgs = dataargs;
+ let LodClampMip = !if(Mip, "mip", "");
+}
+
+class AMDGPUDimAtomicProfile<string opmod,
+ AMDGPUDimProps dim,
+ list<AMDGPUArg> dataargs> : AMDGPUDimProfile<opmod, dim> {
+ let RetTypes = [llvm_anyint_ty];
+ let DataArgs = dataargs;
+ let IsAtomic = 1;
+}
+
+class AMDGPUDimGetResInfoProfile<AMDGPUDimProps dim> : AMDGPUDimProfile<"GET_RESINFO", dim> {
+ let RetTypes = [llvm_anyfloat_ty];
+ let DataArgs = [];
+ let AddrArgs = [AMDGPUArg<llvm_anyint_ty, "mip">];
+ let LodClampMip = "mip";
+}
+
+// All dimension-aware intrinsics are derived from this class.
+class AMDGPUImageDimIntrinsic<AMDGPUDimProfile P_,
+ list<IntrinsicProperty> props,
+ list<SDNodeProperty> sdnodeprops> : Intrinsic<
+ P_.RetTypes, // vdata(VGPR) -- for load/atomic-with-return
+ !listconcat(
+ !foreach(arg, P_.DataArgs, arg.Type), // vdata(VGPR) -- for store/atomic
+ !if(P_.IsAtomic, [], [llvm_i32_ty]), // dmask(imm)
+ P_.AddrTypes, // vaddr(VGPR)
+ [llvm_v8i32_ty], // rsrc(SGPR)
+ !if(P_.IsSample, [llvm_v4i32_ty, // samp(SGPR)
+ llvm_i1_ty], []), // unorm(imm)
+ [llvm_i32_ty, // texfailctrl(imm; bit 0 = tfe, bit 1 = lwe)
+ llvm_i32_ty]), // cachepolicy(imm; bit 0 = glc, bit 1 = slc)
+ props, "", sdnodeprops>,
+ AMDGPURsrcIntrinsic<!add(!size(P_.DataArgs), !size(P_.AddrTypes),
+ !if(P_.IsAtomic, 0, 1)), 1> {
+ AMDGPUDimProfile P = P_;
+
+ AMDGPUImageDimIntrinsic Intr = !cast<AMDGPUImageDimIntrinsic>(NAME);
+
+ let TargetPrefix = "amdgcn";
+}
+
+// Marker class for intrinsics with a DMask that determines the returned
+// channels.
+class AMDGPUImageDMaskIntrinsic;
+
+defset list<AMDGPUImageDimIntrinsic> AMDGPUImageDimIntrinsics = {
+
+ //////////////////////////////////////////////////////////////////////////
+ // Load and store intrinsics
+ //////////////////////////////////////////////////////////////////////////
+ multiclass AMDGPUImageDimIntrinsicsNoMsaa<string opmod,
+ list<LLVMType> retty,
+ list<AMDGPUArg> dataargs,
+ list<IntrinsicProperty> props,
+ list<SDNodeProperty> sdnodeprops,
+ bit Mip = 0> {
+ foreach dim = AMDGPUDims.NoMsaa in {
+ def !strconcat(NAME, "_", dim.Name)
+ : AMDGPUImageDimIntrinsic<
+ AMDGPUDimNoSampleProfile<opmod, dim, retty, dataargs, Mip>,
+ props, sdnodeprops>;
+ }
+ }
+
+ multiclass AMDGPUImageDimIntrinsicsAll<string opmod,
+ list<LLVMType> retty,
+ list<AMDGPUArg> dataargs,
+ list<IntrinsicProperty> props,
+ list<SDNodeProperty> sdnodeprops,
+ bit Mip = 0> {
+ foreach dim = AMDGPUDims.All in {
+ def !strconcat(NAME, "_", dim.Name)
+ : AMDGPUImageDimIntrinsic<
+ AMDGPUDimNoSampleProfile<opmod, dim, retty, dataargs, Mip>,
+ props, sdnodeprops>;
+ }
+ }
+
+ defm int_amdgcn_image_load
+ : AMDGPUImageDimIntrinsicsAll<"LOAD", [llvm_anyfloat_ty], [], [IntrReadMem],
+ [SDNPMemOperand]>,
+ AMDGPUImageDMaskIntrinsic;
+ defm int_amdgcn_image_load_mip
+ : AMDGPUImageDimIntrinsicsNoMsaa<"LOAD_MIP", [llvm_anyfloat_ty], [],
+ [IntrReadMem], [SDNPMemOperand], 1>,
+ AMDGPUImageDMaskIntrinsic;
+
+ defm int_amdgcn_image_store : AMDGPUImageDimIntrinsicsAll<
+ "STORE", [], [AMDGPUArg<llvm_anyfloat_ty, "vdata">],
+ [IntrWriteMem], [SDNPMemOperand]>;
+ defm int_amdgcn_image_store_mip : AMDGPUImageDimIntrinsicsNoMsaa<
+ "STORE_MIP", [], [AMDGPUArg<llvm_anyfloat_ty, "vdata">],
+ [IntrWriteMem], [SDNPMemOperand], 1>;
+
+ //////////////////////////////////////////////////////////////////////////
+ // sample and getlod intrinsics
+ //////////////////////////////////////////////////////////////////////////
+ multiclass AMDGPUImageDimSampleDims<string opmod,
+ AMDGPUSampleVariant sample,
+ bit NoMem = 0> {
+ foreach dim = AMDGPUDims.NoMsaa in {
+ def !strconcat(NAME, "_", dim.Name) : AMDGPUImageDimIntrinsic<
+ AMDGPUDimSampleProfile<opmod, dim, sample>,
+ !if(NoMem, [IntrNoMem], [IntrReadMem]),
+ !if(NoMem, [], [SDNPMemOperand])>;
+ }
+ }
+
+ foreach sample = AMDGPUSampleVariants in {
+ defm int_amdgcn_image_sample # sample.LowerCaseMod
+ : AMDGPUImageDimSampleDims<"SAMPLE" # sample.UpperCaseMod, sample>,
+ AMDGPUImageDMaskIntrinsic;
+ }
+
+ defm int_amdgcn_image_getlod
+ : AMDGPUImageDimSampleDims<"GET_LOD", AMDGPUSample, 1>,
+ AMDGPUImageDMaskIntrinsic;
+
+ //////////////////////////////////////////////////////////////////////////
+ // getresinfo intrinsics
+ //////////////////////////////////////////////////////////////////////////
+ foreach dim = AMDGPUDims.All in {
+ def !strconcat("int_amdgcn_image_getresinfo_", dim.Name)
+ : AMDGPUImageDimIntrinsic<AMDGPUDimGetResInfoProfile<dim>, [IntrNoMem], []>,
+ AMDGPUImageDMaskIntrinsic;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // gather4 intrinsics
+ //////////////////////////////////////////////////////////////////////////
+ foreach sample = AMDGPUSampleVariantsNoGradients in {
+ foreach dim = [AMDGPUDim2D, AMDGPUDimCube, AMDGPUDim2DArray] in {
+ def int_amdgcn_image_gather4 # sample.LowerCaseMod # _ # dim.Name:
+ AMDGPUImageDimIntrinsic<
+ AMDGPUDimSampleProfile<"GATHER4" # sample.UpperCaseMod, dim, sample>,
+ [IntrReadMem], [SDNPMemOperand]>;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// atomic intrinsics
+//////////////////////////////////////////////////////////////////////////
+defset list<AMDGPUImageDimIntrinsic> AMDGPUImageDimAtomicIntrinsics = {
+ multiclass AMDGPUImageDimAtomicX<string opmod, list<AMDGPUArg> dataargs> {
+ foreach dim = AMDGPUDims.All in {
+ def !strconcat(NAME, "_", dim.Name)
+ : AMDGPUImageDimIntrinsic<
+ AMDGPUDimAtomicProfile<opmod, dim, dataargs>,
+ [], [SDNPMemOperand]>;
+ }
+ }
+
+ multiclass AMDGPUImageDimAtomic<string opmod> {
+ defm "" : AMDGPUImageDimAtomicX<opmod, [AMDGPUArg<LLVMMatchType<0>, "vdata">]>;
+ }
+
+ defm int_amdgcn_image_atomic_swap : AMDGPUImageDimAtomic<"ATOMIC_SWAP">;
+ defm int_amdgcn_image_atomic_add : AMDGPUImageDimAtomic<"ATOMIC_ADD">;
+ defm int_amdgcn_image_atomic_sub : AMDGPUImageDimAtomic<"ATOMIC_SUB">;
+ defm int_amdgcn_image_atomic_smin : AMDGPUImageDimAtomic<"ATOMIC_SMIN">;
+ defm int_amdgcn_image_atomic_umin : AMDGPUImageDimAtomic<"ATOMIC_UMIN">;
+ defm int_amdgcn_image_atomic_smax : AMDGPUImageDimAtomic<"ATOMIC_SMAX">;
+ defm int_amdgcn_image_atomic_umax : AMDGPUImageDimAtomic<"ATOMIC_UMAX">;
+ defm int_amdgcn_image_atomic_and : AMDGPUImageDimAtomic<"ATOMIC_AND">;
+ defm int_amdgcn_image_atomic_or : AMDGPUImageDimAtomic<"ATOMIC_OR">;
+ defm int_amdgcn_image_atomic_xor : AMDGPUImageDimAtomic<"ATOMIC_XOR">;
+
+ // TODO: INC/DEC are weird: they seem to have a vdata argument in hardware,
+ // even though it clearly shouldn't be needed
+ defm int_amdgcn_image_atomic_inc : AMDGPUImageDimAtomic<"ATOMIC_INC">;
+ defm int_amdgcn_image_atomic_dec : AMDGPUImageDimAtomic<"ATOMIC_DEC">;
+
+ defm int_amdgcn_image_atomic_cmpswap :
+ AMDGPUImageDimAtomicX<"ATOMIC_CMPSWAP", [AMDGPUArg<LLVMMatchType<0>, "src">,
+ AMDGPUArg<LLVMMatchType<0>, "cmp">]>;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Buffer intrinsics
+//////////////////////////////////////////////////////////////////////////
+
+let TargetPrefix = "amdgcn" in {
+
+defset list<AMDGPURsrcIntrinsic> AMDGPUBufferIntrinsics = {
class AMDGPUBufferLoad : Intrinsic <
[llvm_anyfloat_ty],
@@ -482,7 +797,8 @@ class AMDGPUBufferLoad : Intrinsic <
llvm_i32_ty, // offset(SGPR/VGPR/imm)
llvm_i1_ty, // glc(imm)
llvm_i1_ty], // slc(imm)
- [IntrReadMem], "", [SDNPMemOperand]>;
+ [IntrReadMem], "", [SDNPMemOperand]>,
+ AMDGPURsrcIntrinsic<0>;
def int_amdgcn_buffer_load_format : AMDGPUBufferLoad;
def int_amdgcn_buffer_load : AMDGPUBufferLoad;
@@ -494,7 +810,8 @@ class AMDGPUBufferStore : Intrinsic <
llvm_i32_ty, // offset(SGPR/VGPR/imm)
llvm_i1_ty, // glc(imm)
llvm_i1_ty], // slc(imm)
- [IntrWriteMem], "", [SDNPMemOperand]>;
+ [IntrWriteMem], "", [SDNPMemOperand]>,
+ AMDGPURsrcIntrinsic<1>;
def int_amdgcn_buffer_store_format : AMDGPUBufferStore;
def int_amdgcn_buffer_store : AMDGPUBufferStore;
@@ -509,7 +826,8 @@ def int_amdgcn_tbuffer_load : Intrinsic <
llvm_i32_ty, // nfmt(imm)
llvm_i1_ty, // glc(imm)
llvm_i1_ty], // slc(imm)
- [IntrReadMem], "", [SDNPMemOperand]>;
+ [IntrReadMem], "", [SDNPMemOperand]>,
+ AMDGPURsrcIntrinsic<0>;
def int_amdgcn_tbuffer_store : Intrinsic <
[],
@@ -523,7 +841,8 @@ def int_amdgcn_tbuffer_store : Intrinsic <
llvm_i32_ty, // nfmt(imm)
llvm_i1_ty, // glc(imm)
llvm_i1_ty], // slc(imm)
- [IntrWriteMem], "", [SDNPMemOperand]>;
+ [IntrWriteMem], "", [SDNPMemOperand]>,
+ AMDGPURsrcIntrinsic<1>;
class AMDGPUBufferAtomic : Intrinsic <
[llvm_i32_ty],
@@ -532,7 +851,8 @@ class AMDGPUBufferAtomic : Intrinsic <
llvm_i32_ty, // vindex(VGPR)
llvm_i32_ty, // offset(SGPR/VGPR/imm)
llvm_i1_ty], // slc(imm)
- [], "", [SDNPMemOperand]>;
+ [], "", [SDNPMemOperand]>,
+ AMDGPURsrcIntrinsic<1, 0>;
def int_amdgcn_buffer_atomic_swap : AMDGPUBufferAtomic;
def int_amdgcn_buffer_atomic_add : AMDGPUBufferAtomic;
def int_amdgcn_buffer_atomic_sub : AMDGPUBufferAtomic;
@@ -551,7 +871,10 @@ def int_amdgcn_buffer_atomic_cmpswap : Intrinsic<
llvm_i32_ty, // vindex(VGPR)
llvm_i32_ty, // offset(SGPR/VGPR/imm)
llvm_i1_ty], // slc(imm)
- [], "", [SDNPMemOperand]>;
+ [], "", [SDNPMemOperand]>,
+ AMDGPURsrcIntrinsic<2, 0>;
+
+} // defset AMDGPUBufferIntrinsics
// Uses that do not set the done bit should set IntrWriteMem on the
// call site.
@@ -753,6 +1076,19 @@ def int_amdgcn_readlane :
GCCBuiltin<"__builtin_amdgcn_readlane">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
+// The value to write and lane select arguments must be uniform across the
+// currently active threads of the current wave. Otherwise, the result is
+// undefined.
+def int_amdgcn_writelane :
+ GCCBuiltin<"__builtin_amdgcn_writelane">,
+ Intrinsic<[llvm_i32_ty], [
+ llvm_i32_ty, // uniform value to write: returned by the selected lane
+ llvm_i32_ty, // uniform lane select
+ llvm_i32_ty // returned by all lanes other than the selected one
+ ],
+ [IntrNoMem, IntrConvergent]
+>;
+
def int_amdgcn_alignbit : Intrinsic<[llvm_i32_ty],
[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]
@@ -851,6 +1187,109 @@ def int_amdgcn_ds_bpermute :
GCCBuiltin<"__builtin_amdgcn_ds_bpermute">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
+//===----------------------------------------------------------------------===//
+// Deep learning intrinsics.
+//===----------------------------------------------------------------------===//
+
+// f32 %r = llvm.amdgcn.fdot2(v2f16 %a, v2f16 %b, f32 %c)
+// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c
+def int_amdgcn_fdot2 :
+ GCCBuiltin<"__builtin_amdgcn_fdot2">,
+ Intrinsic<
+ [llvm_float_ty], // %r
+ [
+ llvm_v2f16_ty, // %a
+ llvm_v2f16_ty, // %b
+ llvm_float_ty // %c
+ ],
+ [IntrNoMem, IntrSpeculatable]
+ >;
+
+// i32 %r = llvm.amdgcn.sdot2(v2i16 %a, v2i16 %b, i32 %c)
+// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c
+def int_amdgcn_sdot2 :
+ GCCBuiltin<"__builtin_amdgcn_sdot2">,
+ Intrinsic<
+ [llvm_i32_ty], // %r
+ [
+ llvm_v2i16_ty, // %a
+ llvm_v2i16_ty, // %b
+ llvm_i32_ty // %c
+ ],
+ [IntrNoMem, IntrSpeculatable]
+ >;
+
+// u32 %r = llvm.amdgcn.udot2(v2u16 %a, v2u16 %b, u32 %c)
+// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c
+def int_amdgcn_udot2 :
+ GCCBuiltin<"__builtin_amdgcn_udot2">,
+ Intrinsic<
+ [llvm_i32_ty], // %r
+ [
+ llvm_v2i16_ty, // %a
+ llvm_v2i16_ty, // %b
+ llvm_i32_ty // %c
+ ],
+ [IntrNoMem, IntrSpeculatable]
+ >;
+
+// i32 %r = llvm.amdgcn.sdot4(v4i8 (as i32) %a, v4i8 (as i32) %b, i32 %c)
+// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + %c
+def int_amdgcn_sdot4 :
+ GCCBuiltin<"__builtin_amdgcn_sdot4">,
+ Intrinsic<
+ [llvm_i32_ty], // %r
+ [
+ llvm_i32_ty, // %a
+ llvm_i32_ty, // %b
+ llvm_i32_ty // %c
+ ],
+ [IntrNoMem, IntrSpeculatable]
+ >;
+
+// u32 %r = llvm.amdgcn.udot4(v4u8 (as u32) %a, v4u8 (as u32) %b, u32 %c)
+// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + %c
+def int_amdgcn_udot4 :
+ GCCBuiltin<"__builtin_amdgcn_udot4">,
+ Intrinsic<
+ [llvm_i32_ty], // %r
+ [
+ llvm_i32_ty, // %a
+ llvm_i32_ty, // %b
+ llvm_i32_ty // %c
+ ],
+ [IntrNoMem, IntrSpeculatable]
+ >;
+
+// i32 %r = llvm.amdgcn.sdot8(v8i4 (as i32) %a, v8i4 (as i32) %b, i32 %c)
+// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] +
+// %a[4] * %b[4] + %a[5] * %b[5] + %a[6] * %b[6] + %a[7] * %b[7] + %c
+def int_amdgcn_sdot8 :
+ GCCBuiltin<"__builtin_amdgcn_sdot8">,
+ Intrinsic<
+ [llvm_i32_ty], // %r
+ [
+ llvm_i32_ty, // %a
+ llvm_i32_ty, // %b
+ llvm_i32_ty // %c
+ ],
+ [IntrNoMem, IntrSpeculatable]
+ >;
+
+// u32 %r = llvm.amdgcn.udot8(v8u4 (as u32) %a, v8u4 (as u32) %b, u32 %c)
+// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] +
+// %a[4] * %b[4] + %a[5] * %b[5] + %a[6] * %b[6] + %a[7] * %b[7] + %c
+def int_amdgcn_udot8 :
+ GCCBuiltin<"__builtin_amdgcn_udot8">,
+ Intrinsic<
+ [llvm_i32_ty], // %r
+ [
+ llvm_i32_ty, // %a
+ llvm_i32_ty, // %b
+ llvm_i32_ty // %c
+ ],
+ [IntrNoMem, IntrSpeculatable]
+ >;
//===----------------------------------------------------------------------===//
// Special Intrinsics for backend internal use only. No frontend
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsARM.td b/contrib/llvm/include/llvm/IR/IntrinsicsARM.td
index fe3861301689..f25d2f1dbb5d 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicsARM.td
+++ b/contrib/llvm/include/llvm/IR/IntrinsicsARM.td
@@ -369,6 +369,10 @@ class Neon_3Arg_Long_Intrinsic
: Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMTruncatedType<0>, LLVMTruncatedType<0>],
[IntrNoMem]>;
+
+class Neon_1FloatArg_Intrinsic
+ : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+
class Neon_CvtFxToFP_Intrinsic
: Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>;
class Neon_CvtFPToFx_Intrinsic
@@ -591,8 +595,8 @@ def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic;
def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic;
def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic;
-// Vector Rounding
-def int_arm_neon_vrintn : Neon_1Arg_Intrinsic;
+// Vector and Scalar Rounding.
+def int_arm_neon_vrintn : Neon_1FloatArg_Intrinsic;
def int_arm_neon_vrintx : Neon_1Arg_Intrinsic;
def int_arm_neon_vrinta : Neon_1Arg_Intrinsic;
def int_arm_neon_vrintz : Neon_1Arg_Intrinsic;
@@ -616,6 +620,18 @@ def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
[llvm_anyptr_ty, llvm_i32_ty],
[IntrReadMem, IntrArgMemOnly]>;
+def int_arm_neon_vld1x2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>],
+ [IntrReadMem, IntrArgMemOnly]>;
+def int_arm_neon_vld1x3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
+ LLVMMatchType<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>],
+ [IntrReadMem, IntrArgMemOnly]>;
+def int_arm_neon_vld1x4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
+ LLVMMatchType<0>, LLVMMatchType<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>],
+ [IntrReadMem, IntrArgMemOnly]>;
+
// Vector load N-element structure to one lane.
// Source operands are: the address, the N input vectors (since only one
// lane is assigned), the lane number, and the alignment.
@@ -636,6 +652,20 @@ def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
LLVMMatchType<0>, llvm_i32_ty,
llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>;
+// Vector load N-element structure to all lanes.
+// Source operands are the address and alignment.
+def int_arm_neon_vld2dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>],
+ [llvm_anyptr_ty, llvm_i32_ty],
+ [IntrReadMem, IntrArgMemOnly]>;
+def int_arm_neon_vld3dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
+ LLVMMatchType<0>],
+ [llvm_anyptr_ty, llvm_i32_ty],
+ [IntrReadMem, IntrArgMemOnly]>;
+def int_arm_neon_vld4dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>,
+ LLVMMatchType<0>, LLVMMatchType<0>],
+ [llvm_anyptr_ty, llvm_i32_ty],
+ [IntrReadMem, IntrArgMemOnly]>;
+
// Interleaving vector stores from N-element structures.
// Source operands are: the address, the N vectors, and the alignment.
def int_arm_neon_vst1 : Intrinsic<[],
@@ -655,6 +685,20 @@ def int_arm_neon_vst4 : Intrinsic<[],
LLVMMatchType<1>, llvm_i32_ty],
[IntrArgMemOnly]>;
+def int_arm_neon_vst1x2 : Intrinsic<[],
+ [llvm_anyptr_ty, llvm_anyvector_ty,
+ LLVMMatchType<1>],
+ [IntrArgMemOnly, NoCapture<0>]>;
+def int_arm_neon_vst1x3 : Intrinsic<[],
+ [llvm_anyptr_ty, llvm_anyvector_ty,
+ LLVMMatchType<1>, LLVMMatchType<1>],
+ [IntrArgMemOnly, NoCapture<0>]>;
+def int_arm_neon_vst1x4 : Intrinsic<[],
+ [llvm_anyptr_ty, llvm_anyvector_ty,
+ LLVMMatchType<1>, LLVMMatchType<1>,
+ LLVMMatchType<1>],
+ [IntrArgMemOnly, NoCapture<0>]>;
+
// Vector store N-element structure from one lane.
// Source operands are: the address, the N vectors, the lane number, and
// the alignment.
@@ -713,4 +757,14 @@ def int_arm_neon_sha256h: SHA_3Arg_v4i32_Intrinsic;
def int_arm_neon_sha256h2: SHA_3Arg_v4i32_Intrinsic;
def int_arm_neon_sha256su1: SHA_3Arg_v4i32_Intrinsic;
+// Armv8.2-A dot product instructions
+class Neon_Dot_Intrinsic
+ : Intrinsic<[llvm_anyvector_ty],
+ [LLVMMatchType<0>, llvm_anyvector_ty,
+ LLVMMatchType<1>],
+ [IntrNoMem]>;
+def int_arm_neon_udot : Neon_Dot_Intrinsic;
+def int_arm_neon_sdot : Neon_Dot_Intrinsic;
+
+
} // end TargetPrefix
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td b/contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td
index 5c96702bca76..25f4215d68a8 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td
+++ b/contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td
@@ -21,6 +21,13 @@ let TargetPrefix = "hexagon" in {
list<IntrinsicProperty> properties>
: GCCBuiltin<!strconcat("__builtin_", GCCIntSuffix)>,
Intrinsic<ret_types, param_types, properties>;
+
+ /// Hexagon_NonGCC_Intrinsic - Base class for bitcode convertible Hexagon
+ /// intrinsics.
+ class Hexagon_NonGCC_Intrinsic<list<LLVMType> ret_types,
+ list<LLVMType> param_types,
+ list<IntrinsicProperty> properties>
+ : Intrinsic<ret_types, param_types, properties>;
}
//===----------------------------------------------------------------------===//
@@ -424,13 +431,13 @@ class Hexagon_mem_memsisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty,
llvm_i32_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem]>;
class Hexagon_mem_memdisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty,
llvm_i32_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem]>;
class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
@@ -442,13 +449,13 @@ class Hexagon_mem_memsisisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty,
llvm_i32_ty, llvm_i32_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem]>;
class Hexagon_mem_memdisisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty,
llvm_i32_ty, llvm_i32_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem]>;
class Hexagon_v256_v256v256_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
@@ -636,41 +643,6 @@ class Hexagon_df_dfdfdfqi_Intrinsic<string GCCIntSuffix>
// This one below will not be auto-generated,
// so make sure, you don't overwrite this one.
//
-// BUILTIN_INFO(SI_to_SXTHI_asrh,SI_ftype_SI,1)
-//
-def int_hexagon_SI_to_SXTHI_asrh :
-Hexagon_si_si_Intrinsic<"SI_to_SXTHI_asrh">;
-//
-// BUILTIN_INFO_NONCONST(brev_ldd,PTR_ftype_PTRPTRSI,3)
-//
-def int_hexagon_brev_ldd :
-Hexagon_mem_memmemsi_Intrinsic<"brev_ldd">;
-//
-// BUILTIN_INFO_NONCONST(brev_ldw,PTR_ftype_PTRPTRSI,3)
-//
-def int_hexagon_brev_ldw :
-Hexagon_mem_memmemsi_Intrinsic<"brev_ldw">;
-//
-// BUILTIN_INFO_NONCONST(brev_ldh,PTR_ftype_PTRPTRSI,3)
-//
-def int_hexagon_brev_ldh :
-Hexagon_mem_memmemsi_Intrinsic<"brev_ldh">;
-//
-// BUILTIN_INFO_NONCONST(brev_lduh,PTR_ftype_PTRPTRSI,3)
-//
-def int_hexagon_brev_lduh :
-Hexagon_mem_memmemsi_Intrinsic<"brev_lduh">;
-//
-// BUILTIN_INFO_NONCONST(brev_ldb,PTR_ftype_PTRPTRSI,3)
-//
-def int_hexagon_brev_ldb :
-Hexagon_mem_memmemsi_Intrinsic<"brev_ldb">;
-//
-// BUILTIN_INFO_NONCONST(brev_ldub,PTR_ftype_PTRPTRSI,3)
-//
-def int_hexagon_brev_ldub :
-Hexagon_mem_memmemsi_Intrinsic<"brev_ldub">;
-//
// BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4)
//
def int_hexagon_circ_ldd :
@@ -702,31 +674,6 @@ def int_hexagon_circ_ldub :
Hexagon_mem_memmemsisi_Intrinsic<"circ_ldub">;
//
-// BUILTIN_INFO_NONCONST(brev_stb,PTR_ftype_PTRSISI,3)
-//
-def int_hexagon_brev_stb :
-Hexagon_mem_memsisi_Intrinsic<"brev_stb">;
-//
-// BUILTIN_INFO_NONCONST(brev_sthhi,PTR_ftype_PTRSISI,3)
-//
-def int_hexagon_brev_sthhi :
-Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">;
-//
-// BUILTIN_INFO_NONCONST(brev_sth,PTR_ftype_PTRSISI,3)
-//
-def int_hexagon_brev_sth :
-Hexagon_mem_memsisi_Intrinsic<"brev_sth">;
-//
-// BUILTIN_INFO_NONCONST(brev_stw,PTR_ftype_PTRSISI,3)
-//
-def int_hexagon_brev_stw :
-Hexagon_mem_memsisi_Intrinsic<"brev_stw">;
-//
-// BUILTIN_INFO_NONCONST(brev_std,PTR_ftype_PTRSISI,3)
-//
-def int_hexagon_brev_std :
-Hexagon_mem_memdisi_Intrinsic<"brev_std">;
-//
// BUILTIN_INFO_NONCONST(circ_std,PTR_ftype_PTRDISISI,4)
//
def int_hexagon_circ_std :
@@ -9300,6 +9247,60 @@ Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentq_128B">;
def int_hexagon_V6_vmaskedstorentnq_128B :
Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentnq_128B">;
+multiclass Hexagon_custom_circ_ld_Intrinsic<LLVMType ElTy> {
+ def NAME#_pci : Hexagon_NonGCC_Intrinsic<
+ [ElTy, llvm_ptr_ty],
+ [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty],
+ [IntrArgMemOnly, NoCapture<3>]>;
+ def NAME#_pcr : Hexagon_NonGCC_Intrinsic<
+ [ElTy, llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_ptr_ty],
+ [IntrArgMemOnly, NoCapture<2>]>;
+}
+
+defm int_hexagon_L2_loadrub : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_L2_loadrb : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_L2_loadruh : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_L2_loadrh : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_L2_loadri : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_L2_loadrd : Hexagon_custom_circ_ld_Intrinsic<llvm_i64_ty>;
+
+multiclass Hexagon_custom_circ_st_Intrinsic<LLVMType ElTy> {
+ def NAME#_pci : Hexagon_NonGCC_Intrinsic<
+ [llvm_ptr_ty],
+ [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, ElTy, llvm_ptr_ty],
+ [IntrArgMemOnly, NoCapture<4>]>;
+ def NAME#_pcr : Hexagon_NonGCC_Intrinsic<
+ [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, ElTy, llvm_ptr_ty],
+ [IntrArgMemOnly, NoCapture<3>]>;
+}
+
+defm int_hexagon_S2_storerb : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_S2_storerh : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_S2_storerf : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_S2_storeri : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>;
+defm int_hexagon_S2_storerd : Hexagon_custom_circ_st_Intrinsic<llvm_i64_ty>;
+
+// The front-end emits the intrinsic call with only two arguments. The third
+// argument from the builtin is already used by front-end to write to memory
+// by generating a store.
+class Hexagon_custom_brev_ld_Intrinsic<LLVMType ElTy>
+ : Hexagon_NonGCC_Intrinsic<
+ [ElTy, llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty],
+ [IntrReadMem]>;
+
+def int_hexagon_L2_loadrub_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>;
+def int_hexagon_L2_loadrb_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>;
+def int_hexagon_L2_loadruh_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>;
+def int_hexagon_L2_loadrh_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>;
+def int_hexagon_L2_loadri_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>;
+def int_hexagon_L2_loadrd_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i64_ty>;
+
+def int_hexagon_S2_storerb_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_stb">;
+def int_hexagon_S2_storerh_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_sth">;
+def int_hexagon_S2_storerf_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">;
+def int_hexagon_S2_storeri_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_stw">;
+def int_hexagon_S2_storerd_pbr : Hexagon_mem_memdisi_Intrinsic<"brev_std">;
+
///
/// HexagonV62 intrinsics
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td b/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td
index 73622ce9303f..7f694f68969e 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td
+++ b/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td
@@ -3884,96 +3884,100 @@ def int_nvvm_match_all_sync_i64p :
//
// WMMA.LOAD
-class NVVM_WMMA_LD_ALSTS<string Abc, string Layout, string Space,
- string Type, LLVMType regty, int WithStride>
+class NVVM_WMMA_LD_GALSTS<string Geometry, string Abc, string Layout,
+ string Type, LLVMType regty, int WithStride>
: Intrinsic<!if(!eq(Abc#Type,"cf16"),
[regty, regty, regty, regty],
[regty, regty, regty, regty,
regty, regty, regty, regty]),
- !if(WithStride, [llvm_ptr_ty, llvm_i32_ty], [llvm_ptr_ty]),
- [], // Properties must be set during instantiation.
- "llvm.nvvm.wmma.load."#Abc#".sync."#Layout#".m16n16k16"
- #Space
- #!if(WithStride,".stride","")
- #"."#Type>;
+ !if(WithStride, [llvm_anyptr_ty, llvm_i32_ty], [llvm_anyptr_ty]),
+ [IntrReadMem, IntrArgMemOnly, ReadOnly<0>, NoCapture<0>],
+ "llvm.nvvm.wmma."
+ # Geometry
+ # ".load"
+ # "." # Abc
+ # "." # Layout
+ # !if(WithStride, ".stride", "")
+ # "." # Type>;
-multiclass NVVM_WMMA_LD_ALST<string Abc, string Layout, string Space,
- string Type, LLVMType regty> {
- def _stride: NVVM_WMMA_LD_ALSTS<Abc, Layout, Space, Type, regty, 1>;
- def NAME : NVVM_WMMA_LD_ALSTS<Abc, Layout, Space, Type, regty, 0>;
+multiclass NVVM_WMMA_LD_GALT<string Geometry, string Abc, string Layout,
+ string Type, LLVMType regty> {
+ def _stride: NVVM_WMMA_LD_GALSTS<Geometry, Abc, Layout, Type, regty, 1>;
+ def NAME : NVVM_WMMA_LD_GALSTS<Geometry, Abc, Layout, Type, regty, 0>;
}
-multiclass NVVM_WMMA_LD_ALT<string Abc, string Layout,
- string Type, LLVMType regty> {
- defm _global: NVVM_WMMA_LD_ALST<Abc, Layout, ".global", Type, regty>;
- defm _shared: NVVM_WMMA_LD_ALST<Abc, Layout, ".shared", Type, regty>;
- defm NAME: NVVM_WMMA_LD_ALST<Abc, Layout, "", Type, regty>;
+multiclass NVVM_WMMA_LD_GAT<string Geometry, string Abc,
+ string Type, LLVMType regty> {
+ defm _row: NVVM_WMMA_LD_GALT<Geometry, Abc, "row", Type, regty>;
+ defm _col: NVVM_WMMA_LD_GALT<Geometry, Abc, "col", Type, regty>;
}
-multiclass NVVM_WMMA_LD_AT<string Abc, string Type, LLVMType regty> {
- defm _row: NVVM_WMMA_LD_ALT<Abc, "row", Type, regty>;
- defm _col: NVVM_WMMA_LD_ALT<Abc, "col", Type, regty>;
+multiclass NVVM_WMMA_LD_G<string Geometry> {
+ defm _a_f16: NVVM_WMMA_LD_GAT<Geometry, "a", "f16", llvm_v2f16_ty>;
+ defm _b_f16: NVVM_WMMA_LD_GAT<Geometry, "b", "f16", llvm_v2f16_ty>;
+ defm _c_f16: NVVM_WMMA_LD_GAT<Geometry, "c", "f16", llvm_v2f16_ty>;
+ defm _c_f32: NVVM_WMMA_LD_GAT<Geometry, "c", "f32", llvm_float_ty>;
}
-// For some reason ReadOnly<N> and NoCapture<N> confuses tblgen if they are
-// passed to Intrinsic<> form inside of a multiclass. Setting them globally
-// outside of the multiclass works.
-let IntrProperties = [IntrReadMem, IntrArgMemOnly,
- ReadOnly<0>, NoCapture<0>] in {
- defm int_nvvm_wmma_load_a_f16: NVVM_WMMA_LD_AT<"a", "f16", llvm_v2f16_ty>;
- defm int_nvvm_wmma_load_b_f16: NVVM_WMMA_LD_AT<"b", "f16", llvm_v2f16_ty>;
- defm int_nvvm_wmma_load_c_f16: NVVM_WMMA_LD_AT<"c", "f16", llvm_v2f16_ty>;
- defm int_nvvm_wmma_load_c_f32: NVVM_WMMA_LD_AT<"c", "f32", llvm_float_ty>;
+multiclass NVVM_WMMA_LD {
+ defm _m32n8k16_load: NVVM_WMMA_LD_G<"m32n8k16">;
+ defm _m16n16k16_load: NVVM_WMMA_LD_G<"m16n16k16">;
+ defm _m8n32k16_load: NVVM_WMMA_LD_G<"m8n32k16">;
}
+defm int_nvvm_wmma: NVVM_WMMA_LD;
+
// WMMA.STORE.D
-class NVVM_WMMA_STD_LSTS<string Layout, string Space,
- string Type, LLVMType regty, int WithStride,
- // This is only used to create a typed empty array we
- // need to pass to !if below.
- list<LLVMType>Empty=[]>
+class NVVM_WMMA_STD_GLSTS<string Geometry, string Layout,
+ string Type, LLVMType regty, int WithStride,
+ // This is only used to create a typed empty array we
+ // need to pass to !if below.
+ list<LLVMType>Empty=[]>
: Intrinsic<[],
!listconcat(
- [llvm_ptr_ty],
+ [llvm_anyptr_ty],
!if(!eq(Type,"f16"),
[regty, regty, regty, regty],
[regty, regty, regty, regty,
regty, regty, regty, regty]),
!if(WithStride, [llvm_i32_ty], Empty)),
- [], // Properties must be set during instantiation.
- "llvm.nvvm.wmma.store.d.sync."#Layout
- #".m16n16k16"#Space
- #!if(WithStride,".stride","")
- #"."#Type>;
+ [IntrWriteMem, IntrArgMemOnly, WriteOnly<0>, NoCapture<0>],
+ "llvm.nvvm.wmma."
+ # Geometry
+ # ".store.d"
+ # "." # Layout
+ # !if(WithStride, ".stride", "")
+ # "." # Type>;
-multiclass NVVM_WMMA_STD_LST<string Layout, string Space,
- string Type, LLVMType regty> {
- def _stride: NVVM_WMMA_STD_LSTS<Layout, Space, Type, regty, 1>;
- def NAME: NVVM_WMMA_STD_LSTS<Layout, Space, Type, regty, 0>;
+multiclass NVVM_WMMA_STD_GLT<string Geometry, string Layout,
+ string Type, LLVMType regty> {
+ def _stride: NVVM_WMMA_STD_GLSTS<Geometry, Layout, Type, regty, 1>;
+ def NAME: NVVM_WMMA_STD_GLSTS<Geometry, Layout, Type, regty, 0>;
}
-multiclass NVVM_WMMA_STD_LT<string Layout, string Type, LLVMType regty> {
- defm _global: NVVM_WMMA_STD_LST<Layout, ".global", Type, regty>;
- defm _shared: NVVM_WMMA_STD_LST<Layout, ".shared", Type, regty>;
- defm NAME: NVVM_WMMA_STD_LST<Layout, "", Type, regty>;
+multiclass NVVM_WMMA_STD_GT<string Geometry, string Type, LLVMType regty> {
+ defm _row: NVVM_WMMA_STD_GLT<Geometry, "row", Type, regty>;
+ defm _col: NVVM_WMMA_STD_GLT<Geometry, "col", Type, regty>;
}
-
-multiclass NVVM_WMMA_STD_T<string Type, LLVMType regty> {
- defm _row: NVVM_WMMA_STD_LT<"row", Type, regty>;
- defm _col: NVVM_WMMA_STD_LT<"col", Type, regty>;
+multiclass NVVM_WMMA_STD_G<string Geometry> {
+ defm _d_f16: NVVM_WMMA_STD_GT<Geometry, "f16", llvm_v2f16_ty>;
+ defm _d_f32: NVVM_WMMA_STD_GT<Geometry, "f32", llvm_float_ty>;
}
-let IntrProperties = [IntrWriteMem, IntrArgMemOnly,
- WriteOnly<0>, NoCapture<0>] in {
- defm int_nvvm_wmma_store_d_f16: NVVM_WMMA_STD_T<"f16", llvm_v2f16_ty>;
- defm int_nvvm_wmma_store_d_f32: NVVM_WMMA_STD_T<"f32", llvm_float_ty>;
+multiclass NVVM_WMMA_STD {
+ defm _m32n8k16_store: NVVM_WMMA_STD_G<"m32n8k16">;
+ defm _m16n16k16_store: NVVM_WMMA_STD_G<"m16n16k16">;
+ defm _m8n32k16_store: NVVM_WMMA_STD_G<"m8n32k16">;
}
+defm int_nvvm_wmma: NVVM_WMMA_STD;
+
// WMMA.MMA
-class NVVM_WMMA_MMA_ABDCS<string ALayout, string BLayout,
- string DType, LLVMType d_regty,
- string CType, LLVMType c_regty,
- string Satfinite = "">
+class NVVM_WMMA_MMA_GABDCS<string Geometry,
+ string ALayout, string BLayout,
+ string DType, LLVMType d_regty,
+ string CType, LLVMType c_regty,
+ string Satfinite = "">
: Intrinsic<!if(!eq(DType,"f16"),
[d_regty, d_regty, d_regty, d_regty],
[d_regty, d_regty, d_regty, d_regty,
@@ -3990,39 +3994,54 @@ class NVVM_WMMA_MMA_ABDCS<string ALayout, string BLayout,
[c_regty, c_regty, c_regty, c_regty,
c_regty, c_regty, c_regty, c_regty])),
[IntrNoMem],
- "llvm.nvvm.wmma.mma.sync."#ALayout#"."#BLayout
- #".m16n16k16."#DType#"."#CType#Satfinite>;
+ "llvm.nvvm.wmma."
+ # Geometry
+ # ".mma"
+ # "." # ALayout
+ # "." # BLayout
+ # "." # DType
+ # "." # CType
+ # Satfinite> {
+}
-multiclass NVVM_WMMA_MMA_ABDC<string ALayout, string BLayout,
- string DType, LLVMType d_regty,
- string CType, LLVMType c_regty> {
- def NAME : NVVM_WMMA_MMA_ABDCS<ALayout, BLayout,
- DType, d_regty,
- CType, c_regty>;
- def _satfinite: NVVM_WMMA_MMA_ABDCS<ALayout, BLayout,
- DType, d_regty,
- CType, c_regty,".satfinite">;
+multiclass NVVM_WMMA_MMA_GABDC<string Geometry, string ALayout, string BLayout,
+ string DType, LLVMType d_regty,
+ string CType, LLVMType c_regty> {
+ def NAME : NVVM_WMMA_MMA_GABDCS<Geometry, ALayout, BLayout,
+ DType, d_regty, CType, c_regty>;
+ def _satfinite: NVVM_WMMA_MMA_GABDCS<Geometry, ALayout, BLayout,
+ DType, d_regty, CType, c_regty,".satfinite">;
}
-multiclass NVVM_WMMA_MMA_ABD<string ALayout, string BLayout,
+multiclass NVVM_WMMA_MMA_GABD<string Geometry, string ALayout, string BLayout,
string DType, LLVMType d_regty> {
- defm _f16: NVVM_WMMA_MMA_ABDC<ALayout, BLayout, DType, d_regty,
+ defm _f16: NVVM_WMMA_MMA_GABDC<Geometry, ALayout, BLayout, DType, d_regty,
"f16", llvm_v2f16_ty>;
- defm _f32: NVVM_WMMA_MMA_ABDC<ALayout, BLayout, DType, d_regty,
+ defm _f32: NVVM_WMMA_MMA_GABDC<Geometry, ALayout, BLayout, DType, d_regty,
"f32", llvm_float_ty>;
}
-multiclass NVVM_WMMA_MMA_AB<string ALayout, string BLayout> {
- defm _f16: NVVM_WMMA_MMA_ABD<ALayout, BLayout, "f16", llvm_v2f16_ty>;
- defm _f32: NVVM_WMMA_MMA_ABD<ALayout, BLayout, "f32", llvm_float_ty>;
+multiclass NVVM_WMMA_MMA_GAB<string Geometry, string ALayout, string BLayout> {
+ defm _f16: NVVM_WMMA_MMA_GABD<Geometry, ALayout, BLayout, "f16", llvm_v2f16_ty>;
+ defm _f32: NVVM_WMMA_MMA_GABD<Geometry, ALayout, BLayout, "f32", llvm_float_ty>;
+}
+
+multiclass NVVM_WMMA_MMA_GA<string Geometry, string ALayout> {
+ defm _col: NVVM_WMMA_MMA_GAB<Geometry, ALayout, "col">;
+ defm _row: NVVM_WMMA_MMA_GAB<Geometry, ALayout, "row">;
+}
+
+multiclass NVVM_WMMA_MMA_G<string Geometry> {
+ defm _col: NVVM_WMMA_MMA_GA<Geometry, "col">;
+ defm _row: NVVM_WMMA_MMA_GA<Geometry, "row">;
}
-multiclass NVVM_WMMA_MMA_A<string ALayout> {
- defm _col: NVVM_WMMA_MMA_AB<ALayout, "col">;
- defm _row: NVVM_WMMA_MMA_AB<ALayout, "row">;
+multiclass NVVM_WMMA_MMA {
+ defm _m32n8k16_mma : NVVM_WMMA_MMA_G<"m32n8k16">;
+ defm _m16n16k16_mma : NVVM_WMMA_MMA_G<"m16n16k16">;
+ defm _m8n32k16_mma : NVVM_WMMA_MMA_G<"m8n32k16">;
}
-defm int_nvvm_wmma_mma_sync_col: NVVM_WMMA_MMA_A<"col">;
-defm int_nvvm_wmma_mma_sync_row: NVVM_WMMA_MMA_A<"row">;
+defm int_nvvm_wmma : NVVM_WMMA_MMA;
} // let TargetPrefix = "nvvm"
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td
index a302d5726aa3..c4e753af25ca 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td
@@ -61,6 +61,29 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">,
Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
[IntrNoMem]>;
+
+ def int_ppc_truncf128_round_to_odd
+ : GCCBuiltin<"__builtin_truncf128_round_to_odd">,
+ Intrinsic <[llvm_double_ty], [llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_sqrtf128_round_to_odd
+ : GCCBuiltin<"__builtin_sqrtf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_addf128_round_to_odd
+ : GCCBuiltin<"__builtin_addf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_subf128_round_to_odd
+ : GCCBuiltin<"__builtin_subf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_mulf128_round_to_odd
+ : GCCBuiltin<"__builtin_mulf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_divf128_round_to_odd
+ : GCCBuiltin<"__builtin_divf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_fmaf128_round_to_odd
+ : GCCBuiltin<"__builtin_fmaf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+
}
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
index 640ef627bc46..7afc755a1e37 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
+++ b/contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -8,19 +8,60 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines all of the WebAssembly-specific intrinsics.
+/// This file defines all of the WebAssembly-specific intrinsics.
///
//===----------------------------------------------------------------------===//
let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.".
-// Note that current_memory is not IntrNoMem because it must be sequenced with
-// respect to grow_memory calls.
+// Query the current memory size, and increase the current memory size.
+// Note that memory.size is not IntrNoMem because it must be sequenced with
+// respect to memory.grow calls.
+def int_wasm_memory_size : Intrinsic<[llvm_anyint_ty],
+ [llvm_i32_ty],
+ [IntrReadMem]>;
+def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty],
+ [llvm_i32_ty, LLVMMatchType<0>],
+ []>;
+
+// These are the old names.
+def int_wasm_mem_size : Intrinsic<[llvm_anyint_ty],
+ [llvm_i32_ty],
+ [IntrReadMem]>;
+def int_wasm_mem_grow : Intrinsic<[llvm_anyint_ty],
+ [llvm_i32_ty, LLVMMatchType<0>],
+ []>;
+
+// These are the old old names. They also lack the immediate field.
def int_wasm_current_memory : Intrinsic<[llvm_anyint_ty], [], [IntrReadMem]>;
def int_wasm_grow_memory : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], []>;
+//===----------------------------------------------------------------------===//
// Exception handling intrinsics
-def int_wasm_throw: Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], [Throws]>;
-def int_wasm_rethrow: Intrinsic<[], [], [Throws]>;
+//===----------------------------------------------------------------------===//
+
+// throw / rethrow
+def int_wasm_throw : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty],
+ [Throws, IntrNoReturn]>;
+def int_wasm_rethrow : Intrinsic<[], [], [Throws, IntrNoReturn]>;
+
+// Since wasm does not use landingpad instructions, these instructions return
+// exception pointer and selector values until we lower them in WasmEHPrepare.
+def int_wasm_get_exception : Intrinsic<[llvm_ptr_ty], [llvm_token_ty],
+ [IntrHasSideEffects]>;
+def int_wasm_get_ehselector : Intrinsic<[llvm_i32_ty], [llvm_token_ty],
+ [IntrHasSideEffects]>;
+
+// wasm.catch returns the pointer to the exception object caught by wasm 'catch'
+// instruction.
+def int_wasm_catch : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty],
+ [IntrHasSideEffects]>;
+
+// WebAssembly EH must maintain the landingpads in the order assigned to them
+// by WasmEHPrepare pass to generate landingpad table in EHStreamer. This is
+// used in order to give them the indices in WasmEHPrepare.
+def int_wasm_landingpad_index: Intrinsic<[], [llvm_i32_ty], [IntrNoMem]>;
+// Returns LSDA address of the current function.
+def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
}
diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsX86.td b/contrib/llvm/include/llvm/IR/IntrinsicsX86.td
index 7c000e2b1dc7..905afc130d8f 100644
--- a/contrib/llvm/include/llvm/IR/IntrinsicsX86.td
+++ b/contrib/llvm/include/llvm/IR/IntrinsicsX86.td
@@ -63,6 +63,12 @@ let TargetPrefix = "x86" in {
Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>;
}
+// Read processor ID.
+let TargetPrefix = "x86" in {
+ def int_x86_rdpid : GCCBuiltin<"__builtin_ia32_rdpid">,
+ Intrinsic<[llvm_i32_ty], [], []>;
+}
+
//===----------------------------------------------------------------------===//
// CET SS
let TargetPrefix = "x86" in {
@@ -174,12 +180,6 @@ let TargetPrefix = "x86" in {
// Arithmetic ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_sse_sqrt_ps : GCCBuiltin<"__builtin_ia32_sqrtps">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty],
- [IntrNoMem]>;
def int_x86_sse_rcp_ss : GCCBuiltin<"__builtin_ia32_rcpss">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty],
[IntrNoMem]>;
@@ -211,6 +211,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse_cmp_ss : GCCBuiltin<"__builtin_ia32_cmpss">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ // NOTE: This comparison intrinsic is not used by clang as long as the
+ // distinction in signaling behaviour is not implemented.
def int_x86_sse_cmp_ps :
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
@@ -263,12 +265,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>;
def int_x86_sse_cvttss2si64 : GCCBuiltin<"__builtin_ia32_cvttss2si64">,
Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_sse_cvtsi2ss : // TODO: Remove this intrinsic.
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_sse_cvtsi642ss : // TODO: Remove this intrinsic.
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
- llvm_i64_ty], [IntrNoMem]>;
def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">,
Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>;
@@ -304,12 +300,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// FP arithmetic ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse2_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_sse2_sqrt_pd : GCCBuiltin<"__builtin_ia32_sqrtpd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty],
- [IntrNoMem]>;
def int_x86_sse2_min_sd : GCCBuiltin<"__builtin_ia32_minsd">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty], [IntrNoMem]>;
@@ -329,6 +319,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse2_cmp_sd : GCCBuiltin<"__builtin_ia32_cmpsd">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ // NOTE: This comparison intrinsic is not used by clang as long as the
+ // distinction in signaling behaviour is not implemented.
def int_x86_sse2_cmp_pd :
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
@@ -402,9 +394,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw128">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
llvm_v8i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_sse2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty,
- llvm_v4i32_ty], [IntrNoMem, Commutative]>;
def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty,
llvm_v8i16_ty], [IntrNoMem, Commutative]>;
@@ -468,8 +457,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Conversion ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse2_cvtdq2ps : GCCBuiltin<"__builtin_ia32_cvtdq2ps">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>;
def int_x86_sse2_cvtpd2dq : GCCBuiltin<"__builtin_ia32_cvtpd2dq">,
Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>;
def int_x86_sse2_cvttpd2dq : GCCBuiltin<"__builtin_ia32_cvttpd2dq">,
@@ -488,18 +475,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>;
def int_x86_sse2_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_cvttsd2si64">,
Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>;
- def int_x86_sse2_cvtsi2sd : // TODO: Remove this intrinsic.
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_sse2_cvtsi642sd : // TODO: Remove this intrinsic.
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
- llvm_i64_ty], [IntrNoMem]>;
def int_x86_sse2_cvtsd2ss : GCCBuiltin<"__builtin_ia32_cvtsd2ss">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
llvm_v2f64_ty], [IntrNoMem]>;
- def int_x86_sse2_cvtss2sd : // TODO: Remove this intrinsic.
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
- llvm_v4f32_ty], [IntrNoMem]>;
def int_x86_sse_cvtpd2pi : GCCBuiltin<"__builtin_ia32_cvtpd2pi">,
Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>;
def int_x86_sse_cvttpd2pi: GCCBuiltin<"__builtin_ia32_cvttpd2pi">,
@@ -797,13 +775,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem]>;
}
-// Vector multiply
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse41_pmuldq : GCCBuiltin<"__builtin_ia32_pmuldq128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
- [IntrNoMem, Commutative]>;
-}
-
// Vector insert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">,
@@ -982,11 +953,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
llvm_v8f32_ty], [IntrNoMem]>;
- def int_x86_avx_sqrt_pd_256 : GCCBuiltin<"__builtin_ia32_sqrtpd256">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>;
- def int_x86_avx_sqrt_ps_256 : GCCBuiltin<"__builtin_ia32_sqrtps256">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>;
-
def int_x86_avx_rsqrt_ps_256 : GCCBuiltin<"__builtin_ia32_rsqrtps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>;
@@ -1033,325 +999,99 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
GCCBuiltin<"__builtin_ia32_vpermilvarps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_d_128 :
- GCCBuiltin<"__builtin_ia32_vpermi2vard128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_d_256 :
- GCCBuiltin<"__builtin_ia32_vpermi2vard256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_d_512 :
- GCCBuiltin<"__builtin_ia32_vpermi2vard512_mask">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_hi_128 :
- GCCBuiltin<"__builtin_ia32_vpermi2varhi128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_hi_256 :
- GCCBuiltin<"__builtin_ia32_vpermi2varhi256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_hi_512 :
- GCCBuiltin<"__builtin_ia32_vpermi2varhi512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_pd_128 :
- GCCBuiltin<"__builtin_ia32_vpermi2varpd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_pd_256 :
- GCCBuiltin<"__builtin_ia32_vpermi2varpd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_pd_512 :
- GCCBuiltin<"__builtin_ia32_vpermi2varpd512_mask">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_ps_128 :
- GCCBuiltin<"__builtin_ia32_vpermi2varps128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_ps_256 :
- GCCBuiltin<"__builtin_ia32_vpermi2varps256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_ps_512 :
- GCCBuiltin<"__builtin_ia32_vpermi2varps512_mask">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_q_128 :
- GCCBuiltin<"__builtin_ia32_vpermi2varq128_mask">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_q_256 :
- GCCBuiltin<"__builtin_ia32_vpermi2varq256_mask">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermi2var_q_512 :
- GCCBuiltin<"__builtin_ia32_vpermi2varq512_mask">,
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_d_512:
- GCCBuiltin<"__builtin_ia32_vpermt2vard512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_q_512:
- GCCBuiltin<"__builtin_ia32_vpermt2varq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_ps_512:
- GCCBuiltin<"__builtin_ia32_vpermt2varps512_mask">,
- Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty,
- llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_pd_512:
- GCCBuiltin<"__builtin_ia32_vpermt2varpd512_mask">,
- Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty,
- llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_d_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2vard128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_d_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2vard128_maskz">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_d_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2vard256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_d_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2vard256_maskz">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_d_512 :
- GCCBuiltin<"__builtin_ia32_vpermt2vard512_maskz">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_hi_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varhi128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_hi_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varhi128_maskz">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_hi_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varhi256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_hi_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varhi256_maskz">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_hi_512 :
- GCCBuiltin<"__builtin_ia32_vpermt2varhi512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_hi_512 :
- GCCBuiltin<"__builtin_ia32_vpermt2varhi512_maskz">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_pd_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varpd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2i64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_d_128 :
+ GCCBuiltin<"__builtin_ia32_vpermi2vard128">,
+ Intrinsic<[llvm_v4i32_ty],
+ [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_pd_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varpd128_maskz">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2i64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_pd_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varpd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4i64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_pd_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varpd256_maskz">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4i64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_pd_512 :
- GCCBuiltin<"__builtin_ia32_vpermt2varpd512_maskz">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8i64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_ps_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varps128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vpermt2var_ps_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varps128_maskz">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vpermt2var_ps_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varps256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8i32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_d_256 :
+ GCCBuiltin<"__builtin_ia32_vpermi2vard256">,
+ Intrinsic<[llvm_v8i32_ty],
+ [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_ps_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varps256_maskz">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8i32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_d_512 :
+ GCCBuiltin<"__builtin_ia32_vpermi2vard512">,
+ Intrinsic<[llvm_v16i32_ty],
+ [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_ps_512 :
- GCCBuiltin<"__builtin_ia32_vpermt2varps512_maskz">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16i32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_hi_128 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varhi128">,
+ Intrinsic<[llvm_v8i16_ty],
+ [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_q_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varq128_mask">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_hi_256 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varhi256">,
+ Intrinsic<[llvm_v16i16_ty],
+ [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_q_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varq128_maskz">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_hi_512 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varhi512">,
+ Intrinsic<[llvm_v32i16_ty],
+ [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_q_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varq256_mask">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_pd_128 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varpd128">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2i64_ty, llvm_v2f64_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_q_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varq256_maskz">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_pd_256 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varpd256">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4i64_ty, llvm_v4f64_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_q_512 :
- GCCBuiltin<"__builtin_ia32_vpermt2varq512_maskz">,
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_pd_512 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varpd512">,
+ Intrinsic<[llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8i64_ty, llvm_v8f64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_qi_128 :
- GCCBuiltin<"__builtin_ia32_vpermi2varqi128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
- llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_ps_128 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varps128">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_qi_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varqi128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
- llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_ps_256 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varps256">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8f32_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_qi_128 :
- GCCBuiltin<"__builtin_ia32_vpermt2varqi128_maskz">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
- llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_ps_512 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varps512">,
+ Intrinsic<[llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16f32_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_qi_256 :
- GCCBuiltin<"__builtin_ia32_vpermi2varqi256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
- llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_q_128 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varq128">,
+ Intrinsic<[llvm_v2i64_ty],
+ [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_qi_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varqi256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
- llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_q_256 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varq256">,
+ Intrinsic<[llvm_v4i64_ty],
+ [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_qi_256 :
- GCCBuiltin<"__builtin_ia32_vpermt2varqi256_maskz">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
- llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_q_512 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varq512">,
+ Intrinsic<[llvm_v8i64_ty],
+ [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermi2var_qi_512 :
- GCCBuiltin<"__builtin_ia32_vpermi2varqi512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
- llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_qi_128 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varqi128">,
+ Intrinsic<[llvm_v16i8_ty],
+ [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpermt2var_qi_512 :
- GCCBuiltin<"__builtin_ia32_vpermt2varqi512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
- llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_qi_256 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varqi256">,
+ Intrinsic<[llvm_v32i8_ty],
+ [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpermt2var_qi_512 :
- GCCBuiltin<"__builtin_ia32_vpermt2varqi512_maskz">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
- llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_vpermi2var_qi_512 :
+ GCCBuiltin<"__builtin_ia32_vpermi2varqi512">,
+ Intrinsic<[llvm_v64i8_ty],
+ [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty], [IntrNoMem]>;
def int_x86_avx512_vpermilvar_pd_512 :
GCCBuiltin<"__builtin_ia32_vpermilvarpd512">,
@@ -1450,8 +1190,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector convert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx_cvtdq2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtdq2ps256">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>;
def int_x86_avx_cvt_pd2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtpd2ps256">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f64_ty], [IntrNoMem]>;
def int_x86_avx_cvt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvtps2dq256">,
@@ -1512,29 +1250,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty,
llvm_v4i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_pd_128 :
- GCCBuiltin<"__builtin_ia32_fpclasspd128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_i32_ty, llvm_i8_ty],
+ def int_x86_avx512_fpclass_pd_128 :
+ Intrinsic<[llvm_v2i1_ty], [llvm_v2f64_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_pd_256 :
- GCCBuiltin<"__builtin_ia32_fpclasspd256_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_i32_ty, llvm_i8_ty],
+ def int_x86_avx512_fpclass_pd_256 :
+ Intrinsic<[llvm_v4i1_ty], [llvm_v4f64_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_pd_512 :
- GCCBuiltin<"__builtin_ia32_fpclasspd512_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_i8_ty],
+ def int_x86_avx512_fpclass_pd_512 :
+ Intrinsic<[llvm_v8i1_ty], [llvm_v8f64_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_ps_128 :
- GCCBuiltin<"__builtin_ia32_fpclassps128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_i32_ty, llvm_i8_ty],
+ def int_x86_avx512_fpclass_ps_128 :
+ Intrinsic<[llvm_v4i1_ty], [llvm_v4f32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_ps_256 :
- GCCBuiltin<"__builtin_ia32_fpclassps256_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_i32_ty, llvm_i8_ty],
+ def int_x86_avx512_fpclass_ps_256 :
+ Intrinsic<[llvm_v8i1_ty], [llvm_v8f32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_fpclass_ps_512 :
- GCCBuiltin<"__builtin_ia32_fpclassps512_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_i16_ty],
+ def int_x86_avx512_fpclass_ps_512 :
+ Intrinsic<[llvm_v16i1_ty], [llvm_v16f32_ty, llvm_i32_ty],
[IntrNoMem]>;
def int_x86_avx512_mask_fpclass_sd :
GCCBuiltin<"__builtin_ia32_fpclasssd_mask">,
@@ -1600,11 +1332,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
GCCBuiltin<"__builtin_ia32_maskstoreps256">,
Intrinsic<[], [llvm_ptr_ty,
llvm_v8i32_ty, llvm_v8f32_ty], [IntrArgMemOnly]>;
-
- def int_x86_avx512_mask_store_ss :
- GCCBuiltin<"__builtin_ia32_storess_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrArgMemOnly]>;
}
// BITALG bits shuffle
@@ -1661,12 +1388,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
llvm_v16i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_pmul_dq : GCCBuiltin<"__builtin_ia32_pmuldq256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty], [IntrNoMem, Commutative]>;
def int_x86_avx2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty,
llvm_v16i16_ty], [IntrNoMem, Commutative]>;
@@ -1870,15 +1591,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
llvm_v16i16_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx512_mask_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
- llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmul_hr_sw_256 : GCCBuiltin<"__builtin_ia32_pmulhrsw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
- llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmul_hr_sw_512 : GCCBuiltin<"__builtin_ia32_pmulhrsw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
- llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_pmul_hr_sw_512 : GCCBuiltin<"__builtin_ia32_pmulhrsw512">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
+ llvm_v32i16_ty], [IntrNoMem, Commutative]>;
}
// Vector blend
@@ -2025,81 +1740,81 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_prorv_d_128 : GCCBuiltin<"__builtin_ia32_prorvd128_mask">,
+ def int_x86_avx512_prorv_d_128 : GCCBuiltin<"__builtin_ia32_prorvd128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prorv_d_256 : GCCBuiltin<"__builtin_ia32_prorvd256_mask">,
+ llvm_v4i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prorv_d_256 : GCCBuiltin<"__builtin_ia32_prorvd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prorv_d_512 : GCCBuiltin<"__builtin_ia32_prorvd512_mask">,
+ llvm_v8i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prorv_d_512 : GCCBuiltin<"__builtin_ia32_prorvd512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prorv_q_128 : GCCBuiltin<"__builtin_ia32_prorvq128_mask">,
+ llvm_v16i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prorv_q_128 : GCCBuiltin<"__builtin_ia32_prorvq128">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prorv_q_256 : GCCBuiltin<"__builtin_ia32_prorvq256_mask">,
+ llvm_v2i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_prorv_q_256 : GCCBuiltin<"__builtin_ia32_prorvq256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prorv_q_512 : GCCBuiltin<"__builtin_ia32_prorvq512_mask">,
+ llvm_v4i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_prorv_q_512 : GCCBuiltin<"__builtin_ia32_prorvq512">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_v8i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prol_d_128 : GCCBuiltin<"__builtin_ia32_prold128_mask">,
+ def int_x86_avx512_prol_d_128 : GCCBuiltin<"__builtin_ia32_prold128">,
Intrinsic<[llvm_v4i32_ty] , [llvm_v4i32_ty,
- llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prol_d_256 : GCCBuiltin<"__builtin_ia32_prold256_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prol_d_256 : GCCBuiltin<"__builtin_ia32_prold256">,
Intrinsic<[llvm_v8i32_ty] , [llvm_v8i32_ty,
- llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prol_d_512 : GCCBuiltin<"__builtin_ia32_prold512_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prol_d_512 : GCCBuiltin<"__builtin_ia32_prold512">,
Intrinsic<[llvm_v16i32_ty] , [llvm_v16i32_ty,
- llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prol_q_128 : GCCBuiltin<"__builtin_ia32_prolq128_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prol_q_128 : GCCBuiltin<"__builtin_ia32_prolq128">,
Intrinsic<[llvm_v2i64_ty] , [llvm_v2i64_ty,
- llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prol_q_256 : GCCBuiltin<"__builtin_ia32_prolq256_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prol_q_256 : GCCBuiltin<"__builtin_ia32_prolq256">,
Intrinsic<[llvm_v4i64_ty] , [llvm_v4i64_ty,
- llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prol_q_512 : GCCBuiltin<"__builtin_ia32_prolq512_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prol_q_512 : GCCBuiltin<"__builtin_ia32_prolq512">,
Intrinsic<[llvm_v8i64_ty] , [llvm_v8i64_ty,
- llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prolv_d_128 : GCCBuiltin<"__builtin_ia32_prolvd128_mask">,
+ def int_x86_avx512_prolv_d_128 : GCCBuiltin<"__builtin_ia32_prolvd128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prolv_d_256 : GCCBuiltin<"__builtin_ia32_prolvd256_mask">,
+ llvm_v4i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prolv_d_256 : GCCBuiltin<"__builtin_ia32_prolvd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prolv_d_512 : GCCBuiltin<"__builtin_ia32_prolvd512_mask">,
+ llvm_v8i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prolv_d_512 : GCCBuiltin<"__builtin_ia32_prolvd512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prolv_q_128 : GCCBuiltin<"__builtin_ia32_prolvq128_mask">,
+ llvm_v16i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_prolv_q_128 : GCCBuiltin<"__builtin_ia32_prolvq128">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prolv_q_256 : GCCBuiltin<"__builtin_ia32_prolvq256_mask">,
+ llvm_v2i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_prolv_q_256 : GCCBuiltin<"__builtin_ia32_prolvq256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_prolv_q_512 : GCCBuiltin<"__builtin_ia32_prolvq512_mask">,
+ llvm_v4i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_prolv_q_512 : GCCBuiltin<"__builtin_ia32_prolvq512">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pror_d_128 : GCCBuiltin<"__builtin_ia32_prord128_mask">,
+ llvm_v8i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_pror_d_128 : GCCBuiltin<"__builtin_ia32_prord128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
- llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pror_d_256 : GCCBuiltin<"__builtin_ia32_prord256_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_pror_d_256 : GCCBuiltin<"__builtin_ia32_prord256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pror_d_512 : GCCBuiltin<"__builtin_ia32_prord512_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_pror_d_512 : GCCBuiltin<"__builtin_ia32_prord512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pror_q_128 : GCCBuiltin<"__builtin_ia32_prorq128_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_pror_q_128 : GCCBuiltin<"__builtin_ia32_prorq128">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pror_q_256 : GCCBuiltin<"__builtin_ia32_prorq256_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_pror_q_256 : GCCBuiltin<"__builtin_ia32_prorq256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pror_q_512 : GCCBuiltin<"__builtin_ia32_prorq512_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_pror_q_512 : GCCBuiltin<"__builtin_ia32_prorq512">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_i32_ty], [IntrNoMem]>;
}
@@ -2188,754 +1903,115 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// FMA3 and FMA4
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_fma_vfmadd_ss : GCCBuiltin<"__builtin_ia32_vfmaddss3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmadd_sd : GCCBuiltin<"__builtin_ia32_vfmaddsd3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma4_vfmadd_ss : GCCBuiltin<"__builtin_ia32_vfmaddss">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma4_vfmadd_sd : GCCBuiltin<"__builtin_ia32_vfmaddsd">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmadd_ps : GCCBuiltin<"__builtin_ia32_vfmaddps">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmadd_pd : GCCBuiltin<"__builtin_ia32_vfmaddpd">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
- [IntrNoMem]>;
-
- def int_x86_fma_vfmsub_ss : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsub_sd : // TODO: remove this intrinsic
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsub_ps : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsub_pd : // TODO: remove this intrinsic
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsub_ps_256 : // TODO: remove this intrinsic
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsub_pd_256 : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmadd_ss : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmadd_sd : // TODO: remove this intrinsic
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmadd_ps : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmadd_pd : // TODO: remove this intrinsic
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmadd_ps_256 : // TODO: remove this intrinsic
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmadd_pd_256 : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmsub_ss : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmsub_sd : // TODO: remove this intrinsic
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmsub_ps : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmsub_pd : // TODO: remove this intrinsic
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmsub_ps_256 : // TODO: remove this intrinsic
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfnmsub_pd_256 : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_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],
- [IntrNoMem]>;
- def int_x86_fma_vfmaddsub_pd : GCCBuiltin<"__builtin_ia32_vfmaddsubpd">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmaddsub_ps_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubps256">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmaddsub_pd_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubpd256">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsubadd_ps : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsubadd_pd : // TODO: remove this intrinsic
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsubadd_ps_256 : // TODO: remove this intrinsic
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty],
- [IntrNoMem]>;
- def int_x86_fma_vfmsubadd_pd_256 : // TODO: remove this intrinsic
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfmadd_pd_128 :
- GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmadd_pd_128 :
- GCCBuiltin<"__builtin_ia32_vfmaddpd128_maskz">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfmadd_pd_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask3">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmadd_pd_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddpd256_maskz">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfmadd_pd_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask3">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmadd_pd_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddpd512_maskz">,
- 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_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_avx512_mask3_vfmadd_ps_128 :
- GCCBuiltin<"__builtin_ia32_vfmaddps128_mask3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmadd_ps_128 :
- GCCBuiltin<"__builtin_ia32_vfmaddps128_maskz">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfmadd_ps_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddps256_mask3">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmadd_ps_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddps256_maskz">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vfmadd_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddps512_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_mask3_vfmadd_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddps512_mask3">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmadd_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddps512_maskz">,
- 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_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_avx512_mask3_vfmaddsub_pd_128 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmaddsub_pd_128 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_maskz">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfmaddsub_pd_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask3">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmaddsub_pd_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_maskz">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfmaddsub_pd_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask3">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmaddsub_pd_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_maskz">,
- 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_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_avx512_mask3_vfmaddsub_ps_128 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmaddsub_ps_128 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubps128_maskz">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfmaddsub_ps_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask3">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmaddsub_ps_256 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubps256_maskz">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vfmaddsub_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubps512_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_mask3_vfmaddsub_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask3">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmaddsub_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfmaddsubps512_maskz">,
- 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_vfmadd_sd :
- GCCBuiltin<"__builtin_ia32_vfmaddsd3_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_vfmadd_ss :
- GCCBuiltin<"__builtin_ia32_vfmaddss3_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmadd_sd :
- GCCBuiltin<"__builtin_ia32_vfmaddsd3_maskz">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_maskz_vfmadd_ss :
- GCCBuiltin<"__builtin_ia32_vfmaddss3_maskz">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmadd_sd :
- GCCBuiltin<"__builtin_ia32_vfmaddsd3_mask3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmadd_ss :
- GCCBuiltin<"__builtin_ia32_vfmaddss3_mask3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsub_sd :
- GCCBuiltin<"__builtin_ia32_vfmsubsd3_mask3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsub_ss :
- GCCBuiltin<"__builtin_ia32_vfmsubss3_mask3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsub_pd_128 :
- GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsub_pd_256 :
- GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask3">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsub_pd_512 :
- GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask3">,
+ def int_x86_avx512_vfmadd_pd_512 :
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsub_ps_128 :
- GCCBuiltin<"__builtin_ia32_vfmsubps128_mask3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsub_ps_256 :
- GCCBuiltin<"__builtin_ia32_vfmsubps256_mask3">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsub_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfmsubps512_mask3">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsubadd_pd_128 :
- GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsubadd_pd_256 :
- GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask3">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsubadd_pd_512 :
- GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask3">,
- Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsubadd_ps_128 :
- GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfmsubadd_ps_256 :
- GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask3">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask3_vfmsubadd_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfmsubaddps512_mask3">,
+ def int_x86_avx512_vfmadd_ps_512 :
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_vfnmadd_pd_128 :
- GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_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_avx512_mask_vfnmadd_pd_512 :
- GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">,
+ // TODO: Can we use 2 vfmadds+shufflevector?
+ def int_x86_avx512_vfmaddsub_pd_512 :
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_vfnmadd_ps_128 :
- GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_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_avx512_mask_vfnmadd_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfnmaddps512_mask">,
+ def int_x86_avx512_vfmaddsub_ps_512 :
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfnmsub_sd :
- GCCBuiltin<"__builtin_ia32_vfnmsubsd3_mask3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask3_vfnmsub_ss :
- GCCBuiltin<"__builtin_ia32_vfnmsubss3_mask3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfnmsub_pd_128 :
- GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask3">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfnmsub_pd_256 :
- GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask3">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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_avx512_mask3_vfnmsub_pd_512 :
- GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask3">,
- 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_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_avx512_mask3_vfnmsub_ps_128 :
- GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask3">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_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],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask3_vfnmsub_ps_256 :
- GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask3">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_vfnmsub_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfnmsubps512_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_mask3_vfnmsub_ps_512 :
- GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask3">,
- Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vfmadd_f64 :
+ Intrinsic<[llvm_double_ty],
+ [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_vfmadd_f32 :
+ Intrinsic<[llvm_float_ty],
+ [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_mask_vpmadd52h_uq_128 :
- GCCBuiltin<"__builtin_ia32_vpmadd52huq128_mask">,
+ def int_x86_avx512_vpmadd52h_uq_128 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq128">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpmadd52h_uq_128 :
- GCCBuiltin<"__builtin_ia32_vpmadd52huq128_maskz">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpmadd52l_uq_128 :
- GCCBuiltin<"__builtin_ia32_vpmadd52luq128_mask">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpmadd52l_uq_128 :
- GCCBuiltin<"__builtin_ia32_vpmadd52luq128_maskz">,
+ llvm_v2i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpmadd52l_uq_128 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq128">,
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
- llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpmadd52h_uq_256 :
- GCCBuiltin<"__builtin_ia32_vpmadd52huq256_mask">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpmadd52h_uq_256 :
- GCCBuiltin<"__builtin_ia32_vpmadd52huq256_maskz">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpmadd52l_uq_256 :
- GCCBuiltin<"__builtin_ia32_vpmadd52luq256_mask">,
+ llvm_v2i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpmadd52h_uq_256 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpmadd52l_uq_256 :
- GCCBuiltin<"__builtin_ia32_vpmadd52luq256_maskz">,
+ llvm_v4i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpmadd52l_uq_256 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpmadd52h_uq_512 :
- GCCBuiltin<"__builtin_ia32_vpmadd52huq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpmadd52h_uq_512 :
- GCCBuiltin<"__builtin_ia32_vpmadd52huq512_maskz">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpmadd52l_uq_512 :
- GCCBuiltin<"__builtin_ia32_vpmadd52luq512_mask">,
+ llvm_v4i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpmadd52h_uq_512 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52huq512">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpmadd52l_uq_512 :
- GCCBuiltin<"__builtin_ia32_vpmadd52luq512_maskz">,
+ llvm_v8i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpmadd52l_uq_512 :
+ GCCBuiltin<"__builtin_ia32_vpmadd52luq512">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ llvm_v8i64_ty], [IntrNoMem]>;
}
// VNNI
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_vpdpbusd_128 :
- GCCBuiltin<"__builtin_ia32_vpdpbusd128_mask">,
+ def int_x86_avx512_vpdpbusd_128 :
+ GCCBuiltin<"__builtin_ia32_vpdpbusd128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpbusd_128 :
- GCCBuiltin<"__builtin_ia32_vpdpbusd128_maskz">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpbusd_256 :
- GCCBuiltin<"__builtin_ia32_vpdpbusd256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpbusd_256 :
- GCCBuiltin<"__builtin_ia32_vpdpbusd256_maskz">,
+ llvm_v4i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpdpbusd_256 :
+ GCCBuiltin<"__builtin_ia32_vpdpbusd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpbusd_512 :
- GCCBuiltin<"__builtin_ia32_vpdpbusd512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpbusd_512 :
- GCCBuiltin<"__builtin_ia32_vpdpbusd512_maskz">,
+ llvm_v8i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpdpbusd_512 :
+ GCCBuiltin<"__builtin_ia32_vpdpbusd512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_v16i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpbusds_128 :
- GCCBuiltin<"__builtin_ia32_vpdpbusds128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpbusds_128 :
- GCCBuiltin<"__builtin_ia32_vpdpbusds128_maskz">,
+ def int_x86_avx512_vpdpbusds_128 :
+ GCCBuiltin<"__builtin_ia32_vpdpbusds128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpbusds_256 :
- GCCBuiltin<"__builtin_ia32_vpdpbusds256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpbusds_256 :
- GCCBuiltin<"__builtin_ia32_vpdpbusds256_maskz">,
+ llvm_v4i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpdpbusds_256 :
+ GCCBuiltin<"__builtin_ia32_vpdpbusds256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpbusds_512 :
- GCCBuiltin<"__builtin_ia32_vpdpbusds512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpbusds_512 :
- GCCBuiltin<"__builtin_ia32_vpdpbusds512_maskz">,
+ llvm_v8i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpdpbusds_512 :
+ GCCBuiltin<"__builtin_ia32_vpdpbusds512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_v16i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpwssd_128 :
- GCCBuiltin<"__builtin_ia32_vpdpwssd128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpwssd_128 :
- GCCBuiltin<"__builtin_ia32_vpdpwssd128_maskz">,
+ def int_x86_avx512_vpdpwssd_128 :
+ GCCBuiltin<"__builtin_ia32_vpdpwssd128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpwssd_256 :
- GCCBuiltin<"__builtin_ia32_vpdpwssd256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpwssd_256 :
- GCCBuiltin<"__builtin_ia32_vpdpwssd256_maskz">,
+ llvm_v4i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpdpwssd_256 :
+ GCCBuiltin<"__builtin_ia32_vpdpwssd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpwssd_512 :
- GCCBuiltin<"__builtin_ia32_vpdpwssd512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpwssd_512 :
- GCCBuiltin<"__builtin_ia32_vpdpwssd512_maskz">,
+ llvm_v8i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpdpwssd_512 :
+ GCCBuiltin<"__builtin_ia32_vpdpwssd512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_v16i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpwssds_128 :
- GCCBuiltin<"__builtin_ia32_vpdpwssds128_mask">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpwssds_128 :
- GCCBuiltin<"__builtin_ia32_vpdpwssds128_maskz">,
+ def int_x86_avx512_vpdpwssds_128 :
+ GCCBuiltin<"__builtin_ia32_vpdpwssds128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpwssds_256 :
- GCCBuiltin<"__builtin_ia32_vpdpwssds256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpwssds_256 :
- GCCBuiltin<"__builtin_ia32_vpdpwssds256_maskz">,
+ llvm_v4i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpdpwssds_256 :
+ GCCBuiltin<"__builtin_ia32_vpdpwssds256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpdpwssds_512 :
- GCCBuiltin<"__builtin_ia32_vpdpwssds512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_vpdpwssds_512 :
- GCCBuiltin<"__builtin_ia32_vpdpwssds512_maskz">,
+ llvm_v8i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpdpwssds_512 :
+ GCCBuiltin<"__builtin_ia32_vpdpwssds512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_v16i32_ty], [IntrNoMem]>;
}
//===----------------------------------------------------------------------===//
@@ -3050,62 +2126,62 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
GCCBuiltin<"__builtin_ia32_vpmacsdd">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacsdqh :
GCCBuiltin<"__builtin_ia32_vpmacsdqh">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacsdql :
GCCBuiltin<"__builtin_ia32_vpmacsdql">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacssdd :
GCCBuiltin<"__builtin_ia32_vpmacssdd">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacssdqh :
GCCBuiltin<"__builtin_ia32_vpmacssdqh">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacssdql :
GCCBuiltin<"__builtin_ia32_vpmacssdql">,
Intrinsic<[llvm_v2i64_ty],
[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacsswd :
GCCBuiltin<"__builtin_ia32_vpmacsswd">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacssww :
GCCBuiltin<"__builtin_ia32_vpmacssww">,
Intrinsic<[llvm_v8i16_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacswd :
GCCBuiltin<"__builtin_ia32_vpmacswd">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmacsww :
GCCBuiltin<"__builtin_ia32_vpmacsww">,
Intrinsic<[llvm_v8i16_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmadcsswd :
GCCBuiltin<"__builtin_ia32_vpmadcsswd">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpmadcswd :
GCCBuiltin<"__builtin_ia32_vpmadcswd">,
Intrinsic<[llvm_v4i32_ty],
[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Commutative]>;
def int_x86_xop_vpperm :
GCCBuiltin<"__builtin_ia32_vpperm">,
Intrinsic<[llvm_v16i8_ty],
@@ -3383,48 +2459,42 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
}
// Permute
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_permvar_df_256 : GCCBuiltin<"__builtin_ia32_permvardf256_mask">,
+ def int_x86_avx512_permvar_df_256 : GCCBuiltin<"__builtin_ia32_permvardf256">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
- llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_df_512 : GCCBuiltin<"__builtin_ia32_permvardf512_mask">,
+ llvm_v4i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_df_512 : GCCBuiltin<"__builtin_ia32_permvardf512">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty,
- llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_di_256 : GCCBuiltin<"__builtin_ia32_permvardi256_mask">,
+ llvm_v8i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_di_256 : GCCBuiltin<"__builtin_ia32_permvardi256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_di_512 : GCCBuiltin<"__builtin_ia32_permvardi512_mask">,
+ llvm_v4i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_di_512 : GCCBuiltin<"__builtin_ia32_permvardi512">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_hi_128 : GCCBuiltin<"__builtin_ia32_permvarhi128_mask">,
+ llvm_v8i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_hi_128 : GCCBuiltin<"__builtin_ia32_permvarhi128">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty,
- llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_hi_256 : GCCBuiltin<"__builtin_ia32_permvarhi256_mask">,
+ llvm_v8i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_hi_256 : GCCBuiltin<"__builtin_ia32_permvarhi256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty,
- llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_hi_512 : GCCBuiltin<"__builtin_ia32_permvarhi512_mask">,
+ llvm_v16i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_hi_512 : GCCBuiltin<"__builtin_ia32_permvarhi512">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
- llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_qi_128 : GCCBuiltin<"__builtin_ia32_permvarqi128_mask">,
+ llvm_v32i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_qi_128 : GCCBuiltin<"__builtin_ia32_permvarqi128">,
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
- llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_qi_256 : GCCBuiltin<"__builtin_ia32_permvarqi256_mask">,
+ llvm_v16i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_qi_256 : GCCBuiltin<"__builtin_ia32_permvarqi256">,
Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty,
- llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_qi_512 : GCCBuiltin<"__builtin_ia32_permvarqi512_mask">,
+ llvm_v32i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_qi_512 : GCCBuiltin<"__builtin_ia32_permvarqi512">,
Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty,
- llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_sf_256 : GCCBuiltin<"__builtin_ia32_permvarsf256_mask">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
- llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_sf_512 : GCCBuiltin<"__builtin_ia32_permvarsf512_mask">,
+ llvm_v64i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_sf_512 : GCCBuiltin<"__builtin_ia32_permvarsf512">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty,
- llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_si_256 : GCCBuiltin<"__builtin_ia32_permvarsi256_mask">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_permvar_si_512 : GCCBuiltin<"__builtin_ia32_permvarsi512_mask">,
+ llvm_v16i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_permvar_si_512 : GCCBuiltin<"__builtin_ia32_permvarsi512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ llvm_v16i32_ty], [IntrNoMem]>;
}
// Pack ops.
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
@@ -3717,44 +2787,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
//===----------------------------------------------------------------------===//
// AVX512
-// Mask ops
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- // Mask instructions
- // 16-bit mask
- def int_x86_avx512_kand_w : // TODO: remove this intrinsic
- Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_kandn_w : // TODO: remove this intrinsic
- Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_knot_w : // TODO: remove this intrinsic
- Intrinsic<[llvm_i16_ty], [llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_kor_w : // TODO: remove this intrinsic
- Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_kxor_w : // TODO: remove this intrinsic
- Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_kxnor_w : // TODO: remove this intrinsic
- Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_kunpck_bw : GCCBuiltin<"__builtin_ia32_kunpckhi">,
- Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_kunpck_wd : GCCBuiltin<"__builtin_ia32_kunpcksi">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem]>;
- def int_x86_avx512_kunpck_dq : GCCBuiltin<"__builtin_ia32_kunpckdi">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem]>;
- def int_x86_avx512_kortestz_w : GCCBuiltin<"__builtin_ia32_kortestzhi">,
- Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_kortestc_w : GCCBuiltin<"__builtin_ia32_kortestchi">,
- Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
-}
-
// Conversion ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_cvttss2si : GCCBuiltin<"__builtin_ia32_vcvttss2si32">,
@@ -3779,9 +2811,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvttsd2usi64 : GCCBuiltin<"__builtin_ia32_vcvttsd2usi64">,
Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtusi2sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd32">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
- llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd64">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>;
@@ -3810,35 +2839,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_cvtsi2sd64 : GCCBuiltin<"__builtin_ia32_cvtsi2sd64">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtb2mask_128 : GCCBuiltin<"__builtin_ia32_cvtb2mask128">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtb2mask_256 : GCCBuiltin<"__builtin_ia32_cvtb2mask256">,
- Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtb2mask_512 : GCCBuiltin<"__builtin_ia32_cvtb2mask512">,
- Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtw2mask_128 : GCCBuiltin<"__builtin_ia32_cvtw2mask128">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtw2mask_256 : GCCBuiltin<"__builtin_ia32_cvtw2mask256">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtw2mask_512 : GCCBuiltin<"__builtin_ia32_cvtw2mask512">,
- Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtd2mask_128 : GCCBuiltin<"__builtin_ia32_cvtd2mask128">,
- Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtd2mask_256 : GCCBuiltin<"__builtin_ia32_cvtd2mask256">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtd2mask_512 : GCCBuiltin<"__builtin_ia32_cvtd2mask512">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtq2mask_128 : GCCBuiltin<"__builtin_ia32_cvtq2mask128">,
- Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtq2mask_256 : GCCBuiltin<"__builtin_ia32_cvtq2mask256">,
- Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtq2mask_512 : GCCBuiltin<"__builtin_ia32_cvtq2mask512">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty], [IntrNoMem]>;
-
}
// Pack ops.
@@ -3859,18 +2859,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector convert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_cvtdq2ps_128 :
- GCCBuiltin<"__builtin_ia32_cvtdq2ps128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cvtdq2ps_256 :
- GCCBuiltin<"__builtin_ia32_cvtdq2ps256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvtdq2ps_512 :
GCCBuiltin<"__builtin_ia32_cvtdq2ps512_mask">,
Intrinsic<[llvm_v16f32_ty],
@@ -3883,24 +2871,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2dq_256 :
- GCCBuiltin<"__builtin_ia32_cvtpd2dq256_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvtpd2dq_512 :
GCCBuiltin<"__builtin_ia32_cvtpd2dq512_mask">,
Intrinsic<[llvm_v8i32_ty],
[llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtpd2ps_256 :
- GCCBuiltin<"__builtin_ia32_cvtpd2ps256_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4f64_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvtpd2ps_512 :
GCCBuiltin<"__builtin_ia32_cvtpd2ps512_mask">,
Intrinsic<[llvm_v8f32_ty],
@@ -3997,18 +2973,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtps2pd_128 :
- GCCBuiltin<"__builtin_ia32_cvtps2pd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v4f32_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cvtps2pd_256 :
- GCCBuiltin<"__builtin_ia32_cvtps2pd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4f32_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvtps2pd_512 :
GCCBuiltin<"__builtin_ia32_cvtps2pd512_mask">,
Intrinsic<[llvm_v8f64_ty],
@@ -4069,18 +3033,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtqq2pd_128 :
- GCCBuiltin<"__builtin_ia32_cvtqq2pd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cvtqq2pd_256 :
- GCCBuiltin<"__builtin_ia32_cvtqq2pd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvtqq2pd_512 :
GCCBuiltin<"__builtin_ia32_cvtqq2pd512_mask">,
Intrinsic<[llvm_v8f64_ty],
@@ -4111,12 +3063,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttpd2dq_256 :
- GCCBuiltin<"__builtin_ia32_cvttpd2dq256_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvttpd2dq_512 :
GCCBuiltin<"__builtin_ia32_cvttpd2dq512_mask">,
Intrinsic<[llvm_v8i32_ty],
@@ -4177,18 +3123,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvttps2dq_128 :
- GCCBuiltin<"__builtin_ia32_cvttps2dq128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cvttps2dq_256 :
- GCCBuiltin<"__builtin_ia32_cvttps2dq256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvttps2dq_512 :
GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">,
Intrinsic<[llvm_v16i32_ty],
@@ -4249,36 +3183,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtudq2ps_128 :
- GCCBuiltin<"__builtin_ia32_cvtudq2ps128_mask">,
- Intrinsic<[llvm_v4f32_ty],
- [llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cvtudq2ps_256 :
- GCCBuiltin<"__builtin_ia32_cvtudq2ps256_mask">,
- Intrinsic<[llvm_v8f32_ty],
- [llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvtudq2ps_512 :
GCCBuiltin<"__builtin_ia32_cvtudq2ps512_mask">,
Intrinsic<[llvm_v16f32_ty],
[llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_avx512_mask_cvtuqq2pd_128 :
- GCCBuiltin<"__builtin_ia32_cvtuqq2pd128_mask">,
- Intrinsic<[llvm_v2f64_ty],
- [llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_cvtuqq2pd_256 :
- GCCBuiltin<"__builtin_ia32_cvtuqq2pd256_mask">,
- Intrinsic<[llvm_v4f64_ty],
- [llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty],
- [IntrNoMem]>;
-
def int_x86_avx512_mask_cvtuqq2pd_512 :
GCCBuiltin<"__builtin_ia32_cvtuqq2pd512_mask">,
Intrinsic<[llvm_v8f64_ty],
@@ -4361,13 +3271,6 @@ def int_x86_avx512_mask_range_ps_512 : GCCBuiltin<"__builtin_ia32_rangeps512_mas
// Vector load with broadcast
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- // TODO: Remove the broadcast intrinsics with no gcc builtin and autoupgrade
- def int_x86_avx512_vbroadcast_ss_512 :
- Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
-
- def int_x86_avx512_vbroadcast_sd_512 :
- Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>;
-
def int_x86_avx512_broadcastmw_512 :
GCCBuiltin<"__builtin_ia32_broadcastmw512">,
Intrinsic<[llvm_v16i32_ty], [llvm_i16_ty], [IntrNoMem]>;
@@ -4391,42 +3294,43 @@ 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">,
+ def int_x86_avx512_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512">,
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">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512">,
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">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512">,
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">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512">,
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">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512">,
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">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512">,
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">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512">,
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">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512">,
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">,
+ llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512">,
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_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512">,
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_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512">,
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_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512_mask">,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
- llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
@@ -4514,31 +3418,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
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_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss_round_mask">,
+ def int_x86_avx512_mask_sqrt_ss :
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd_round_mask">,
+ def int_x86_avx512_mask_sqrt_sd :
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_pd_128 : GCCBuiltin<"__builtin_ia32_sqrtpd128_mask">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_pd_256 : GCCBuiltin<"__builtin_ia32_sqrtpd256_mask">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">,
- Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
- llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_ps_128 : GCCBuiltin<"__builtin_ia32_sqrtps128_mask">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_ps_256 : GCCBuiltin<"__builtin_ia32_sqrtps256_mask">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">,
- Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
- llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_sqrt_pd_512 :
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_sqrt_ps_512 :
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_fixupimm_pd_128 :
GCCBuiltin<"__builtin_ia32_fixupimmpd128_mask">,
Intrinsic<[llvm_v2f64_ty],
@@ -4787,148 +3677,105 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
}
// Integer arithmetic ops
let TargetPrefix = "x86" in {
- def int_x86_avx512_mask_padds_b_128 : GCCBuiltin<"__builtin_ia32_paddsb128_mask">,
+ def int_x86_avx512_mask_padds_b_128 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_padds_b_256 : GCCBuiltin<"__builtin_ia32_paddsb256_mask">,
+ def int_x86_avx512_mask_padds_b_256 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_padds_b_512 : GCCBuiltin<"__builtin_ia32_paddsb512_mask">,
Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_padds_w_128 : GCCBuiltin<"__builtin_ia32_paddsw128_mask">,
+ def int_x86_avx512_mask_padds_w_128 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_padds_w_256 : GCCBuiltin<"__builtin_ia32_paddsw256_mask">,
+ def int_x86_avx512_mask_padds_w_256 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_padds_w_512 : GCCBuiltin<"__builtin_ia32_paddsw512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_paddus_b_128 : GCCBuiltin<"__builtin_ia32_paddusb128_mask">,
+ def int_x86_avx512_mask_paddus_b_128 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_paddus_b_256 : GCCBuiltin<"__builtin_ia32_paddusb256_mask">,
+ def int_x86_avx512_mask_paddus_b_256 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_paddus_b_512 : GCCBuiltin<"__builtin_ia32_paddusb512_mask">,
Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_paddus_w_128 : GCCBuiltin<"__builtin_ia32_paddusw128_mask">,
+ def int_x86_avx512_mask_paddus_w_128 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_paddus_w_256 : GCCBuiltin<"__builtin_ia32_paddusw256_mask">,
+ def int_x86_avx512_mask_paddus_w_256 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_paddus_w_512 : GCCBuiltin<"__builtin_ia32_paddusw512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psubs_b_128 : GCCBuiltin<"__builtin_ia32_psubsb128_mask">,
+ def int_x86_avx512_mask_psubs_b_128 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psubs_b_256 : GCCBuiltin<"__builtin_ia32_psubsb256_mask">,
+ def int_x86_avx512_mask_psubs_b_256 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psubs_b_512 : GCCBuiltin<"__builtin_ia32_psubsb512_mask">,
Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psubs_w_128 : GCCBuiltin<"__builtin_ia32_psubsw128_mask">,
+ def int_x86_avx512_mask_psubs_w_128 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psubs_w_256 : GCCBuiltin<"__builtin_ia32_psubsw256_mask">,
+ def int_x86_avx512_mask_psubs_w_256 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psubs_w_512 : GCCBuiltin<"__builtin_ia32_psubsw512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psubus_b_128 : GCCBuiltin<"__builtin_ia32_psubusb128_mask">,
+ def int_x86_avx512_mask_psubus_b_128 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psubus_b_256 : GCCBuiltin<"__builtin_ia32_psubusb256_mask">,
+ def int_x86_avx512_mask_psubus_b_256 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psubus_b_512 : GCCBuiltin<"__builtin_ia32_psubusb512_mask">,
Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psubus_w_128 : GCCBuiltin<"__builtin_ia32_psubusw128_mask">,
+ def int_x86_avx512_mask_psubus_w_128 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_psubus_w_256 : GCCBuiltin<"__builtin_ia32_psubusw256_mask">,
+ def int_x86_avx512_mask_psubus_w_256 : // FIXME: remove this intrinsic
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
def int_x86_avx512_mask_psubus_w_512 : GCCBuiltin<"__builtin_ia32_psubusw512_mask">,
Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty], [IntrNoMem]>;
- def int_x86_avx512_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmulhu_w_512 : GCCBuiltin<"__builtin_ia32_pmulhuw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
- llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmulh_w_512 : GCCBuiltin<"__builtin_ia32_pmulhw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
- llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmulhu_w_128 : GCCBuiltin<"__builtin_ia32_pmulhuw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
- llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmulhu_w_256 : GCCBuiltin<"__builtin_ia32_pmulhuw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
- llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmulh_w_128 : GCCBuiltin<"__builtin_ia32_pmulhw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
- llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmulh_w_256 : GCCBuiltin<"__builtin_ia32_pmulhw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
- llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmaddw_d_128 :
- GCCBuiltin<"__builtin_ia32_pmaddwd128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pmaddw_d_256 :
- GCCBuiltin<"__builtin_ia32_pmaddwd256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pmaddw_d_512 :
- GCCBuiltin<"__builtin_ia32_pmaddwd512_mask">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pmaddubs_w_128 :
- GCCBuiltin<"__builtin_ia32_pmaddubsw128_mask">,
- Intrinsic<[llvm_v8i16_ty],
- [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v8i16_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pmaddubs_w_256 :
- GCCBuiltin<"__builtin_ia32_pmaddubsw256_mask">,
- Intrinsic<[llvm_v16i16_ty],
- [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v16i16_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pmaddubs_w_512 :
- GCCBuiltin<"__builtin_ia32_pmaddubsw512_mask">,
- Intrinsic<[llvm_v32i16_ty],
- [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v32i16_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ def int_x86_avx512_pmulhu_w_512 : GCCBuiltin<"__builtin_ia32_pmulhuw512">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
+ llvm_v32i16_ty], [IntrNoMem, Commutative]>;
+ def int_x86_avx512_pmulh_w_512 : GCCBuiltin<"__builtin_ia32_pmulhw512">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty,
+ llvm_v32i16_ty], [IntrNoMem, Commutative]>;
+ def int_x86_avx512_pmaddw_d_512 : GCCBuiltin<"__builtin_ia32_pmaddwd512">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v32i16_ty,
+ llvm_v32i16_ty], [IntrNoMem, Commutative]>;
+ def int_x86_avx512_pmaddubs_w_512 : GCCBuiltin<"__builtin_ia32_pmaddubsw512">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v64i8_ty,
+ llvm_v64i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_dbpsadbw_128 :
- GCCBuiltin<"__builtin_ia32_dbpsadbw128_mask">,
+ def int_x86_avx512_dbpsadbw_128 :
+ GCCBuiltin<"__builtin_ia32_dbpsadbw128">,
Intrinsic<[llvm_v8i16_ty],
- [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_v8i16_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_dbpsadbw_256 :
- GCCBuiltin<"__builtin_ia32_dbpsadbw256_mask">,
+ def int_x86_avx512_dbpsadbw_256 :
+ GCCBuiltin<"__builtin_ia32_dbpsadbw256">,
Intrinsic<[llvm_v16i16_ty],
- [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, llvm_v16i16_ty,
- llvm_i16_ty], [IntrNoMem]>;
+ [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_dbpsadbw_512 :
- GCCBuiltin<"__builtin_ia32_dbpsadbw512_mask">,
+ def int_x86_avx512_dbpsadbw_512 :
+ GCCBuiltin<"__builtin_ia32_dbpsadbw512">,
Intrinsic<[llvm_v32i16_ty],
- [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, llvm_v32i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty], [IntrNoMem]>;
}
// Gather and Scatter ops
@@ -5299,31 +4146,6 @@ let TargetPrefix = "x86" in {
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], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_pd_512 :
- GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_ps_256 :
- GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_pd_256 :
- GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_ps_128 :
- GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_pd_128 :
- GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
-
def int_x86_avx512_mask_compress_d_512 :
GCCBuiltin<"__builtin_ia32_compresssi512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
@@ -5349,31 +4171,6 @@ let TargetPrefix = "x86" in {
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], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_q_512 :
- GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_d_256 :
- GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_q_256 :
- GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_d_128 :
- GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_q_128 :
- GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
-
def int_x86_avx512_mask_compress_b_512 :
GCCBuiltin<"__builtin_ia32_compressqi512_mask">,
Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
@@ -5399,31 +4196,6 @@ let TargetPrefix = "x86" in {
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_compress_store_b_512 :
- GCCBuiltin<"__builtin_ia32_compressstoreqi512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v64i8_ty,
- llvm_i64_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_w_512 :
- GCCBuiltin<"__builtin_ia32_compressstorehi512_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v32i16_ty,
- llvm_i32_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_b_256 :
- GCCBuiltin<"__builtin_ia32_compressstoreqi256_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v32i8_ty,
- llvm_i32_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_w_256 :
- GCCBuiltin<"__builtin_ia32_compressstorehi256_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v16i16_ty,
- llvm_i16_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_b_128 :
- GCCBuiltin<"__builtin_ia32_compressstoreqi128_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v16i8_ty,
- llvm_i16_ty], [IntrArgMemOnly]>;
- def int_x86_avx512_mask_compress_store_w_128 :
- GCCBuiltin<"__builtin_ia32_compressstorehi128_mask">,
- Intrinsic<[], [llvm_ptr_ty, llvm_v8i16_ty,
- llvm_i8_ty], [IntrArgMemOnly]>;
-
// expand
def int_x86_avx512_mask_expand_ps_512 :
GCCBuiltin<"__builtin_ia32_expandsf512_mask">,
@@ -5450,31 +4222,6 @@ let TargetPrefix = "x86" in {
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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
-
def int_x86_avx512_mask_expand_d_512 :
GCCBuiltin<"__builtin_ia32_expandsi512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
@@ -5500,31 +4247,6 @@ let TargetPrefix = "x86" in {
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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
- 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], [IntrReadMem, IntrArgMemOnly]>;
-
def int_x86_avx512_mask_expand_b_512 :
GCCBuiltin<"__builtin_ia32_expandqi512_mask">,
Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
@@ -5549,130 +4271,87 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_expandhi128_mask">,
Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_expand_load_b_512 :
- GCCBuiltin<"__builtin_ia32_expandloadqi512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_ptr_ty, llvm_v64i8_ty,
- llvm_i64_ty], [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_mask_expand_load_w_512 :
- GCCBuiltin<"__builtin_ia32_expandloadhi512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_ptr_ty, llvm_v32i16_ty,
- llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_mask_expand_load_b_256 :
- GCCBuiltin<"__builtin_ia32_expandloadqi256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty, llvm_v32i8_ty,
- llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_mask_expand_load_w_256 :
- GCCBuiltin<"__builtin_ia32_expandloadhi256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_ptr_ty, llvm_v16i16_ty,
- llvm_i16_ty], [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_mask_expand_load_b_128 :
- GCCBuiltin<"__builtin_ia32_expandloadqi128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_v16i8_ty,
- llvm_i16_ty], [IntrReadMem, IntrArgMemOnly]>;
- def int_x86_avx512_mask_expand_load_w_128 :
- GCCBuiltin<"__builtin_ia32_expandloadhi128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_v8i16_ty,
- llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>;
}
// VBMI2 Concat & Shift
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_vpshld_q_512 :
- GCCBuiltin<"__builtin_ia32_vpshldq512_mask">,
+ def int_x86_avx512_vpshld_q_512 :
+ GCCBuiltin<"__builtin_ia32_vpshldq512">,
Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_v8i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshld_q_256 :
- GCCBuiltin<"__builtin_ia32_vpshldq256_mask">,
+ [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshld_q_256 :
+ GCCBuiltin<"__builtin_ia32_vpshldq256">,
Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_v4i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshld_q_128 :
- GCCBuiltin<"__builtin_ia32_vpshldq128_mask">,
+ [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshld_q_128 :
+ GCCBuiltin<"__builtin_ia32_vpshldq128">,
Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshld_d_512 :
- GCCBuiltin<"__builtin_ia32_vpshldd512_mask">,
+ def int_x86_avx512_vpshld_d_512 :
+ GCCBuiltin<"__builtin_ia32_vpshldd512">,
Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty,
- llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshld_d_256 :
- GCCBuiltin<"__builtin_ia32_vpshldd256_mask">,
+ [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshld_d_256 :
+ GCCBuiltin<"__builtin_ia32_vpshldd256">,
Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_v8i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshld_d_128 :
- GCCBuiltin<"__builtin_ia32_vpshldd128_mask">,
+ [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshld_d_128 :
+ GCCBuiltin<"__builtin_ia32_vpshldd128">,
Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshld_w_512 :
- GCCBuiltin<"__builtin_ia32_vpshldw512_mask">,
+ def int_x86_avx512_vpshld_w_512 :
+ GCCBuiltin<"__builtin_ia32_vpshldw512">,
Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_v32i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshld_w_256 :
- GCCBuiltin<"__builtin_ia32_vpshldw256_mask">,
+ [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshld_w_256 :
+ GCCBuiltin<"__builtin_ia32_vpshldw256">,
Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, llvm_v16i16_ty,
- llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshld_w_128 :
- GCCBuiltin<"__builtin_ia32_vpshldw128_mask">,
+ [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshld_w_128 :
+ GCCBuiltin<"__builtin_ia32_vpshldw128">,
Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_q_512 :
- GCCBuiltin<"__builtin_ia32_vpshrdq512_mask">,
+ def int_x86_avx512_vpshrd_q_512 :
+ GCCBuiltin<"__builtin_ia32_vpshrdq512">,
Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_v8i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_q_256 :
- GCCBuiltin<"__builtin_ia32_vpshrdq256_mask">,
+ [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshrd_q_256 :
+ GCCBuiltin<"__builtin_ia32_vpshrdq256">,
Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_v4i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_q_128 :
- GCCBuiltin<"__builtin_ia32_vpshrdq128_mask">,
+ [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshrd_q_128 :
+ GCCBuiltin<"__builtin_ia32_vpshrdq128">,
Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_d_512 :
- GCCBuiltin<"__builtin_ia32_vpshrdd512_mask">,
+ def int_x86_avx512_vpshrd_d_512 :
+ GCCBuiltin<"__builtin_ia32_vpshrdd512">,
Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty,
- llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_d_256 :
- GCCBuiltin<"__builtin_ia32_vpshrdd256_mask">,
+ [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshrd_d_256 :
+ GCCBuiltin<"__builtin_ia32_vpshrdd256">,
Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_v8i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_d_128 :
- GCCBuiltin<"__builtin_ia32_vpshrdd128_mask">,
+ [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshrd_d_128 :
+ GCCBuiltin<"__builtin_ia32_vpshrdd128">,
Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_w_512 :
- GCCBuiltin<"__builtin_ia32_vpshrdw512_mask">,
+ def int_x86_avx512_vpshrd_w_512 :
+ GCCBuiltin<"__builtin_ia32_vpshrdw512">,
Intrinsic<[llvm_v32i16_ty],
- [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_v32i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_w_256 :
- GCCBuiltin<"__builtin_ia32_vpshrdw256_mask">,
+ [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshrd_w_256 :
+ GCCBuiltin<"__builtin_ia32_vpshrdw256">,
Intrinsic<[llvm_v16i16_ty],
- [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, llvm_v16i16_ty,
- llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_vpshrd_w_128 :
- GCCBuiltin<"__builtin_ia32_vpshrdw128_mask">,
+ [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_vpshrd_w_128 :
+ GCCBuiltin<"__builtin_ia32_vpshrdw128">,
Intrinsic<[llvm_v8i16_ty],
- [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_vpshldv_w_128 :
GCCBuiltin<"__builtin_ia32_vpshldvw128_mask">,
@@ -5978,7 +4657,6 @@ let TargetPrefix = "x86" in {
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_qw_512 :
- GCCBuiltin<"__builtin_ia32_pmovqw512_mask">,
Intrinsic<[llvm_v8i16_ty],
[llvm_v8i64_ty, llvm_v8i16_ty, llvm_i8_ty],
[IntrNoMem]>;
@@ -6037,8 +4715,7 @@ let TargetPrefix = "x86" in {
Intrinsic<[],
[llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty],
[IntrArgMemOnly]>;
- def int_x86_avx512_mask_pmov_qd_256 :
- GCCBuiltin<"__builtin_ia32_pmovqd256_mask">,
+ def int_x86_avx512_mask_pmov_qd_256 : // FIXME: Replace with trunc+select.
Intrinsic<[llvm_v4i32_ty],
[llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty],
[IntrNoMem]>;
@@ -6067,8 +4744,7 @@ let TargetPrefix = "x86" in {
Intrinsic<[],
[llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty],
[IntrArgMemOnly]>;
- def int_x86_avx512_mask_pmov_qd_512 :
- GCCBuiltin<"__builtin_ia32_pmovqd512_mask">,
+ def int_x86_avx512_mask_pmov_qd_512 : // FIXME: Replace with trunc+select.
Intrinsic<[llvm_v8i32_ty],
[llvm_v8i64_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrNoMem]>;
@@ -6158,7 +4834,6 @@ let TargetPrefix = "x86" in {
[llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_db_512 :
- GCCBuiltin<"__builtin_ia32_pmovdb512_mask">,
Intrinsic<[llvm_v16i8_ty],
[llvm_v16i32_ty, llvm_v16i8_ty, llvm_i16_ty],
[IntrNoMem]>;
@@ -6248,7 +4923,6 @@ let TargetPrefix = "x86" in {
[llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty],
[IntrArgMemOnly]>;
def int_x86_avx512_mask_pmov_dw_512 :
- GCCBuiltin<"__builtin_ia32_pmovdw512_mask">,
Intrinsic<[llvm_v16i16_ty],
[llvm_v16i32_ty, llvm_v16i16_ty, llvm_i16_ty],
[IntrNoMem]>;
@@ -6307,8 +4981,7 @@ let TargetPrefix = "x86" in {
Intrinsic<[],
[llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty],
[IntrArgMemOnly]>;
- def int_x86_avx512_mask_pmov_wb_256 :
- GCCBuiltin<"__builtin_ia32_pmovwb256_mask">,
+ def int_x86_avx512_mask_pmov_wb_256 : // FIXME: Replace with trunc+select.
Intrinsic<[llvm_v16i8_ty],
[llvm_v16i16_ty, llvm_v16i8_ty, llvm_i16_ty],
[IntrNoMem]>;
@@ -6337,8 +5010,7 @@ let TargetPrefix = "x86" in {
Intrinsic<[],
[llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty],
[IntrArgMemOnly]>;
- def int_x86_avx512_mask_pmov_wb_512 :
- GCCBuiltin<"__builtin_ia32_pmovwb512_mask">,
+ def int_x86_avx512_mask_pmov_wb_512 : // FIXME: Replace with trunc+select.
Intrinsic<[llvm_v32i8_ty],
[llvm_v32i16_ty, llvm_v32i8_ty, llvm_i32_ty],
[IntrNoMem]>;
@@ -6371,105 +5043,66 @@ let TargetPrefix = "x86" in {
// Bitwise ternary logic
let TargetPrefix = "x86" in {
- def int_x86_avx512_mask_pternlog_d_128 :
- GCCBuiltin<"__builtin_ia32_pternlogd128_mask">,
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_maskz_pternlog_d_128 :
- GCCBuiltin<"__builtin_ia32_pternlogd128_maskz">,
+ def int_x86_avx512_pternlog_d_128 :
+ GCCBuiltin<"__builtin_ia32_pternlogd128">,
Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_pternlog_d_256 :
- GCCBuiltin<"__builtin_ia32_pternlogd256_mask">,
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_maskz_pternlog_d_256 :
- GCCBuiltin<"__builtin_ia32_pternlogd256_maskz">,
+ def int_x86_avx512_pternlog_d_256 :
+ GCCBuiltin<"__builtin_ia32_pternlogd256">,
Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_pternlog_d_512 :
- GCCBuiltin<"__builtin_ia32_pternlogd512_mask">,
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty,
- llvm_i16_ty], [IntrNoMem]>;
+ [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_maskz_pternlog_d_512 :
- GCCBuiltin<"__builtin_ia32_pternlogd512_maskz">,
+ def int_x86_avx512_pternlog_d_512 :
+ GCCBuiltin<"__builtin_ia32_pternlogd512">,
Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty,
- llvm_i16_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_pternlog_q_128 :
- GCCBuiltin<"__builtin_ia32_pternlogq128_mask">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_maskz_pternlog_q_128 :
- GCCBuiltin<"__builtin_ia32_pternlogq128_maskz">,
+ def int_x86_avx512_pternlog_q_128 :
+ GCCBuiltin<"__builtin_ia32_pternlogq128">,
Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_pternlog_q_256 :
- GCCBuiltin<"__builtin_ia32_pternlogq256_mask">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_maskz_pternlog_q_256 :
- GCCBuiltin<"__builtin_ia32_pternlogq256_maskz">,
+ def int_x86_avx512_pternlog_q_256 :
+ GCCBuiltin<"__builtin_ia32_pternlogq256">,
Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_pternlog_q_512 :
- GCCBuiltin<"__builtin_ia32_pternlogq512_mask">,
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty],
+ [IntrNoMem]>;
- def int_x86_avx512_maskz_pternlog_q_512 :
- GCCBuiltin<"__builtin_ia32_pternlogq512_maskz">,
+ def int_x86_avx512_pternlog_q_512 :
+ GCCBuiltin<"__builtin_ia32_pternlogq512">,
Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
+ [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty],
+ [IntrNoMem]>;
}
// 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, 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, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_ps_256 :
- GCCBuiltin<"__builtin_ia32_cmpps256_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
- llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_pd_256 :
- GCCBuiltin<"__builtin_ia32_cmppd256_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
- llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_ps_128 :
- GCCBuiltin<"__builtin_ia32_cmpps128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
- llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_pd_128 :
- GCCBuiltin<"__builtin_ia32_cmppd128_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
- llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ // NOTE: These comparison intrinsics are not used by clang as long as the
+ // distinction in signaling behaviour is not implemented.
+ def int_x86_avx512_cmp_ps_512 :
+ Intrinsic<[llvm_v16i1_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_cmp_pd_512 :
+ Intrinsic<[llvm_v8i1_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_cmp_ps_256 :
+ Intrinsic<[llvm_v8i1_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_cmp_pd_256 :
+ Intrinsic<[llvm_v4i1_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_cmp_ps_128 :
+ Intrinsic<[llvm_v4i1_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_cmp_pd_128 :
+ Intrinsic<[llvm_v2i1_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+
def int_x86_avx512_mask_cmp_ss :
GCCBuiltin<"__builtin_ia32_cmpss_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
@@ -6518,3 +5151,65 @@ let TargetPrefix = "x86" in {
def int_x86_clzero : GCCBuiltin<"__builtin_ia32_clzero">,
Intrinsic<[], [llvm_ptr_ty], []>;
}
+
+//===----------------------------------------------------------------------===//
+// Cache write back intrinsics
+
+let TargetPrefix = "x86" in {
+ // Write back and invalidate
+ def int_x86_wbinvd : GCCBuiltin<"__builtin_ia32_wbinvd">,
+ Intrinsic<[], [], []>;
+
+ // Write back no-invalidate
+ def int_x86_wbnoinvd : GCCBuiltin<"__builtin_ia32_wbnoinvd">,
+ Intrinsic<[], [], []>;
+}
+
+//===----------------------------------------------------------------------===//
+// Cache-line demote
+
+let TargetPrefix = "x86" in {
+ def int_x86_cldemote : GCCBuiltin<"__builtin_ia32_cldemote">,
+ Intrinsic<[], [llvm_ptr_ty], []>;
+}
+
+//===----------------------------------------------------------------------===//
+// Wait and pause enhancements
+let TargetPrefix = "x86" in {
+ def int_x86_umonitor : GCCBuiltin<"__builtin_ia32_umonitor">,
+ Intrinsic<[], [llvm_ptr_ty], []>;
+ def int_x86_umwait : GCCBuiltin<"__builtin_ia32_umwait">,
+ Intrinsic<[llvm_i8_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_tpause : GCCBuiltin<"__builtin_ia32_tpause">,
+ Intrinsic<[llvm_i8_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
+}
+
+//===----------------------------------------------------------------------===//
+// Direct Move Instructions
+
+let TargetPrefix = "x86" in {
+ def int_x86_directstore32 : GCCBuiltin<"__builtin_ia32_directstore_u32">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], []>;
+ def int_x86_directstore64 : GCCBuiltin<"__builtin_ia32_directstore_u64">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty], []>;
+ def int_x86_movdir64b : GCCBuiltin<"__builtin_ia32_movdir64b">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], []>;
+}
+
+//===----------------------------------------------------------------------===//
+// PTWrite - Write data to processor trace pocket
+
+let TargetPrefix = "x86" in {
+ def int_x86_ptwrite32 : GCCBuiltin<"__builtin_ia32_ptwrite32">,
+ Intrinsic<[], [llvm_i32_ty], []>;
+ def int_x86_ptwrite64 : GCCBuiltin<"__builtin_ia32_ptwrite64">,
+ Intrinsic<[], [llvm_i64_ty], []>;
+}
+
+//===----------------------------------------------------------------------===//
+// INVPCID - Invalidate Process-Context Identifier
+
+let TargetPrefix = "x86" in {
+ def int_x86_invpcid : GCCBuiltin<"__builtin_ia32_invpcid">,
+ Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], []>;
+}
diff --git a/contrib/llvm/include/llvm/IR/LLVMContext.h b/contrib/llvm/include/llvm/IR/LLVMContext.h
index a95634d32c21..ebd445553167 100644
--- a/contrib/llvm/include/llvm/IR/LLVMContext.h
+++ b/contrib/llvm/include/llvm/IR/LLVMContext.h
@@ -31,7 +31,7 @@ class Function;
class Instruction;
class LLVMContextImpl;
class Module;
-class OptBisect;
+class OptPassGate;
template <typename T> class SmallVectorImpl;
class SMDiagnostic;
class StringRef;
@@ -76,7 +76,7 @@ public:
// Pinned metadata names, which always have the same value. This is a
// compile-time performance optimization, not a correctness optimization.
- enum {
+ enum : unsigned {
MD_dbg = 0, // "dbg"
MD_tbaa = 1, // "tbaa"
MD_prof = 2, // "prof"
@@ -108,7 +108,7 @@ public:
/// operand bundle tags that LLVM has special knowledge of are listed here.
/// Additionally, this scheme allows LLVM to efficiently check for specific
/// operand bundle tags without comparing strings.
- enum {
+ enum : unsigned {
OB_deopt = 0, // "deopt"
OB_funclet = 1, // "funclet"
OB_gc_transition = 2, // "gc-transition"
@@ -229,23 +229,23 @@ public:
/// to caller.
std::unique_ptr<DiagnosticHandler> getDiagnosticHandler();
- /// \brief Return if a code hotness metric should be included in optimization
+ /// Return if a code hotness metric should be included in optimization
/// diagnostics.
bool getDiagnosticsHotnessRequested() const;
- /// \brief Set if a code hotness metric should be included in optimization
+ /// Set if a code hotness metric should be included in optimization
/// diagnostics.
void setDiagnosticsHotnessRequested(bool Requested);
- /// \brief Return the minimum hotness value a diagnostic would need in order
+ /// Return the minimum hotness value a diagnostic would need in order
/// to be included in optimization diagnostics. If there is no minimum, this
/// returns None.
uint64_t getDiagnosticsHotnessThreshold() const;
- /// \brief Set the minimum hotness value a diagnostic needs in order to be
+ /// Set the minimum hotness value a diagnostic needs in order to be
/// included in optimization diagnostics.
void setDiagnosticsHotnessThreshold(uint64_t Threshold);
- /// \brief Return the YAML file used by the backend to save optimization
+ /// Return the YAML file used by the backend to save optimization
/// diagnostics. If null, diagnostics are not saved in a file but only
/// emitted via the diagnostic handler.
yaml::Output *getDiagnosticsOutputFile();
@@ -256,11 +256,11 @@ public:
/// set, the handler is invoked for each diagnostic message.
void setDiagnosticsOutputFile(std::unique_ptr<yaml::Output> F);
- /// \brief Get the prefix that should be printed in front of a diagnostic of
+ /// Get the prefix that should be printed in front of a diagnostic of
/// the given \p Severity
static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity);
- /// \brief Report a message to the currently installed diagnostic handler.
+ /// Report a message to the currently installed diagnostic handler.
///
/// This function returns, in particular in the case of error reporting
/// (DI.Severity == \a DS_Error), so the caller should leave the compilation
@@ -272,7 +272,7 @@ public:
/// "warning: " for \a DS_Warning, and "note: " for \a DS_Note.
void diagnose(const DiagnosticInfo &DI);
- /// \brief Registers a yield callback with the given context.
+ /// Registers a yield callback with the given context.
///
/// The yield callback function may be called by LLVM to transfer control back
/// to the client that invoked the LLVM compilation. This can be used to yield
@@ -291,7 +291,7 @@ public:
/// control to LLVM. Other LLVM contexts are unaffected by this restriction.
void setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle);
- /// \brief Calls the yield callback (if applicable).
+ /// Calls the yield callback (if applicable).
///
/// This transfers control of the current thread back to the client, which may
/// suspend the current thread. Only call this method when LLVM doesn't hold
@@ -307,7 +307,7 @@ public:
void emitError(const Instruction *I, const Twine &ErrorStr);
void emitError(const Twine &ErrorStr);
- /// \brief Query for a debug option's value.
+ /// Query for a debug option's value.
///
/// This function returns typed data populated from command line parsing.
template <typename ValT, typename Base, ValT(Base::*Mem)>
@@ -315,9 +315,17 @@ public:
return OptionRegistry::instance().template get<ValT, Base, Mem>();
}
- /// \brief Access the object which manages optimization bisection for failure
- /// analysis.
- OptBisect &getOptBisect();
+ /// Access the object which can disable optional passes and individual
+ /// optimizations at compile time.
+ OptPassGate &getOptPassGate() const;
+
+ /// Set the object which can disable optional passes and individual
+ /// optimizations at compile time.
+ ///
+ /// The lifetime of the object must be guaranteed to extend as long as the
+ /// LLVMContext is used by compilation.
+ void setOptPassGate(OptPassGate&);
+
private:
// Module needs access to the add/removeModule methods.
friend class Module;
diff --git a/contrib/llvm/include/llvm/IR/LegacyPassManagers.h b/contrib/llvm/include/llvm/IR/LegacyPassManagers.h
index 3dc4a776dba0..90036c6ce248 100644
--- a/contrib/llvm/include/llvm/IR/LegacyPassManagers.h
+++ b/contrib/llvm/include/llvm/IR/LegacyPassManagers.h
@@ -403,6 +403,15 @@ public:
InheritedAnalysis[Index++] = (*I)->getAvailableAnalysis();
}
+ /// Set the initial size of the module if the user has specified that they
+ /// want remarks for size.
+ /// Returns 0 if the remark was not requested.
+ unsigned initSizeRemarkInfo(Module &M);
+
+ /// Emit a remark signifying that the number of IR instructions in the module
+ /// changed.
+ void emitInstrCountChangedRemark(Pass *P, Module &M, unsigned CountBefore);
+
protected:
// Top level manager.
PMTopLevelManager *TPM;
diff --git a/contrib/llvm/include/llvm/IR/MDBuilder.h b/contrib/llvm/include/llvm/IR/MDBuilder.h
index dff1ca12407f..174616c7ab1d 100644
--- a/contrib/llvm/include/llvm/IR/MDBuilder.h
+++ b/contrib/llvm/include/llvm/IR/MDBuilder.h
@@ -38,17 +38,17 @@ class MDBuilder {
public:
MDBuilder(LLVMContext &context) : Context(context) {}
- /// \brief Return the given string as metadata.
+ /// Return the given string as metadata.
MDString *createString(StringRef Str);
- /// \brief Return the given constant as metadata.
+ /// Return the given constant as metadata.
ConstantAsMetadata *createConstant(Constant *C);
//===------------------------------------------------------------------===//
// FPMath metadata.
//===------------------------------------------------------------------===//
- /// \brief Return metadata with the given settings. The special value 0.0
+ /// Return metadata with the given settings. The special value 0.0
/// for the Accuracy parameter indicates the default (maximal precision)
/// setting.
MDNode *createFPMath(float Accuracy);
@@ -57,19 +57,20 @@ public:
// Prof metadata.
//===------------------------------------------------------------------===//
- /// \brief Return metadata containing two branch weights.
+ /// Return metadata containing two branch weights.
MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight);
- /// \brief Return metadata containing a number of branch weights.
+ /// Return metadata containing a number of branch weights.
MDNode *createBranchWeights(ArrayRef<uint32_t> Weights);
/// Return metadata specifying that a branch or switch is unpredictable.
MDNode *createUnpredictable();
- /// Return metadata containing the entry \p Count for a function, and the
+ /// Return metadata containing the entry \p Count for a function, a boolean
+ /// \Synthetic indicating whether the counts were synthetized, and the
/// GUIDs stored in \p Imports that need to be imported for sample PGO, to
/// enable the same inlines as the profiled optimized binary
- MDNode *createFunctionEntryCount(uint64_t Count,
+ MDNode *createFunctionEntryCount(uint64_t Count, bool Synthetic,
const DenseSet<GlobalValue::GUID> *Imports);
/// Return metadata containing the section prefix for a function.
@@ -79,17 +80,17 @@ public:
// Range metadata.
//===------------------------------------------------------------------===//
- /// \brief Return metadata describing the range [Lo, Hi).
+ /// Return metadata describing the range [Lo, Hi).
MDNode *createRange(const APInt &Lo, const APInt &Hi);
- /// \brief Return metadata describing the range [Lo, Hi).
+ /// Return metadata describing the range [Lo, Hi).
MDNode *createRange(Constant *Lo, Constant *Hi);
//===------------------------------------------------------------------===//
// Callees metadata.
//===------------------------------------------------------------------===//
- /// \brief Return metadata indicating the possible callees of indirect
+ /// Return metadata indicating the possible callees of indirect
/// calls.
MDNode *createCallees(ArrayRef<Function *> Callees);
@@ -98,28 +99,28 @@ public:
//===------------------------------------------------------------------===//
protected:
- /// \brief Return metadata appropriate for a AA root node (scope or TBAA).
+ /// Return metadata appropriate for a AA root node (scope or TBAA).
/// Each returned node is distinct from all other metadata and will never
/// be identified (uniqued) with anything else.
MDNode *createAnonymousAARoot(StringRef Name = StringRef(),
MDNode *Extra = nullptr);
public:
- /// \brief Return metadata appropriate for a TBAA root node. Each returned
+ /// Return metadata appropriate for a TBAA root node. Each returned
/// node is distinct from all other metadata and will never be identified
/// (uniqued) with anything else.
MDNode *createAnonymousTBAARoot() {
return createAnonymousAARoot();
}
- /// \brief Return metadata appropriate for an alias scope domain node.
+ /// Return metadata appropriate for an alias scope domain node.
/// Each returned node is distinct from all other metadata and will never
/// be identified (uniqued) with anything else.
MDNode *createAnonymousAliasScopeDomain(StringRef Name = StringRef()) {
return createAnonymousAARoot(Name);
}
- /// \brief Return metadata appropriate for an alias scope root node.
+ /// Return metadata appropriate for an alias scope root node.
/// Each returned node is distinct from all other metadata and will never
/// be identified (uniqued) with anything else.
MDNode *createAnonymousAliasScope(MDNode *Domain,
@@ -127,22 +128,22 @@ public:
return createAnonymousAARoot(Name, Domain);
}
- /// \brief Return metadata appropriate for a TBAA root node with the given
+ /// Return metadata appropriate for a TBAA root node with the given
/// name. This may be identified (uniqued) with other roots with the same
/// name.
MDNode *createTBAARoot(StringRef Name);
- /// \brief Return metadata appropriate for an alias scope domain node with
+ /// Return metadata appropriate for an alias scope domain node with
/// the given name. This may be identified (uniqued) with other roots with
/// the same name.
MDNode *createAliasScopeDomain(StringRef Name);
- /// \brief Return metadata appropriate for an alias scope node with
+ /// Return metadata appropriate for an alias scope node with
/// the given name. This may be identified (uniqued) with other scopes with
/// the same name and domain.
MDNode *createAliasScope(StringRef Name, MDNode *Domain);
- /// \brief Return metadata for a non-root TBAA node with the given name,
+ /// Return metadata for a non-root TBAA node with the given name,
/// parent in the TBAA tree, and value for 'pointsToConstantMemory'.
MDNode *createTBAANode(StringRef Name, MDNode *Parent,
bool isConstant = false);
@@ -155,33 +156,33 @@ public:
Offset(Offset), Size(Size), Type(Type) {}
};
- /// \brief Return metadata for a tbaa.struct node with the given
+ /// Return metadata for a tbaa.struct node with the given
/// struct field descriptions.
MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields);
- /// \brief Return metadata for a TBAA struct node in the type DAG
+ /// Return metadata for a TBAA struct node in the type DAG
/// with the given name, a list of pairs (offset, field type in the type DAG).
MDNode *
createTBAAStructTypeNode(StringRef Name,
ArrayRef<std::pair<MDNode *, uint64_t>> Fields);
- /// \brief Return metadata for a TBAA scalar type node with the
+ /// Return metadata for a TBAA scalar type node with the
/// given name, an offset and a parent in the TBAA type DAG.
MDNode *createTBAAScalarTypeNode(StringRef Name, MDNode *Parent,
uint64_t Offset = 0);
- /// \brief Return metadata for a TBAA tag node with the given
+ /// Return metadata for a TBAA tag node with the given
/// base type, access type and offset relative to the base type.
MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType,
uint64_t Offset, bool IsConstant = false);
- /// \brief Return metadata for a TBAA type node in the TBAA type DAG with the
+ /// Return metadata for a TBAA type node in the TBAA type DAG with the
/// given parent type, size in bytes, type identifier and a list of fields.
MDNode *createTBAATypeNode(MDNode *Parent, uint64_t Size, Metadata *Id,
ArrayRef<TBAAStructField> Fields =
ArrayRef<TBAAStructField>());
- /// \brief Return metadata for a TBAA access tag with the given base type,
+ /// Return metadata for a TBAA access tag with the given base type,
/// final access type, offset of the access relative to the base type, size of
/// the access and flag indicating whether the accessed object can be
/// considered immutable for the purposes of the TBAA analysis.
@@ -189,7 +190,11 @@ public:
uint64_t Offset, uint64_t Size,
bool IsImmutable = false);
- /// \brief Return metadata containing an irreducible loop header weight.
+ /// Return mutable version of the given mutable or immutable TBAA
+ /// access tag.
+ MDNode *createMutableTBAAAccessTag(MDNode *Tag);
+
+ /// Return metadata containing an irreducible loop header weight.
MDNode *createIrrLoopHeaderWeight(uint64_t Weight);
};
diff --git a/contrib/llvm/include/llvm/IR/Mangler.h b/contrib/llvm/include/llvm/IR/Mangler.h
index 56ee21392ccd..0261c00f524c 100644
--- a/contrib/llvm/include/llvm/IR/Mangler.h
+++ b/contrib/llvm/include/llvm/IR/Mangler.h
@@ -50,6 +50,9 @@ public:
void emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
const Triple &TT, Mangler &Mangler);
+void emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV,
+ const Triple &T, Mangler &M);
+
} // End llvm namespace
#endif
diff --git a/contrib/llvm/include/llvm/IR/Metadata.def b/contrib/llvm/include/llvm/IR/Metadata.def
index 03cdcab7dc47..70a03f28b488 100644
--- a/contrib/llvm/include/llvm/IR/Metadata.def
+++ b/contrib/llvm/include/llvm/IR/Metadata.def
@@ -108,6 +108,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateValueParameter)
HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILabel)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity)
HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode)
diff --git a/contrib/llvm/include/llvm/IR/Metadata.h b/contrib/llvm/include/llvm/IR/Metadata.h
index bc0b87a6c348..9ac97f4224ac 100644
--- a/contrib/llvm/include/llvm/IR/Metadata.h
+++ b/contrib/llvm/include/llvm/IR/Metadata.h
@@ -52,20 +52,20 @@ enum LLVMConstants : uint32_t {
DEBUG_METADATA_VERSION = 3 // Current debug info version number.
};
-/// \brief Root of the metadata hierarchy.
+/// Root of the metadata hierarchy.
///
/// This is a root class for typeless data in the IR.
class Metadata {
friend class ReplaceableMetadataImpl;
- /// \brief RTTI.
+ /// RTTI.
const unsigned char SubclassID;
protected:
- /// \brief Active type of storage.
+ /// Active type of storage.
enum StorageType { Uniqued, Distinct, Temporary };
- /// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
+ /// Storage flag for non-uniqued, otherwise unowned, metadata.
unsigned char Storage;
// TODO: expose remaining bits to subclasses.
@@ -86,7 +86,7 @@ protected:
~Metadata() = default;
- /// \brief Default handling of a changed operand, which asserts.
+ /// 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.
@@ -97,7 +97,7 @@ protected:
public:
unsigned getMetadataID() const { return SubclassID; }
- /// \brief User-friendly dump.
+ /// User-friendly dump.
///
/// If \c M is provided, metadata nodes will be numbered canonically;
/// otherwise, pointer addresses are substituted.
@@ -110,7 +110,7 @@ public:
void dump(const Module *M) const;
/// @}
- /// \brief Print.
+ /// Print.
///
/// Prints definition of \c this.
///
@@ -123,7 +123,7 @@ public:
bool IsForDebug = false) const;
/// @}
- /// \brief Print as operand.
+ /// Print as operand.
///
/// Prints reference of \c this.
///
@@ -162,7 +162,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) {
return OS;
}
-/// \brief Metadata wrapper in the Value hierarchy.
+/// 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.
@@ -177,7 +177,7 @@ class MetadataAsValue : public Value {
MetadataAsValue(Type *Ty, Metadata *MD);
- /// \brief Drop use of metadata (during teardown).
+ /// Drop use of metadata (during teardown).
void dropUse() { MD = nullptr; }
public:
@@ -198,7 +198,7 @@ private:
void untrack();
};
-/// \brief API for tracking metadata references through RAUW and deletion.
+/// API for tracking metadata references through RAUW and deletion.
///
/// Shared API for updating \a Metadata pointers in subclasses that support
/// RAUW.
@@ -207,7 +207,7 @@ private:
/// user-friendly tracking reference.
class MetadataTracking {
public:
- /// \brief Track the reference to metadata.
+ /// 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
@@ -220,7 +220,7 @@ public:
return track(&MD, *MD, static_cast<Metadata *>(nullptr));
}
- /// \brief Track the reference to metadata for \a Metadata.
+ /// 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
@@ -229,7 +229,7 @@ public:
return track(Ref, MD, &Owner);
}
- /// \brief Track the reference to metadata for \a MetadataAsValue.
+ /// 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
@@ -238,13 +238,13 @@ public:
return track(Ref, MD, &Owner);
}
- /// \brief Stop tracking a reference to metadata.
+ /// 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.
+ /// Move tracking from one reference to another.
///
/// Semantically equivalent to \c untrack(MD) followed by \c track(New),
/// except that ownership callbacks are maintained.
@@ -257,19 +257,19 @@ public:
}
static bool retrack(void *Ref, Metadata &MD, void *New);
- /// \brief Check whether metadata is replaceable.
+ /// Check whether metadata is replaceable.
static bool isReplaceable(const Metadata &MD);
using OwnerTy = PointerUnion<MetadataAsValue *, Metadata *>;
private:
- /// \brief Track a reference to metadata for an owner.
+ /// Track a reference to metadata for an owner.
///
/// Generalized version of tracking.
static bool track(void *Ref, Metadata &MD, OwnerTy Owner);
};
-/// \brief Shared implementation of use-lists for replaceable metadata.
+/// 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
@@ -294,12 +294,12 @@ public:
LLVMContext &getContext() const { return Context; }
- /// \brief Replace all uses of this with MD.
+ /// 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.
///
/// Resolve all uses of this, turning off RAUW permanently. If \c
/// ResolveUsers, call \a MDNode::resolve() on any users whose last operand
@@ -326,7 +326,7 @@ private:
static bool isReplaceable(const Metadata &MD);
};
-/// \brief Value wrapper in the Metadata hierarchy.
+/// Value wrapper in the Metadata hierarchy.
///
/// This is a custom value handle that allows other metadata to refer to
/// classes in the Value hierarchy.
@@ -340,7 +340,7 @@ class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl {
Value *V;
- /// \brief Drop users without RAUW (during teardown).
+ /// Drop users without RAUW (during teardown).
void dropUsers() {
ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false);
}
@@ -382,7 +382,7 @@ public:
static void handleRAUW(Value *From, Value *To);
protected:
- /// \brief Handle collisions after \a Value::replaceAllUsesWith().
+ /// 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
@@ -444,7 +444,7 @@ public:
}
};
-/// \brief Transitional API for extracting constants from Metadata.
+/// Transitional API for extracting constants from Metadata.
///
/// This namespace contains transitional functions for metadata that points to
/// \a Constants.
@@ -520,7 +520,7 @@ template <class V, class M> struct IsValidReference {
} // end namespace detail
-/// \brief Check whether Metadata has a Value.
+/// 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.
@@ -539,7 +539,7 @@ inline
return hasa(&MD);
}
-/// \brief Extract a Value from Metadata.
+/// 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>
@@ -554,7 +554,7 @@ inline
return extract(&MD);
}
-/// \brief Extract a Value from Metadata, allowing null.
+/// 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.
@@ -566,7 +566,7 @@ extract_or_null(Y &&MD) {
return nullptr;
}
-/// \brief Extract a Value from Metadata, if any.
+/// 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
@@ -579,7 +579,7 @@ dyn_extract(Y &&MD) {
return nullptr;
}
-/// \brief Extract a Value from Metadata, if any, allowing null.
+/// 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
@@ -595,7 +595,7 @@ dyn_extract_or_null(Y &&MD) {
} // end namespace mdconst
//===----------------------------------------------------------------------===//
-/// \brief A single uniqued string.
+/// A single uniqued string.
///
/// These are used to efficiently contain a byte sequence for metadata.
/// MDString is always unnamed.
@@ -622,22 +622,22 @@ public:
using iterator = StringRef::iterator;
- /// \brief Pointer to the first byte of the string.
+ /// Pointer to the first byte of the string.
iterator begin() const { return getString().begin(); }
- /// \brief Pointer to one byte past the end of the string.
+ /// 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.
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDStringKind;
}
};
-/// \brief A collection of metadata nodes that might be associated with a
+/// A collection of metadata nodes that might be associated with a
/// memory access used by the alias-analysis infrastructure.
struct AAMDNodes {
explicit AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr,
@@ -652,16 +652,16 @@ struct AAMDNodes {
explicit operator bool() const { return TBAA || Scope || NoAlias; }
- /// \brief The tag for type-based alias analysis.
+ /// The tag for type-based alias analysis.
MDNode *TBAA;
- /// \brief The tag for alias scope specification (used with noalias).
+ /// The tag for alias scope specification (used with noalias).
MDNode *Scope;
- /// \brief The tag specifying the noalias scope.
+ /// The tag specifying the noalias scope.
MDNode *NoAlias;
- /// \brief Given two sets of AAMDNodes that apply to the same pointer,
+ /// Given two sets of AAMDNodes that apply to the same pointer,
/// give the best AAMDNodes that are compatible with both (i.e. a set of
/// nodes whose allowable aliasing conclusions are a subset of those
/// allowable by both of the inputs). However, for efficiency
@@ -699,7 +699,7 @@ struct DenseMapInfo<AAMDNodes> {
}
};
-/// \brief Tracking metadata reference owned by Metadata.
+/// 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
@@ -761,7 +761,7 @@ template <> struct simplify_type<const MDOperand> {
static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); }
};
-/// \brief Pointer to the context, with optional RAUW support.
+/// 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).
@@ -785,7 +785,7 @@ public:
operator LLVMContext &() { return getContext(); }
- /// \brief Whether this contains RAUW support.
+ /// Whether this contains RAUW support.
bool hasReplaceableUses() const {
return Ptr.is<ReplaceableMetadataImpl *>();
}
@@ -809,7 +809,7 @@ public:
return getReplaceableUses();
}
- /// \brief Assign RAUW support to this.
+ /// Assign RAUW support to this.
///
/// Make this replaceable, taking ownership of \c ReplaceableUses (which must
/// not be null).
@@ -822,7 +822,7 @@ public:
Ptr = ReplaceableUses.release();
}
- /// \brief Drop RAUW support.
+ /// Drop RAUW support.
///
/// Cede ownership of RAUW support, returning it.
std::unique_ptr<ReplaceableMetadataImpl> takeReplaceableUses() {
@@ -843,7 +843,7 @@ struct TempMDNodeDeleter {
#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS)
#include "llvm/IR/Metadata.def"
-/// \brief Metadata node.
+/// 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
@@ -876,12 +876,12 @@ protected:
void *operator new(size_t Size, unsigned NumOps);
void operator delete(void *Mem);
- /// \brief Required by std, but never called.
+ /// Required by std, but never called.
void operator delete(void *, unsigned) {
llvm_unreachable("Constructor throws?");
}
- /// \brief Required by std, but never called.
+ /// Required by std, but never called.
void operator delete(void *, unsigned, bool) {
llvm_unreachable("Constructor throws?");
}
@@ -910,10 +910,10 @@ public:
static inline TempMDTuple getTemporary(LLVMContext &Context,
ArrayRef<Metadata *> MDs);
- /// \brief Create a (temporary) clone of this.
+ /// Create a (temporary) clone of this.
TempMDNode clone() const;
- /// \brief Deallocate a node created by getTemporary.
+ /// Deallocate a node created by getTemporary.
///
/// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining
/// references will be reset.
@@ -921,10 +921,10 @@ public:
LLVMContext &getContext() const { return Context.getContext(); }
- /// \brief Replace a specific operand.
+ /// Replace a specific operand.
void replaceOperandWith(unsigned I, Metadata *New);
- /// \brief Check if node is fully resolved.
+ /// Check if node is fully resolved.
///
/// If \a isTemporary(), this always returns \c false; if \a isDistinct(),
/// this always returns \c true.
@@ -941,7 +941,7 @@ public:
bool isDistinct() const { return Storage == Distinct; }
bool isTemporary() const { return Storage == Temporary; }
- /// \brief RAUW a temporary.
+ /// RAUW a temporary.
///
/// \pre \a isTemporary() must be \c true.
void replaceAllUsesWith(Metadata *MD) {
@@ -950,7 +950,7 @@ public:
Context.getReplaceableUses()->replaceAllUsesWith(MD);
}
- /// \brief Resolve cycles.
+ /// Resolve cycles.
///
/// Once all forward declarations have been resolved, force cycles to be
/// resolved.
@@ -961,7 +961,7 @@ public:
/// Resolve a unique, unresolved node.
void resolve();
- /// \brief Replace a temporary node with a permanent one.
+ /// 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.
@@ -971,7 +971,7 @@ public:
return cast<T>(N.release()->replaceWithPermanentImpl());
}
- /// \brief Replace a temporary node with a uniqued one.
+ /// 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.
@@ -983,7 +983,7 @@ public:
return cast<T>(N.release()->replaceWithUniquedImpl());
}
- /// \brief Replace a temporary node with a distinct one.
+ /// 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.
@@ -999,7 +999,7 @@ private:
MDNode *replaceWithDistinctImpl();
protected:
- /// \brief Set an operand.
+ /// Set an operand.
///
/// Sets the operand directly, without worrying about uniquing.
void setOperand(unsigned I, Metadata *New);
@@ -1019,14 +1019,14 @@ private:
void decrementUnresolvedOperandCount();
void countUnresolvedOperands();
- /// \brief Mutate this to be "uniqued".
+ /// Mutate this to be "uniqued".
///
/// 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 to be "distinct".
///
/// Mutate this so that \a isDistinct().
/// \pre \a isTemporary().
@@ -1069,10 +1069,10 @@ public:
return op_begin()[I];
}
- /// \brief Return number of MDNode operands.
+ /// Return number of MDNode operands.
unsigned getNumOperands() const { return NumOperands; }
- /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Metadata *MD) {
switch (MD->getMetadataID()) {
default:
@@ -1084,10 +1084,10 @@ public:
}
}
- /// \brief Check whether MDNode is a vtable access.
+ /// Check whether MDNode is a vtable access.
bool isTBAAVtableAccess() const;
- /// \brief Methods for metadata merging.
+ /// Methods for metadata merging.
static MDNode *concatenate(MDNode *A, MDNode *B);
static MDNode *intersect(MDNode *A, MDNode *B);
static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B);
@@ -1097,7 +1097,7 @@ public:
static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B);
};
-/// \brief Tuple of metadata.
+/// Tuple of metadata.
///
/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by
/// default based on their operands.
@@ -1125,7 +1125,7 @@ class MDTuple : public MDNode {
}
public:
- /// \brief Get the hash, if any.
+ /// Get the hash, if any.
unsigned getHash() const { return SubclassData32; }
static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
@@ -1136,14 +1136,14 @@ public:
return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false);
}
- /// \brief Return a distinct node.
+ /// 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);
}
- /// \brief Return a temporary node.
+ /// 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
@@ -1153,7 +1153,7 @@ public:
return TempMDTuple(getImpl(Context, MDs, Temporary));
}
- /// \brief Return a (temporary) clone of this.
+ /// Return a (temporary) clone of this.
TempMDTuple clone() const { return cloneImpl(); }
static bool classof(const Metadata *MD) {
@@ -1182,7 +1182,7 @@ void TempMDNodeDeleter::operator()(MDNode *Node) const {
MDNode::deleteTemporary(Node);
}
-/// \brief Typed iterator through MDNode operands.
+/// Typed iterator through MDNode operands.
///
/// An iterator that transforms an \a MDNode::iterator into an iterator over a
/// particular Metadata subclass.
@@ -1213,7 +1213,7 @@ public:
bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; }
};
-/// \brief Typed, array-like tuple of metadata.
+/// Typed, array-like tuple of metadata.
///
/// This is a wrapper for \a MDTuple that makes it act like an array holding a
/// particular type of metadata.
@@ -1314,7 +1314,7 @@ public:
};
//===----------------------------------------------------------------------===//
-/// \brief A tuple of MDNodes.
+/// A tuple of MDNodes.
///
/// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong
/// to modules, have names, and contain lists of MDNodes.
@@ -1377,7 +1377,7 @@ public:
NamedMDNode(const NamedMDNode &) = delete;
~NamedMDNode();
- /// \brief Drop all references and remove the node from parent module.
+ /// Drop all references and remove the node from parent module.
void eraseFromParent();
/// Remove all uses and clear node vector.
@@ -1385,7 +1385,7 @@ public:
/// Drop all references to this node's operands.
void clearOperands();
- /// \brief Get the module that holds this named metadata collection.
+ /// Get the module that holds this named metadata collection.
inline Module *getParent() { return Parent; }
inline const Module *getParent() const { return Parent; }
diff --git a/contrib/llvm/include/llvm/IR/Module.h b/contrib/llvm/include/llvm/IR/Module.h
index 196e32e3615c..a405f7df3efe 100644
--- a/contrib/llvm/include/llvm/IR/Module.h
+++ b/contrib/llvm/include/llvm/IR/Module.h
@@ -59,7 +59,7 @@ class StructType;
/// A module maintains a GlobalValRefMap object that is used to hold all
/// constant references to global variables in the module. When a global
/// variable is destroyed, it should have no entries in the GlobalValueRefMap.
-/// @brief The main container class for the LLVM Intermediate Representation.
+/// The main container class for the LLVM Intermediate Representation.
class Module {
/// @name Types And Enumerations
/// @{
@@ -207,13 +207,18 @@ public:
/// @returns the module identifier as a string
const std::string &getModuleIdentifier() const { return ModuleID; }
+ /// Returns the number of non-debug IR instructions in the module.
+ /// This is equivalent to the sum of the IR instruction counts of each
+ /// function contained in the module.
+ unsigned getInstructionCount();
+
/// Get the module's original source file name. When compiling from
/// bitcode, this is taken from a bitcode record where it was recorded.
/// For other compiles it is the same as the ModuleID, which would
/// contain the source file name.
const std::string &getSourceFileName() const { return SourceFileName; }
- /// \brief Get a short "name" for the module.
+ /// Get a short "name" for the module.
///
/// This is useful for debugging or logging. It is essentially a convenience
/// wrapper around getModuleIdentifier().
@@ -251,9 +256,16 @@ public:
/// versions when the pass does not change.
std::unique_ptr<RandomNumberGenerator> createRNG(const Pass* P) const;
-/// @}
-/// @name Module Level Mutators
-/// @{
+ /// Return true if size-info optimization remark is enabled, false
+ /// otherwise.
+ bool shouldEmitInstrCountChangedRemark() {
+ return getContext().getDiagHandlerPtr()->isAnalysisRemarkEnabled(
+ "size-info");
+ }
+
+ /// @}
+ /// @name Module Level Mutators
+ /// @{
/// Set the module identifier.
void setModuleIdentifier(StringRef ID) { ModuleID = ID; }
@@ -795,14 +807,14 @@ public:
/// @name Utility functions for querying Debug information.
/// @{
- /// \brief Returns the Number of Register ParametersDwarf Version by checking
+ /// Returns the Number of Register ParametersDwarf Version by checking
/// module flags.
unsigned getNumberRegisterParameters() const;
- /// \brief Returns the Dwarf Version by checking module flags.
+ /// Returns the Dwarf Version by checking module flags.
unsigned getDwarfVersion() const;
- /// \brief Returns the CodeView Version by checking module flags.
+ /// Returns the CodeView Version by checking module flags.
/// Returns zero if not present in module.
unsigned getCodeViewFlag() const;
@@ -810,10 +822,10 @@ public:
/// @name Utility functions for querying and setting PIC level
/// @{
- /// \brief Returns the PIC level (small or large model)
+ /// Returns the PIC level (small or large model)
PICLevel::Level getPICLevel() const;
- /// \brief Set the PIC level (small or large model)
+ /// Set the PIC level (small or large model)
void setPICLevel(PICLevel::Level PL);
/// @}
@@ -821,28 +833,35 @@ public:
/// @name Utility functions for querying and setting PIE level
/// @{
- /// \brief Returns the PIE level (small or large model)
+ /// Returns the PIE level (small or large model)
PIELevel::Level getPIELevel() const;
- /// \brief Set the PIE level (small or large model)
+ /// Set the PIE level (small or large model)
void setPIELevel(PIELevel::Level PL);
/// @}
/// @name Utility functions for querying and setting PGO summary
/// @{
- /// \brief Attach profile summary metadata to this module.
+ /// Attach profile summary metadata to this module.
void setProfileSummary(Metadata *M);
- /// \brief Returns profile summary metadata
+ /// Returns profile summary metadata
Metadata *getProfileSummary();
/// @}
+ /// Returns true if PLT should be avoided for RTLib calls.
+ bool getRtLibUseGOT() const;
+
+ /// Set that PLT should be avoid for RTLib calls.
+ void setRtLibUseGOT();
+
+
/// Take ownership of the given memory buffer.
void setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB);
};
-/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
+/// Given "llvm.used" or "llvm.compiler.used" as a global name, collect
/// the initializer elements of that global in Set and return the global itself.
GlobalVariable *collectUsedGlobalVariables(const Module &M,
SmallPtrSetImpl<GlobalValue *> &Set,
diff --git a/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h b/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h
index dd7a0db83774..fdf3d4b5f1ce 100644
--- a/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -25,6 +25,10 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/ScaledNumber.h"
+#include "llvm/Support/StringSaver.h"
#include <algorithm>
#include <array>
#include <cassert>
@@ -45,7 +49,7 @@ template <typename T> struct MappingTraits;
} // end namespace yaml
-/// \brief Class to accumulate and hold information about a callee.
+/// Class to accumulate and hold information about a callee.
struct CalleeInfo {
enum class HotnessType : uint8_t {
Unknown = 0,
@@ -54,13 +58,44 @@ struct CalleeInfo {
Hot = 3,
Critical = 4
};
- HotnessType Hotness = HotnessType::Unknown;
- CalleeInfo() = default;
- explicit CalleeInfo(HotnessType Hotness) : Hotness(Hotness) {}
+ // The size of the bit-field might need to be adjusted if more values are
+ // added to HotnessType enum.
+ uint32_t Hotness : 3;
+
+ /// The value stored in RelBlockFreq has to be interpreted as the digits of
+ /// a scaled number with a scale of \p -ScaleShift.
+ uint32_t RelBlockFreq : 29;
+ static constexpr int32_t ScaleShift = 8;
+ static constexpr uint64_t MaxRelBlockFreq = (1 << 29) - 1;
+
+ CalleeInfo()
+ : Hotness(static_cast<uint32_t>(HotnessType::Unknown)), RelBlockFreq(0) {}
+ explicit CalleeInfo(HotnessType Hotness, uint64_t RelBF)
+ : Hotness(static_cast<uint32_t>(Hotness)), RelBlockFreq(RelBF) {}
void updateHotness(const HotnessType OtherHotness) {
- Hotness = std::max(Hotness, OtherHotness);
+ Hotness = std::max(Hotness, static_cast<uint32_t>(OtherHotness));
+ }
+
+ HotnessType getHotness() const { return HotnessType(Hotness); }
+
+ /// Update \p RelBlockFreq from \p BlockFreq and \p EntryFreq
+ ///
+ /// BlockFreq is divided by EntryFreq and added to RelBlockFreq. To represent
+ /// fractional values, the result is represented as a fixed point number with
+ /// scale of -ScaleShift.
+ void updateRelBlockFreq(uint64_t BlockFreq, uint64_t EntryFreq) {
+ if (EntryFreq == 0)
+ return;
+ using Scaled64 = ScaledNumber<uint64_t>;
+ Scaled64 Temp(BlockFreq, ScaleShift);
+ Temp /= Scaled64::get(EntryFreq);
+
+ uint64_t Sum =
+ SaturatingAdd<uint64_t>(Temp.toInt<uint64_t>(), RelBlockFreq);
+ Sum = std::min(Sum, uint64_t(MaxRelBlockFreq));
+ RelBlockFreq = static_cast<uint32_t>(Sum);
}
};
@@ -69,9 +104,29 @@ class GlobalValueSummary;
using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;
struct GlobalValueSummaryInfo {
- /// The GlobalValue corresponding to this summary. This is only used in
- /// per-module summaries.
- const GlobalValue *GV = nullptr;
+ union NameOrGV {
+ NameOrGV(bool HaveGVs) {
+ if (HaveGVs)
+ GV = nullptr;
+ else
+ Name = "";
+ }
+
+ /// The GlobalValue corresponding to this summary. This is only used in
+ /// per-module summaries and when the IR is available. E.g. when module
+ /// analysis is being run, or when parsing both the IR and the summary
+ /// from assembly.
+ const GlobalValue *GV;
+
+ /// Summary string representation. This StringRef points to BC module
+ /// string table and is valid until module data is stored in memory.
+ /// This is guaranteed to happen until runThinLTOBackend function is
+ /// called, so it is safe to use this field during thin link. This field
+ /// is only valid if summary index was loaded from BC file.
+ StringRef Name;
+ } U;
+
+ GlobalValueSummaryInfo(bool HaveGVs) : U(HaveGVs) {}
/// List of global value summary structures for a particular value held
/// in the GlobalValueMap. Requires a vector in the case of multiple
@@ -91,44 +146,98 @@ using GlobalValueSummaryMapTy =
/// Struct that holds a reference to a particular GUID in a global value
/// summary.
struct ValueInfo {
- const GlobalValueSummaryMapTy::value_type *Ref = nullptr;
+ PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 1, bool>
+ RefAndFlag;
ValueInfo() = default;
- ValueInfo(const GlobalValueSummaryMapTy::value_type *Ref) : Ref(Ref) {}
+ ValueInfo(bool HaveGVs, const GlobalValueSummaryMapTy::value_type *R) {
+ RefAndFlag.setPointer(R);
+ RefAndFlag.setInt(HaveGVs);
+ }
- operator bool() const { return Ref; }
+ operator bool() const { return getRef(); }
- GlobalValue::GUID getGUID() const { return Ref->first; }
- const GlobalValue *getValue() const { return Ref->second.GV; }
+ GlobalValue::GUID getGUID() const { return getRef()->first; }
+ const GlobalValue *getValue() const {
+ assert(haveGVs());
+ return getRef()->second.U.GV;
+ }
ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const {
- return Ref->second.SummaryList;
+ return getRef()->second.SummaryList;
+ }
+
+ StringRef name() const {
+ return haveGVs() ? getRef()->second.U.GV->getName()
+ : getRef()->second.U.Name;
}
+
+ bool haveGVs() const { return RefAndFlag.getInt(); }
+
+ const GlobalValueSummaryMapTy::value_type *getRef() const {
+ return RefAndFlag.getPointer();
+ }
+
+ bool isDSOLocal() const;
};
+inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) {
+ OS << VI.getGUID();
+ if (!VI.name().empty())
+ OS << " (" << VI.name() << ")";
+ return OS;
+}
+
+inline bool operator==(const ValueInfo &A, const ValueInfo &B) {
+ assert(A.getRef() && B.getRef() &&
+ "Need ValueInfo with non-null Ref for comparison");
+ return A.getRef() == B.getRef();
+}
+
+inline bool operator!=(const ValueInfo &A, const ValueInfo &B) {
+ assert(A.getRef() && B.getRef() &&
+ "Need ValueInfo with non-null Ref for comparison");
+ return A.getRef() != B.getRef();
+}
+
+inline bool operator<(const ValueInfo &A, const ValueInfo &B) {
+ assert(A.getRef() && B.getRef() &&
+ "Need ValueInfo with non-null Ref to compare GUIDs");
+ return A.getGUID() < B.getGUID();
+}
+
template <> struct DenseMapInfo<ValueInfo> {
static inline ValueInfo getEmptyKey() {
- return ValueInfo((GlobalValueSummaryMapTy::value_type *)-1);
+ return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
}
static inline ValueInfo getTombstoneKey() {
- return ValueInfo((GlobalValueSummaryMapTy::value_type *)-2);
+ return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-16);
+ }
+
+ static inline bool isSpecialKey(ValueInfo V) {
+ return V == getTombstoneKey() || V == getEmptyKey();
}
- static bool isEqual(ValueInfo L, ValueInfo R) { return L.Ref == R.Ref; }
- static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.Ref; }
+ static bool isEqual(ValueInfo L, ValueInfo R) {
+ // We are not supposed to mix ValueInfo(s) with different HaveGVs flag
+ // in a same container.
+ assert(isSpecialKey(L) || isSpecialKey(R) || (L.haveGVs() == R.haveGVs()));
+ return L.getRef() == R.getRef();
+ }
+ static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.getRef(); }
};
-/// \brief Function and variable summary information to aid decisions and
+/// Function and variable summary information to aid decisions and
/// implementation of importing.
class GlobalValueSummary {
public:
- /// \brief Sububclass discriminator (for dyn_cast<> et al.)
+ /// Sububclass discriminator (for dyn_cast<> et al.)
enum SummaryKind : unsigned { AliasKind, FunctionKind, GlobalVarKind };
/// Group flags (Linkage, NotEligibleToImport, etc.) as a bitfield.
struct GVFlags {
- /// \brief The linkage type of the associated global value.
+ /// The linkage type of the associated global value.
///
/// One use is to flag values that have local linkage types and need to
/// have module identifier appended before placing into the combined
@@ -170,7 +279,7 @@ private:
/// GUID includes the module level id in the hash.
GlobalValue::GUID OriginalName = 0;
- /// \brief Path of module IR containing value's definition, used to locate
+ /// Path of module IR containing value's definition, used to locate
/// module during importing.
///
/// This is only used during parsing of the combined index, or when
@@ -185,8 +294,6 @@ private:
/// are listed in the derived FunctionSummary object.
std::vector<ValueInfo> RefEdgeList;
- bool isLive() const { return Flags.Live; }
-
protected:
GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector<ValueInfo> Refs)
: Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) {
@@ -199,7 +306,7 @@ public:
/// Returns the hash of the original name, it is identical to the GUID for
/// externally visible symbols, but not for local ones.
- GlobalValue::GUID getOriginalName() { return OriginalName; }
+ GlobalValue::GUID getOriginalName() const { return OriginalName; }
/// Initialize the original name hash in this summary.
void setOriginalName(GlobalValue::GUID Name) { OriginalName = Name; }
@@ -215,7 +322,7 @@ public:
StringRef modulePath() const { return ModulePath; }
/// Get the flags for this GlobalValue (see \p struct GVFlags).
- GVFlags flags() { return Flags; }
+ GVFlags flags() const { return Flags; }
/// Return linkage type recorded for this global value.
GlobalValue::LinkageTypes linkage() const {
@@ -231,6 +338,8 @@ public:
/// Return true if this global value can't be imported.
bool notEligibleToImport() const { return Flags.NotEligibleToImport; }
+ bool isLive() const { return Flags.Live; }
+
void setLive(bool Live) { Flags.Live = Live; }
void setDSOLocal(bool Local) { Flags.DSOLocal = Local; }
@@ -249,11 +358,9 @@ public:
const GlobalValueSummary *getBaseObject() const;
friend class ModuleSummaryIndex;
- friend void computeDeadSymbols(class ModuleSummaryIndex &,
- const DenseSet<GlobalValue::GUID> &);
};
-/// \brief Alias summary information.
+/// Alias summary information.
class AliasSummary : public GlobalValueSummary {
GlobalValueSummary *AliaseeSummary;
// AliaseeGUID is only set and accessed when we are building a combined index
@@ -273,6 +380,8 @@ public:
void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; }
void setAliaseeGUID(GlobalValue::GUID GUID) { AliaseeGUID = GUID; }
+ bool hasAliasee() const { return !!AliaseeSummary; }
+
const GlobalValueSummary &getAliasee() const {
assert(AliaseeSummary && "Unexpected missing aliasee summary");
return *AliaseeSummary;
@@ -300,13 +409,20 @@ inline GlobalValueSummary *GlobalValueSummary::getBaseObject() {
return this;
}
-/// \brief Function summary information to aid decisions and implementation of
+/// Function summary information to aid decisions and implementation of
/// importing.
class FunctionSummary : public GlobalValueSummary {
public:
/// <CalleeValueInfo, CalleeInfo> call edge pair.
using EdgeTy = std::pair<ValueInfo, CalleeInfo>;
+ /// Types for -force-summary-edges-cold debugging option.
+ enum ForceSummaryHotnessType : unsigned {
+ FSHT_None,
+ FSHT_AllNonCritical,
+ FSHT_All
+ };
+
/// An "identifier" for a virtual function. This contains the type identifier
/// represented as a GUID and the offset from the address point to the virtual
/// function pointer, where "address point" is as defined in the Itanium ABI:
@@ -324,6 +440,26 @@ public:
std::vector<uint64_t> Args;
};
+ /// All type identifier related information. Because these fields are
+ /// relatively uncommon we only allocate space for them if necessary.
+ struct TypeIdInfo {
+ /// List of type identifiers used by this function in llvm.type.test
+ /// intrinsics referenced by something other than an llvm.assume intrinsic,
+ /// represented as GUIDs.
+ std::vector<GlobalValue::GUID> TypeTests;
+
+ /// List of virtual calls made by this function using (respectively)
+ /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do
+ /// not have all constant integer arguments.
+ std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls;
+
+ /// List of virtual calls made by this function using (respectively)
+ /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with
+ /// all constant integer arguments.
+ std::vector<ConstVCall> TypeTestAssumeConstVCalls,
+ TypeCheckedLoadConstVCalls;
+ };
+
/// Function attribute flags. Used to track if a function accesses memory,
/// recurses or aliases.
struct FFlags {
@@ -333,6 +469,25 @@ public:
unsigned ReturnDoesNotAlias : 1;
};
+ /// Create an empty FunctionSummary (with specified call edges).
+ /// Used to represent external nodes and the dummy root node.
+ static FunctionSummary
+ makeDummyFunctionSummary(std::vector<FunctionSummary::EdgeTy> Edges) {
+ return FunctionSummary(
+ FunctionSummary::GVFlags(
+ GlobalValue::LinkageTypes::AvailableExternallyLinkage,
+ /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false),
+ 0, FunctionSummary::FFlags{}, std::vector<ValueInfo>(),
+ std::move(Edges), std::vector<GlobalValue::GUID>(),
+ std::vector<FunctionSummary::VFuncId>(),
+ std::vector<FunctionSummary::VFuncId>(),
+ std::vector<FunctionSummary::ConstVCall>(),
+ std::vector<FunctionSummary::ConstVCall>());
+ }
+
+ /// A dummy node to reference external functions that aren't in the index
+ static FunctionSummary ExternalNode;
+
private:
/// Number of instructions (ignoring debug instructions, e.g.) computed
/// during the initial compile step when the summary index is first built.
@@ -345,25 +500,6 @@ private:
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
std::vector<EdgeTy> CallGraphEdgeList;
- /// All type identifier related information. Because these fields are
- /// relatively uncommon we only allocate space for them if necessary.
- struct TypeIdInfo {
- /// List of type identifiers used by this function in llvm.type.test
- /// intrinsics other than by an llvm.assume intrinsic, represented as GUIDs.
- std::vector<GlobalValue::GUID> TypeTests;
-
- /// List of virtual calls made by this function using (respectively)
- /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do
- /// not have all constant integer arguments.
- std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls;
-
- /// List of virtual calls made by this function using (respectively)
- /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with
- /// all constant integer arguments.
- std::vector<ConstVCall> TypeTestAssumeConstVCalls,
- TypeCheckedLoadConstVCalls;
- };
-
std::unique_ptr<TypeIdInfo> TIdInfo;
public:
@@ -393,7 +529,7 @@ public:
}
/// Get function attribute flags.
- FFlags &fflags() { return FunFlags; }
+ FFlags fflags() const { return FunFlags; }
/// Get the instruction count recorded for this function.
unsigned instCount() const { return InstCount; }
@@ -452,6 +588,10 @@ public:
TIdInfo = llvm::make_unique<TypeIdInfo>();
TIdInfo->TypeTests.push_back(Guid);
}
+
+ const TypeIdInfo *getTypeIdInfo() const { return TIdInfo.get(); };
+
+ friend struct GraphTraits<ValueInfo>;
};
template <> struct DenseMapInfo<FunctionSummary::VFuncId> {
@@ -488,7 +628,7 @@ template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
}
};
-/// \brief Global variable summary information to aid decisions and
+/// Global variable summary information to aid decisions and
/// implementation of importing.
///
/// Currently this doesn't add anything to the base \p GlobalValueSummary,
@@ -538,8 +678,11 @@ struct TypeTestResolution {
struct WholeProgramDevirtResolution {
enum Kind {
- Indir, ///< Just do a regular virtual call
- SingleImpl, ///< Single implementation devirtualization
+ Indir, ///< Just do a regular virtual call
+ SingleImpl, ///< Single implementation devirtualization
+ BranchFunnel, ///< When retpoline mitigation is enabled, use a branch funnel
+ ///< that is defined in the merged module. Otherwise same as
+ ///< Indir.
} TheKind = Indir;
std::string SingleImplName;
@@ -607,7 +750,6 @@ private:
/// Mapping from type identifiers to summary information for that type
/// identifier.
- // FIXME: Add bitcode read/write support for this field.
std::map<std::string, TypeIdSummary> TypeIdMap;
/// Mapping from original ID to GUID. If original ID can map to multiple
@@ -619,24 +761,111 @@ private:
/// considered live.
bool WithGlobalValueDeadStripping = false;
+ /// Indicates that distributed backend should skip compilation of the
+ /// module. Flag is suppose to be set by distributed ThinLTO indexing
+ /// when it detected that the module is not needed during the final
+ /// linking. As result distributed backend should just output a minimal
+ /// valid object file.
+ bool SkipModuleByDistributedBackend = false;
+
+ /// If true then we're performing analysis of IR module, or parsing along with
+ /// the IR from assembly. The value of 'false' means we're reading summary
+ /// from BC or YAML source. Affects the type of value stored in NameOrGV
+ /// union.
+ bool HaveGVs;
+
std::set<std::string> CfiFunctionDefs;
std::set<std::string> CfiFunctionDecls;
+ // Used in cases where we want to record the name of a global, but
+ // don't have the string owned elsewhere (e.g. the Strtab on a module).
+ StringSaver Saver;
+ BumpPtrAllocator Alloc;
+
// YAML I/O support.
friend yaml::MappingTraits<ModuleSummaryIndex>;
GlobalValueSummaryMapTy::value_type *
getOrInsertValuePtr(GlobalValue::GUID GUID) {
- return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo{}).first;
+ return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo(HaveGVs))
+ .first;
}
public:
+ // See HaveGVs variable comment.
+ ModuleSummaryIndex(bool HaveGVs) : HaveGVs(HaveGVs), Saver(Alloc) {}
+
+ bool haveGVs() const { return HaveGVs; }
+
gvsummary_iterator begin() { return GlobalValueMap.begin(); }
const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
gvsummary_iterator end() { return GlobalValueMap.end(); }
const_gvsummary_iterator end() const { return GlobalValueMap.end(); }
size_t size() const { return GlobalValueMap.size(); }
+ /// Convenience function for doing a DFS on a ValueInfo. Marks the function in
+ /// the FunctionHasParent map.
+ static void discoverNodes(ValueInfo V,
+ std::map<ValueInfo, bool> &FunctionHasParent) {
+ if (!V.getSummaryList().size())
+ return; // skip external functions that don't have summaries
+
+ // Mark discovered if we haven't yet
+ auto S = FunctionHasParent.emplace(V, false);
+
+ // Stop if we've already discovered this node
+ if (!S.second)
+ return;
+
+ FunctionSummary *F =
+ dyn_cast<FunctionSummary>(V.getSummaryList().front().get());
+ assert(F != nullptr && "Expected FunctionSummary node");
+
+ for (auto &C : F->calls()) {
+ // Insert node if necessary
+ auto S = FunctionHasParent.emplace(C.first, true);
+
+ // Skip nodes that we're sure have parents
+ if (!S.second && S.first->second)
+ continue;
+
+ if (S.second)
+ discoverNodes(C.first, FunctionHasParent);
+ else
+ S.first->second = true;
+ }
+ }
+
+ // Calculate the callgraph root
+ FunctionSummary calculateCallGraphRoot() {
+ // Functions that have a parent will be marked in FunctionHasParent pair.
+ // Once we've marked all functions, the functions in the map that are false
+ // have no parent (so they're the roots)
+ std::map<ValueInfo, bool> FunctionHasParent;
+
+ for (auto &S : *this) {
+ // Skip external functions
+ if (!S.second.SummaryList.size() ||
+ !isa<FunctionSummary>(S.second.SummaryList.front().get()))
+ continue;
+ discoverNodes(ValueInfo(HaveGVs, &S), FunctionHasParent);
+ }
+
+ std::vector<FunctionSummary::EdgeTy> Edges;
+ // create edges to all roots in the Index
+ for (auto &P : FunctionHasParent) {
+ if (P.second)
+ continue; // skip over non-root nodes
+ Edges.push_back(std::make_pair(P.first, CalleeInfo{}));
+ }
+ if (Edges.empty()) {
+ // Failed to find root - return an empty node
+ return FunctionSummary::makeDummyFunctionSummary({});
+ }
+ auto CallGraphRoot = FunctionSummary::makeDummyFunctionSummary(Edges);
+ return CallGraphRoot;
+ }
+
bool withGlobalValueDeadStripping() const {
return WithGlobalValueDeadStripping;
}
@@ -644,27 +873,54 @@ public:
WithGlobalValueDeadStripping = true;
}
+ bool skipModuleByDistributedBackend() const {
+ return SkipModuleByDistributedBackend;
+ }
+ void setSkipModuleByDistributedBackend() {
+ SkipModuleByDistributedBackend = true;
+ }
+
bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
return !WithGlobalValueDeadStripping || GVS->isLive();
}
bool isGUIDLive(GlobalValue::GUID GUID) const;
+ /// Return a ValueInfo for the index value_type (convenient when iterating
+ /// index).
+ ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const {
+ return ValueInfo(HaveGVs, &R);
+ }
+
/// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
auto I = GlobalValueMap.find(GUID);
- return ValueInfo(I == GlobalValueMap.end() ? nullptr : &*I);
+ return ValueInfo(HaveGVs, I == GlobalValueMap.end() ? nullptr : &*I);
}
/// Return a ValueInfo for \p GUID.
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
- return ValueInfo(getOrInsertValuePtr(GUID));
+ return ValueInfo(HaveGVs, getOrInsertValuePtr(GUID));
+ }
+
+ // Save a string in the Index. Use before passing Name to
+ // getOrInsertValueInfo when the string isn't owned elsewhere (e.g. on the
+ // module's Strtab).
+ StringRef saveString(std::string String) { return Saver.save(String); }
+
+ /// Return a ValueInfo for \p GUID setting value \p Name.
+ ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) {
+ assert(!HaveGVs);
+ auto VP = getOrInsertValuePtr(GUID);
+ VP->second.U.Name = Name;
+ return ValueInfo(HaveGVs, VP);
}
/// Return a ValueInfo for \p GV and mark it as belonging to GV.
ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
+ assert(HaveGVs);
auto VP = getOrInsertValuePtr(GV->getGUID());
- VP->second.GV = GV;
- return ValueInfo(VP);
+ VP->second.U.GV = GV;
+ return ValueInfo(HaveGVs, VP);
}
/// Return the GUID for \p OriginalId in the OidGuidMap.
@@ -679,6 +935,12 @@ public:
std::set<std::string> &cfiFunctionDecls() { return CfiFunctionDecls; }
const std::set<std::string> &cfiFunctionDecls() const { return CfiFunctionDecls; }
+ /// Add a global value summary for a value.
+ void addGlobalValueSummary(const GlobalValue &GV,
+ std::unique_ptr<GlobalValueSummary> Summary) {
+ addGlobalValueSummary(getOrInsertValueInfo(&GV), std::move(Summary));
+ }
+
/// Add a global value summary for a value of the given name.
void addGlobalValueSummary(StringRef ValueName,
std::unique_ptr<GlobalValueSummary> Summary) {
@@ -692,7 +954,7 @@ public:
addOriginalName(VI.getGUID(), Summary->getOriginalName());
// Here we have a notionally const VI, but the value it points to is owned
// by the non-const *this.
- const_cast<GlobalValueSummaryMapTy::value_type *>(VI.Ref)
+ const_cast<GlobalValueSummaryMapTy::value_type *>(VI.getRef())
->second.SummaryList.push_back(std::move(Summary));
}
@@ -730,8 +992,7 @@ public:
GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV,
bool PerModuleIndex = true) const {
assert(GV.hasName() && "Can't get GlobalValueSummary for GV with no name");
- return getGlobalValueSummary(GlobalValue::getGUID(GV.getName()),
- PerModuleIndex);
+ return getGlobalValueSummary(GV.getGUID(), PerModuleIndex);
}
/// Returns the first GlobalValueSummary for \p ValueGUID, asserting that
@@ -788,6 +1049,13 @@ public:
return &*ModulePathStringTable.insert({ModPath, {ModId, Hash}}).first;
}
+ /// Return module entry for module with the given \p ModPath.
+ ModuleInfo *getModule(StringRef ModPath) {
+ auto It = ModulePathStringTable.find(ModPath);
+ assert(It != ModulePathStringTable.end() && "Module not registered");
+ return &*It;
+ }
+
/// Check if the given Module has any functions available for exporting
/// in the index. We consider any module present in the ModulePathStringTable
/// to have exported functions.
@@ -814,7 +1082,7 @@ public:
return &I->second;
}
- /// Collect for the given module the list of function it defines
+ /// Collect for the given module the list of functions it defines
/// (GUID -> Summary).
void collectDefinedFunctionsForModule(StringRef ModulePath,
GVSummaryMapTy &GVSummaryMap) const;
@@ -823,6 +1091,65 @@ public:
/// Summary).
void collectDefinedGVSummariesPerModule(
StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const;
+
+ /// Print to an output stream.
+ void print(raw_ostream &OS, bool IsForDebug = false) const;
+
+ /// Dump to stderr (for debugging).
+ void dump() const;
+
+ /// Export summary to dot file for GraphViz.
+ void exportToDot(raw_ostream& OS) const;
+
+ /// Print out strongly connected components for debugging.
+ void dumpSCCs(raw_ostream &OS);
+};
+
+/// GraphTraits definition to build SCC for the index
+template <> struct GraphTraits<ValueInfo> {
+ typedef ValueInfo NodeRef;
+
+ static NodeRef valueInfoFromEdge(FunctionSummary::EdgeTy &P) {
+ return P.first;
+ }
+ using ChildIteratorType =
+ mapped_iterator<std::vector<FunctionSummary::EdgeTy>::iterator,
+ decltype(&valueInfoFromEdge)>;
+
+ static NodeRef getEntryNode(ValueInfo V) { return V; }
+
+ static ChildIteratorType child_begin(NodeRef N) {
+ if (!N.getSummaryList().size()) // handle external function
+ return ChildIteratorType(
+ FunctionSummary::ExternalNode.CallGraphEdgeList.begin(),
+ &valueInfoFromEdge);
+ FunctionSummary *F =
+ cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
+ return ChildIteratorType(F->CallGraphEdgeList.begin(), &valueInfoFromEdge);
+ }
+
+ static ChildIteratorType child_end(NodeRef N) {
+ if (!N.getSummaryList().size()) // handle external function
+ return ChildIteratorType(
+ FunctionSummary::ExternalNode.CallGraphEdgeList.end(),
+ &valueInfoFromEdge);
+ FunctionSummary *F =
+ cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
+ return ChildIteratorType(F->CallGraphEdgeList.end(), &valueInfoFromEdge);
+ }
+};
+
+template <>
+struct GraphTraits<ModuleSummaryIndex *> : public GraphTraits<ValueInfo> {
+ static NodeRef getEntryNode(ModuleSummaryIndex *I) {
+ std::unique_ptr<GlobalValueSummary> Root =
+ make_unique<FunctionSummary>(I->calculateCallGraphRoot());
+ GlobalValueSummaryInfo G(I->haveGVs());
+ G.SummaryList.push_back(std::move(Root));
+ static auto P =
+ GlobalValueSummaryMapTy::value_type(GlobalValue::GUID(0), std::move(G));
+ return ValueInfo(I->haveGVs(), &P);
+ }
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h b/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h
index 4687f2d53e7e..1b339ab32cf1 100644
--- a/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h
+++ b/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h
@@ -98,6 +98,8 @@ template <> struct ScalarEnumerationTraits<WholeProgramDevirtResolution::Kind> {
static void enumeration(IO &io, WholeProgramDevirtResolution::Kind &value) {
io.enumCase(value, "Indir", WholeProgramDevirtResolution::Indir);
io.enumCase(value, "SingleImpl", WholeProgramDevirtResolution::SingleImpl);
+ io.enumCase(value, "BranchFunnel",
+ WholeProgramDevirtResolution::BranchFunnel);
}
};
@@ -136,6 +138,7 @@ template <> struct MappingTraits<TypeIdSummary> {
struct FunctionSummaryYaml {
unsigned Linkage;
bool NotEligibleToImport, Live, IsLocal;
+ std::vector<uint64_t> Refs;
std::vector<uint64_t> TypeTests;
std::vector<FunctionSummary::VFuncId> TypeTestAssumeVCalls,
TypeCheckedLoadVCalls;
@@ -178,6 +181,7 @@ template <> struct MappingTraits<FunctionSummaryYaml> {
io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport);
io.mapOptional("Live", summary.Live);
io.mapOptional("Local", summary.IsLocal);
+ io.mapOptional("Refs", summary.Refs);
io.mapOptional("TypeTests", summary.TypeTests);
io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls);
io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls);
@@ -207,13 +211,21 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
io.setError("key not an integer");
return;
}
- auto &Elem = V[KeyInt];
+ if (!V.count(KeyInt))
+ V.emplace(KeyInt, /*IsAnalysis=*/false);
+ auto &Elem = V.find(KeyInt)->second;
for (auto &FSum : FSums) {
+ std::vector<ValueInfo> Refs;
+ for (auto &RefGUID : FSum.Refs) {
+ if (!V.count(RefGUID))
+ V.emplace(RefGUID, /*IsAnalysis=*/false);
+ Refs.push_back(ValueInfo(/*IsAnalysis=*/false, &*V.find(RefGUID)));
+ }
Elem.SummaryList.push_back(llvm::make_unique<FunctionSummary>(
GlobalValueSummary::GVFlags(
static_cast<GlobalValue::LinkageTypes>(FSum.Linkage),
FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal),
- 0, FunctionSummary::FFlags{}, ArrayRef<ValueInfo>{},
+ 0, FunctionSummary::FFlags{}, Refs,
ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
std::move(FSum.TypeTestAssumeVCalls),
std::move(FSum.TypeCheckedLoadVCalls),
@@ -225,15 +237,20 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
for (auto &P : V) {
std::vector<FunctionSummaryYaml> FSums;
for (auto &Sum : P.second.SummaryList) {
- if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get()))
+ if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get())) {
+ std::vector<uint64_t> Refs;
+ for (auto &VI : FSum->refs())
+ Refs.push_back(VI.getGUID());
FSums.push_back(FunctionSummaryYaml{
FSum->flags().Linkage,
static_cast<bool>(FSum->flags().NotEligibleToImport),
static_cast<bool>(FSum->flags().Live),
- static_cast<bool>(FSum->flags().DSOLocal), FSum->type_tests(),
- FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(),
+ static_cast<bool>(FSum->flags().DSOLocal), Refs,
+ FSum->type_tests(), FSum->type_test_assume_vcalls(),
+ FSum->type_checked_load_vcalls(),
FSum->type_test_assume_const_vcalls(),
FSum->type_checked_load_const_vcalls()});
+ }
}
if (!FSums.empty())
io.mapRequired(llvm::utostr(P.first).c_str(), FSums);
diff --git a/contrib/llvm/include/llvm/IR/Operator.h b/contrib/llvm/include/llvm/IR/Operator.h
index 01746e4b6a29..939cec7f4aa4 100644
--- a/contrib/llvm/include/llvm/IR/Operator.h
+++ b/contrib/llvm/include/llvm/IR/Operator.h
@@ -207,17 +207,28 @@ public:
bool isFast() const { return all(); }
/// Flag setters
- void setAllowReassoc() { Flags |= AllowReassoc; }
- void setNoNaNs() { Flags |= NoNaNs; }
- void setNoInfs() { Flags |= NoInfs; }
- void setNoSignedZeros() { Flags |= NoSignedZeros; }
- void setAllowReciprocal() { Flags |= AllowReciprocal; }
- // TODO: Change the other set* functions to take a parameter?
- void setAllowContract(bool B) {
+ void setAllowReassoc(bool B = true) {
+ Flags = (Flags & ~AllowReassoc) | B * AllowReassoc;
+ }
+ void setNoNaNs(bool B = true) {
+ Flags = (Flags & ~NoNaNs) | B * NoNaNs;
+ }
+ void setNoInfs(bool B = true) {
+ Flags = (Flags & ~NoInfs) | B * NoInfs;
+ }
+ void setNoSignedZeros(bool B = true) {
+ Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros;
+ }
+ void setAllowReciprocal(bool B = true) {
+ Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal;
+ }
+ void setAllowContract(bool B = true) {
Flags = (Flags & ~AllowContract) | B * AllowContract;
}
- void setApproxFunc() { Flags |= ApproxFunc; }
- void setFast() { set(); }
+ void setApproxFunc(bool B = true) {
+ Flags = (Flags & ~ApproxFunc) | B * ApproxFunc;
+ }
+ void setFast(bool B = true) { B ? set() : clear(); }
void operator&=(const FastMathFlags &OtherFlags) {
Flags &= OtherFlags.Flags;
@@ -507,7 +518,7 @@ public:
});
}
- /// \brief Accumulate the constant address offset of this GEP if possible.
+ /// Accumulate the constant address offset of this GEP if possible.
///
/// This routine accepts an APInt into which it will accumulate the constant
/// offset of this GEP if the GEP is in fact constant. If the GEP is not
diff --git a/contrib/llvm/include/llvm/IR/OptBisect.h b/contrib/llvm/include/llvm/IR/OptBisect.h
index 09e67aa79246..aa24c94c0130 100644
--- a/contrib/llvm/include/llvm/IR/OptBisect.h
+++ b/contrib/llvm/include/llvm/IR/OptBisect.h
@@ -20,14 +20,34 @@
namespace llvm {
class Pass;
+class Module;
+class Function;
+class BasicBlock;
+class Region;
+class Loop;
+class CallGraphSCC;
+
+/// Extensions to this class implement mechanisms to disable passes and
+/// individual optimizations at compile time.
+class OptPassGate {
+public:
+ virtual ~OptPassGate() = default;
+
+ virtual bool shouldRunPass(const Pass *P, const Module &U) { return true; }
+ virtual bool shouldRunPass(const Pass *P, const Function &U) {return true; }
+ virtual bool shouldRunPass(const Pass *P, const BasicBlock &U) { return true; }
+ virtual bool shouldRunPass(const Pass *P, const Region &U) { return true; }
+ virtual bool shouldRunPass(const Pass *P, const Loop &U) { return true; }
+ virtual bool shouldRunPass(const Pass *P, const CallGraphSCC &U) { return true; }
+};
/// This class implements a mechanism to disable passes and individual
/// optimizations at compile time based on a command line option
/// (-opt-bisect-limit) in order to perform a bisecting search for
/// optimization-related problems.
-class OptBisect {
+class OptBisect : public OptPassGate {
public:
- /// \brief Default constructor, initializes the OptBisect state based on the
+ /// Default constructor, initializes the OptBisect state based on the
/// -opt-bisect-limit command line argument.
///
/// By default, bisection is disabled.
@@ -36,20 +56,26 @@ public:
/// through LLVMContext.
OptBisect();
+ virtual ~OptBisect() = default;
+
/// Checks the bisect limit to determine if the specified pass should run.
///
- /// This function will immediate return true if bisection is disabled. If the
- /// bisect limit is set to -1, the function will print a message describing
+ /// These functions immediately return true if bisection is disabled. If the
+ /// bisect limit is set to -1, the functions print a message describing
/// the pass and the bisect number assigned to it and return true. Otherwise,
- /// the function will print a message with the bisect number assigned to the
+ /// the functions print a message with the bisect number assigned to the
/// pass and indicating whether or not the pass will be run and return true if
- /// the bisect limit has not yet been exceded or false if it has.
+ /// the bisect limit has not yet been exceeded or false if it has.
///
- /// Most passes should not call this routine directly. Instead, it is called
- /// through a helper routine provided by the pass base class. For instance,
- /// function passes should call FunctionPass::skipFunction().
- template <class UnitT>
- bool shouldRunPass(const Pass *P, const UnitT &U);
+ /// Most passes should not call these routines directly. Instead, they are
+ /// called through helper routines provided by the pass base classes. For
+ /// instance, function passes should call FunctionPass::skipFunction().
+ bool shouldRunPass(const Pass *P, const Module &U) override;
+ bool shouldRunPass(const Pass *P, const Function &U) override;
+ bool shouldRunPass(const Pass *P, const BasicBlock &U) override;
+ bool shouldRunPass(const Pass *P, const Region &U) override;
+ bool shouldRunPass(const Pass *P, const Loop &U) override;
+ bool shouldRunPass(const Pass *P, const CallGraphSCC &U) override;
private:
bool checkPass(const StringRef PassName, const StringRef TargetDesc);
diff --git a/contrib/llvm/include/llvm/IR/PassManager.h b/contrib/llvm/include/llvm/IR/PassManager.h
index 4f838a719512..a5d4aaf71c0e 100644
--- a/contrib/llvm/include/llvm/IR/PassManager.h
+++ b/contrib/llvm/include/llvm/IR/PassManager.h
@@ -152,17 +152,17 @@ private:
/// ```
class PreservedAnalyses {
public:
- /// \brief Convenience factory function for the empty preserved set.
+ /// Convenience factory function for the empty preserved set.
static PreservedAnalyses none() { return PreservedAnalyses(); }
- /// \brief Construct a special preserved set that preserves all passes.
+ /// Construct a special preserved set that preserves all passes.
static PreservedAnalyses all() {
PreservedAnalyses PA;
PA.PreservedIDs.insert(&AllAnalysesKey);
return PA;
}
- /// \brief Construct a preserved analyses object with a single preserved set.
+ /// Construct a preserved analyses object with a single preserved set.
template <typename AnalysisSetT>
static PreservedAnalyses allInSet() {
PreservedAnalyses PA;
@@ -173,7 +173,7 @@ public:
/// Mark an analysis as preserved.
template <typename AnalysisT> void preserve() { preserve(AnalysisT::ID()); }
- /// \brief Given an analysis's ID, mark the analysis as preserved, adding it
+ /// Given an analysis's ID, mark the analysis as preserved, adding it
/// to the set.
void preserve(AnalysisKey *ID) {
// Clear this ID from the explicit not-preserved set if present.
@@ -218,7 +218,7 @@ public:
NotPreservedAnalysisIDs.insert(ID);
}
- /// \brief Intersect this set with another in place.
+ /// Intersect this set with another in place.
///
/// This is a mutating operation on this preserved set, removing all
/// preserved passes which are not also preserved in the argument.
@@ -240,7 +240,7 @@ public:
PreservedIDs.erase(ID);
}
- /// \brief Intersect this set with a temporary other set in place.
+ /// Intersect this set with a temporary other set in place.
///
/// This is a mutating operation on this preserved set, removing all
/// preserved passes which are not also preserved in the argument.
@@ -402,7 +402,7 @@ struct AnalysisInfoMixin : PassInfoMixin<DerivedT> {
}
};
-/// \brief Manages a sequence of passes over a particular unit of IR.
+/// Manages a sequence of passes over a particular unit of IR.
///
/// A pass manager contains a sequence of passes to run over a particular unit
/// of IR (e.g. Functions, Modules). It is itself a valid pass over that unit of
@@ -420,7 +420,7 @@ template <typename IRUnitT,
class PassManager : public PassInfoMixin<
PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
public:
- /// \brief Construct a pass manager.
+ /// Construct a pass manager.
///
/// If \p DebugLogging is true, we'll log our progress to llvm::dbgs().
explicit PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}
@@ -439,7 +439,7 @@ public:
return *this;
}
- /// \brief Run all of the passes in this manager over the given unit of IR.
+ /// Run all of the passes in this manager over the given unit of IR.
/// ExtraArgs are passed to each pass.
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
ExtraArgTs... ExtraArgs) {
@@ -496,21 +496,21 @@ private:
std::vector<std::unique_ptr<PassConceptT>> Passes;
- /// \brief Flag indicating whether we should do debug logging.
+ /// Flag indicating whether we should do debug logging.
bool DebugLogging;
};
extern template class PassManager<Module>;
-/// \brief Convenience typedef for a pass manager over modules.
+/// Convenience typedef for a pass manager over modules.
using ModulePassManager = PassManager<Module>;
extern template class PassManager<Function>;
-/// \brief Convenience typedef for a pass manager over functions.
+/// Convenience typedef for a pass manager over functions.
using FunctionPassManager = PassManager<Function>;
-/// \brief A container for analyses that lazily runs them and caches their
+/// A container for analyses that lazily runs them and caches their
/// results.
///
/// This class can manage analyses for any IR unit where the address of the IR
@@ -527,7 +527,7 @@ private:
detail::AnalysisPassConcept<IRUnitT, PreservedAnalyses, Invalidator,
ExtraArgTs...>;
- /// \brief List of analysis pass IDs and associated concept pointers.
+ /// List of analysis pass IDs and associated concept pointers.
///
/// Requires iterators to be valid across appending new entries and arbitrary
/// erases. Provides the analysis ID to enable finding iterators to a given
@@ -536,10 +536,10 @@ private:
using AnalysisResultListT =
std::list<std::pair<AnalysisKey *, std::unique_ptr<ResultConceptT>>>;
- /// \brief Map type from IRUnitT pointer to our custom list type.
+ /// Map type from IRUnitT pointer to our custom list type.
using AnalysisResultListMapT = DenseMap<IRUnitT *, AnalysisResultListT>;
- /// \brief Map type from a pair of analysis ID and IRUnitT pointer to an
+ /// Map type from a pair of analysis ID and IRUnitT pointer to an
/// iterator into a particular result list (which is where the actual analysis
/// result is stored).
using AnalysisResultMapT =
@@ -634,14 +634,14 @@ public:
const AnalysisResultMapT &Results;
};
- /// \brief Construct an empty analysis manager.
+ /// Construct an empty analysis manager.
///
/// If \p DebugLogging is true, we'll log our progress to llvm::dbgs().
AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}
AnalysisManager(AnalysisManager &&) = default;
AnalysisManager &operator=(AnalysisManager &&) = default;
- /// \brief Returns true if the analysis manager has an empty results cache.
+ /// Returns true if the analysis manager has an empty results cache.
bool empty() const {
assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&
"The storage and index of analysis results disagree on how many "
@@ -649,7 +649,7 @@ public:
return AnalysisResults.empty();
}
- /// \brief Clear any cached analysis results for a single unit of IR.
+ /// Clear any cached analysis results for a single unit of IR.
///
/// This doesn't invalidate, but instead simply deletes, the relevant results.
/// It is useful when the IR is being removed and we want to clear out all the
@@ -669,7 +669,7 @@ public:
AnalysisResultLists.erase(ResultsListI);
}
- /// \brief Clear all analysis results cached by this AnalysisManager.
+ /// Clear all analysis results cached by this AnalysisManager.
///
/// Like \c clear(IRUnitT&), this doesn't invalidate the results; it simply
/// deletes them. This lets you clean up the AnalysisManager when the set of
@@ -680,7 +680,7 @@ public:
AnalysisResultLists.clear();
}
- /// \brief Get the result of an analysis pass for a given IR unit.
+ /// Get the result of an analysis pass for a given IR unit.
///
/// Runs the analysis if a cached result is not available.
template <typename PassT>
@@ -697,7 +697,7 @@ public:
return static_cast<ResultModelT &>(ResultConcept).Result;
}
- /// \brief Get the cached result of an analysis pass for a given IR unit.
+ /// Get the cached result of an analysis pass for a given IR unit.
///
/// This method never runs the analysis.
///
@@ -718,7 +718,7 @@ public:
return &static_cast<ResultModelT *>(ResultConcept)->Result;
}
- /// \brief Register an analysis pass with the manager.
+ /// Register an analysis pass with the manager.
///
/// The parameter is a callable whose result is an analysis pass. This allows
/// passing in a lambda to construct the analysis.
@@ -752,7 +752,7 @@ public:
return true;
}
- /// \brief Invalidate a specific analysis pass for an IR module.
+ /// Invalidate a specific analysis pass for an IR module.
///
/// Note that the analysis result can disregard invalidation, if it determines
/// it is in fact still valid.
@@ -762,7 +762,7 @@ public:
invalidateImpl(PassT::ID(), IR);
}
- /// \brief Invalidate cached analyses for an IR unit.
+ /// Invalidate cached analyses 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.
@@ -829,7 +829,7 @@ public:
}
private:
- /// \brief Look up a registered analysis pass.
+ /// Look up a registered analysis pass.
PassConceptT &lookUpPass(AnalysisKey *ID) {
typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(ID);
assert(PI != AnalysisPasses.end() &&
@@ -837,7 +837,7 @@ private:
return *PI->second;
}
- /// \brief Look up a registered analysis pass.
+ /// Look up a registered analysis pass.
const PassConceptT &lookUpPass(AnalysisKey *ID) const {
typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(ID);
assert(PI != AnalysisPasses.end() &&
@@ -845,7 +845,7 @@ private:
return *PI->second;
}
- /// \brief Get an analysis result, running the pass if necessary.
+ /// Get an analysis result, running the pass if necessary.
ResultConceptT &getResultImpl(AnalysisKey *ID, IRUnitT &IR,
ExtraArgTs... ExtraArgs) {
typename AnalysisResultMapT::iterator RI;
@@ -874,14 +874,14 @@ private:
return *RI->second->second;
}
- /// \brief Get a cached analysis result or return null.
+ /// Get a cached analysis result or return null.
ResultConceptT *getCachedResultImpl(AnalysisKey *ID, IRUnitT &IR) const {
typename AnalysisResultMapT::const_iterator RI =
AnalysisResults.find({ID, &IR});
return RI == AnalysisResults.end() ? nullptr : &*RI->second->second;
}
- /// \brief Invalidate a function pass result.
+ /// Invalidate a function pass result.
void invalidateImpl(AnalysisKey *ID, IRUnitT &IR) {
typename AnalysisResultMapT::iterator RI =
AnalysisResults.find({ID, &IR});
@@ -895,38 +895,38 @@ private:
AnalysisResults.erase(RI);
}
- /// \brief Map type from module analysis pass ID to pass concept pointer.
+ /// Map type from module analysis pass ID to pass concept pointer.
using AnalysisPassMapT =
DenseMap<AnalysisKey *, std::unique_ptr<PassConceptT>>;
- /// \brief Collection of module analysis passes, indexed by ID.
+ /// Collection of module analysis passes, indexed by ID.
AnalysisPassMapT AnalysisPasses;
- /// \brief Map from function to a list of function analysis results.
+ /// 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.
AnalysisResultListMapT AnalysisResultLists;
- /// \brief Map from an analysis ID and function to a particular cached
+ /// Map from an analysis ID and function to a particular cached
/// analysis result.
AnalysisResultMapT AnalysisResults;
- /// \brief Indicates whether we log to \c llvm::dbgs().
+ /// Indicates whether we log to \c llvm::dbgs().
bool DebugLogging;
};
extern template class AnalysisManager<Module>;
-/// \brief Convenience typedef for the Module analysis manager.
+/// Convenience typedef for the Module analysis manager.
using ModuleAnalysisManager = AnalysisManager<Module>;
extern template class AnalysisManager<Function>;
-/// \brief Convenience typedef for the Function analysis manager.
+/// Convenience typedef for the Function analysis manager.
using FunctionAnalysisManager = AnalysisManager<Function>;
-/// \brief An analysis over an "outer" IR unit that provides access to an
+/// An analysis over an "outer" IR unit that provides access to an
/// analysis manager over an "inner" IR unit. The inner unit must be contained
/// in the outer unit.
///
@@ -977,10 +977,10 @@ public:
return *this;
}
- /// \brief Accessor for the analysis manager.
+ /// Accessor for the analysis manager.
AnalysisManagerT &getManager() { return *InnerAM; }
- /// \brief Handler for invalidation of the outer IR unit, \c IRUnitT.
+ /// Handler for invalidation of the outer IR unit, \c IRUnitT.
///
/// If the proxy analysis itself is not preserved, we assume that the set of
/// inner IR objects contained in IRUnit may have changed. In this case,
@@ -1001,7 +1001,7 @@ public:
explicit InnerAnalysisManagerProxy(AnalysisManagerT &InnerAM)
: InnerAM(&InnerAM) {}
- /// \brief Run the analysis pass and create our proxy result object.
+ /// Run the analysis pass and create our proxy result object.
///
/// This doesn't do any interesting work; it is primarily used to insert our
/// proxy result object into the outer analysis cache so that we can proxy
@@ -1040,7 +1040,7 @@ bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
Module>;
-/// \brief An analysis over an "inner" IR unit that provides access to an
+/// An analysis over an "inner" IR unit that provides access to an
/// analysis manager over a "outer" IR unit. The inner unit must be contained
/// in the outer unit.
///
@@ -1063,7 +1063,7 @@ class OuterAnalysisManagerProxy
: public AnalysisInfoMixin<
OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>> {
public:
- /// \brief Result proxy object for \c OuterAnalysisManagerProxy.
+ /// Result proxy object for \c OuterAnalysisManagerProxy.
class Result {
public:
explicit Result(const AnalysisManagerT &AM) : AM(&AM) {}
@@ -1130,7 +1130,7 @@ public:
OuterAnalysisManagerProxy(const AnalysisManagerT &AM) : AM(&AM) {}
- /// \brief Run the analysis pass and create our proxy result object.
+ /// Run the analysis pass and create our proxy result object.
/// Nothing to see here, it just forwards the \c AM reference into the
/// result.
Result run(IRUnitT &, AnalysisManager<IRUnitT, ExtraArgTs...> &,
@@ -1157,7 +1157,7 @@ extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
using ModuleAnalysisManagerFunctionProxy =
OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>;
-/// \brief Trivial adaptor that maps from a module to its functions.
+/// Trivial adaptor that maps from a module to its functions.
///
/// Designed to allow composition of a FunctionPass(Manager) and
/// a ModulePassManager, by running the FunctionPass(Manager) over every
@@ -1187,7 +1187,7 @@ public:
explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass)
: Pass(std::move(Pass)) {}
- /// \brief Runs the function pass across every function in the module.
+ /// Runs the function pass across every function in the module.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
@@ -1223,7 +1223,7 @@ private:
FunctionPassT Pass;
};
-/// \brief A function to deduce a function pass type and wrap it in the
+/// A function to deduce a function pass type and wrap it in the
/// templated adaptor.
template <typename FunctionPassT>
ModuleToFunctionPassAdaptor<FunctionPassT>
@@ -1231,7 +1231,7 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
}
-/// \brief A utility pass template to force an analysis result to be available.
+/// A utility pass template to force an analysis result to be available.
///
/// If there are extra arguments at the pass's run level there may also be
/// extra arguments to the analysis manager's \c getResult routine. We can't
@@ -1246,7 +1246,7 @@ template <typename AnalysisT, typename IRUnitT,
struct RequireAnalysisPass
: PassInfoMixin<RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManagerT,
ExtraArgTs...>> {
- /// \brief Run this pass over some unit of IR.
+ /// 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
@@ -1261,12 +1261,12 @@ struct RequireAnalysisPass
}
};
-/// \brief A no-op pass template which simply forces a specific analysis result
+/// A no-op pass template which simply forces a specific analysis result
/// to be invalidated.
template <typename AnalysisT>
struct InvalidateAnalysisPass
: PassInfoMixin<InvalidateAnalysisPass<AnalysisT>> {
- /// \brief Run this pass over some unit of IR.
+ /// 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
@@ -1280,12 +1280,12 @@ struct InvalidateAnalysisPass
}
};
-/// \brief A utility pass that does nothing, but preserves no analyses.
+/// A utility pass that does nothing, but preserves no analyses.
///
/// Because this preserves no analyses, any analysis passes queried after this
/// pass runs will recompute fresh results.
struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> {
- /// \brief Run this pass over some unit of IR.
+ /// Run this pass over some unit of IR.
template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
PreservedAnalyses run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) {
return PreservedAnalyses::none();
diff --git a/contrib/llvm/include/llvm/IR/PassManagerInternal.h b/contrib/llvm/include/llvm/IR/PassManagerInternal.h
index 9195d4dfa428..16a3258b4121 100644
--- a/contrib/llvm/include/llvm/IR/PassManagerInternal.h
+++ b/contrib/llvm/include/llvm/IR/PassManagerInternal.h
@@ -29,17 +29,17 @@ template <typename IRUnitT> class AllAnalysesOn;
template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
class PreservedAnalyses;
-/// \brief Implementation details of the pass manager interfaces.
+/// Implementation details of the pass manager interfaces.
namespace detail {
-/// \brief Template for the abstract base class used to dispatch
+/// Template for the abstract base class used to dispatch
/// polymorphically over pass objects.
template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
struct PassConcept {
// Boiler plate necessary for the container of derived classes.
virtual ~PassConcept() = default;
- /// \brief The polymorphic API which runs the pass over a given IR entity.
+ /// 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
@@ -47,11 +47,11 @@ struct PassConcept {
virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
ExtraArgTs... ExtraArgs) = 0;
- /// \brief Polymorphic method to access the name of a pass.
+ /// Polymorphic method to access the name of a pass.
virtual StringRef name() = 0;
};
-/// \brief A template wrapper used to implement the polymorphic API.
+/// 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& and an \c AnalysisManager<IRUnit>&. It requires the pass to
@@ -85,7 +85,7 @@ struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
PassT Pass;
};
-/// \brief Abstract concept of an analysis result.
+/// Abstract concept of an analysis result.
///
/// This concept is parameterized over the IR unit that this result pertains
/// to.
@@ -93,7 +93,7 @@ template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT>
struct AnalysisResultConcept {
virtual ~AnalysisResultConcept() = default;
- /// \brief Method to try and mark a result as invalid.
+ /// 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.
@@ -112,7 +112,7 @@ struct AnalysisResultConcept {
InvalidatorT &Inv) = 0;
};
-/// \brief SFINAE metafunction for computing whether \c ResultT provides an
+/// SFINAE metafunction for computing whether \c ResultT provides an
/// \c invalidate member function.
template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
using EnabledType = char;
@@ -148,7 +148,7 @@ public:
enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) };
};
-/// \brief Wrapper to model the analysis result concept.
+/// 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
@@ -160,7 +160,7 @@ template <typename IRUnitT, typename PassT, typename ResultT,
ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
struct AnalysisResultModel;
-/// \brief Specialization of \c AnalysisResultModel which provides the default
+/// Specialization of \c AnalysisResultModel which provides the default
/// invalidate functionality.
template <typename IRUnitT, typename PassT, typename ResultT,
typename PreservedAnalysesT, typename InvalidatorT>
@@ -184,7 +184,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
return *this;
}
- /// \brief The model bases invalidation solely on being in the preserved set.
+ /// 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
@@ -199,7 +199,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
ResultT Result;
};
-/// \brief Specialization of \c AnalysisResultModel which delegates invalidate
+/// Specialization of \c AnalysisResultModel which delegates invalidate
/// handling to \c ResultT.
template <typename IRUnitT, typename PassT, typename ResultT,
typename PreservedAnalysesT, typename InvalidatorT>
@@ -223,7 +223,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
return *this;
}
- /// \brief The model delegates to the \c ResultT method.
+ /// The model delegates to the \c ResultT method.
bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
InvalidatorT &Inv) override {
return Result.invalidate(IR, PA, Inv);
@@ -232,7 +232,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
ResultT Result;
};
-/// \brief Abstract concept of an analysis pass.
+/// Abstract concept of an analysis pass.
///
/// This concept is parameterized over the IR unit that it can run over and
/// produce an analysis result.
@@ -241,7 +241,7 @@ template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT,
struct AnalysisPassConcept {
virtual ~AnalysisPassConcept() = default;
- /// \brief Method to run this analysis over a unit of IR.
+ /// 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<
@@ -249,11 +249,11 @@ struct AnalysisPassConcept {
run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
ExtraArgTs... ExtraArgs) = 0;
- /// \brief Polymorphic method to access the name of a pass.
+ /// Polymorphic method to access the name of a pass.
virtual StringRef name() = 0;
};
-/// \brief Wrapper to model the analysis pass concept.
+/// Wrapper to model the analysis pass concept.
///
/// Can wrap any type which implements a suitable \c run method. The method
/// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments
@@ -283,7 +283,7 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
PreservedAnalysesT, InvalidatorT>;
- /// \brief The model delegates to the \c PassT::run method.
+ /// The model delegates to the \c PassT::run method.
///
/// The return is wrapped in an \c AnalysisResultModel.
std::unique_ptr<
@@ -293,7 +293,7 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
return llvm::make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...));
}
- /// \brief The model delegates to a static \c PassT::name method.
+ /// 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(); }
diff --git a/contrib/llvm/include/llvm/IR/PatternMatch.h b/contrib/llvm/include/llvm/IR/PatternMatch.h
index 245d72fbd16e..af0616cd8221 100644
--- a/contrib/llvm/include/llvm/IR/PatternMatch.h
+++ b/contrib/llvm/include/llvm/IR/PatternMatch.h
@@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===//
//
// This file provides a simple and efficient mechanism for performing general
-// tree-based pattern matches on the LLVM IR. The power of these routines is
+// tree-based pattern matches on the LLVM IR. The power of these routines is
// that it allows you to write concise patterns that are expressive and easy to
-// understand. The other major advantage of this is that it allows you to
-// trivially capture/bind elements in the pattern to variables. For example,
+// understand. The other major advantage of this is that it allows you to
+// trivially capture/bind elements in the pattern to variables. For example,
// you can do something like this:
//
// Value *Exp = ...
@@ -68,26 +68,26 @@ template <typename Class> struct class_match {
template <typename ITy> bool match(ITy *V) { return isa<Class>(V); }
};
-/// \brief Match an arbitrary value and ignore it.
+/// Match an arbitrary value and ignore it.
inline class_match<Value> m_Value() { return class_match<Value>(); }
-/// \brief Match an arbitrary binary operation and ignore it.
+/// 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.
+/// 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.
+/// Match an arbitrary ConstantInt and ignore it.
inline class_match<ConstantInt> m_ConstantInt() {
return class_match<ConstantInt>();
}
-/// \brief Match an arbitrary undef constant.
+/// Match an arbitrary undef constant.
inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
-/// \brief Match an arbitrary Constant and ignore it.
+/// Match an arbitrary Constant and ignore it.
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
/// Matching combinators
@@ -132,89 +132,6 @@ 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 auto *C = dyn_cast<Constant>(V))
- return C->isNullValue();
- return false;
- }
-};
-
-/// \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 auto *C = dyn_cast<Constant>(V))
- return C->isNegativeZeroValue();
- return false;
- }
-};
-
-/// \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(); }
-
-struct match_any_zero {
- template <typename ITy> bool match(ITy *V) {
- if (const auto *C = dyn_cast<Constant>(V))
- return C->isZeroValue();
- return false;
- }
-};
-
-/// \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_any_zero m_AnyZero() { return match_any_zero(); }
-
-struct match_nan {
- template <typename ITy> bool match(ITy *V) {
- if (const auto *C = dyn_cast<ConstantFP>(V))
- return C->isNaN();
- return false;
- }
-};
-
-/// Match an arbitrary NaN constant. This includes quiet and signalling nans.
-inline match_nan m_NaN() { return match_nan(); }
-
-struct match_one {
- template <typename ITy> bool match(ITy *V) {
- if (const auto *C = dyn_cast<Constant>(V))
- return C->isOneValue();
- return false;
- }
-};
-
-/// \brief Match an integer 1 or a vector with all elements equal to 1.
-inline match_one m_One() { return match_one(); }
-
-struct match_all_ones {
- template <typename ITy> bool match(ITy *V) {
- if (const auto *C = dyn_cast<Constant>(V))
- return C->isAllOnesValue();
- return false;
- }
-};
-
-/// \brief Match an integer or vector with all bits set to true.
-inline match_all_ones m_AllOnes() { return match_all_ones(); }
-
-struct match_sign_mask {
- template <typename ITy> bool match(ITy *V) {
- if (const auto *C = dyn_cast<Constant>(V))
- return C->isMinSignedValue();
- return false;
- }
-};
-
-/// \brief Match an integer or vector with only the sign bit(s) set.
-inline match_sign_mask m_SignMask() { return match_sign_mask(); }
-
struct apint_match {
const APInt *&Res;
@@ -255,11 +172,11 @@ struct apfloat_match {
}
};
-/// \brief Match a ConstantInt or splatted ConstantVector, binding the
+/// Match a ConstantInt or splatted ConstantVector, binding the
/// specified pointer to the contained APInt.
inline apint_match m_APInt(const APInt *&Res) { return Res; }
-/// \brief Match a ConstantFP or splatted ConstantVector, binding the
+/// Match a ConstantFP or splatted ConstantVector, binding the
/// specified pointer to the contained APFloat.
inline apfloat_match m_APFloat(const APFloat *&Res) { return Res; }
@@ -278,26 +195,44 @@ template <int64_t Val> struct constantint_match {
}
};
-/// \brief Match a ConstantInt with a specific value.
+/// Match a ConstantInt with a specific value.
template <int64_t Val> inline constantint_match<Val> m_ConstantInt() {
return constantint_match<Val>();
}
-/// \brief This helper class is used to match scalar and vector constants that
+/// This helper class is used to match scalar and vector integer constants that
/// satisfy a specified predicate.
+/// For vector constants, undefined elements are ignored.
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 auto *C = dyn_cast<Constant>(V))
+ if (V->getType()->isVectorTy()) {
+ if (const auto *C = dyn_cast<Constant>(V)) {
if (const auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
return this->isValue(CI->getValue());
+
+ // Non-splat vector constant: check each element for a match.
+ unsigned NumElts = V->getType()->getVectorNumElements();
+ assert(NumElts != 0 && "Constant vector with no elements?");
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *Elt = C->getAggregateElement(i);
+ if (!Elt)
+ return false;
+ if (isa<UndefValue>(Elt))
+ continue;
+ auto *CI = dyn_cast<ConstantInt>(Elt);
+ if (!CI || !this->isValue(CI->getValue()))
+ return false;
+ }
+ return true;
+ }
+ }
return false;
}
};
-/// \brief This helper class is used to match scalar and vector constants that
+/// 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;
@@ -322,20 +257,202 @@ template <typename Predicate> struct api_pred_ty : public Predicate {
}
};
-struct is_power2 {
- bool isValue(const APInt &C) { return C.isPowerOf2(); }
+/// This helper class is used to match scalar and vector floating-point
+/// constants that satisfy a specified predicate.
+/// For vector constants, undefined elements are ignored.
+template <typename Predicate> struct cstfp_pred_ty : public Predicate {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CF = dyn_cast<ConstantFP>(V))
+ return this->isValue(CF->getValueAPF());
+ if (V->getType()->isVectorTy()) {
+ if (const auto *C = dyn_cast<Constant>(V)) {
+ if (const auto *CF = dyn_cast_or_null<ConstantFP>(C->getSplatValue()))
+ return this->isValue(CF->getValueAPF());
+
+ // Non-splat vector constant: check each element for a match.
+ unsigned NumElts = V->getType()->getVectorNumElements();
+ assert(NumElts != 0 && "Constant vector with no elements?");
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *Elt = C->getAggregateElement(i);
+ if (!Elt)
+ return false;
+ if (isa<UndefValue>(Elt))
+ continue;
+ auto *CF = dyn_cast<ConstantFP>(Elt);
+ if (!CF || !this->isValue(CF->getValueAPF()))
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
};
-/// \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; }
+///////////////////////////////////////////////////////////////////////////////
+//
+// Encapsulate constant value queries for use in templated predicate matchers.
+// This allows checking if constants match using compound predicates and works
+// with vector constants, possibly with relaxed constraints. For example, ignore
+// undef values.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+struct is_all_ones {
+ bool isValue(const APInt &C) { return C.isAllOnesValue(); }
+};
+/// Match an integer or vector with all bits set.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_all_ones> m_AllOnes() {
+ return cst_pred_ty<is_all_ones>();
+}
struct is_maxsignedvalue {
bool isValue(const APInt &C) { return C.isMaxSignedValue(); }
};
+/// Match an integer or vector with values having all bits except for the high
+/// bit set (0x7f...).
+/// For vectors, this includes constants with undefined elements.
+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;
+}
-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; }
+struct is_negative {
+ bool isValue(const APInt &C) { return C.isNegative(); }
+};
+/// Match an integer or vector of negative values.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_negative> m_Negative() {
+ return cst_pred_ty<is_negative>();
+}
+inline api_pred_ty<is_negative> m_Negative(const APInt *&V) {
+ return V;
+}
+
+struct is_nonnegative {
+ bool isValue(const APInt &C) { return C.isNonNegative(); }
+};
+/// Match an integer or vector of nonnegative values.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_nonnegative> m_NonNegative() {
+ return cst_pred_ty<is_nonnegative>();
+}
+inline api_pred_ty<is_nonnegative> m_NonNegative(const APInt *&V) {
+ return V;
+}
+
+struct is_one {
+ bool isValue(const APInt &C) { return C.isOneValue(); }
+};
+/// Match an integer 1 or a vector with all elements equal to 1.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_one> m_One() {
+ return cst_pred_ty<is_one>();
+}
+
+struct is_zero_int {
+ bool isValue(const APInt &C) { return C.isNullValue(); }
+};
+/// Match an integer 0 or a vector with all elements equal to 0.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_zero_int> m_ZeroInt() {
+ return cst_pred_ty<is_zero_int>();
+}
+
+struct is_zero {
+ template <typename ITy> bool match(ITy *V) {
+ auto *C = dyn_cast<Constant>(V);
+ return C && (C->isNullValue() || cst_pred_ty<is_zero_int>().match(C));
+ }
+};
+/// Match any null constant or a vector with all elements equal to 0.
+/// For vectors, this includes constants with undefined elements.
+inline is_zero m_Zero() {
+ return is_zero();
+}
+
+struct is_power2 {
+ bool isValue(const APInt &C) { return C.isPowerOf2(); }
+};
+/// Match an integer or vector power-of-2.
+/// For vectors, this includes constants with undefined elements.
+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;
+}
+
+struct is_power2_or_zero {
+ bool isValue(const APInt &C) { return !C || C.isPowerOf2(); }
+};
+/// Match an integer or vector of 0 or power-of-2 values.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_power2_or_zero> m_Power2OrZero() {
+ return cst_pred_ty<is_power2_or_zero>();
+}
+inline api_pred_ty<is_power2_or_zero> m_Power2OrZero(const APInt *&V) {
+ return V;
+}
+
+struct is_sign_mask {
+ bool isValue(const APInt &C) { return C.isSignMask(); }
+};
+/// Match an integer or vector with only the sign bit(s) set.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_sign_mask> m_SignMask() {
+ return cst_pred_ty<is_sign_mask>();
+}
+
+struct is_lowbit_mask {
+ bool isValue(const APInt &C) { return C.isMask(); }
+};
+/// Match an integer or vector with only the low bit(s) set.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_lowbit_mask> m_LowBitMask() {
+ return cst_pred_ty<is_lowbit_mask>();
+}
+
+struct is_nan {
+ bool isValue(const APFloat &C) { return C.isNaN(); }
+};
+/// Match an arbitrary NaN constant. This includes quiet and signalling nans.
+/// For vectors, this includes constants with undefined elements.
+inline cstfp_pred_ty<is_nan> m_NaN() {
+ return cstfp_pred_ty<is_nan>();
+}
+
+struct is_any_zero_fp {
+ bool isValue(const APFloat &C) { return C.isZero(); }
+};
+/// Match a floating-point negative zero or positive zero.
+/// For vectors, this includes constants with undefined elements.
+inline cstfp_pred_ty<is_any_zero_fp> m_AnyZeroFP() {
+ return cstfp_pred_ty<is_any_zero_fp>();
+}
+
+struct is_pos_zero_fp {
+ bool isValue(const APFloat &C) { return C.isPosZero(); }
+};
+/// Match a floating-point positive zero.
+/// For vectors, this includes constants with undefined elements.
+inline cstfp_pred_ty<is_pos_zero_fp> m_PosZeroFP() {
+ return cstfp_pred_ty<is_pos_zero_fp>();
+}
+
+struct is_neg_zero_fp {
+ bool isValue(const APFloat &C) { return C.isNegZero(); }
+};
+/// Match a floating-point negative zero.
+/// For vectors, this includes constants with undefined elements.
+inline cstfp_pred_ty<is_neg_zero_fp> m_NegZeroFP() {
+ return cstfp_pred_ty<is_neg_zero_fp>();
+}
+
+///////////////////////////////////////////////////////////////////////////////
template <typename Class> struct bind_ty {
Class *&VR;
@@ -351,25 +468,25 @@ template <typename Class> struct bind_ty {
}
};
-/// \brief Match a value, capturing it if we match.
+/// Match a value, capturing it if we match.
inline bind_ty<Value> m_Value(Value *&V) { return V; }
inline bind_ty<const Value> m_Value(const Value *&V) { return V; }
-/// \brief Match an instruction, capturing it if we match.
+/// Match an instruction, capturing it if we match.
inline bind_ty<Instruction> m_Instruction(Instruction *&I) { return I; }
-/// \brief Match a binary operator, capturing it if we match.
+/// 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.
+/// Match a ConstantInt, capturing the value if we match.
inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; }
-/// \brief Match a Constant, capturing the value if we match.
+/// Match a Constant, capturing the value if we match.
inline bind_ty<Constant> m_Constant(Constant *&C) { return C; }
-/// \brief Match a ConstantFP, capturing the value if we match.
+/// Match a ConstantFP, capturing the value if we match.
inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; }
-/// \brief Match a specified Value*.
+/// Match a specified Value*.
struct specificval_ty {
const Value *Val;
@@ -378,10 +495,26 @@ struct specificval_ty {
template <typename ITy> bool match(ITy *V) { return V == Val; }
};
-/// \brief Match if we have a specific specified value.
+/// Match if we have a specific specified value.
inline specificval_ty m_Specific(const Value *V) { return V; }
-/// \brief Match a specified floating point value or vector of all elements of
+/// Stores a reference to the Value *, not the Value * itself,
+/// thus can be used in commutative matchers.
+template <typename Class> struct deferredval_ty {
+ Class *const &Val;
+
+ deferredval_ty(Class *const &V) : Val(V) {}
+
+ template <typename ITy> bool match(ITy *const V) { return V == Val; }
+};
+
+/// A commutative-friendly version of m_Specific().
+inline deferredval_ty<Value> m_Deferred(Value *const &V) { return V; }
+inline deferredval_ty<const Value> m_Deferred(const Value *const &V) {
+ return V;
+}
+
+/// Match a specified floating point value or vector of all elements of
/// that value.
struct specific_fpval {
double Val;
@@ -399,11 +532,11 @@ struct specific_fpval {
}
};
-/// \brief Match a specific floating point value or vector with all elements
+/// 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); }
-/// \brief Match a float 1.0 or vector with all elements equal to 1.0.
+/// 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 {
@@ -421,7 +554,7 @@ struct bind_const_intval_ty {
}
};
-/// \brief Match a specified integer value or vector of all elements of that
+/// Match a specified integer value or vector of all elements of that
// value.
struct specific_intval {
uint64_t Val;
@@ -438,11 +571,11 @@ struct specific_intval {
}
};
-/// \brief Match a specific integer value or vector with all elements equal to
+/// 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); }
-/// \brief Match a ConstantInt and bind to its value. This does not match
+/// 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; }
@@ -454,13 +587,15 @@ struct AnyBinaryOp_match {
LHS_t L;
RHS_t R;
+ // The evaluation order is always stable, regardless of Commutability.
+ // The LHS is always matched first.
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))) ||
- (Commutable && R.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)));
+ (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0)));
return false;
}
};
@@ -480,20 +615,22 @@ struct BinaryOp_match {
LHS_t L;
RHS_t R;
+ // The evaluation order is always stable, regardless of Commutability.
+ // The LHS is always matched first.
BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opcode) {
auto *I = cast<BinaryOperator>(V);
return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
- (Commutable && R.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)));
+ (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0)));
}
if (auto *CE = dyn_cast<ConstantExpr>(V))
return CE->getOpcode() == Opcode &&
((L.match(CE->getOperand(0)) && R.match(CE->getOperand(1))) ||
- (Commutable && R.match(CE->getOperand(0)) &&
- L.match(CE->getOperand(1))));
+ (Commutable && L.match(CE->getOperand(1)) &&
+ R.match(CE->getOperand(0))));
return false;
}
};
@@ -522,6 +659,13 @@ inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L,
return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R);
}
+/// Match 'fneg X' as 'fsub -0.0, X'.
+template <typename RHS>
+inline BinaryOp_match<cstfp_pred_ty<is_neg_zero_fp>, RHS, Instruction::FSub>
+m_FNeg(const RHS &X) {
+ return m_FSub(m_NegZeroFP(), X);
+}
+
template <typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
const RHS &R) {
@@ -746,35 +890,35 @@ struct is_idiv_op {
}
};
-/// \brief Matches shift operations.
+/// Matches shift operations.
template <typename LHS, typename RHS>
inline BinOpPred_match<LHS, RHS, is_shift_op> m_Shift(const LHS &L,
const RHS &R) {
return BinOpPred_match<LHS, RHS, is_shift_op>(L, R);
}
-/// \brief Matches logical shift operations.
+/// Matches logical shift operations.
template <typename LHS, typename RHS>
inline BinOpPred_match<LHS, RHS, is_right_shift_op> m_Shr(const LHS &L,
const RHS &R) {
return BinOpPred_match<LHS, RHS, is_right_shift_op>(L, R);
}
-/// \brief Matches logical shift operations.
+/// Matches logical shift operations.
template <typename LHS, typename RHS>
inline BinOpPred_match<LHS, RHS, is_logical_shift_op>
m_LogicalShift(const LHS &L, const RHS &R) {
return BinOpPred_match<LHS, RHS, is_logical_shift_op>(L, R);
}
-/// \brief Matches bitwise logic operations.
+/// Matches bitwise logic operations.
template <typename LHS, typename RHS>
inline BinOpPred_match<LHS, RHS, is_bitwiselogic_op>
m_BitwiseLogic(const LHS &L, const RHS &R) {
return BinOpPred_match<LHS, RHS, is_bitwiselogic_op>(L, R);
}
-/// \brief Matches integer division operations.
+/// Matches integer division operations.
template <typename LHS, typename RHS>
inline BinOpPred_match<LHS, RHS, is_idiv_op> m_IDiv(const LHS &L,
const RHS &R) {
@@ -811,14 +955,16 @@ struct CmpClass_match {
LHS_t L;
RHS_t R;
+ // The evaluation order is always stable, regardless of Commutability.
+ // The LHS is always matched first.
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(Pred), L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<Class>(V))
if ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
- (Commutable && R.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)))) {
+ (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0)))) {
Predicate = I->getPredicate();
return true;
}
@@ -871,7 +1017,7 @@ inline SelectClass_match<Cond, LHS, RHS> m_Select(const Cond &C, const LHS &L,
return SelectClass_match<Cond, LHS, RHS>(C, L, R);
}
-/// \brief This matches a select of two constants, e.g.:
+/// 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>>
@@ -880,6 +1026,84 @@ m_SelectCst(const Cond &C) {
}
//===----------------------------------------------------------------------===//
+// Matchers for InsertElementInst classes
+//
+
+template <typename Val_t, typename Elt_t, typename Idx_t>
+struct InsertElementClass_match {
+ Val_t V;
+ Elt_t E;
+ Idx_t I;
+
+ InsertElementClass_match(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
+ : V(Val), E(Elt), I(Idx) {}
+
+ template <typename OpTy> bool match(OpTy *VV) {
+ if (auto *II = dyn_cast<InsertElementInst>(VV))
+ return V.match(II->getOperand(0)) && E.match(II->getOperand(1)) &&
+ I.match(II->getOperand(2));
+ return false;
+ }
+};
+
+template <typename Val_t, typename Elt_t, typename Idx_t>
+inline InsertElementClass_match<Val_t, Elt_t, Idx_t>
+m_InsertElement(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx) {
+ return InsertElementClass_match<Val_t, Elt_t, Idx_t>(Val, Elt, Idx);
+}
+
+//===----------------------------------------------------------------------===//
+// Matchers for ExtractElementInst classes
+//
+
+template <typename Val_t, typename Idx_t> struct ExtractElementClass_match {
+ Val_t V;
+ Idx_t I;
+
+ ExtractElementClass_match(const Val_t &Val, const Idx_t &Idx)
+ : V(Val), I(Idx) {}
+
+ template <typename OpTy> bool match(OpTy *VV) {
+ if (auto *II = dyn_cast<ExtractElementInst>(VV))
+ return V.match(II->getOperand(0)) && I.match(II->getOperand(1));
+ return false;
+ }
+};
+
+template <typename Val_t, typename Idx_t>
+inline ExtractElementClass_match<Val_t, Idx_t>
+m_ExtractElement(const Val_t &Val, const Idx_t &Idx) {
+ return ExtractElementClass_match<Val_t, Idx_t>(Val, Idx);
+}
+
+//===----------------------------------------------------------------------===//
+// Matchers for ShuffleVectorInst classes
+//
+
+template <typename V1_t, typename V2_t, typename Mask_t>
+struct ShuffleVectorClass_match {
+ V1_t V1;
+ V2_t V2;
+ Mask_t M;
+
+ ShuffleVectorClass_match(const V1_t &v1, const V2_t &v2, const Mask_t &m)
+ : V1(v1), V2(v2), M(m) {}
+
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *SI = dyn_cast<ShuffleVectorInst>(V))
+ return V1.match(SI->getOperand(0)) && V2.match(SI->getOperand(1)) &&
+ M.match(SI->getOperand(2));
+ return false;
+ }
+};
+
+template <typename V1_t, typename V2_t, typename Mask_t>
+inline ShuffleVectorClass_match<V1_t, V2_t, Mask_t>
+m_ShuffleVector(const V1_t &v1, const V2_t &v2, const Mask_t &m) {
+ return ShuffleVectorClass_match<V1_t, V2_t, Mask_t>(v1, v2, m);
+}
+
+//===----------------------------------------------------------------------===//
// Matchers for CastInst classes
//
@@ -895,31 +1119,31 @@ template <typename Op_t, unsigned Opcode> struct CastClass_match {
}
};
-/// \brief Matches BitCast.
+/// Matches BitCast.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::BitCast> m_BitCast(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::BitCast>(Op);
}
-/// \brief Matches PtrToInt.
+/// Matches PtrToInt.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::PtrToInt> m_PtrToInt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::PtrToInt>(Op);
}
-/// \brief Matches Trunc.
+/// Matches Trunc.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::Trunc> m_Trunc(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::Trunc>(Op);
}
-/// \brief Matches SExt.
+/// Matches SExt.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::SExt> m_SExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SExt>(Op);
}
-/// \brief Matches ZExt.
+/// Matches ZExt.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::ZExt>(Op);
@@ -932,25 +1156,25 @@ m_ZExtOrSExt(const OpTy &Op) {
return m_CombineOr(m_ZExt(Op), m_SExt(Op));
}
-/// \brief Matches UIToFP.
+/// Matches UIToFP.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::UIToFP>(Op);
}
-/// \brief Matches SIToFP.
+/// Matches SIToFP.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::SIToFP> m_SIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SIToFP>(Op);
}
-/// \brief Matches FPTrunc
+/// Matches FPTrunc
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::FPTrunc> m_FPTrunc(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::FPTrunc>(Op);
}
-/// \brief Matches FPExt
+/// Matches FPExt
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::FPExt> m_FPExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::FPExt>(Op);
@@ -976,80 +1200,32 @@ template <typename Op_t> struct LoadClass_match {
template <typename OpTy> inline LoadClass_match<OpTy> m_Load(const OpTy &Op) {
return LoadClass_match<OpTy>(Op);
}
+
//===----------------------------------------------------------------------===//
-// Matchers for unary operators
+// Matcher for StoreInst classes
//
-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 (auto *O = dyn_cast<Operator>(V))
- if (O->getOpcode() == Instruction::Xor) {
- if (isAllOnes(O->getOperand(1)))
- return L.match(O->getOperand(0));
- if (isAllOnes(O->getOperand(0)))
- return L.match(O->getOperand(1));
- }
- return false;
- }
-
-private:
- bool isAllOnes(Value *V) {
- return isa<Constant>(V) && cast<Constant>(V)->isAllOnesValue();
- }
-};
-
-template <typename LHS> inline not_match<LHS> m_Not(const LHS &L) { return L; }
+template <typename ValueOp_t, typename PointerOp_t> struct StoreClass_match {
+ ValueOp_t ValueOp;
+ PointerOp_t PointerOp;
-template <typename LHS_t> struct neg_match {
- LHS_t L;
-
- neg_match(const LHS_t &LHS) : L(LHS) {}
+ StoreClass_match(const ValueOp_t &ValueOpMatch,
+ const PointerOp_t &PointerOpMatch) :
+ ValueOp(ValueOpMatch), PointerOp(PointerOpMatch) {}
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));
+ if (auto *LI = dyn_cast<StoreInst>(V))
+ return ValueOp.match(LI->getValueOperand()) &&
+ PointerOp.match(LI->getPointerOperand());
return false;
}
-
-private:
- bool matchIfNeg(Value *LHS, Value *RHS) {
- return ((isa<ConstantInt>(LHS) && cast<ConstantInt>(LHS)->isZero()) ||
- isa<ConstantAggregateZero>(LHS)) &&
- L.match(RHS);
- }
};
-/// \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 {
- LHS_t L;
-
- fneg_match(const LHS_t &LHS) : L(LHS) {}
-
- 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 (const auto *C = dyn_cast<ConstantFP>(LHS))
- return C->isNegativeZeroValue() && L.match(RHS);
- return false;
- }
-};
-
-/// \brief Match a floating point negate.
-template <typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) {
- return L;
+/// Matches StoreInst.
+template <typename ValueOpTy, typename PointerOpTy>
+inline StoreClass_match<ValueOpTy, PointerOpTy>
+m_Store(const ValueOpTy &ValueOp, const PointerOpTy &PointerOp) {
+ return StoreClass_match<ValueOpTy, PointerOpTy>(ValueOp, PointerOp);
}
//===----------------------------------------------------------------------===//
@@ -1106,6 +1282,8 @@ struct MaxMin_match {
LHS_t L;
RHS_t R;
+ // The evaluation order is always stable, regardless of Commutability.
+ // The LHS is always matched first.
MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
@@ -1132,60 +1310,60 @@ struct MaxMin_match {
return false;
// It does! Bind the operands.
return (L.match(LHS) && R.match(RHS)) ||
- (Commutable && R.match(LHS) && L.match(RHS));
+ (Commutable && L.match(RHS) && R.match(LHS));
}
};
-/// \brief Helper class for identifying signed max predicates.
+/// 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;
}
};
-/// \brief Helper class for identifying signed min predicates.
+/// 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;
}
};
-/// \brief Helper class for identifying unsigned max predicates.
+/// 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;
}
};
-/// \brief Helper class for identifying unsigned min predicates.
+/// 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;
}
};
-/// \brief Helper class for identifying ordered max predicates.
+/// 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;
}
};
-/// \brief Helper class for identifying ordered min predicates.
+/// 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;
}
};
-/// \brief Helper class for identifying unordered max predicates.
+/// 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;
}
};
-/// \brief Helper class for identifying unordered min predicates.
+/// 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;
@@ -1216,7 +1394,7 @@ inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> m_UMin(const LHS &L,
return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>(L, R);
}
-/// \brief Match an 'ordered' floating point maximum function.
+/// Match an 'ordered' floating point maximum function.
/// Floating point has one special value 'NaN'. Therefore, there is no total
/// order. However, if we can ignore the 'NaN' value (for example, because of a
/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum'
@@ -1231,7 +1409,7 @@ inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> m_OrdFMax(const LHS &L,
return MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>(L, R);
}
-/// \brief Match an 'ordered' floating point minimum function.
+/// Match an 'ordered' floating point minimum function.
/// Floating point has one special value 'NaN'. Therefore, there is no total
/// order. However, if we can ignore the 'NaN' value (for example, because of a
/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum'
@@ -1246,7 +1424,7 @@ inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L,
return MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>(L, R);
}
-/// \brief Match an 'unordered' floating point maximum function.
+/// Match an 'unordered' floating point maximum function.
/// Floating point has one special value 'NaN'. Therefore, there is no total
/// order. However, if we can ignore the 'NaN' value (for example, because of a
/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum'
@@ -1261,7 +1439,7 @@ m_UnordFMax(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R);
}
-/// \brief Match an 'unordered' floating point minimum function.
+/// Match an 'unordered' floating point minimum function.
/// Floating point has one special value 'NaN'. Therefore, there is no total
/// order. However, if we can ignore the 'NaN' value (for example, because of a
/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum'
@@ -1312,7 +1490,7 @@ struct UAddWithOverflow_match {
}
};
-/// \brief Match an icmp instruction checking for unsigned overflow on addition.
+/// Match an icmp instruction checking for unsigned overflow on addition.
///
/// S is matched to the addition whose result is being checked for overflow, and
/// L and R are matched to the LHS and RHS of S.
@@ -1334,13 +1512,13 @@ template <typename Opnd_t> struct Argument_match {
}
};
-/// \brief Match an argument.
+/// 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);
}
-/// \brief Intrinsic matchers.
+/// Intrinsic matchers.
struct IntrinsicID_match {
unsigned ID;
@@ -1383,7 +1561,7 @@ struct m_Intrinsic_Ty<T0, T1, T2, T3> {
Argument_match<T3>>;
};
-/// \brief Match intrinsic calls like this:
+/// 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);
@@ -1424,6 +1602,16 @@ inline typename m_Intrinsic_Ty<Opnd0>::Ty m_BSwap(const Opnd0 &Op0) {
return m_Intrinsic<Intrinsic::bswap>(Op0);
}
+template <typename Opnd0>
+inline typename m_Intrinsic_Ty<Opnd0>::Ty m_FAbs(const Opnd0 &Op0) {
+ return m_Intrinsic<Intrinsic::fabs>(Op0);
+}
+
+template <typename Opnd0>
+inline typename m_Intrinsic_Ty<Opnd0>::Ty m_FCanonicalize(const Opnd0 &Op0) {
+ return m_Intrinsic<Intrinsic::canonicalize>(Op0);
+}
+
template <typename Opnd0, typename Opnd1>
inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMin(const Opnd0 &Op0,
const Opnd1 &Op1) {
@@ -1436,57 +1624,17 @@ inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMax(const Opnd0 &Op0,
return m_Intrinsic<Intrinsic::maxnum>(Op0, Op1);
}
-template <typename Opnd_t> struct Signum_match {
- Opnd_t Val;
- Signum_match(const Opnd_t &V) : Val(V) {}
-
- template <typename OpTy> bool match(OpTy *V) {
- unsigned TypeSize = V->getType()->getScalarSizeInBits();
- if (TypeSize == 0)
- return false;
-
- unsigned ShiftWidth = TypeSize - 1;
- Value *OpL = nullptr, *OpR = nullptr;
-
- // This is the representation of signum we match:
- //
- // signum(x) == (x >> 63) | (-x >>u 63)
- //
- // An i1 value is its own signum, so it's correct to match
- //
- // signum(x) == (x >> 0) | (-x >>u 0)
- //
- // for i1 values.
-
- auto LHS = m_AShr(m_Value(OpL), m_SpecificInt(ShiftWidth));
- auto RHS = m_LShr(m_Neg(m_Value(OpR)), m_SpecificInt(ShiftWidth));
- auto Signum = m_Or(LHS, RHS);
-
- return Signum.match(V) && OpL == OpR && Val.match(OpL);
- }
-};
-
-/// \brief Matches a signum pattern.
-///
-/// signum(x) =
-/// x > 0 -> 1
-/// x == 0 -> 0
-/// x < 0 -> -1
-template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) {
- return Signum_match<Val_t>(V);
-}
-
//===----------------------------------------------------------------------===//
// Matchers for two-operands operators with the operators in either order
//
-/// \brief Matches a BinaryOperator with LHS and RHS in either order.
+/// Matches a BinaryOperator with LHS and RHS in either order.
template <typename LHS, typename RHS>
inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) {
return AnyBinaryOp_match<LHS, RHS, true>(L, R);
}
-/// \brief Matches an ICmp with a predicate over LHS and RHS in either order.
+/// Matches an ICmp with a predicate over LHS and RHS in either order.
/// Does not swap the predicate.
template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
@@ -1495,41 +1643,55 @@ m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
R);
}
-/// \brief Matches a Add with LHS and RHS in either order.
+/// Matches a Add with LHS and RHS in either order.
template <typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::Add, true> m_c_Add(const LHS &L,
const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Add, true>(L, R);
}
-/// \brief Matches a Mul with LHS and RHS in either order.
+/// Matches a Mul with LHS and RHS in either order.
template <typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::Mul, true> m_c_Mul(const LHS &L,
const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Mul, true>(L, R);
}
-/// \brief Matches an And with LHS and RHS in either order.
+/// Matches an And with LHS and RHS in either order.
template <typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::And, true> m_c_And(const LHS &L,
const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::And, true>(L, R);
}
-/// \brief Matches an Or with LHS and RHS in either order.
+/// Matches an Or with LHS and RHS in either order.
template <typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::Or, true> m_c_Or(const LHS &L,
const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Or, true>(L, R);
}
-/// \brief Matches an Xor with LHS and RHS in either order.
+/// Matches an Xor with LHS and RHS in either order.
template <typename LHS, typename RHS>
inline BinaryOp_match<LHS, RHS, Instruction::Xor, true> m_c_Xor(const LHS &L,
const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Xor, true>(L, R);
}
+/// Matches a 'Neg' as 'sub 0, V'.
+template <typename ValTy>
+inline BinaryOp_match<cst_pred_ty<is_zero_int>, ValTy, Instruction::Sub>
+m_Neg(const ValTy &V) {
+ return m_Sub(m_ZeroInt(), V);
+}
+
+/// Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
+template <typename ValTy>
+inline BinaryOp_match<ValTy, cst_pred_ty<is_all_ones>, Instruction::Xor, true>
+m_Not(const ValTy &V) {
+ return m_c_Xor(V, m_AllOnes());
+}
+
/// Matches an SMin with LHS and RHS in either order.
template <typename LHS, typename RHS>
inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty, true>
@@ -1555,6 +1717,60 @@ m_c_UMax(const LHS &L, const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty, true>(L, R);
}
+/// Matches FAdd with LHS and RHS in either order.
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FAdd, true>
+m_c_FAdd(const LHS &L, const RHS &R) {
+ return BinaryOp_match<LHS, RHS, Instruction::FAdd, true>(L, R);
+}
+
+/// Matches FMul with LHS and RHS in either order.
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FMul, true>
+m_c_FMul(const LHS &L, const RHS &R) {
+ return BinaryOp_match<LHS, RHS, Instruction::FMul, true>(L, R);
+}
+
+template <typename Opnd_t> struct Signum_match {
+ Opnd_t Val;
+ Signum_match(const Opnd_t &V) : Val(V) {}
+
+ template <typename OpTy> bool match(OpTy *V) {
+ unsigned TypeSize = V->getType()->getScalarSizeInBits();
+ if (TypeSize == 0)
+ return false;
+
+ unsigned ShiftWidth = TypeSize - 1;
+ Value *OpL = nullptr, *OpR = nullptr;
+
+ // This is the representation of signum we match:
+ //
+ // signum(x) == (x >> 63) | (-x >>u 63)
+ //
+ // An i1 value is its own signum, so it's correct to match
+ //
+ // signum(x) == (x >> 0) | (-x >>u 0)
+ //
+ // for i1 values.
+
+ auto LHS = m_AShr(m_Value(OpL), m_SpecificInt(ShiftWidth));
+ auto RHS = m_LShr(m_Neg(m_Value(OpR)), m_SpecificInt(ShiftWidth));
+ auto Signum = m_Or(LHS, RHS);
+
+ return Signum.match(V) && OpL == OpR && Val.match(OpL);
+ }
+};
+
+/// Matches a signum pattern.
+///
+/// signum(x) =
+/// x > 0 -> 1
+/// x == 0 -> 0
+/// x < 0 -> -1
+template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) {
+ return Signum_match<Val_t>(V);
+}
+
} // end namespace PatternMatch
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/IR/ProfileSummary.h b/contrib/llvm/include/llvm/IR/ProfileSummary.h
index d85ce8c443ec..e38663770a13 100644
--- a/contrib/llvm/include/llvm/IR/ProfileSummary.h
+++ b/contrib/llvm/include/llvm/IR/ProfileSummary.h
@@ -51,7 +51,7 @@ private:
SummaryEntryVector DetailedSummary;
uint64_t TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount;
uint32_t NumCounts, NumFunctions;
- /// \brief Return detailed summary as metadata.
+ /// Return detailed summary as metadata.
Metadata *getDetailedSummaryMD(LLVMContext &Context);
public:
@@ -67,9 +67,9 @@ public:
NumCounts(NumCounts), NumFunctions(NumFunctions) {}
Kind getKind() const { return PSK; }
- /// \brief Return summary information as metadata.
+ /// Return summary information as metadata.
Metadata *getMD(LLVMContext &Context);
- /// \brief Construct profile summary from metdata.
+ /// Construct profile summary from metdata.
static ProfileSummary *getFromMD(Metadata *MD);
SummaryEntryVector &getDetailedSummary() { return DetailedSummary; }
uint32_t getNumFunctions() { return NumFunctions; }
diff --git a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.def b/contrib/llvm/include/llvm/IR/RuntimeLibcalls.def
index 7695e9d782ef..7ed90d959f01 100644
--- a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.def
+++ b/contrib/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -130,26 +130,51 @@ HANDLE_LIBCALL(LOG_F64, "log")
HANDLE_LIBCALL(LOG_F80, "logl")
HANDLE_LIBCALL(LOG_F128, "logl")
HANDLE_LIBCALL(LOG_PPCF128, "logl")
+HANDLE_LIBCALL(LOG_FINITE_F32, "__logf_finite")
+HANDLE_LIBCALL(LOG_FINITE_F64, "__log_finite")
+HANDLE_LIBCALL(LOG_FINITE_F80, "__logl_finite")
+HANDLE_LIBCALL(LOG_FINITE_F128, "__logl_finite")
+HANDLE_LIBCALL(LOG_FINITE_PPCF128, "__logl_finite")
HANDLE_LIBCALL(LOG2_F32, "log2f")
HANDLE_LIBCALL(LOG2_F64, "log2")
HANDLE_LIBCALL(LOG2_F80, "log2l")
HANDLE_LIBCALL(LOG2_F128, "log2l")
HANDLE_LIBCALL(LOG2_PPCF128, "log2l")
+HANDLE_LIBCALL(LOG2_FINITE_F32, "__log2f_finite")
+HANDLE_LIBCALL(LOG2_FINITE_F64, "__log2_finite")
+HANDLE_LIBCALL(LOG2_FINITE_F80, "__log2l_finite")
+HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2l_finite")
+HANDLE_LIBCALL(LOG2_FINITE_PPCF128, "__log2l_finite")
HANDLE_LIBCALL(LOG10_F32, "log10f")
HANDLE_LIBCALL(LOG10_F64, "log10")
HANDLE_LIBCALL(LOG10_F80, "log10l")
HANDLE_LIBCALL(LOG10_F128, "log10l")
HANDLE_LIBCALL(LOG10_PPCF128, "log10l")
+HANDLE_LIBCALL(LOG10_FINITE_F32, "__log10f_finite")
+HANDLE_LIBCALL(LOG10_FINITE_F64, "__log10_finite")
+HANDLE_LIBCALL(LOG10_FINITE_F80, "__log10l_finite")
+HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10l_finite")
+HANDLE_LIBCALL(LOG10_FINITE_PPCF128, "__log10l_finite")
HANDLE_LIBCALL(EXP_F32, "expf")
HANDLE_LIBCALL(EXP_F64, "exp")
HANDLE_LIBCALL(EXP_F80, "expl")
HANDLE_LIBCALL(EXP_F128, "expl")
HANDLE_LIBCALL(EXP_PPCF128, "expl")
+HANDLE_LIBCALL(EXP_FINITE_F32, "__expf_finite")
+HANDLE_LIBCALL(EXP_FINITE_F64, "__exp_finite")
+HANDLE_LIBCALL(EXP_FINITE_F80, "__expl_finite")
+HANDLE_LIBCALL(EXP_FINITE_F128, "__expl_finite")
+HANDLE_LIBCALL(EXP_FINITE_PPCF128, "__expl_finite")
HANDLE_LIBCALL(EXP2_F32, "exp2f")
HANDLE_LIBCALL(EXP2_F64, "exp2")
HANDLE_LIBCALL(EXP2_F80, "exp2l")
HANDLE_LIBCALL(EXP2_F128, "exp2l")
HANDLE_LIBCALL(EXP2_PPCF128, "exp2l")
+HANDLE_LIBCALL(EXP2_FINITE_F32, "__exp2f_finite")
+HANDLE_LIBCALL(EXP2_FINITE_F64, "__exp2_finite")
+HANDLE_LIBCALL(EXP2_FINITE_F80, "__exp2l_finite")
+HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2l_finite")
+HANDLE_LIBCALL(EXP2_FINITE_PPCF128, "__exp2l_finite")
HANDLE_LIBCALL(SIN_F32, "sinf")
HANDLE_LIBCALL(SIN_F64, "sin")
HANDLE_LIBCALL(SIN_F80, "sinl")
@@ -172,6 +197,11 @@ HANDLE_LIBCALL(POW_F64, "pow")
HANDLE_LIBCALL(POW_F80, "powl")
HANDLE_LIBCALL(POW_F128, "powl")
HANDLE_LIBCALL(POW_PPCF128, "powl")
+HANDLE_LIBCALL(POW_FINITE_F32, "__powf_finite")
+HANDLE_LIBCALL(POW_FINITE_F64, "__pow_finite")
+HANDLE_LIBCALL(POW_FINITE_F80, "__powl_finite")
+HANDLE_LIBCALL(POW_FINITE_F128, "__powl_finite")
+HANDLE_LIBCALL(POW_FINITE_PPCF128, "__powl_finite")
HANDLE_LIBCALL(CEIL_F32, "ceilf")
HANDLE_LIBCALL(CEIL_F64, "ceil")
HANDLE_LIBCALL(CEIL_F80, "ceill")
@@ -221,6 +251,7 @@ HANDLE_LIBCALL(FMAX_PPCF128, "fmaxl")
// Conversion
HANDLE_LIBCALL(FPEXT_F32_PPCF128, "__gcc_stoq")
HANDLE_LIBCALL(FPEXT_F64_PPCF128, "__gcc_dtoq")
+HANDLE_LIBCALL(FPEXT_F80_F128, "__extendxftf2")
HANDLE_LIBCALL(FPEXT_F64_F128, "__extenddftf2")
HANDLE_LIBCALL(FPEXT_F32_F128, "__extendsftf2")
HANDLE_LIBCALL(FPEXT_F32_F64, "__extendsfdf2")
@@ -237,6 +268,7 @@ HANDLE_LIBCALL(FPROUND_PPCF128_F32, "__gcc_qtos")
HANDLE_LIBCALL(FPROUND_F80_F64, "__truncxfdf2")
HANDLE_LIBCALL(FPROUND_F128_F64, "__trunctfdf2")
HANDLE_LIBCALL(FPROUND_PPCF128_F64, "__gcc_qtod")
+HANDLE_LIBCALL(FPROUND_F128_F80, "__trunctfxf2")
HANDLE_LIBCALL(FPTOSINT_F32_I32, "__fixsfsi")
HANDLE_LIBCALL(FPTOSINT_F32_I64, "__fixsfdi")
HANDLE_LIBCALL(FPTOSINT_F32_I128, "__fixsfti")
diff --git a/contrib/llvm/include/llvm/IR/Statepoint.h b/contrib/llvm/include/llvm/IR/Statepoint.h
index ad9537e9762e..c8e905b21a30 100644
--- a/contrib/llvm/include/llvm/IR/Statepoint.h
+++ b/contrib/llvm/include/llvm/IR/Statepoint.h
@@ -196,7 +196,7 @@ public:
return make_range(arg_begin(), arg_end());
}
- /// \brief Return true if the call or the callee has the given attribute.
+ /// Return true if the call or the callee has the given attribute.
bool paramHasAttr(unsigned i, Attribute::AttrKind A) const {
Function *F = getCalledFunction();
return getCallSite().paramHasAttr(i + CallArgsBeginPos, A) ||
@@ -465,7 +465,7 @@ struct StatepointDirectives {
/// AS.
StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS);
-/// Return \c true if the the \p Attr is an attribute that is a statepoint
+/// Return \c true if the \p Attr is an attribute that is a statepoint
/// directive.
bool isStatepointDirectiveAttr(Attribute Attr);
diff --git a/contrib/llvm/include/llvm/IR/TrackingMDRef.h b/contrib/llvm/include/llvm/IR/TrackingMDRef.h
index bdec904ad1e1..084efada221f 100644
--- a/contrib/llvm/include/llvm/IR/TrackingMDRef.h
+++ b/contrib/llvm/include/llvm/IR/TrackingMDRef.h
@@ -20,7 +20,7 @@
namespace llvm {
-/// \brief Tracking metadata reference.
+/// Tracking metadata reference.
///
/// This class behaves like \a TrackingVH, but for metadata.
class TrackingMDRef {
@@ -70,7 +70,7 @@ public:
track();
}
- /// \brief Check whether this has a trivial destructor.
+ /// Check whether this has a trivial destructor.
///
/// If \c MD isn't replaceable, the destructor will be a no-op.
bool hasTrivialDestructor() const {
@@ -100,7 +100,7 @@ private:
}
};
-/// \brief Typed tracking ref.
+/// Typed tracking ref.
///
/// Track refererences of a particular type. It's useful to use this for \a
/// MDNode and \a ValueAsMetadata.
@@ -135,7 +135,7 @@ public:
void reset() { Ref.reset(); }
void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
- /// \brief Check whether this has a trivial destructor.
+ /// Check whether this has a trivial destructor.
bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
};
diff --git a/contrib/llvm/include/llvm/IR/Type.h b/contrib/llvm/include/llvm/IR/Type.h
index 1574fc334ffc..9c1f99d1b3a2 100644
--- a/contrib/llvm/include/llvm/IR/Type.h
+++ b/contrib/llvm/include/llvm/IR/Type.h
@@ -208,6 +208,9 @@ public:
return getScalarType()->isIntegerTy(BitWidth);
}
+ /// Return true if this is an integer type or a pointer type.
+ bool isIntOrPtrTy() const { return isIntegerTy() || isPointerTy(); }
+
/// True if this is an instance of FunctionType.
bool isFunctionTy() const { return getTypeID() == FunctionTyID; }
@@ -229,7 +232,7 @@ public:
/// Return true if this type could be converted with a lossless BitCast to
/// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the
/// same size only where no re-interpretation of the bits is done.
- /// @brief Determine if this type could be losslessly bitcast to Ty
+ /// Determine if this type could be losslessly bitcast to Ty
bool canLosslesslyBitCastTo(Type *Ty) const;
/// Return true if this type is empty, that is, it has no elements or all of
@@ -407,6 +410,20 @@ public:
static IntegerType *getInt32Ty(LLVMContext &C);
static IntegerType *getInt64Ty(LLVMContext &C);
static IntegerType *getInt128Ty(LLVMContext &C);
+ template <typename ScalarTy> static Type *getScalarTy(LLVMContext &C) {
+ int noOfBits = sizeof(ScalarTy) * CHAR_BIT;
+ if (std::is_integral<ScalarTy>::value) {
+ return (Type*) Type::getIntNTy(C, noOfBits);
+ } else if (std::is_floating_point<ScalarTy>::value) {
+ switch (noOfBits) {
+ case 32:
+ return Type::getFloatTy(C);
+ case 64:
+ return Type::getDoubleTy(C);
+ }
+ }
+ llvm_unreachable("Unsupported type in Type::getScalarTy");
+ }
//===--------------------------------------------------------------------===//
// Convenience methods for getting pointer types with one of the above builtin
diff --git a/contrib/llvm/include/llvm/IR/Use.h b/contrib/llvm/include/llvm/IR/Use.h
index 0ac13935c7ce..25c44e0871a9 100644
--- a/contrib/llvm/include/llvm/IR/Use.h
+++ b/contrib/llvm/include/llvm/IR/Use.h
@@ -36,7 +36,7 @@ template <typename> struct simplify_type;
class User;
class Value;
-/// \brief A Use represents the edge between a Value definition and its users.
+/// A Use represents the edge between a Value definition and its users.
///
/// This is notionally a two-dimensional linked list. It supports traversing
/// all of the uses for a particular value definition. It also supports jumping
@@ -57,7 +57,7 @@ class Use {
public:
Use(const Use &U) = delete;
- /// \brief Provide a fast substitute to std::swap<Use>
+ /// Provide a fast substitute to std::swap<Use>
/// that also works with less standard-compliant compilers
void swap(Use &RHS);
@@ -107,7 +107,7 @@ public:
operator Value *() const { return Val; }
Value *get() const { return Val; }
- /// \brief Returns the User that contains this Use.
+ /// Returns the User that contains this Use.
///
/// For an instruction operand, for example, this will return the
/// instruction.
@@ -123,16 +123,16 @@ public:
Use *getNext() const { return Next; }
- /// \brief Return the operand # of this use in its User.
+ /// Return the operand # of this use in its User.
unsigned getOperandNo() const;
- /// \brief Initializes the waymarking tags on an array of Uses.
+ /// Initializes the waymarking tags on an array of Uses.
///
/// This sets up the array of Uses such that getUser() can find the User from
/// any of those Uses.
static Use *initTags(Use *Start, Use *Stop);
- /// \brief Destroys Use operands when the number of operands of
+ /// Destroys Use operands when the number of operands of
/// a User changes.
static void zap(Use *Start, const Use *Stop, bool del = false);
@@ -161,7 +161,7 @@ private:
}
};
-/// \brief Allow clients to treat uses just like values when using
+/// Allow clients to treat uses just like values when using
/// casting operators.
template <> struct simplify_type<Use> {
using SimpleType = Value *;
diff --git a/contrib/llvm/include/llvm/IR/UseListOrder.h b/contrib/llvm/include/llvm/IR/UseListOrder.h
index a8b394fc6302..b6bb0f19a0aa 100644
--- a/contrib/llvm/include/llvm/IR/UseListOrder.h
+++ b/contrib/llvm/include/llvm/IR/UseListOrder.h
@@ -23,7 +23,7 @@ namespace llvm {
class Function;
class Value;
-/// \brief Structure to hold a use-list order.
+/// Structure to hold a use-list order.
struct UseListOrder {
const Value *V = nullptr;
const Function *F = nullptr;
diff --git a/contrib/llvm/include/llvm/IR/User.h b/contrib/llvm/include/llvm/IR/User.h
index 4dfa19cf241f..d6a603ce845d 100644
--- a/contrib/llvm/include/llvm/IR/User.h
+++ b/contrib/llvm/include/llvm/IR/User.h
@@ -36,7 +36,7 @@ namespace llvm {
template <typename T> class ArrayRef;
template <typename T> class MutableArrayRef;
-/// \brief Compile-time customization of User operands.
+/// Compile-time customization of User operands.
///
/// Customizes operand-related allocators and accessors.
template <class>
@@ -81,13 +81,13 @@ protected:
"Error in initializing hung off uses for User");
}
- /// \brief Allocate the array of Uses, followed by a pointer
+ /// Allocate the array of Uses, followed by a pointer
/// (with bottom bit set) to the User.
/// \param IsPhi identifies callers which are phi nodes and which need
/// N BasicBlock* allocated along with N
void allocHungoffUses(unsigned N, bool IsPhi = false);
- /// \brief Grow the number of hung off uses. Note that allocHungoffUses
+ /// Grow the number of hung off uses. Note that allocHungoffUses
/// should be called if there are no uses.
void growHungoffUses(unsigned N, bool IsPhi = false);
@@ -97,15 +97,31 @@ protected:
public:
User(const User &) = delete;
- /// \brief Free memory allocated for User and Use objects.
+ /// Free memory allocated for User and Use objects.
void operator delete(void *Usr);
- /// \brief Placement delete - required by std, but never called.
- void operator delete(void*, unsigned) {
+ /// Placement delete - required by std, called if the ctor throws.
+ void operator delete(void *Usr, unsigned) {
+ // Note: If a subclass manipulates the information which is required to calculate the
+ // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has
+ // to restore the changed information to the original value, since the dtor of that class
+ // is not called if the ctor fails.
+ User::operator delete(Usr);
+
+#ifndef LLVM_ENABLE_EXCEPTIONS
llvm_unreachable("Constructor throws?");
+#endif
}
- /// \brief Placement delete - required by std, but never called.
- void operator delete(void*, unsigned, bool) {
+ /// Placement delete - required by std, called if the ctor throws.
+ void operator delete(void *Usr, unsigned, bool) {
+ // Note: If a subclass manipulates the information which is required to calculate the
+ // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has
+ // to restore the changed information to the original value, since the dtor of that class
+ // is not called if the ctor fails.
+ User::operator delete(Usr);
+
+#ifndef LLVM_ENABLE_EXCEPTIONS
llvm_unreachable("Constructor throws?");
+#endif
}
protected:
@@ -194,7 +210,7 @@ public:
NumUserOperands = NumOps;
}
- /// \brief Subclasses with hung off uses need to manage the operand count
+ /// Subclasses with hung off uses need to manage the operand count
/// themselves. In these instances, the operand count isn't used to find the
/// OperandList, so there's no issue in having the operand count change.
void setNumHungOffUseOperands(unsigned NumOps) {
@@ -226,7 +242,7 @@ public:
return const_op_range(op_begin(), op_end());
}
- /// \brief Iterator for directly iterating over the operand Values.
+ /// Iterator for directly iterating over the operand Values.
struct value_op_iterator
: iterator_adaptor_base<value_op_iterator, op_iterator,
std::random_access_iterator_tag, Value *,
@@ -268,7 +284,7 @@ public:
return make_range(value_op_begin(), value_op_end());
}
- /// \brief Drop all references to operands.
+ /// Drop all references to operands.
///
/// This function is in charge of "letting go" of all objects that this User
/// refers to. This allows one to 'delete' a whole class at a time, even
@@ -281,7 +297,7 @@ public:
U.set(nullptr);
}
- /// \brief Replace uses of one Value with another.
+ /// Replace uses of one Value with another.
///
/// Replaces all references to the "From" definition with references to the
/// "To" definition.
diff --git a/contrib/llvm/include/llvm/IR/Value.h b/contrib/llvm/include/llvm/IR/Value.h
index d848fe921868..f396db995ab0 100644
--- a/contrib/llvm/include/llvm/IR/Value.h
+++ b/contrib/llvm/include/llvm/IR/Value.h
@@ -57,7 +57,7 @@ using ValueName = StringMapEntry<Value *>;
// Value Class
//===----------------------------------------------------------------------===//
-/// \brief LLVM Value Representation
+/// LLVM Value Representation
///
/// This is a very important LLVM class. It is the base class of all values
/// computed by a program that may be used as operands to other values. Value is
@@ -83,7 +83,7 @@ class Value {
unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this?
protected:
- /// \brief Hold subclass data that can be dropped.
+ /// Hold subclass data that can be dropped.
///
/// This member is similar to SubclassData, however it is for holding
/// information which may be used to aid optimization, but which may be
@@ -91,7 +91,7 @@ protected:
unsigned char SubclassOptionalData : 7;
private:
- /// \brief Hold arbitrary subclass data.
+ /// Hold arbitrary subclass data.
///
/// This member is defined by this class, but is not used for anything.
/// Subclasses can use it to hold whatever state they find useful. This
@@ -99,7 +99,7 @@ private:
unsigned short SubclassData;
protected:
- /// \brief The number of operands in the subclass.
+ /// The number of operands in the subclass.
///
/// This member is defined by this class, but not used for anything.
/// Subclasses can use it to store their number of operands, if they have
@@ -173,7 +173,7 @@ private:
bool operator==(const user_iterator_impl &x) const { return UI == x.UI; }
bool operator!=(const user_iterator_impl &x) const { return !operator==(x); }
- /// \brief Returns true if this iterator is equal to user_end() on the value.
+ /// Returns true if this iterator is equal to user_end() on the value.
bool atEnd() const { return *this == user_iterator_impl(); }
user_iterator_impl &operator++() { // Preincrement
@@ -218,17 +218,17 @@ public:
/// Delete a pointer to a generic Value.
void deleteValue();
- /// \brief Support for debugging, callable in GDB: V->dump()
+ /// Support for debugging, callable in GDB: V->dump()
void dump() const;
- /// \brief Implement operator<< on Value.
+ /// Implement operator<< on Value.
/// @{
void print(raw_ostream &O, bool IsForDebug = false) const;
void print(raw_ostream &O, ModuleSlotTracker &MST,
bool IsForDebug = false) const;
/// @}
- /// \brief Print the name of this Value out to the specified raw_ostream.
+ /// Print the name of this Value out to the specified raw_ostream.
///
/// This is useful when you just want to print 'int %reg126', not the
/// instruction that generated it. If you specify a Module for context, then
@@ -241,13 +241,13 @@ public:
ModuleSlotTracker &MST) const;
/// @}
- /// \brief All values are typed, get the type of this value.
+ /// All values are typed, get the type of this value.
Type *getType() const { return VTy; }
- /// \brief All values hold a context through their type.
+ /// All values hold a context through their type.
LLVMContext &getContext() const;
- // \brief All values can potentially be named.
+ // All values can potentially be named.
bool hasName() const { return HasName; }
ValueName *getValueName() const;
void setValueName(ValueName *VN);
@@ -258,35 +258,35 @@ private:
void setNameImpl(const Twine &Name);
public:
- /// \brief Return a constant reference to the value's name.
+ /// Return a constant reference to the value's name.
///
/// This guaranteed to return the same reference as long as the value is not
/// modified. If the value has a name, this does a hashtable lookup, so it's
/// not free.
StringRef getName() const;
- /// \brief Change the name of the value.
+ /// Change the name of the value.
///
/// Choose a new unique name if the provided name is taken.
///
/// \param Name The new name; or "" if the value's name should be removed.
void setName(const Twine &Name);
- /// \brief Transfer the name from V to this value.
+ /// Transfer the name from V to this value.
///
/// After taking V's name, sets V's name to empty.
///
/// \note It is an error to call V->takeName(V).
void takeName(Value *V);
- /// \brief Change all uses of this to point to a new Value.
+ /// Change all uses of this to point to a new Value.
///
/// Go through the uses list for this definition and make each use point to
/// "V" instead of "this". After this completes, 'this's use list is
/// guaranteed to be empty.
void replaceAllUsesWith(Value *V);
- /// \brief Change non-metadata uses of this to point to a new Value.
+ /// Change non-metadata uses of this to point to a new Value.
///
/// Go through the uses list for this definition and make each use point to
/// "V" instead of "this". This function skips metadata entries in the list.
@@ -299,12 +299,6 @@ public:
/// values or constant users.
void replaceUsesOutsideBlock(Value *V, BasicBlock *BB);
- /// replaceUsesExceptBlockAddr - 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 skips blockaddr uses.
- void replaceUsesExceptBlockAddr(Value *New);
-
//----------------------------------------------------------------------
// Methods for handling the chain of uses of this Value.
//
@@ -411,7 +405,7 @@ public:
return materialized_users();
}
- /// \brief Return true if there is exactly one user of this value.
+ /// Return true if there is exactly one user of this value.
///
/// This is specialized because it is a common request and does not require
/// traversing the whole use list.
@@ -421,27 +415,27 @@ public:
return ++I == E;
}
- /// \brief Return true if this Value has exactly N users.
+ /// Return true if this Value has exactly N users.
bool hasNUses(unsigned N) const;
- /// \brief Return true if this value has N users or more.
+ /// Return true if this value has N users or more.
///
/// This is logically equivalent to getNumUses() >= N.
bool hasNUsesOrMore(unsigned N) const;
- /// \brief Check if this value is used in the specified basic block.
+ /// Check if this value is used in the specified basic block.
bool isUsedInBasicBlock(const BasicBlock *BB) const;
- /// \brief This method computes the number of uses of this Value.
+ /// This method computes the number of uses of this Value.
///
/// This is a linear time operation. Use hasOneUse, hasNUses, or
/// hasNUsesOrMore to check for specific values.
unsigned getNumUses() const;
- /// \brief This method should only be used by the Use class.
+ /// This method should only be used by the Use class.
void addUse(Use &U) { U.addToList(&UseList); }
- /// \brief Concrete subclass of this.
+ /// Concrete subclass of this.
///
/// An enumeration for keeping track of the concrete subclass of Value that
/// is actually instantiated. Values of this enumeration are kept in the
@@ -456,7 +450,7 @@ public:
#include "llvm/IR/Value.def"
};
- /// \brief Return an ID for the concrete type of this object.
+ /// Return an ID for the concrete type of this object.
///
/// This is used to implement the classof checks. This should not be used
/// for any other purpose, as the values may change as LLVM evolves. Also,
@@ -470,36 +464,36 @@ public:
return SubclassID;
}
- /// \brief Return the raw optional flags value contained in this value.
+ /// Return the raw optional flags value contained in this value.
///
/// This should only be used when testing two Values for equivalence.
unsigned getRawSubclassOptionalData() const {
return SubclassOptionalData;
}
- /// \brief Clear the optional flags contained in this value.
+ /// Clear the optional flags contained in this value.
void clearSubclassOptionalData() {
SubclassOptionalData = 0;
}
- /// \brief Check the optional flags for equality.
+ /// Check the optional flags for equality.
bool hasSameSubclassOptionalData(const Value *V) const {
return SubclassOptionalData == V->SubclassOptionalData;
}
- /// \brief Return true if there is a value handle associated with this value.
+ /// 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.
+ /// Return true if there is metadata referencing this value.
bool isUsedByMetadata() const { return IsUsedByMD; }
- /// \brief Return true if this value is a swifterror value.
+ /// Return true if this value is a swifterror value.
///
/// swifterror values can be either a function argument or an alloca with a
/// swifterror attribute.
bool isSwiftError() const;
- /// \brief Strip off pointer casts, all-zero GEPs, and aliases.
+ /// Strip off pointer casts, all-zero GEPs, and aliases.
///
/// Returns the original uncasted value. If this is called on a non-pointer
/// value, it returns 'this'.
@@ -509,18 +503,19 @@ public:
static_cast<const Value *>(this)->stripPointerCasts());
}
- /// \brief Strip off pointer casts, all-zero GEPs, aliases and barriers.
+ /// Strip off pointer casts, all-zero GEPs, aliases and invariant group
+ /// info.
///
/// Returns the original uncasted value. If this is called on a non-pointer
/// value, it returns 'this'. This function should be used only in
/// Alias analysis.
- const Value *stripPointerCastsAndBarriers() const;
- Value *stripPointerCastsAndBarriers() {
+ const Value *stripPointerCastsAndInvariantGroups() const;
+ Value *stripPointerCastsAndInvariantGroups() {
return const_cast<Value *>(
- static_cast<const Value *>(this)->stripPointerCastsAndBarriers());
+ static_cast<const Value *>(this)->stripPointerCastsAndInvariantGroups());
}
- /// \brief Strip off pointer casts and all-zero GEPs.
+ /// Strip off pointer casts and all-zero GEPs.
///
/// Returns the original uncasted value. If this is called on a non-pointer
/// value, it returns 'this'.
@@ -530,7 +525,7 @@ public:
static_cast<const Value *>(this)->stripPointerCastsNoFollowAliases());
}
- /// \brief Strip off pointer casts and all-constant inbounds GEPs.
+ /// Strip off pointer casts and all-constant inbounds GEPs.
///
/// Returns the original pointer value. If this is called on a non-pointer
/// value, it returns 'this'.
@@ -540,7 +535,7 @@ public:
static_cast<const Value *>(this)->stripInBoundsConstantOffsets());
}
- /// \brief Accumulate offsets from \a stripInBoundsConstantOffsets().
+ /// Accumulate offsets from \a stripInBoundsConstantOffsets().
///
/// Stores the resulting constant offset stripped into the APInt provided.
/// The provided APInt will be extended or truncated as needed to be the
@@ -555,7 +550,7 @@ public:
->stripAndAccumulateInBoundsConstantOffsets(DL, Offset));
}
- /// \brief Strip off pointer casts and inbounds GEPs.
+ /// Strip off pointer casts and inbounds GEPs.
///
/// Returns the original pointer value. If this is called on a non-pointer
/// value, it returns 'this'.
@@ -565,7 +560,7 @@ public:
static_cast<const Value *>(this)->stripInBoundsOffsets());
}
- /// \brief Returns the number of bytes known to be dereferenceable for the
+ /// Returns the number of bytes known to be dereferenceable for the
/// pointer value.
///
/// If CanBeNull is set by this function the pointer can either be null or be
@@ -573,13 +568,13 @@ public:
uint64_t getPointerDereferenceableBytes(const DataLayout &DL,
bool &CanBeNull) const;
- /// \brief Returns an alignment of the pointer value.
+ /// Returns an alignment of the pointer value.
///
/// Returns an alignment which is either specified explicitly, e.g. via
/// align attribute of a function argument, or guaranteed by DataLayout.
unsigned getPointerAlignment(const DataLayout &DL) const;
- /// \brief Translate PHI node to its predecessor from the given basic block.
+ /// Translate PHI node to its predecessor from the given basic block.
///
/// If this value is a PHI node with CurBB as its parent, return the value in
/// the PHI node corresponding to PredBB. If not, return ourself. This is
@@ -592,14 +587,14 @@ public:
static_cast<const Value *>(this)->DoPHITranslation(CurBB, PredBB));
}
- /// \brief The maximum alignment for instructions.
+ /// The maximum alignment for instructions.
///
/// This is the greatest alignment value supported by load, store, and alloca
/// instructions, and global values.
static const unsigned MaxAlignmentExponent = 29;
static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent;
- /// \brief Mutate the type of this Value to be of the specified type.
+ /// Mutate the type of this Value to be of the specified type.
///
/// Note that this is an extremely dangerous operation which can create
/// completely invalid IR very easily. It is strongly recommended that you
@@ -609,17 +604,17 @@ public:
VTy = Ty;
}
- /// \brief Sort the use-list.
+ /// Sort the use-list.
///
/// Sorts the Value's use-list by Cmp using a stable mergesort. Cmp is
/// expected to compare two \a Use references.
template <class Compare> void sortUseList(Compare Cmp);
- /// \brief Reverse the use-list.
+ /// Reverse the use-list.
void reverseUseList();
private:
- /// \brief Merge two lists together.
+ /// Merge two lists together.
///
/// Merges \c L and \c R using \c Cmp. To enable stable sorts, always pushes
/// "equal" items from L before items from R.
diff --git a/contrib/llvm/include/llvm/IR/ValueHandle.h b/contrib/llvm/include/llvm/IR/ValueHandle.h
index b45cc7b6dc02..d94472ce1be1 100644
--- a/contrib/llvm/include/llvm/IR/ValueHandle.h
+++ b/contrib/llvm/include/llvm/IR/ValueHandle.h
@@ -22,7 +22,7 @@
namespace llvm {
-/// \brief This is the common base class of value handles.
+/// This is the common base class of value handles.
///
/// ValueHandle's are smart pointers to Value's that have special behavior when
/// the value is deleted or ReplaceAllUsesWith'd. See the specific handles
@@ -31,7 +31,7 @@ class ValueHandleBase {
friend class Value;
protected:
- /// \brief This indicates what sub class the handle actually is.
+ /// This indicates what sub class the handle actually is.
///
/// This is to avoid having a vtable for the light-weight handle pointers. The
/// fully general Callback version does have a vtable.
@@ -101,10 +101,10 @@ protected:
V != DenseMapInfo<Value *>::getTombstoneKey();
}
- /// \brief Remove this ValueHandle from its current use list.
+ /// Remove this ValueHandle from its current use list.
void RemoveFromUseList();
- /// \brief Clear the underlying pointer without clearing the use list.
+ /// Clear the underlying pointer without clearing the use list.
///
/// This should only be used if a derived class has manually removed the
/// handle from the use list.
@@ -121,20 +121,20 @@ private:
HandleBaseKind getKind() const { return PrevPair.getInt(); }
void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); }
- /// \brief Add this ValueHandle to the use list for V.
+ /// 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.
void AddToExistingUseList(ValueHandleBase **List);
- /// \brief Add this ValueHandle to the use list after Node.
+ /// Add this ValueHandle to the use list after Node.
void AddToExistingUseListAfter(ValueHandleBase *Node);
- /// \brief Add this ValueHandle to the use list for V.
+ /// Add this ValueHandle to the use list for V.
void AddToUseList();
};
-/// \brief A nullable Value handle that is nullable.
+/// A nullable Value handle that is nullable.
///
/// This is a value handle that points to a value, and nulls itself
/// out if that value is deleted.
@@ -172,7 +172,7 @@ template <> struct simplify_type<const WeakVH> {
static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; }
};
-/// \brief Value handle that is nullable, but tries to track the Value.
+/// Value handle that is nullable, but tries to track the Value.
///
/// This is a value handle that tries hard to point to a Value, even across
/// RAUW operations, but will null itself out if the value is destroyed. this
@@ -219,7 +219,7 @@ template <> struct simplify_type<const WeakTrackingVH> {
}
};
-/// \brief Value handle that asserts if the Value is deleted.
+/// Value handle that asserts if the Value is deleted.
///
/// This is a Value Handle that points to a value and asserts out if the value
/// is destroyed while the handle is still live. This is very useful for
@@ -318,7 +318,7 @@ struct isPodLike<AssertingVH<T>> {
#endif
};
-/// \brief Value handle that tracks a Value across RAUW.
+/// Value handle that tracks a Value across RAUW.
///
/// TrackingVH is designed for situations where a client needs to hold a handle
/// to a Value (or subclass) across some operations which may move that value,
@@ -379,7 +379,7 @@ public:
ValueTy &operator*() const { return *getValPtr(); }
};
-/// \brief Value handle with callbacks on RAUW and destruction.
+/// Value handle with callbacks on RAUW and destruction.
///
/// This is a value handle that allows subclasses to define callbacks that run
/// when the underlying Value has RAUW called on it or is destroyed. This
@@ -405,7 +405,7 @@ public:
return getValPtr();
}
- /// \brief Callback for Value destruction.
+ /// Callback for Value destruction.
///
/// Called when this->getValPtr() is destroyed, inside ~Value(), so you
/// may call any non-virtual Value method on getValPtr(), but no subclass
@@ -418,7 +418,7 @@ public:
/// Value that's being destroyed.
virtual void deleted() { setValPtr(nullptr); }
- /// \brief Callback for Value RAUW.
+ /// Callback for Value RAUW.
///
/// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called,
/// _before_ any of the uses have actually been replaced. If WeakTrackingVH
diff --git a/contrib/llvm/include/llvm/IR/ValueMap.h b/contrib/llvm/include/llvm/IR/ValueMap.h
index 11d5823ee479..e7e33918a613 100644
--- a/contrib/llvm/include/llvm/IR/ValueMap.h
+++ b/contrib/llvm/include/llvm/IR/ValueMap.h
@@ -106,8 +106,12 @@ public:
: Map(NumInitBuckets), Data() {}
explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64)
: Map(NumInitBuckets), Data(Data) {}
+ // ValueMap can't be copied nor moved, beucase the callbacks store pointer
+ // to it.
ValueMap(const ValueMap &) = delete;
+ ValueMap(ValueMap &&) = delete;
ValueMap &operator=(const ValueMap &) = delete;
+ ValueMap &operator=(ValueMap &&) = delete;
bool hasMD() const { return bool(MDMap); }
MDMapT &MD() {
diff --git a/contrib/llvm/include/llvm/IR/ValueSymbolTable.h b/contrib/llvm/include/llvm/IR/ValueSymbolTable.h
index 26cbbfabfc0c..012e717c7470 100644
--- a/contrib/llvm/include/llvm/IR/ValueSymbolTable.h
+++ b/contrib/llvm/include/llvm/IR/ValueSymbolTable.h
@@ -48,13 +48,13 @@ class ValueSymbolTable {
/// @name Types
/// @{
public:
- /// @brief A mapping of names to values.
+ /// A mapping of names to values.
using ValueMap = StringMap<Value*>;
- /// @brief An iterator over a ValueMap.
+ /// An iterator over a ValueMap.
using iterator = ValueMap::iterator;
- /// @brief A const_iterator over a ValueMap.
+ /// A const_iterator over a ValueMap.
using const_iterator = ValueMap::const_iterator;
/// @}
@@ -71,35 +71,35 @@ public:
/// This method finds the value with the given \p Name in the
/// the symbol table.
/// @returns the value associated with the \p Name
- /// @brief Lookup a named Value.
+ /// Lookup a named Value.
Value *lookup(StringRef Name) const { return vmap.lookup(Name); }
/// @returns true iff the symbol table is empty
- /// @brief Determine if the symbol table is empty
+ /// Determine if the symbol table is empty
inline bool empty() const { return vmap.empty(); }
- /// @brief The number of name/type pairs is returned.
+ /// The number of name/type pairs is returned.
inline unsigned size() const { return unsigned(vmap.size()); }
/// This function can be used from the debugger to display the
/// content of the symbol table while debugging.
- /// @brief Print out symbol table on stderr
+ /// Print out symbol table on stderr
void dump() const;
/// @}
/// @name Iteration
/// @{
- /// @brief Get an iterator that from the beginning of the symbol table.
+ /// Get an iterator that from the beginning of the symbol table.
inline iterator begin() { return vmap.begin(); }
- /// @brief Get a const_iterator that from the beginning of the symbol table.
+ /// Get a const_iterator that from the beginning of the symbol table.
inline const_iterator begin() const { return vmap.begin(); }
- /// @brief Get an iterator to the end of the symbol table.
+ /// Get an iterator to the end of the symbol table.
inline iterator end() { return vmap.end(); }
- /// @brief Get a const_iterator to the end of the symbol table.
+ /// Get a const_iterator to the end of the symbol table.
inline const_iterator end() const { return vmap.end(); }
/// @}
@@ -111,7 +111,7 @@ private:
/// This method adds the provided value \p N to the symbol table. The Value
/// must have a name which is used to place the value in the symbol table.
/// If the inserted name conflicts, this renames the value.
- /// @brief Add a named value to the symbol table
+ /// Add a named value to the symbol table
void reinsertValue(Value *V);
/// createValueName - This method attempts to create a value name and insert
diff --git a/contrib/llvm/include/llvm/IR/Verifier.h b/contrib/llvm/include/llvm/IR/Verifier.h
index bc10f330bc8a..7255132e1e65 100644
--- a/contrib/llvm/include/llvm/IR/Verifier.h
+++ b/contrib/llvm/include/llvm/IR/Verifier.h
@@ -80,7 +80,7 @@ public:
bool visitTBAAMetadata(Instruction &I, const MDNode *MD);
};
-/// \brief Check a function for errors, useful for use when debugging a
+/// Check a function for errors, useful for use when debugging a
/// pass.
///
/// If there are no errors, the function returns false. If an error is found,
@@ -88,7 +88,7 @@ public:
/// returned.
bool verifyFunction(const Function &F, raw_ostream *OS = nullptr);
-/// \brief Check a module for errors.
+/// Check a module for errors.
///
/// If there are no errors, the function returns false. If an error is
/// found, a message describing the error is written to OS (if
@@ -124,7 +124,7 @@ public:
/// "recovered" from by stripping the debug info.
bool verifyModule(bool &BrokenDebugInfo, const Module &M, raw_ostream *OS);
-/// \brief Create a verifier pass.
+/// Create a verifier pass.
///
/// Check a module or function for validity. This is essentially a pass wrapped
/// around the above verifyFunction and verifyModule routines and
diff --git a/contrib/llvm/include/llvm/IRReader/IRReader.h b/contrib/llvm/include/llvm/IRReader/IRReader.h
index f5621647db06..bedde8954fbb 100644
--- a/contrib/llvm/include/llvm/IRReader/IRReader.h
+++ b/contrib/llvm/include/llvm/IRReader/IRReader.h
@@ -15,6 +15,7 @@
#ifndef LLVM_IRREADER_IRREADER_H
#define LLVM_IRREADER_IRREADER_H
+#include "llvm/ADT/StringRef.h"
#include <memory>
namespace llvm {
@@ -40,9 +41,11 @@ getLazyIRFileModule(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context,
/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier.
/// This option should only be set to false by llvm-as
/// for use inside the LLVM testuite!
+/// \param DataLayoutString Override datalayout in the llvm assembly.
std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err,
LLVMContext &Context,
- bool UpgradeDebugInfo = true);
+ bool UpgradeDebugInfo = true,
+ StringRef DataLayoutString = "");
/// If the given file holds a bitcode image, return a Module for it.
/// Otherwise, attempt to parse it as LLVM Assembly and return a Module
@@ -50,9 +53,11 @@ std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err,
/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier.
/// This option should only be set to false by llvm-as
/// for use inside the LLVM testuite!
+/// \param DataLayoutString Override datalayout in the llvm assembly.
std::unique_ptr<Module> parseIRFile(StringRef Filename, SMDiagnostic &Err,
LLVMContext &Context,
- bool UpgradeDebugInfo = true);
+ bool UpgradeDebugInfo = true,
+ StringRef DataLayoutString = "");
}
#endif
diff --git a/contrib/llvm/include/llvm/InitializePasses.h b/contrib/llvm/include/llvm/InitializePasses.h
index 4c79333f5d2e..d67b1d48f274 100644
--- a/contrib/llvm/include/llvm/InitializePasses.h
+++ b/contrib/llvm/include/llvm/InitializePasses.h
@@ -37,6 +37,9 @@ void initializeVectorization(PassRegistry&);
/// Initialize all passes linked into the InstCombine library.
void initializeInstCombine(PassRegistry&);
+/// Initialize all passes linked into the AggressiveInstCombine library.
+void initializeAggressiveInstCombine(PassRegistry&);
+
/// Initialize all passes linked into the IPO library.
void initializeIPO(PassRegistry&);
@@ -64,6 +67,7 @@ void initializeADCELegacyPassPass(PassRegistry&);
void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&);
void initializeAddressSanitizerModulePass(PassRegistry&);
void initializeAddressSanitizerPass(PassRegistry&);
+void initializeAggressiveInstCombinerLegacyPassPass(PassRegistry&);
void initializeAliasSetPrinterPass(PassRegistry&);
void initializeAlignmentFromAssumptionsPass(PassRegistry&);
void initializeAlwaysInlinerLegacyPassPass(PassRegistry&);
@@ -73,34 +77,34 @@ void initializeAtomicExpandPass(PassRegistry&);
void initializeBDCELegacyPassPass(PassRegistry&);
void initializeBarrierNoopPass(PassRegistry&);
void initializeBasicAAWrapperPassPass(PassRegistry&);
-void initializeBlockExtractorPassPass(PassRegistry&);
+void initializeBlockExtractorPass(PassRegistry &);
void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&);
void initializeBoundsCheckingLegacyPassPass(PassRegistry&);
void initializeBranchFolderPassPass(PassRegistry&);
void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&);
void initializeBranchRelaxationPass(PassRegistry&);
void initializeBreakCriticalEdgesPass(PassRegistry&);
-void initializeCallSiteSplittingLegacyPassPass(PassRegistry&);
+void initializeBreakFalseDepsPass(PassRegistry&);
void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry&);
void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&);
void initializeCFGPrinterLegacyPassPass(PassRegistry&);
void initializeCFGSimplifyPassPass(PassRegistry&);
void initializeCFGViewerLegacyPassPass(PassRegistry&);
+void initializeCFIInstrInserterPass(PassRegistry&);
void initializeCFLAndersAAWrapperPassPass(PassRegistry&);
void initializeCFLSteensAAWrapperPassPass(PassRegistry&);
void initializeCallGraphDOTPrinterPass(PassRegistry&);
void initializeCallGraphPrinterLegacyPassPass(PassRegistry&);
void initializeCallGraphViewerPass(PassRegistry&);
void initializeCallGraphWrapperPassPass(PassRegistry&);
+void initializeCallSiteSplittingLegacyPassPass(PassRegistry&);
+void initializeCalledValuePropagationLegacyPassPass(PassRegistry &);
void initializeCodeGenPreparePass(PassRegistry&);
void initializeConstantHoistingLegacyPassPass(PassRegistry&);
-void initializeCalledValuePropagationLegacyPassPass(PassRegistry &);
void initializeConstantMergeLegacyPassPass(PassRegistry&);
void initializeConstantPropagationPass(PassRegistry&);
void initializeCorrelatedValuePropagationPass(PassRegistry&);
void initializeCostModelAnalysisPass(PassRegistry&);
-void initializeEntryExitInstrumenterPass(PassRegistry&);
-void initializePostInlineEntryExitInstrumenterPass(PassRegistry&);
void initializeCrossDSOCFIPass(PassRegistry&);
void initializeDAEPass(PassRegistry&);
void initializeDAHPass(PassRegistry&);
@@ -114,8 +118,8 @@ void initializeDemandedBitsWrapperPassPass(PassRegistry&);
void initializeDependenceAnalysisPass(PassRegistry&);
void initializeDependenceAnalysisWrapperPassPass(PassRegistry&);
void initializeDetectDeadLanesPass(PassRegistry&);
-void initializeDivergenceAnalysisPass(PassRegistry&);
void initializeDivRemPairsLegacyPassPass(PassRegistry&);
+void initializeDivergenceAnalysisPass(PassRegistry&);
void initializeDomOnlyPrinterPass(PassRegistry&);
void initializeDomOnlyViewerPass(PassRegistry&);
void initializeDomPrinterPass(PassRegistry&);
@@ -126,9 +130,12 @@ void initializeDwarfEHPreparePass(PassRegistry&);
void initializeEarlyCSELegacyPassPass(PassRegistry&);
void initializeEarlyCSEMemSSALegacyPassPass(PassRegistry&);
void initializeEarlyIfConverterPass(PassRegistry&);
+void initializeEarlyMachineLICMPass(PassRegistry&);
+void initializeEarlyTailDuplicatePass(PassRegistry&);
void initializeEdgeBundlesPass(PassRegistry&);
void initializeEfficiencySanitizerPass(PassRegistry&);
void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry&);
+void initializeEntryExitInstrumenterPass(PassRegistry&);
void initializeExpandISelPseudosPass(PassRegistry&);
void initializeExpandMemCmpPassPass(PassRegistry&);
void initializeExpandPostRAPass(PassRegistry&);
@@ -154,21 +161,22 @@ void initializeGlobalOptLegacyPassPass(PassRegistry&);
void initializeGlobalSplitPass(PassRegistry&);
void initializeGlobalsAAWrapperPassPass(PassRegistry&);
void initializeGuardWideningLegacyPassPass(PassRegistry&);
+void initializeHWAddressSanitizerPass(PassRegistry&);
void initializeIPCPPass(PassRegistry&);
void initializeIPSCCPLegacyPassPass(PassRegistry&);
+void initializeIRCELegacyPassPass(PassRegistry&);
void initializeIRTranslatorPass(PassRegistry&);
void initializeIVUsersWrapperPassPass(PassRegistry&);
void initializeIfConverterPass(PassRegistry&);
void initializeImplicitNullChecksPass(PassRegistry&);
void initializeIndVarSimplifyLegacyPassPass(PassRegistry&);
void initializeIndirectBrExpandPassPass(PassRegistry&);
-void initializeInductiveRangeCheckEliminationPass(PassRegistry&);
void initializeInferAddressSpacesPass(PassRegistry&);
void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&);
void initializeInlineCostAnalysisPass(PassRegistry&);
void initializeInstCountPass(PassRegistry&);
void initializeInstNamerPass(PassRegistry&);
-void initializeInstSimplifierPass(PassRegistry&);
+void initializeInstSimplifyLegacyPassPass(PassRegistry &);
void initializeInstrProfilingLegacyPassPass(PassRegistry&);
void initializeInstructionCombiningPassPass(PassRegistry&);
void initializeInstructionSelectPass(PassRegistry&);
@@ -204,6 +212,7 @@ void initializeLoopDataPrefetchLegacyPassPass(PassRegistry&);
void initializeLoopDeletionLegacyPassPass(PassRegistry&);
void initializeLoopDistributeLegacyPass(PassRegistry&);
void initializeLoopExtractorPass(PassRegistry&);
+void initializeLoopGuardWideningLegacyPassPass(PassRegistry&);
void initializeLoopIdiomRecognizeLegacyPassPass(PassRegistry&);
void initializeLoopInfoWrapperPassPass(PassRegistry&);
void initializeLoopInstSimplifyLegacyPassPass(PassRegistry&);
@@ -216,6 +225,7 @@ void initializeLoopRotateLegacyPassPass(PassRegistry&);
void initializeLoopSimplifyCFGLegacyPassPass(PassRegistry&);
void initializeLoopSimplifyPass(PassRegistry&);
void initializeLoopStrengthReducePass(PassRegistry&);
+void initializeLoopUnrollAndJamPass(PassRegistry&);
void initializeLoopUnrollPass(PassRegistry&);
void initializeLoopUnswitchPass(PassRegistry&);
void initializeLoopVectorizePass(PassRegistry&);
@@ -229,6 +239,7 @@ void initializeLowerIntrinsicsPass(PassRegistry&);
void initializeLowerInvokeLegacyPassPass(PassRegistry&);
void initializeLowerSwitchPass(PassRegistry&);
void initializeLowerTypeTestsPass(PassRegistry&);
+void initializeMIRCanonicalizerPass(PassRegistry &);
void initializeMIRPrintingPassPass(PassRegistry&);
void initializeMachineBlockFrequencyInfoPass(PassRegistry&);
void initializeMachineBlockPlacementPass(PassRegistry&);
@@ -265,6 +276,7 @@ void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry&);
void initializeMetaRenamerPass(PassRegistry&);
void initializeModuleDebugInfoPrinterPass(PassRegistry&);
void initializeModuleSummaryIndexWrapperPassPass(PassRegistry&);
+void initializeMustExecutePrinterPass(PassRegistry&);
void initializeNameAnonGlobalLegacyPassPass(PassRegistry&);
void initializeNaryReassociateLegacyPassPass(PassRegistry&);
void initializeNewGVNLegacyPassPass(PassRegistry&);
@@ -286,6 +298,7 @@ void initializePartialInlinerLegacyPassPass(PassRegistry&);
void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry&);
void initializePatchableFunctionPass(PassRegistry&);
void initializePeepholeOptimizerPass(PassRegistry&);
+void initializePhiValuesWrapperPassPass(PassRegistry&);
void initializePhysicalRegisterUsageInfoPass(PassRegistry&);
void initializePlaceBackedgeSafepointsImplPass(PassRegistry&);
void initializePlaceSafepointsPass(PassRegistry&);
@@ -294,9 +307,11 @@ void initializePostDomOnlyViewerPass(PassRegistry&);
void initializePostDomPrinterPass(PassRegistry&);
void initializePostDomViewerPass(PassRegistry&);
void initializePostDominatorTreeWrapperPassPass(PassRegistry&);
+void initializePostInlineEntryExitInstrumenterPass(PassRegistry&);
void initializePostMachineSchedulerPass(PassRegistry&);
void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
void initializePostRAHazardRecognizerPass(PassRegistry&);
+void initializePostRAMachineSinkingPass(PassRegistry&);
void initializePostRASchedulerPass(PassRegistry&);
void initializePreISelIntrinsicLoweringLegacyPassPass(PassRegistry&);
void initializePredicateInfoPrinterLegacyPassPass(PassRegistry&);
@@ -308,11 +323,14 @@ void initializeProfileSummaryInfoWrapperPassPass(PassRegistry&);
void initializePromoteLegacyPassPass(PassRegistry&);
void initializePruneEHPass(PassRegistry&);
void initializeRABasicPass(PassRegistry&);
-void initializeRegAllocFastPass(PassRegistry&);
void initializeRAGreedyPass(PassRegistry&);
+void initializeReachingDefAnalysisPass(PassRegistry&);
void initializeReassociateLegacyPassPass(PassRegistry&);
+void initializeRegAllocFastPass(PassRegistry&);
void initializeRegBankSelectPass(PassRegistry&);
void initializeRegToMemPass(PassRegistry&);
+void initializeRegUsageInfoCollectorPass(PassRegistry&);
+void initializeRegUsageInfoPropagationPass(PassRegistry&);
void initializeRegionInfoPassPass(PassRegistry&);
void initializeRegionOnlyPrinterPass(PassRegistry&);
void initializeRegionOnlyViewerPass(PassRegistry&);
@@ -324,12 +342,12 @@ void initializeResetMachineFunctionPass(PassRegistry&);
void initializeReversePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
void initializeRewriteStatepointsForGCLegacyPassPass(PassRegistry &);
void initializeRewriteSymbolsLegacyPassPass(PassRegistry&);
-void initializeSafepointIRVerifierPass(PassRegistry&);
void initializeSCCPLegacyPassPass(PassRegistry&);
void initializeSCEVAAWrapperPassPass(PassRegistry&);
void initializeSLPVectorizerPass(PassRegistry&);
void initializeSROALegacyPassPass(PassRegistry&);
void initializeSafeStackLegacyPassPass(PassRegistry&);
+void initializeSafepointIRVerifierPass(PassRegistry&);
void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&);
void initializeSanitizerCoverageModulePass(PassRegistry&);
void initializeScalarEvolutionWrapperPassPass(PassRegistry&);
@@ -361,9 +379,8 @@ void initializeStripNonDebugSymbolsPass(PassRegistry&);
void initializeStripNonLineTableDebugInfoPass(PassRegistry&);
void initializeStripSymbolsPass(PassRegistry&);
void initializeStructurizeCFGPass(PassRegistry&);
-void initializeHWAddressSanitizerPass(PassRegistry&);
void initializeTailCallElimPass(PassRegistry&);
-void initializeTailDuplicatePassPass(PassRegistry&);
+void initializeTailDuplicatePass(PassRegistry&);
void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&);
void initializeTargetPassConfigPass(PassRegistry&);
void initializeTargetTransformInfoWrapperPassPass(PassRegistry&);
@@ -377,12 +394,12 @@ void initializeUnreachableMachineBlockElimPass(PassRegistry&);
void initializeVerifierLegacyPassPass(PassRegistry&);
void initializeVirtRegMapPass(PassRegistry&);
void initializeVirtRegRewriterPass(PassRegistry&);
+void initializeWasmEHPreparePass(PassRegistry&);
void initializeWholeProgramDevirtPass(PassRegistry&);
void initializeWinEHPreparePass(PassRegistry&);
void initializeWriteBitcodePassPass(PassRegistry&);
void initializeWriteThinLTOBitcodePass(PassRegistry&);
void initializeXRayInstrumentationPass(PassRegistry&);
-void initializeMIRCanonicalizerPass(PassRegistry &);
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/LTO/Caching.h b/contrib/llvm/include/llvm/LTO/Caching.h
index 25c719a68b92..7201ab31f5b0 100644
--- a/contrib/llvm/include/llvm/LTO/Caching.h
+++ b/contrib/llvm/include/llvm/LTO/Caching.h
@@ -24,13 +24,8 @@ namespace lto {
/// This type defines the callback to add a pre-existing native object file
/// (e.g. in a cache).
///
-/// Path is generally expected to be a valid path for the file at the point when
-/// the AddBufferFn function is called, but clients should prefer to access MB
-/// directly in order to avoid a potential race condition.
-///
/// Buffer callbacks must be thread safe.
-typedef std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB,
- StringRef Path)>
+typedef std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB)>
AddBufferFn;
/// Create a local file system cache which uses the given cache directory and
diff --git a/contrib/llvm/include/llvm/LTO/Config.h b/contrib/llvm/include/llvm/LTO/Config.h
index 4bd981c090b1..57bba5e34840 100644
--- a/contrib/llvm/include/llvm/LTO/Config.h
+++ b/contrib/llvm/include/llvm/LTO/Config.h
@@ -73,6 +73,14 @@ struct Config {
/// Sample PGO profile path.
std::string SampleProfile;
+ /// The directory to store .dwo files.
+ std::string DwoDir;
+
+ /// The path to write a .dwo file to. This should generally only be used when
+ /// running an individual backend directly via thinBackend(), as otherwise
+ /// all .dwo files will be written to the same path.
+ std::string DwoPath;
+
/// Optimization remarks file path.
std::string RemarksFilename = "";
@@ -82,6 +90,9 @@ struct Config {
/// Whether to emit the pass manager debuggging informations.
bool DebugPassManager = false;
+ /// Statistics output file path.
+ std::string StatsFile;
+
bool ShouldDiscardValueNames = true;
DiagnosticHandlerFunction DiagHandler;
diff --git a/contrib/llvm/include/llvm/LTO/LTO.h b/contrib/llvm/include/llvm/LTO/LTO.h
index 2a2b59847281..7d6beab6b441 100644
--- a/contrib/llvm/include/llvm/LTO/LTO.h
+++ b/contrib/llvm/include/llvm/LTO/LTO.h
@@ -19,7 +19,6 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/Analysis/ObjectUtils.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/LTO/Config.h"
@@ -210,10 +209,16 @@ ThinBackend createInProcessThinBackend(unsigned ParallelismLevel);
/// appends ".thinlto.bc" and writes the index to that path. If
/// ShouldEmitImportsFiles is true it also writes a list of imported files to a
/// similar path with ".imports" appended instead.
+/// LinkedObjectsFile is an output stream to write the list of object files for
+/// the final ThinLTO linking. Can be nullptr.
+/// OnWrite is callback which receives module identifier and notifies LTO user
+/// that index file for the module (and optionally imports file) was created.
+using IndexWriteCallback = std::function<void(const std::string &)>;
ThinBackend createWriteIndexesThinBackend(std::string OldPrefix,
std::string NewPrefix,
bool ShouldEmitImportsFiles,
- std::string LinkedObjectsFile);
+ raw_fd_ostream *LinkedObjectsFile,
+ IndexWriteCallback OnWrite);
/// This class implements a resolution-based interface to LLVM's LTO
/// functionality. It supports regular LTO, parallel LTO code generation and
@@ -320,6 +325,14 @@ private:
bool UnnamedAddr = true;
+ /// True if module contains the prevailing definition.
+ bool Prevailing = false;
+
+ /// Returns true if module contains the prevailing definition and symbol is
+ /// an IR symbol. For example when module-level inline asm block is used,
+ /// symbol can be prevailing in module but have no IR name.
+ bool isPrevailingIRSymbol() const { return Prevailing && !IRName.empty(); }
+
/// This field keeps track of the partition number of this global. The
/// regular LTO object is partition 0, while each ThinLTO object has its own
/// partition number from 1 onwards.
diff --git a/contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
index d794535700e5..b32a972542c8 100644
--- a/contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
+++ b/contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
@@ -131,7 +131,8 @@ public:
* To avoid filling the disk space, a few knobs are provided:
* - The pruning interval limit the frequency at which the garbage collector
* will try to scan the cache directory to prune it from expired entries.
- * Setting to -1 disable the pruning (default).
+ * Setting to -1 disable the pruning (default). Setting to 0 will force
+ * pruning to occur.
* - The pruning expiration time indicates to the garbage collector how old
* an entry needs to be to be removed.
* - Finally, the garbage collector can be instructed to prune the cache till
@@ -149,10 +150,9 @@ public:
void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); }
/// Cache policy: interval (seconds) between two prunes of the cache. Set to a
- /// negative value to disable pruning. A value of 0 will be ignored.
+ /// negative value to disable pruning. A value of 0 will force pruning to
+ /// occur.
void setCachePruningInterval(int Interval) {
- if (Interval == 0)
- return;
if(Interval < 0)
CacheOptions.Policy.Interval.reset();
else
@@ -168,8 +168,8 @@ public:
/**
* Sets the maximum cache size that can be persistent across build, in terms
- * of percentage of the available space on the the disk. Set to 100 to
- * indicate no limit, 50 to indicate that the cache size will not be left over
+ * of percentage of the available space on the disk. Set to 100 to indicate
+ * no limit, 50 to indicate that the cache size will not be left over
* half the available space. A value over 100 will be reduced to 100, and a
* value of 0 will be ignored.
*
@@ -184,6 +184,21 @@ public:
CacheOptions.Policy.MaxSizePercentageOfAvailableSpace = Percentage;
}
+ /// Cache policy: the maximum size for the cache directory in bytes. A value
+ /// over the amount of available space on the disk will be reduced to the
+ /// amount of available space. A value of 0 will be ignored.
+ void setCacheMaxSizeBytes(unsigned MaxSizeBytes) {
+ if (MaxSizeBytes)
+ CacheOptions.Policy.MaxSizeBytes = MaxSizeBytes;
+ }
+
+ /// Cache policy: the maximum number of files in the cache directory. A value
+ /// of 0 will be ignored.
+ void setCacheMaxSizeFiles(unsigned MaxSizeFiles) {
+ if (MaxSizeFiles)
+ CacheOptions.Policy.MaxSizeFiles = MaxSizeFiles;
+ }
+
/**@}*/
/// Set the path to a directory where to save temporaries at various stages of
diff --git a/contrib/llvm/include/llvm/LinkAllPasses.h b/contrib/llvm/include/llvm/LinkAllPasses.h
index 39d1ec6cffb5..bd432c58b613 100644
--- a/contrib/llvm/include/llvm/LinkAllPasses.h
+++ b/contrib/llvm/include/llvm/LinkAllPasses.h
@@ -39,14 +39,18 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/Support/Valgrind.h"
+#include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include "llvm/Transforms/IPO/FunctionAttrs.h"
+#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
+#include "llvm/Transforms/Scalar/InstSimplifyPass.h"
+#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/SymbolRewriter.h"
#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
#include "llvm/Transforms/Vectorize.h"
@@ -64,6 +68,7 @@ namespace {
(void) llvm::createAAEvalPass();
(void) llvm::createAggressiveDCEPass();
+ (void) llvm::createAggressiveInstCombinerPass();
(void) llvm::createBitTrackingDCEPass();
(void) llvm::createArgumentPromotionPass();
(void) llvm::createAlignmentFromAssumptionsPass();
@@ -107,10 +112,12 @@ namespace {
(void) llvm::createGlobalOptimizerPass();
(void) llvm::createGlobalsAAWrapperPass();
(void) llvm::createGuardWideningPass();
+ (void) llvm::createLoopGuardWideningPass();
(void) llvm::createIPConstantPropagationPass();
(void) llvm::createIPSCCPPass();
(void) llvm::createInductiveRangeCheckEliminationPass();
(void) llvm::createIndVarSimplifyPass();
+ (void) llvm::createInstSimplifyLegacyPass();
(void) llvm::createInstructionCombiningPass();
(void) llvm::createInternalizePass();
(void) llvm::createLCSSAPass();
@@ -125,6 +132,7 @@ namespace {
(void) llvm::createLoopStrengthReducePass();
(void) llvm::createLoopRerollPass();
(void) llvm::createLoopUnrollPass();
+ (void) llvm::createLoopUnrollAndJamPass();
(void) llvm::createLoopUnswitchPass();
(void) llvm::createLoopVersioningLICMPass();
(void) llvm::createLoopIdiomPass();
@@ -195,7 +203,6 @@ namespace {
(void) llvm::createLowerAtomicPass();
(void) llvm::createCorrelatedValuePropagationPass();
(void) llvm::createMemDepPrinter();
- (void) llvm::createInstructionSimplifierPass();
(void) llvm::createLoopVectorizePass();
(void) llvm::createSLPVectorizerPass();
(void) llvm::createLoadStoreVectorizerPass();
@@ -207,6 +214,7 @@ namespace {
(void) llvm::createRewriteSymbolsPass();
(void) llvm::createStraightLineStrengthReducePass();
(void) llvm::createMemDerefPrinter();
+ (void) llvm::createMustExecutePrinter();
(void) llvm::createFloat2IntPass();
(void) llvm::createEliminateAvailableExternallyPass();
(void) llvm::createScalarizeMaskedMemIntrinPass();
diff --git a/contrib/llvm/include/llvm/Linker/Linker.h b/contrib/llvm/include/llvm/Linker/Linker.h
index 628e0112bd9d..7776c720ec53 100644
--- a/contrib/llvm/include/llvm/Linker/Linker.h
+++ b/contrib/llvm/include/llvm/Linker/Linker.h
@@ -34,7 +34,7 @@ public:
Linker(Module &M);
- /// \brief Link \p Src into the composite.
+ /// Link \p Src into the composite.
///
/// Passing OverrideSymbols as true will have symbols from Src
/// shadow those in the Dest.
diff --git a/contrib/llvm/include/llvm/MC/MCAsmBackend.h b/contrib/llvm/include/llvm/MC/MCAsmBackend.h
index ef2007ff6920..030d3c05aa5a 100644
--- a/contrib/llvm/include/llvm/MC/MCAsmBackend.h
+++ b/contrib/llvm/include/llvm/MC/MCAsmBackend.h
@@ -16,6 +16,7 @@
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCFragment.h"
+#include "llvm/Support/Endian.h"
#include <cstdint>
#include <memory>
@@ -29,6 +30,7 @@ struct MCFixupKindInfo;
class MCFragment;
class MCInst;
class MCObjectStreamer;
+class MCObjectTargetWriter;
class MCObjectWriter;
struct MCCodePaddingContext;
class MCRelaxableFragment;
@@ -41,21 +43,31 @@ class MCAsmBackend {
std::unique_ptr<MCCodePadder> CodePadder;
protected: // Can only create subclasses.
- MCAsmBackend();
- MCAsmBackend(std::unique_ptr<MCCodePadder> TargetCodePadder);
+ MCAsmBackend(support::endianness Endian);
public:
MCAsmBackend(const MCAsmBackend &) = delete;
MCAsmBackend &operator=(const MCAsmBackend &) = delete;
virtual ~MCAsmBackend();
+ const support::endianness Endian;
+
/// lifetime management
virtual void reset() {}
/// Create a new MCObjectWriter instance for use by the assembler backend to
/// emit the final object file.
- virtual std::unique_ptr<MCObjectWriter>
- createObjectWriter(raw_pwrite_stream &OS) const = 0;
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const;
+
+ /// Create an MCObjectWriter that writes two object files: a .o file which is
+ /// linked into the final program and a .dwo file which is used by debuggers.
+ /// This function is only supported with ELF targets.
+ std::unique_ptr<MCObjectWriter>
+ createDwoObjectWriter(raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS) const;
+
+ virtual std::unique_ptr<MCObjectTargetWriter>
+ createObjectTargetWriter() const = 0;
/// \name Target Fixup Interfaces
/// @{
@@ -80,9 +92,16 @@ public:
/// the offset specified by the fixup and following the fixup kind as
/// appropriate. Errors (such as an out of range fixup value) should be
/// reported via \p Ctx.
+ /// The \p STI is present only for fragments of type MCRelaxableFragment and
+ /// MCDataFragment with hasInstructions() == true.
virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target, MutableArrayRef<char> Data,
- uint64_t Value, bool IsResolved) const = 0;
+ uint64_t Value, bool IsResolved,
+ const MCSubtargetInfo *STI) const = 0;
+
+ /// Check whether the given target requires emitting differences of two
+ /// symbols as a set of relocations.
+ virtual bool requiresDiffExpressionRelocations() const { return false; }
/// @}
@@ -92,14 +111,18 @@ public:
/// Check whether the given instruction may need relaxation.
///
/// \param Inst - The instruction to test.
- virtual bool mayNeedRelaxation(const MCInst &Inst) const = 0;
+ /// \param STI - The MCSubtargetInfo in effect when the instruction was
+ /// encoded.
+ virtual bool mayNeedRelaxation(const MCInst &Inst,
+ const MCSubtargetInfo &STI) const = 0;
/// Target specific predicate for whether a given fixup requires the
/// associated instruction to be relaxed.
virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
uint64_t Value,
const MCRelaxableFragment *DF,
- const MCAsmLayout &Layout) const;
+ const MCAsmLayout &Layout,
+ const bool WasForced) const;
/// Simple predicate for targets where !Resolved implies requiring relaxation
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
@@ -127,7 +150,7 @@ public:
/// target cannot generate such a sequence, it should return an error.
///
/// \return - True on success.
- virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW) const = 0;
+ virtual bool writeNopData(raw_ostream &OS, uint64_t Count) const = 0;
/// Give backend an opportunity to finish layout after relaxation
virtual void finishLayout(MCAssembler const &Asm,
@@ -136,7 +159,7 @@ public:
/// Handle any target-specific assembler flags. By default, do nothing.
virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}
- /// \brief Generate the compact unwind encoding for the CFI instructions.
+ /// Generate the compact unwind encoding for the CFI instructions.
virtual uint32_t
generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const {
return 0;
@@ -173,7 +196,7 @@ public:
/// \param PF The fragment to relax.
/// \param Layout Code layout information.
///
- /// \returns true iff any relaxation occured.
+ /// \returns true iff any relaxation occurred.
bool relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout);
};
diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h
index c538c46fc072..120fb8fa7492 100644
--- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/contrib/llvm/include/llvm/MC/MCAsmInfo.h
@@ -84,6 +84,15 @@ protected:
/// directive for emitting thread local BSS Symbols. Default is false.
bool HasMachoTBSSDirective = false;
+ /// True if this is a non-GNU COFF target. The COFF port of the GNU linker
+ /// doesn't handle associative comdats in the way that we would like to use
+ /// them.
+ bool HasCOFFAssociativeComdats = false;
+
+ /// True if this is a non-GNU COFF target. For GNU targets, we don't generate
+ /// constants into comdat sections.
+ bool HasCOFFComdatConstants = false;
+
/// This is the maximum possible length of an instruction, which is needed to
/// compute the size of an inline asm. Defaults to 4.
unsigned MaxInstLength = 4;
@@ -344,6 +353,10 @@ protected:
/// For example, foo(plt) instead of foo@plt. Defaults to false.
bool UseParensForSymbolVariant = false;
+ /// True if the target supports flags in ".loc" directive, false if only
+ /// location is allowed.
+ bool SupportsExtendedDwarfLocDirective = true;
+
//===--- Prologue State ----------------------------------------------===//
std::vector<MCCFIInstruction> InitialFrameState;
@@ -416,7 +429,7 @@ public:
return nullptr;
}
- /// \brief True if the section is atomized using the symbols in it.
+ /// 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).
@@ -459,6 +472,8 @@ public:
bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; }
bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; }
+ bool hasCOFFAssociativeComdats() const { return HasCOFFAssociativeComdats; }
+ bool hasCOFFComdatConstants() const { return HasCOFFComdatConstants; }
unsigned getMaxInstLength() const { return MaxInstLength; }
unsigned getMinInstAlignment() const { return MinInstAlignment; }
bool getDollarIsPC() const { return DollarIsPC; }
@@ -579,6 +594,9 @@ public:
bool doDwarfFDESymbolsUseAbsDiff() const { return DwarfFDESymbolsUseAbsDiff; }
bool useDwarfRegNumForCFI() const { return DwarfRegNumForCFI; }
bool useParensForSymbolVariant() const { return UseParensForSymbolVariant; }
+ bool supportsExtendedDwarfLocDirective() const {
+ return SupportsExtendedDwarfLocDirective;
+ }
void addInitialFrameState(const MCCFIInstruction &Inst) {
InitialFrameState.push_back(Inst);
diff --git a/contrib/llvm/include/llvm/MC/MCAsmLayout.h b/contrib/llvm/include/llvm/MC/MCAsmLayout.h
index 1b20d5b804a4..b711db319302 100644
--- a/contrib/llvm/include/llvm/MC/MCAsmLayout.h
+++ b/contrib/llvm/include/llvm/MC/MCAsmLayout.h
@@ -37,11 +37,11 @@ class MCAsmLayout {
/// lower ordinal will be valid.
mutable DenseMap<const MCSection *, MCFragment *> LastValidFragment;
- /// \brief Make sure that the layout for the given fragment is valid, lazily
+ /// Make sure that the layout for the given fragment is valid, lazily
/// computing it if necessary.
void ensureValid(const MCFragment *F) const;
- /// \brief Is the layout for this fragment valid?
+ /// Is the layout for this fragment valid?
bool isFragmentValid(const MCFragment *F) const;
public:
@@ -50,12 +50,12 @@ public:
/// Get the assembler object this is a layout for.
MCAssembler &getAssembler() const { return Assembler; }
- /// \brief Invalidate the fragments starting with F because it has been
+ /// Invalidate the fragments starting with F because it has been
/// resized. The fragment's size should have already been updated, but
/// its bundle padding will be recomputed.
void invalidateFragmentsFrom(MCFragment *F);
- /// \brief Perform layout for a single fragment, assuming that the previous
+ /// Perform layout for a single fragment, assuming that the previous
/// fragment has already been laid out correctly, and the parent section has
/// been initialized.
void layoutFragment(MCFragment *Fragment);
@@ -72,31 +72,31 @@ public:
/// \name Fragment Layout Data
/// @{
- /// \brief Get the offset of the given fragment inside its containing section.
+ /// Get the offset of the given fragment inside its containing section.
uint64_t getFragmentOffset(const MCFragment *F) const;
/// @}
/// \name Utility Functions
/// @{
- /// \brief Get the address space size of the given section, as it effects
+ /// Get the address space size of the given section, as it effects
/// layout. This may differ from the size reported by \see getSectionSize() by
/// not including section tail padding.
uint64_t getSectionAddressSize(const MCSection *Sec) const;
- /// \brief Get the data size of the given section, as emitted to the object
+ /// Get the data size of the given section, as emitted to the object
/// file. This may include additional padding, or be 0 for virtual sections.
uint64_t getSectionFileSize(const MCSection *Sec) const;
- /// \brief Get the offset of the given symbol, as computed in the current
+ /// Get the offset of the given symbol, as computed in the current
/// layout.
/// \return True on success.
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const;
- /// \brief Variant that reports a fatal error if the offset is not computable.
+ /// Variant that reports a fatal error if the offset is not computable.
uint64_t getSymbolOffset(const MCSymbol &S) const;
- /// \brief If this symbol is equivalent to A + Constant, return A.
+ /// If this symbol is equivalent to A + Constant, return A.
const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const;
/// @}
diff --git a/contrib/llvm/include/llvm/MC/MCAsmMacro.h b/contrib/llvm/include/llvm/MC/MCAsmMacro.h
index dac8d1a80050..09b32c7ea333 100644
--- a/contrib/llvm/include/llvm/MC/MCAsmMacro.h
+++ b/contrib/llvm/include/llvm/MC/MCAsmMacro.h
@@ -10,10 +10,124 @@
#ifndef LLVM_MC_MCASMMACRO_H
#define LLVM_MC_MCASMMACRO_H
-#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/SMLoc.h"
+#include <vector>
namespace llvm {
+/// Target independent representation for an assembler token.
+class AsmToken {
+public:
+ enum TokenKind {
+ // Markers
+ Eof, Error,
+
+ // String values.
+ Identifier,
+ String,
+
+ // Integer values.
+ Integer,
+ BigNum, // larger than 64 bits
+
+ // Real values.
+ Real,
+
+ // Comments
+ Comment,
+ HashDirective,
+ // No-value.
+ EndOfStatement,
+ Colon,
+ Space,
+ Plus, Minus, Tilde,
+ Slash, // '/'
+ BackSlash, // '\'
+ LParen, RParen, LBrac, RBrac, LCurly, RCurly,
+ Star, Dot, Comma, Dollar, Equal, EqualEqual,
+
+ Pipe, PipePipe, Caret,
+ Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash,
+ Less, LessEqual, LessLess, LessGreater,
+ Greater, GreaterEqual, GreaterGreater, At,
+
+ // MIPS unary expression operators such as %neg.
+ PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi,
+ PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo,
+ PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi,
+ PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi,
+ PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi,
+ PercentTprel_Lo
+ };
+
+private:
+ TokenKind Kind;
+
+ /// A reference to the entire token contents; this is always a pointer into
+ /// a memory buffer owned by the source manager.
+ StringRef Str;
+
+ APInt IntVal;
+
+public:
+ AsmToken() = default;
+ AsmToken(TokenKind Kind, StringRef Str, APInt IntVal)
+ : Kind(Kind), Str(Str), IntVal(std::move(IntVal)) {}
+ AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0)
+ : Kind(Kind), Str(Str), IntVal(64, IntVal, true) {}
+
+ TokenKind getKind() const { return Kind; }
+ bool is(TokenKind K) const { return Kind == K; }
+ bool isNot(TokenKind K) const { return Kind != K; }
+
+ SMLoc getLoc() const;
+ SMLoc getEndLoc() const;
+ SMRange getLocRange() const;
+
+ /// Get the contents of a string token (without quotes).
+ StringRef getStringContents() const {
+ assert(Kind == String && "This token isn't a string!");
+ return Str.slice(1, Str.size() - 1);
+ }
+
+ /// Get the identifier string for the current token, which should be an
+ /// identifier or a string. This gets the portion of the string which should
+ /// be used as the identifier, e.g., it does not include the quotes on
+ /// strings.
+ StringRef getIdentifier() const {
+ if (Kind == Identifier)
+ return getString();
+ return getStringContents();
+ }
+
+ /// Get the string for the current token, this includes all characters (for
+ /// example, the quotes on strings) in the token.
+ ///
+ /// The returned StringRef points into the source manager's memory buffer, and
+ /// is safe to store across calls to Lex().
+ StringRef getString() const { return Str; }
+
+ // FIXME: Don't compute this in advance, it makes every token larger, and is
+ // also not generally what we want (it is nicer for recovery etc. to lex 123br
+ // as a single token, then diagnose as an invalid number).
+ int64_t getIntVal() const {
+ assert(Kind == Integer && "This token isn't an integer!");
+ return IntVal.getZExtValue();
+ }
+
+ APInt getAPIntVal() const {
+ assert((Kind == Integer || Kind == BigNum) &&
+ "This token isn't an integer!");
+ return IntVal;
+ }
+
+ void dump(raw_ostream &OS) const;
+ void dump() const { dump(dbgs()); }
+};
+
struct MCAsmMacroParameter {
StringRef Name;
std::vector<AsmToken> Value;
@@ -21,6 +135,9 @@ struct MCAsmMacroParameter {
bool Vararg = false;
MCAsmMacroParameter() = default;
+
+ void dump() const { dump(dbgs()); }
+ void dump(raw_ostream &OS) const;
};
typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters;
@@ -32,6 +149,9 @@ struct MCAsmMacro {
public:
MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P)
: Name(N), Body(B), Parameters(std::move(P)) {}
+
+ void dump() const { dump(dbgs()); }
+ void dump(raw_ostream &OS) const;
};
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/MC/MCAssembler.h b/contrib/llvm/include/llvm/MC/MCAssembler.h
index b91b04414021..0f9499d705e4 100644
--- a/contrib/llvm/include/llvm/MC/MCAssembler.h
+++ b/contrib/llvm/include/llvm/MC/MCAssembler.h
@@ -99,11 +99,11 @@ public:
private:
MCContext &Context;
- MCAsmBackend &Backend;
+ std::unique_ptr<MCAsmBackend> Backend;
- MCCodeEmitter &Emitter;
+ std::unique_ptr<MCCodeEmitter> Emitter;
- MCObjectWriter &Writer;
+ std::unique_ptr<MCObjectWriter> Writer;
SectionListType Sections;
@@ -130,7 +130,7 @@ private:
// refactoring too.
mutable SmallPtrSet<const MCSymbol *, 32> ThumbFuncs;
- /// \brief The bundle alignment size currently set in the assembler.
+ /// The bundle alignment size currently set in the assembler.
///
/// By default it's 0, which means bundling is disabled.
unsigned BundleAlignSize;
@@ -162,12 +162,14 @@ private:
/// evaluates to.
/// \param Value [out] On return, the value of the fixup as currently laid
/// out.
+ /// \param WasForced [out] On return, the value in the fixup is set to the
+ /// correct value if WasForced is true, even if evaluateFixup returns false.
/// \return Whether the fixup value was fully resolved. This is true if the
/// \p Value result is fixed, otherwise the value may change due to
/// relocation.
bool evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup,
const MCFragment *DF, MCValue &Target,
- uint64_t &Value) const;
+ uint64_t &Value, bool &WasForced) const;
/// Check whether a fixup can be satisfied, or whether it needs to be relaxed
/// (increased in size, in order to hold its value correctly).
@@ -178,11 +180,11 @@ private:
bool fragmentNeedsRelaxation(const MCRelaxableFragment *IF,
const MCAsmLayout &Layout) const;
- /// \brief Perform one layout iteration and return true if any offsets
+ /// Perform one layout iteration and return true if any offsets
/// were adjusted.
bool layoutOnce(MCAsmLayout &Layout);
- /// \brief Perform one layout iteration of the given section and return true
+ /// Perform one layout iteration of the given section and return true
/// if any offsets were adjusted.
bool layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec);
@@ -214,8 +216,9 @@ public:
// concrete and require clients to pass in a target like object. The other
// option is to make this abstract, and have targets provide concrete
// implementations as we do with AsmParser.
- MCAssembler(MCContext &Context, MCAsmBackend &Backend,
- MCCodeEmitter &Emitter, MCObjectWriter &Writer);
+ MCAssembler(MCContext &Context, std::unique_ptr<MCAsmBackend> Backend,
+ std::unique_ptr<MCCodeEmitter> Emitter,
+ std::unique_ptr<MCObjectWriter> Writer);
MCAssembler(const MCAssembler &) = delete;
MCAssembler &operator=(const MCAssembler &) = delete;
~MCAssembler();
@@ -235,8 +238,8 @@ public:
/// defining a separate atom.
bool isSymbolLinkerVisible(const MCSymbol &SD) const;
- /// Emit the section contents using the given object writer.
- void writeSectionData(const MCSection *Section,
+ /// Emit the section contents to \p OS.
+ void writeSectionData(raw_ostream &OS, const MCSection *Section,
const MCAsmLayout &Layout) const;
/// Check whether a given symbol has been flagged with .thumb_func.
@@ -274,11 +277,17 @@ public:
MCContext &getContext() const { return Context; }
- MCAsmBackend &getBackend() const { return Backend; }
+ MCAsmBackend *getBackendPtr() const { return Backend.get(); }
- MCCodeEmitter &getEmitter() const { return Emitter; }
+ MCCodeEmitter *getEmitterPtr() const { return Emitter.get(); }
- MCObjectWriter &getWriter() const { return Writer; }
+ MCObjectWriter *getWriterPtr() const { return Writer.get(); }
+
+ MCAsmBackend &getBackend() const { return *Backend; }
+
+ MCCodeEmitter &getEmitter() const { return *Emitter; }
+
+ MCObjectWriter &getWriter() const { return *Writer; }
MCDwarfLineTableParams getDWARFLinetableParams() const { return LTParams; }
void setDWARFLinetableParams(MCDwarfLineTableParams P) { LTParams = P; }
@@ -409,6 +418,13 @@ public:
const MCLOHContainer &getLOHContainer() const {
return const_cast<MCAssembler *>(this)->getLOHContainer();
}
+
+ struct CGProfileEntry {
+ const MCSymbolRefExpr *From;
+ const MCSymbolRefExpr *To;
+ uint64_t Count;
+ };
+ std::vector<CGProfileEntry> CGProfile;
/// @}
/// \name Backend Data Access
/// @{
@@ -424,21 +440,22 @@ public:
FileNames.push_back(FileName);
}
- /// \brief Write the necessary bundle padding to the given object writer.
+ /// Write the necessary bundle padding to \p OS.
/// Expects a fragment \p F containing instructions and its size \p FSize.
- void writeFragmentPadding(const MCFragment &F, uint64_t FSize,
- MCObjectWriter *OW) const;
+ void writeFragmentPadding(raw_ostream &OS, const MCEncodedFragment &F,
+ uint64_t FSize) const;
/// @}
void dump() const;
};
-/// \brief Compute the amount of padding required before the fragment \p F to
+/// Compute the amount of padding required before the fragment \p F to
/// obey bundling restrictions, where \p FOffset is the fragment's offset in
/// its section and \p FSize is the fragment's size.
-uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F,
- uint64_t FOffset, uint64_t FSize);
+uint64_t computeBundlePadding(const MCAssembler &Assembler,
+ const MCEncodedFragment *F, uint64_t FOffset,
+ uint64_t FSize);
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/MC/MCCodePadder.h b/contrib/llvm/include/llvm/MC/MCCodePadder.h
index 1e91198597c3..4dde6bf59272 100644
--- a/contrib/llvm/include/llvm/MC/MCCodePadder.h
+++ b/contrib/llvm/include/llvm/MC/MCCodePadder.h
@@ -28,7 +28,6 @@ typedef SmallVector<const MCPaddingFragment *, 8> MCPFRange;
struct MCCodePaddingContext {
bool IsPaddingActive;
- bool IsBasicBlockInsideInnermostLoop;
bool IsBasicBlockReachableViaFallthrough;
bool IsBasicBlockReachableViaBranch;
};
@@ -119,7 +118,7 @@ public:
/// \param Fragment The fragment to relax.
/// \param Layout Code layout information.
///
- /// \returns true iff any relaxation occured.
+ /// \returns true iff any relaxation occurred.
bool relaxFragment(MCPaddingFragment *Fragment, MCAsmLayout &Layout);
};
diff --git a/contrib/llvm/include/llvm/MC/MCCodeView.h b/contrib/llvm/include/llvm/MC/MCCodeView.h
index c8f14515ed34..1d9e3c6698cf 100644
--- a/contrib/llvm/include/llvm/MC/MCCodeView.h
+++ b/contrib/llvm/include/llvm/MC/MCCodeView.h
@@ -27,7 +27,7 @@ class MCObjectStreamer;
class MCStreamer;
class CodeViewContext;
-/// \brief Instances of this class represent the information from a
+/// Instances of this class represent the information from a
/// .cv_loc directive.
class MCCVLoc {
uint32_t FunctionId;
@@ -50,13 +50,13 @@ private: // CodeViewContext manages these
public:
unsigned getFunctionId() const { return FunctionId; }
- /// \brief Get the FileNum of this MCCVLoc.
+ /// Get the FileNum of this MCCVLoc.
unsigned getFileNum() const { return FileNum; }
- /// \brief Get the Line of this MCCVLoc.
+ /// Get the Line of this MCCVLoc.
unsigned getLine() const { return Line; }
- /// \brief Get the Column of this MCCVLoc.
+ /// Get the Column of this MCCVLoc.
unsigned getColumn() const { return Column; }
bool isPrologueEnd() const { return PrologueEnd; }
@@ -64,13 +64,13 @@ public:
void setFunctionId(unsigned FID) { FunctionId = FID; }
- /// \brief Set the FileNum of this MCCVLoc.
+ /// Set the FileNum of this MCCVLoc.
void setFileNum(unsigned fileNum) { FileNum = fileNum; }
- /// \brief Set the Line of this MCCVLoc.
+ /// Set the Line of this MCCVLoc.
void setLine(unsigned line) { Line = line; }
- /// \brief Set the Column of this MCCVLoc.
+ /// Set the Column of this MCCVLoc.
void setColumn(unsigned column) {
assert(column <= UINT16_MAX);
Column = column;
@@ -80,7 +80,7 @@ public:
void setIsStmt(bool IS) { IsStmt = IS; }
};
-/// \brief Instances of this class represent the line information for
+/// Instances of this class represent the line information for
/// the CodeView line table entries. Which is created after a machine
/// instruction is assembled and uses an address from a temporary label
/// created at the current address in the current section and the info from
@@ -201,7 +201,7 @@ public:
bool isValidCVFileNumber(unsigned FileNumber);
- /// \brief Add a line entry.
+ /// Add a line entry.
void addLineEntry(const MCCVLineEntry &LineEntry);
std::vector<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId);
diff --git a/contrib/llvm/include/llvm/MC/MCContext.h b/contrib/llvm/include/llvm/MC/MCContext.h
index 358f67c4db6d..a712e2d95cbc 100644
--- a/contrib/llvm/include/llvm/MC/MCContext.h
+++ b/contrib/llvm/include/llvm/MC/MCContext.h
@@ -11,6 +11,7 @@
#define LLVM_MC_MCCONTEXT_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -24,6 +25,8 @@
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -134,6 +137,9 @@ namespace llvm {
/// The compilation directory to use for DW_AT_comp_dir.
SmallString<128> CompilationDir;
+ /// Prefix replacement map for source file information.
+ std::map<const std::string, const std::string> DebugPrefixMap;
+
/// The main file name if passed in explicitly.
std::string MainFileName;
@@ -269,7 +275,7 @@ namespace llvm {
unsigned UniqueID,
const MCSymbolELF *Associated);
- /// \brief Map of currently defined macros.
+ /// Map of currently defined macros.
StringMap<MCAsmMacro> MacroMap;
public:
@@ -292,6 +298,10 @@ namespace llvm {
CodeViewContext &getCVContext();
+ /// Clear the current cv_loc, if there is one. Avoids lazily creating a
+ /// CodeViewContext if none is needed.
+ void clearCVLocSeen();
+
void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; }
void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; }
@@ -335,7 +345,7 @@ namespace llvm {
/// Gets a symbol that will be defined to the final stack offset of a local
/// variable after codegen.
///
- /// \param Idx - The index of a local variable passed to @llvm.localescape.
+ /// \param Idx - The index of a local variable passed to \@llvm.localescape.
MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx);
MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName);
@@ -475,25 +485,39 @@ namespace llvm {
/// \name Dwarf Management
/// @{
- /// \brief Get the compilation directory for DW_AT_comp_dir
+ /// Get the compilation directory for DW_AT_comp_dir
/// The compilation directory should be set with \c setCompilationDir before
/// calling this function. If it is unset, an empty string will be returned.
StringRef getCompilationDir() const { return CompilationDir; }
- /// \brief Set the compilation directory for DW_AT_comp_dir
+ /// Set the compilation directory for DW_AT_comp_dir
void setCompilationDir(StringRef S) { CompilationDir = S.str(); }
- /// \brief Get the main file name for use in error messages and debug
+ /// Get the debug prefix map.
+ const std::map<const std::string, const std::string> &
+ getDebugPrefixMap() const {
+ return DebugPrefixMap;
+ }
+
+ /// Add an entry to the debug prefix map.
+ void addDebugPrefixMapEntry(const std::string &From, const std::string &To);
+
+ // Remaps all debug directory paths in-place as per the debug prefix map.
+ void RemapDebugPaths();
+
+ /// Get the main file name for use in error messages and debug
/// info. This can be set to ensure we've got the correct file name
/// after preprocessing or for -save-temps.
const std::string &getMainFileName() const { return MainFileName; }
- /// \brief Set the main file name and override the default.
+ /// Set the main file name and override the default.
void setMainFileName(StringRef S) { MainFileName = S; }
/// Creates an entry in the dwarf file and directory tables.
- unsigned getDwarfFile(StringRef Directory, StringRef FileName,
- unsigned FileNumber, unsigned CUID);
+ Expected<unsigned> getDwarfFile(StringRef Directory, StringRef FileName,
+ unsigned FileNumber,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source, unsigned CUID);
bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0);
@@ -532,8 +556,18 @@ namespace llvm {
DwarfCompileUnitID = CUIndex;
}
- void setMCLineTableCompilationDir(unsigned CUID, StringRef CompilationDir) {
- getMCDwarfLineTable(CUID).setCompilationDir(CompilationDir);
+ /// Specifies the "root" file and directory of the compilation unit.
+ /// These are "file 0" and "directory 0" in DWARF v5.
+ void setMCLineTableRootFile(unsigned CUID, StringRef CompilationDir,
+ StringRef Filename, MD5::MD5Result *Checksum,
+ Optional<StringRef> Source) {
+ getMCDwarfLineTable(CUID).setRootFile(CompilationDir, Filename, Checksum,
+ Source);
+ }
+
+ /// Reports whether MD5 checksum usage is consistent (all-or-none).
+ bool isDwarfMD5UsageConsistent(unsigned CUID) const {
+ return getMCDwarfLineTable(CUID).isMD5UsageConsistent();
}
/// Saves the information from the currently parsed dwarf .loc directive
@@ -639,7 +673,7 @@ namespace llvm {
// operator new and delete aren't allowed inside namespaces.
// The throw specifications are mandated by the standard.
-/// \brief Placement new for using the MCContext's allocator.
+/// Placement new for using the MCContext's allocator.
///
/// This placement form of operator new uses the MCContext's allocator for
/// obtaining memory. It is a non-throwing new, which means that it returns
@@ -665,7 +699,7 @@ inline void *operator new(size_t Bytes, llvm::MCContext &C,
size_t Alignment = 8) noexcept {
return C.allocate(Bytes, Alignment);
}
-/// \brief Placement delete companion to the new above.
+/// Placement delete companion to the new above.
///
/// This operator is just a companion to the new above. There is no way of
/// invoking it directly; see the new operator for more details. This operator
@@ -699,7 +733,7 @@ inline void *operator new[](size_t Bytes, llvm::MCContext &C,
return C.allocate(Bytes, Alignment);
}
-/// \brief Placement delete[] companion to the new[] above.
+/// Placement delete[] companion to the new[] above.
///
/// This operator is just a companion to the new[] above. There is no way of
/// invoking it directly; see the new[] operator for more details. This operator
diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h b/contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h
index bd3e5d4638e5..df909a0dccd3 100644
--- a/contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h
+++ b/contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h
@@ -22,7 +22,7 @@
namespace llvm {
-/// \brief Symbolize using user-provided, C API, callbacks.
+/// Symbolize using user-provided, C API, callbacks.
///
/// See llvm-c/Disassembler.h.
class MCExternalSymbolizer : public MCSymbolizer {
diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h b/contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h
index 7836e886c303..6030ae660d38 100644
--- a/contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h
+++ b/contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h
@@ -21,7 +21,7 @@ namespace llvm {
class MCContext;
class MCExpr;
-/// \brief Create MCExprs from relocations found in an object file.
+/// Create MCExprs from relocations found in an object file.
class MCRelocationInfo {
protected:
MCContext &Ctx;
@@ -32,7 +32,7 @@ public:
MCRelocationInfo &operator=(const MCRelocationInfo &) = delete;
virtual ~MCRelocationInfo();
- /// \brief Create an MCExpr for the target-specific \p VariantKind.
+ /// Create an MCExpr for the target-specific \p VariantKind.
/// The VariantKinds are defined in llvm-c/Disassembler.h.
/// Used by MCExternalSymbolizer.
/// \returns If possible, an MCExpr corresponding to VariantKind, else 0.
diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h b/contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h
index d85cf5e066f5..0bfa569474ec 100644
--- a/contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h
+++ b/contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h
@@ -27,7 +27,7 @@ class MCContext;
class MCInst;
class raw_ostream;
-/// \brief Symbolize and annotate disassembled instructions.
+/// Symbolize and annotate disassembled instructions.
///
/// For now this mimics the old symbolization logic (from both ARM and x86), that
/// relied on user-provided (C API) callbacks to do the actual symbol lookup in
@@ -42,7 +42,7 @@ protected:
std::unique_ptr<MCRelocationInfo> RelInfo;
public:
- /// \brief Construct an MCSymbolizer, taking ownership of \p RelInfo.
+ /// Construct an MCSymbolizer, taking ownership of \p RelInfo.
MCSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo)
: Ctx(Ctx), RelInfo(std::move(RelInfo)) {
}
@@ -51,7 +51,7 @@ public:
MCSymbolizer &operator=(const MCSymbolizer &) = delete;
virtual ~MCSymbolizer();
- /// \brief Try to add a symbolic operand instead of \p Value to the MCInst.
+ /// Try to add a symbolic operand instead of \p Value to the MCInst.
///
/// Instead of having a difficult to read immediate, a symbolic operand would
/// represent this immediate in a more understandable way, for instance as a
@@ -70,7 +70,7 @@ public:
bool IsBranch, uint64_t Offset,
uint64_t InstSize) = 0;
- /// \brief Try to add a comment on the PC-relative load.
+ /// Try to add a comment on the PC-relative load.
/// For instance, in Mach-O, this is used to add annotations to instructions
/// that use C string literals, as found in __cstring.
virtual void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
diff --git a/contrib/llvm/include/llvm/MC/MCDwarf.h b/contrib/llvm/include/llvm/MC/MCDwarf.h
index 88ffa04128e6..785f42d2f9d7 100644
--- a/contrib/llvm/include/llvm/MC/MCDwarf.h
+++ b/contrib/llvm/include/llvm/MC/MCDwarf.h
@@ -16,10 +16,13 @@
#define LLVM_MC_MCDWARF_H
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCSection.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MD5.h"
#include <cassert>
#include <cstdint>
#include <string>
@@ -31,6 +34,7 @@ namespace llvm {
template <typename T> class ArrayRef;
class MCAsmBackend;
class MCContext;
+class MCDwarfLineStr;
class MCObjectStreamer;
class MCStreamer;
class MCSymbol;
@@ -38,21 +42,28 @@ class raw_ostream;
class SMLoc;
class SourceMgr;
-/// \brief Instances of this class represent the name of the dwarf
+/// Instances of this class represent the name of the dwarf
/// .file directive and its associated dwarf file number in the MC file,
/// and MCDwarfFile's are created and uniqued by the MCContext class where
/// the file number for each is its index into the vector of DwarfFiles (note
/// index 0 is not used and not a valid dwarf file number).
struct MCDwarfFile {
- // \brief The base name of the file without its directory path.
- // The StringRef references memory allocated in the MCContext.
+ // The base name of the file without its directory path.
std::string Name;
- // \brief The index into the list of directory names for this file name.
+ // The index into the list of directory names for this file name.
unsigned DirIndex;
+
+ /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
+ /// in MCContext.
+ MD5::MD5Result *Checksum = nullptr;
+
+ /// The source code of the file. Non-owning reference to data allocated in
+ /// MCContext.
+ Optional<StringRef> Source;
};
-/// \brief Instances of this class represent the information from a
+/// Instances of this class represent the information from a
/// dwarf .loc directive.
class MCDwarfLoc {
uint32_t FileNum;
@@ -84,55 +95,55 @@ private: // MCContext manages these
// for an MCDwarfLoc object.
public:
- /// \brief Get the FileNum of this MCDwarfLoc.
+ /// Get the FileNum of this MCDwarfLoc.
unsigned getFileNum() const { return FileNum; }
- /// \brief Get the Line of this MCDwarfLoc.
+ /// Get the Line of this MCDwarfLoc.
unsigned getLine() const { return Line; }
- /// \brief Get the Column of this MCDwarfLoc.
+ /// Get the Column of this MCDwarfLoc.
unsigned getColumn() const { return Column; }
- /// \brief Get the Flags of this MCDwarfLoc.
+ /// Get the Flags of this MCDwarfLoc.
unsigned getFlags() const { return Flags; }
- /// \brief Get the Isa of this MCDwarfLoc.
+ /// Get the Isa of this MCDwarfLoc.
unsigned getIsa() const { return Isa; }
- /// \brief Get the Discriminator of this MCDwarfLoc.
+ /// Get the Discriminator of this MCDwarfLoc.
unsigned getDiscriminator() const { return Discriminator; }
- /// \brief Set the FileNum of this MCDwarfLoc.
+ /// Set the FileNum of this MCDwarfLoc.
void setFileNum(unsigned fileNum) { FileNum = fileNum; }
- /// \brief Set the Line of this MCDwarfLoc.
+ /// Set the Line of this MCDwarfLoc.
void setLine(unsigned line) { Line = line; }
- /// \brief Set the Column of this MCDwarfLoc.
+ /// Set the Column of this MCDwarfLoc.
void setColumn(unsigned column) {
assert(column <= UINT16_MAX);
Column = column;
}
- /// \brief Set the Flags of this MCDwarfLoc.
+ /// Set the Flags of this MCDwarfLoc.
void setFlags(unsigned flags) {
assert(flags <= UINT8_MAX);
Flags = flags;
}
- /// \brief Set the Isa of this MCDwarfLoc.
+ /// Set the Isa of this MCDwarfLoc.
void setIsa(unsigned isa) {
assert(isa <= UINT8_MAX);
Isa = isa;
}
- /// \brief Set the Discriminator of this MCDwarfLoc.
+ /// Set the Discriminator of this MCDwarfLoc.
void setDiscriminator(unsigned discriminator) {
Discriminator = discriminator;
}
};
-/// \brief Instances of this class represent the line information for
+/// Instances of this class represent the line information for
/// the dwarf line table entries. Which is created after a machine
/// instruction is assembled and uses an address from a temporary label
/// created at the current address in the current section and the info from
@@ -157,13 +168,13 @@ public:
static void Make(MCObjectStreamer *MCOS, MCSection *Section);
};
-/// \brief Instances of this class represent the line information for a compile
+/// Instances of this class represent the line information for a compile
/// unit where machine instructions have been assembled after seeing .loc
/// directives. This is the information used to build the dwarf line
/// table for a section.
class MCLineSection {
public:
- // \brief Add an entry to this MCLineSection's line entries.
+ // Add an entry to this MCLineSection's line entries.
void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
MCLineDivisions[Sec].push_back(LineEntry);
}
@@ -202,32 +213,69 @@ struct MCDwarfLineTableHeader {
SmallVector<std::string, 3> MCDwarfDirs;
SmallVector<MCDwarfFile, 3> MCDwarfFiles;
StringMap<unsigned> SourceIdMap;
- StringRef CompilationDir;
+ std::string CompilationDir;
+ MCDwarfFile RootFile;
+ bool HasSource = false;
+private:
+ bool HasAllMD5 = true;
+ bool HasAnyMD5 = false;
+public:
MCDwarfLineTableHeader() = default;
- unsigned getFile(StringRef &Directory, StringRef &FileName,
- unsigned FileNumber = 0);
- std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS,
- MCDwarfLineTableParams Params) const;
+ Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> &Source,
+ unsigned FileNumber = 0);
std::pair<MCSymbol *, MCSymbol *>
Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
- ArrayRef<char> SpecialOpcodeLengths) const;
+ Optional<MCDwarfLineStr> &LineStr) const;
+ std::pair<MCSymbol *, MCSymbol *>
+ Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
+ ArrayRef<char> SpecialOpcodeLengths,
+ Optional<MCDwarfLineStr> &LineStr) const;
+ void resetMD5Usage() {
+ HasAllMD5 = true;
+ HasAnyMD5 = false;
+ }
+ void trackMD5Usage(bool MD5Used) {
+ HasAllMD5 &= MD5Used;
+ HasAnyMD5 |= MD5Used;
+ }
+ bool isMD5UsageConsistent() const {
+ return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
+ }
+
+private:
+ void emitV2FileDirTables(MCStreamer *MCOS) const;
+ void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr,
+ StringRef CtxCompilationDir) const;
};
class MCDwarfDwoLineTable {
MCDwarfLineTableHeader Header;
public:
- void setCompilationDir(StringRef CompilationDir) {
- Header.CompilationDir = CompilationDir;
+ void maybeSetRootFile(StringRef Directory, StringRef FileName,
+ MD5::MD5Result *Checksum, Optional<StringRef> Source) {
+ if (!Header.RootFile.Name.empty())
+ return;
+ Header.CompilationDir = Directory;
+ Header.RootFile.Name = FileName;
+ Header.RootFile.DirIndex = 0;
+ Header.RootFile.Checksum = Checksum;
+ Header.RootFile.Source = Source;
+ Header.trackMD5Usage(Checksum);
+ Header.HasSource = Source.hasValue();
}
- unsigned getFile(StringRef Directory, StringRef FileName) {
- return Header.getFile(Directory, FileName);
+ unsigned getFile(StringRef Directory, StringRef FileName,
+ MD5::MD5Result *Checksum, Optional<StringRef> Source) {
+ return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source));
}
- void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const;
+ void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
+ MCSection *Section) const;
};
class MCDwarfLineTable {
@@ -239,10 +287,42 @@ public:
static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params);
// This emits the Dwarf file and the line tables for a given Compile Unit.
- void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params) const;
+ void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params,
+ Optional<MCDwarfLineStr> &LineStr) const;
+ Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned FileNumber = 0);
unsigned getFile(StringRef &Directory, StringRef &FileName,
- unsigned FileNumber = 0);
+ MD5::MD5Result *Checksum, Optional<StringRef> &Source,
+ unsigned FileNumber = 0) {
+ return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
+ FileNumber));
+ }
+
+ void setRootFile(StringRef Directory, StringRef FileName,
+ MD5::MD5Result *Checksum, Optional<StringRef> Source) {
+ Header.CompilationDir = Directory;
+ Header.RootFile.Name = FileName;
+ Header.RootFile.DirIndex = 0;
+ Header.RootFile.Checksum = Checksum;
+ Header.RootFile.Source = Source;
+ Header.trackMD5Usage(Checksum);
+ Header.HasSource = Source.hasValue();
+ }
+
+ void resetRootFile() {
+ assert(Header.MCDwarfFiles.empty());
+ Header.RootFile.Name.clear();
+ Header.resetMD5Usage();
+ Header.HasSource = false;
+ }
+
+ bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
+
+ // Report whether MD5 usage has been consistent (all-or-none).
+ bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
MCSymbol *getLabel() const {
return Header.Label;
@@ -252,10 +332,6 @@ public:
Header.Label = Label;
}
- void setCompilationDir(StringRef CompilationDir) {
- Header.CompilationDir = CompilationDir;
- }
-
const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
return Header.MCDwarfDirs;
}
@@ -372,41 +448,41 @@ private:
}
public:
- /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from
+ /// .cfi_def_cfa defines a rule for computing CFA as: take address from
/// Register and add Offset to it.
static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register,
int Offset) {
return MCCFIInstruction(OpDefCfa, L, Register, -Offset, "");
}
- /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now
+ /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
/// on Register will be used instead of the old one. Offset remains the same.
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
}
- /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register
+ /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
/// remains the same, but offset is new. Note that it is the absolute offset
/// that will be added to a defined register to the compute CFA address.
static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) {
return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, "");
}
- /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
+ /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
/// Offset is a relative value that is added/subtracted from the previous
/// offset.
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
}
- /// \brief .cfi_offset Previous value of Register is saved at offset Offset
+ /// .cfi_offset Previous value of Register is saved at offset Offset
/// from CFA.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
int Offset) {
return MCCFIInstruction(OpOffset, L, Register, Offset, "");
}
- /// \brief .cfi_rel_offset Previous value of Register is saved at offset
+ /// .cfi_rel_offset Previous value of Register is saved at offset
/// Offset from the current CFA register. This is transformed to .cfi_offset
/// using the known displacement of the CFA register from the CFA.
static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
@@ -414,54 +490,54 @@ public:
return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
}
- /// \brief .cfi_register Previous value of Register1 is saved in
+ /// .cfi_register Previous value of Register1 is saved in
/// register Register2.
static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
unsigned Register2) {
return MCCFIInstruction(OpRegister, L, Register1, Register2);
}
- /// \brief .cfi_window_save SPARC register window is saved.
+ /// .cfi_window_save SPARC register window is saved.
static MCCFIInstruction createWindowSave(MCSymbol *L) {
return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
}
- /// \brief .cfi_restore says that the rule for Register is now the same as it
+ /// .cfi_restore says that the rule for Register is now the same as it
/// was at the beginning of the function, after all initial instructions added
/// by .cfi_startproc were executed.
static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
return MCCFIInstruction(OpRestore, L, Register, 0, "");
}
- /// \brief .cfi_undefined From now on the previous value of Register can't be
+ /// .cfi_undefined From now on the previous value of Register can't be
/// restored anymore.
static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
return MCCFIInstruction(OpUndefined, L, Register, 0, "");
}
- /// \brief .cfi_same_value Current value of Register is the same as in the
+ /// .cfi_same_value Current value of Register is the same as in the
/// previous frame. I.e., no restoration is needed.
static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
return MCCFIInstruction(OpSameValue, L, Register, 0, "");
}
- /// \brief .cfi_remember_state Save all current rules for all registers.
+ /// .cfi_remember_state Save all current rules for all registers.
static MCCFIInstruction createRememberState(MCSymbol *L) {
return MCCFIInstruction(OpRememberState, L, 0, 0, "");
}
- /// \brief .cfi_restore_state Restore the previously saved state.
+ /// .cfi_restore_state Restore the previously saved state.
static MCCFIInstruction createRestoreState(MCSymbol *L) {
return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
}
- /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind
+ /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
/// info.
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
}
- /// \brief A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
+ /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
}
diff --git a/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h b/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h
index fd8d118ccdc5..bff58fef6af9 100644
--- a/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h
+++ b/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
@@ -50,7 +51,7 @@ struct ELFRelocationEntry {
void dump() const { print(errs()); }
};
-class MCELFObjectTargetWriter {
+class MCELFObjectTargetWriter : public MCObjectTargetWriter {
const uint8_t OSABI;
const uint16_t EMachine;
const unsigned HasRelocationAddend : 1;
@@ -63,6 +64,11 @@ protected:
public:
virtual ~MCELFObjectTargetWriter() = default;
+ virtual Triple::ObjectFormatType getFormat() const { return Triple::ELF; }
+ static bool classof(const MCObjectTargetWriter *W) {
+ return W->getFormat() == Triple::ELF;
+ }
+
static uint8_t getOSABI(Triple::OSType OSType) {
switch (OSType) {
case Triple::CloudABI:
@@ -132,7 +138,7 @@ public:
}
};
-/// \brief Construct a new ELF writer instance.
+/// Construct a new ELF writer instance.
///
/// \param MOTW - The target specific ELF writer subclass.
/// \param OS - The stream to write to.
@@ -141,6 +147,11 @@ std::unique_ptr<MCObjectWriter>
createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS, bool IsLittleEndian);
+std::unique_ptr<MCObjectWriter>
+createELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
+ bool IsLittleEndian);
+
} // end namespace llvm
#endif // LLVM_MC_MCELFOBJECTWRITER_H
diff --git a/contrib/llvm/include/llvm/MC/MCELFStreamer.h b/contrib/llvm/include/llvm/MC/MCELFStreamer.h
index 2f23cd64ee03..3797079661e4 100644
--- a/contrib/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/contrib/llvm/include/llvm/MC/MCELFStreamer.h
@@ -24,7 +24,8 @@ class MCInst;
class MCELFStreamer : public MCObjectStreamer {
public:
MCELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
- raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter);
+ std::unique_ptr<MCObjectWriter> OW,
+ std::unique_ptr<MCCodeEmitter> Emitter);
~MCELFStreamer() override = default;
@@ -58,7 +59,8 @@ public:
unsigned ByteAlignment) override;
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0) override;
+ uint64_t Size = 0, unsigned ByteAlignment = 0,
+ SMLoc L = SMLoc()) override;
void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment = 0) override;
void EmitValueImpl(const MCExpr *Value, unsigned Size,
@@ -68,6 +70,9 @@ public:
void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override;
+ void emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count) override;
+
void FinishImpl() override;
void EmitBundleAlignMode(unsigned AlignPow2) override;
@@ -80,8 +85,10 @@ private:
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
void fixSymbolsInTLSFixups(const MCExpr *expr);
+ void finalizeCGProfileEntry(const MCSymbolRefExpr *&S);
+ void finalizeCGProfile();
- /// \brief Merge the content of the fragment \p EF into the fragment \p DF.
+ /// Merge the content of the fragment \p EF into the fragment \p DF.
void mergeFragment(MCDataFragment *, MCDataFragment *);
bool SeenIdent = false;
@@ -93,7 +100,7 @@ private:
MCELFStreamer *createARMELFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> OW,
std::unique_ptr<MCCodeEmitter> Emitter,
bool RelaxAll, bool IsThumb);
diff --git a/contrib/llvm/include/llvm/MC/MCExpr.h b/contrib/llvm/include/llvm/MC/MCExpr.h
index fcbbe650d26f..c4dfbe949078 100644
--- a/contrib/llvm/include/llvm/MC/MCExpr.h
+++ b/contrib/llvm/include/llvm/MC/MCExpr.h
@@ -31,7 +31,7 @@ class StringRef;
using SectionAddrMap = DenseMap<const MCSection *, uint64_t>;
-/// \brief Base class for the full range of assembler expressions which are
+/// Base class for the full range of assembler expressions which are
/// needed for parsing.
class MCExpr {
public:
@@ -85,7 +85,7 @@ public:
/// \name Expression Evaluation
/// @{
- /// \brief Try to evaluate the expression to an absolute value.
+ /// Try to evaluate the expression to an absolute value.
///
/// \param Res - The absolute value, if evaluation succeeds.
/// \param Layout - The assembler layout object to use for evaluating symbol
@@ -96,11 +96,12 @@ public:
const SectionAddrMap &Addrs) const;
bool evaluateAsAbsolute(int64_t &Res) const;
bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
+ bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const;
bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
- /// \brief Try to evaluate the expression to a relocatable value, i.e. an
+ /// Try to evaluate the expression to a relocatable value, i.e. an
/// expression of the fixed form (a - b + constant).
///
/// \param Res - The relocatable value, if evaluation succeeds.
@@ -110,14 +111,14 @@ public:
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
const MCFixup *Fixup) const;
- /// \brief Try to evaluate the expression to the form (a - b + constant) where
+ /// Try to evaluate the expression to the form (a - b + constant) where
/// neither a nor b are variables.
///
/// This is a more aggressive variant of evaluateAsRelocatable. The intended
/// use is for when relocations are not available, like the .size directive.
bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const;
- /// \brief Find the "associated section" for this expression, which is
+ /// Find the "associated section" for this expression, which is
/// currently defined as the absolute section for constants, or
/// otherwise the section associated with the first defined symbol in the
/// expression.
@@ -131,7 +132,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) {
return OS;
}
-//// \brief Represent a constant integer expression.
+//// Represent a constant integer expression.
class MCConstantExpr : public MCExpr {
int64_t Value;
@@ -157,7 +158,7 @@ public:
}
};
-/// \brief Represent a reference to a symbol from inside an expression.
+/// Represent a reference to a symbol from inside an expression.
///
/// A symbol reference in an expression may be a use of a label, a use of an
/// assembler variable (defined constant), or constitute an implicit definition
@@ -217,6 +218,8 @@ public:
VK_PPC_LO, // symbol@l
VK_PPC_HI, // symbol@h
VK_PPC_HA, // symbol@ha
+ VK_PPC_HIGH, // symbol@high
+ VK_PPC_HIGHA, // symbol@higha
VK_PPC_HIGHER, // symbol@higher
VK_PPC_HIGHERA, // symbol@highera
VK_PPC_HIGHEST, // symbol@highest
@@ -233,6 +236,8 @@ public:
VK_PPC_TPREL_LO, // symbol@tprel@l
VK_PPC_TPREL_HI, // symbol@tprel@h
VK_PPC_TPREL_HA, // symbol@tprel@ha
+ VK_PPC_TPREL_HIGH, // symbol@tprel@high
+ VK_PPC_TPREL_HIGHA, // symbol@tprel@higha
VK_PPC_TPREL_HIGHER, // symbol@tprel@higher
VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera
VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest
@@ -240,6 +245,8 @@ public:
VK_PPC_DTPREL_LO, // symbol@dtprel@l
VK_PPC_DTPREL_HI, // symbol@dtprel@h
VK_PPC_DTPREL_HA, // symbol@dtprel@ha
+ VK_PPC_DTPREL_HIGH, // symbol@dtprel@high
+ VK_PPC_DTPREL_HIGHA, // symbol@dtprel@higha
VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher
VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera
VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest
@@ -285,6 +292,7 @@ public:
VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi
VK_AMDGPU_REL32_LO, // symbol@rel32@lo
VK_AMDGPU_REL32_HI, // symbol@rel32@hi
+ VK_AMDGPU_REL64, // symbol@rel64
VK_TPREL,
VK_DTPREL
@@ -346,7 +354,7 @@ public:
}
};
-/// \brief Unary assembler expressions.
+/// Unary assembler expressions.
class MCUnaryExpr : public MCExpr {
public:
enum Opcode {
@@ -390,10 +398,10 @@ public:
/// \name Accessors
/// @{
- /// \brief Get the kind of this unary expression.
+ /// Get the kind of this unary expression.
Opcode getOpcode() const { return Op; }
- /// \brief Get the child of this unary expression.
+ /// Get the child of this unary expression.
const MCExpr *getSubExpr() const { return Expr; }
/// @}
@@ -403,7 +411,7 @@ public:
}
};
-/// \brief Binary assembler expressions.
+/// Binary assembler expressions.
class MCBinaryExpr : public MCExpr {
public:
enum Opcode {
@@ -547,13 +555,13 @@ public:
/// \name Accessors
/// @{
- /// \brief Get the kind of this binary expression.
+ /// Get the kind of this binary expression.
Opcode getOpcode() const { return Op; }
- /// \brief Get the left-hand side expression of the binary operator.
+ /// Get the left-hand side expression of the binary operator.
const MCExpr *getLHS() const { return LHS; }
- /// \brief Get the right-hand side expression of the binary operator.
+ /// Get the right-hand side expression of the binary operator.
const MCExpr *getRHS() const { return RHS; }
/// @}
@@ -563,7 +571,7 @@ public:
}
};
-/// \brief This is an extension point for target-specific MCExpr subclasses to
+/// This is an extension point for target-specific MCExpr subclasses to
/// implement.
///
/// NOTE: All subclasses are required to have trivial destructors because
@@ -580,6 +588,9 @@ public:
virtual bool evaluateAsRelocatableImpl(MCValue &Res,
const MCAsmLayout *Layout,
const MCFixup *Fixup) const = 0;
+ // This should be set when assigned expressions are not valid ".set"
+ // expressions, e.g. registers, and must be inlined.
+ virtual bool inlineAssignedExpr() const { return false; }
virtual void visitUsedExpr(MCStreamer& Streamer) const = 0;
virtual MCFragment *findAssociatedFragment() const = 0;
diff --git a/contrib/llvm/include/llvm/MC/MCFixup.h b/contrib/llvm/include/llvm/MC/MCFixup.h
index b83086c327f2..5f301eafc556 100644
--- a/contrib/llvm/include/llvm/MC/MCFixup.h
+++ b/contrib/llvm/include/llvm/MC/MCFixup.h
@@ -19,7 +19,7 @@
namespace llvm {
class MCExpr;
-/// \brief Extensible enumeration to represent the type of a fixup.
+/// Extensible enumeration to represent the type of a fixup.
enum MCFixupKind {
FK_Data_1 = 0, ///< A one-byte fixup.
FK_Data_2, ///< A two-byte fixup.
@@ -41,6 +41,14 @@ enum MCFixupKind {
FK_SecRel_2, ///< A two-byte section relative fixup.
FK_SecRel_4, ///< A four-byte section relative fixup.
FK_SecRel_8, ///< A eight-byte section relative fixup.
+ FK_Data_Add_1, ///< A one-byte add fixup.
+ FK_Data_Add_2, ///< A two-byte add fixup.
+ FK_Data_Add_4, ///< A four-byte add fixup.
+ FK_Data_Add_8, ///< A eight-byte add fixup.
+ FK_Data_Sub_1, ///< A one-byte sub fixup.
+ FK_Data_Sub_2, ///< A two-byte sub fixup.
+ FK_Data_Sub_4, ///< A four-byte sub fixup.
+ FK_Data_Sub_8, ///< A eight-byte sub fixup.
FirstTargetFixupKind = 128,
@@ -49,7 +57,7 @@ enum MCFixupKind {
MaxTargetFixupKind = (1 << 8)
};
-/// \brief Encode information on a single operation to perform on a byte
+/// Encode information on a single operation to perform on a byte
/// sequence (e.g., an encoded instruction) which requires assemble- or run-
/// time patching.
///
@@ -90,6 +98,28 @@ public:
return FI;
}
+ /// Return a fixup corresponding to the add half of a add/sub fixup pair for
+ /// the given Fixup.
+ static MCFixup createAddFor(const MCFixup &Fixup) {
+ MCFixup FI;
+ FI.Value = Fixup.getValue();
+ FI.Offset = Fixup.getOffset();
+ FI.Kind = (unsigned)getAddKindForKind(Fixup.getKind());
+ FI.Loc = Fixup.getLoc();
+ return FI;
+ }
+
+ /// Return a fixup corresponding to the sub half of a add/sub fixup pair for
+ /// the given Fixup.
+ static MCFixup createSubFor(const MCFixup &Fixup) {
+ MCFixup FI;
+ FI.Value = Fixup.getValue();
+ FI.Offset = Fixup.getOffset();
+ FI.Kind = (unsigned)getSubKindForKind(Fixup.getKind());
+ FI.Loc = Fixup.getLoc();
+ return FI;
+ }
+
MCFixupKind getKind() const { return MCFixupKind(Kind); }
uint32_t getOffset() const { return Offset; }
@@ -97,7 +127,7 @@ public:
const MCExpr *getValue() const { return Value; }
- /// \brief Return the generic fixup kind for a value with the given size. It
+ /// Return the generic fixup kind for a value with the given size. It
/// is an error to pass an unsupported size.
static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) {
switch (Size) {
@@ -109,6 +139,30 @@ public:
}
}
+ /// Return the generic fixup kind for an addition with a given size. It
+ /// is an error to pass an unsupported size.
+ static MCFixupKind getAddKindForKind(unsigned Kind) {
+ switch (Kind) {
+ default: llvm_unreachable("Unknown type to convert!");
+ case FK_Data_1: return FK_Data_Add_1;
+ case FK_Data_2: return FK_Data_Add_2;
+ case FK_Data_4: return FK_Data_Add_4;
+ case FK_Data_8: return FK_Data_Add_8;
+ }
+ }
+
+ /// Return the generic fixup kind for an subtraction with a given size. It
+ /// is an error to pass an unsupported size.
+ static MCFixupKind getSubKindForKind(unsigned Kind) {
+ switch (Kind) {
+ default: llvm_unreachable("Unknown type to convert!");
+ case FK_Data_1: return FK_Data_Sub_1;
+ case FK_Data_2: return FK_Data_Sub_2;
+ case FK_Data_4: return FK_Data_Sub_4;
+ case FK_Data_8: return FK_Data_Sub_8;
+ }
+ }
+
SMLoc getLoc() const { return Loc; }
};
diff --git a/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h b/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h
index 58183bd778e6..483abb39403f 100644
--- a/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h
+++ b/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h
@@ -12,7 +12,7 @@
namespace llvm {
-/// \brief Target independent information on a fixup kind.
+/// Target independent information on a fixup kind.
struct MCFixupKindInfo {
enum FixupKindFlags {
/// Is this fixup kind PCrelative? This is used by the assembler backend to
diff --git a/contrib/llvm/include/llvm/MC/MCFragment.h b/contrib/llvm/include/llvm/MC/MCFragment.h
index 85b55e85469a..47b35175fec8 100644
--- a/contrib/llvm/include/llvm/MC/MCFragment.h
+++ b/contrib/llvm/include/llvm/MC/MCFragment.h
@@ -56,18 +56,13 @@ protected:
bool HasInstructions;
private:
- /// \brief Should this fragment be aligned to the end of a bundle?
- bool AlignToBundleEnd;
-
- uint8_t BundlePadding;
-
/// LayoutOrder - The layout order of this fragment.
unsigned LayoutOrder;
/// The data for the section this fragment is in.
MCSection *Parent;
- /// Atom - The atom this fragment is in, as represented by it's defining
+ /// Atom - The atom this fragment is in, as represented by its defining
/// symbol.
const MCSymbol *Atom;
@@ -84,7 +79,7 @@ private:
protected:
MCFragment(FragmentType Kind, bool HasInstructions,
- uint8_t BundlePadding, MCSection *Parent = nullptr);
+ MCSection *Parent = nullptr);
~MCFragment();
@@ -110,26 +105,11 @@ public:
unsigned getLayoutOrder() const { return LayoutOrder; }
void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
- /// \brief Does this fragment have instructions emitted into it? By default
+ /// Does this fragment have instructions emitted into it? By default
/// this is false, but specific fragment types may set it to true.
bool hasInstructions() const { return HasInstructions; }
- /// \brief Should this fragment be placed at the end of an aligned bundle?
- bool alignToBundleEnd() const { return AlignToBundleEnd; }
- void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
-
- /// \brief Get the padding size that must be inserted before this fragment.
- /// Used for bundling. By default, no padding is inserted.
- /// Note that padding size is restricted to 8 bits. This is an optimization
- /// to reduce the amount of space used for each fragment. In practice, larger
- /// padding should never be required.
- uint8_t getBundlePadding() const { return BundlePadding; }
-
- /// \brief Set the padding size for this fragment. By default it's a no-op,
- /// and only some fragments have a meaningful implementation.
- void setBundlePadding(uint8_t N) { BundlePadding = N; }
-
- /// \brief Return true if given frgment has FT_Dummy type.
+ /// Return true if given frgment has FT_Dummy type.
bool isDummy() const { return Kind == FT_Dummy; }
void dump() const;
@@ -137,8 +117,7 @@ public:
class MCDummyFragment : public MCFragment {
public:
- explicit MCDummyFragment(MCSection *Sec)
- : MCFragment(FT_Dummy, false, 0, Sec) {}
+ explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {}
static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
};
@@ -147,10 +126,19 @@ public:
/// data.
///
class MCEncodedFragment : public MCFragment {
+ /// Should this fragment be aligned to the end of a bundle?
+ bool AlignToBundleEnd = false;
+
+ uint8_t BundlePadding = 0;
+
protected:
MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
MCSection *Sec)
- : MCFragment(FType, HasInstructions, 0, Sec) {}
+ : MCFragment(FType, HasInstructions, Sec) {}
+
+ /// STI - The MCSubtargetInfo in effect when the instruction was encoded.
+ /// must be non-null for instructions.
+ const MCSubtargetInfo *STI = nullptr;
public:
static bool classof(const MCFragment *F) {
@@ -164,6 +152,32 @@ public:
return true;
}
}
+
+ /// Should this fragment be placed at the end of an aligned bundle?
+ bool alignToBundleEnd() const { return AlignToBundleEnd; }
+ void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
+
+ /// Get the padding size that must be inserted before this fragment.
+ /// Used for bundling. By default, no padding is inserted.
+ /// Note that padding size is restricted to 8 bits. This is an optimization
+ /// to reduce the amount of space used for each fragment. In practice, larger
+ /// padding should never be required.
+ uint8_t getBundlePadding() const { return BundlePadding; }
+
+ /// Set the padding size for this fragment. By default it's a no-op,
+ /// and only some fragments have a meaningful implementation.
+ void setBundlePadding(uint8_t N) { BundlePadding = N; }
+
+ /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
+ /// Guaranteed to be non-null if hasInstructions() == true
+ const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
+
+ /// Record that the fragment contains instructions with the MCSubtargetInfo in
+ /// effect when the instruction was encoded.
+ void setHasInstructions(const MCSubtargetInfo &STI) {
+ HasInstructions = true;
+ this->STI = &STI;
+ }
};
/// Interface implemented by fragments that contain encoded instructions and/or
@@ -202,6 +216,7 @@ protected:
Sec) {}
public:
+
using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
@@ -228,8 +243,6 @@ public:
MCDataFragment(MCSection *Sec = nullptr)
: MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
- void setHasInstructions(bool V) { HasInstructions = V; }
-
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Data;
}
@@ -259,20 +272,15 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
/// Inst - The instruction this is a fragment for.
MCInst Inst;
- /// STI - The MCSubtargetInfo in effect when the instruction was encoded.
- const MCSubtargetInfo &STI;
-
public:
MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
MCSection *Sec = nullptr)
: MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
- Inst(Inst), STI(STI) {}
+ Inst(Inst) { this->STI = &STI; }
const MCInst &getInst() const { return Inst; }
void setInst(const MCInst &Value) { Inst = Value; }
- const MCSubtargetInfo &getSubtargetInfo() { return STI; }
-
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Relaxable;
}
@@ -300,9 +308,8 @@ class MCAlignFragment : public MCFragment {
public:
MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
- : MCFragment(FT_Align, false, 0, Sec), Alignment(Alignment),
- EmitNops(false), Value(Value),
- ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
+ : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
+ Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
/// \name Accessors
/// @{
@@ -370,7 +377,7 @@ public:
};
MCPaddingFragment(MCSection *Sec = nullptr)
- : MCFragment(FT_Padding, false, 0, Sec), PaddingPoliciesMask(PFK_None),
+ : MCFragment(FT_Padding, false, Sec), PaddingPoliciesMask(PFK_None),
IsInsertionPoint(false), Size(UINT64_C(0)),
InstInfo({false, MCInst(), false, {0}}) {}
@@ -419,22 +426,23 @@ public:
class MCFillFragment : public MCFragment {
/// Value to use for filling bytes.
- uint8_t Value;
-
+ uint64_t Value;
+ uint8_t ValueSize;
/// The number of bytes to insert.
- const MCExpr &Size;
+ const MCExpr &NumValues;
/// Source location of the directive that this fragment was created for.
SMLoc Loc;
public:
- MCFillFragment(uint8_t Value, const MCExpr &Size, SMLoc Loc,
- MCSection *Sec = nullptr)
- : MCFragment(FT_Fill, false, 0, Sec), Value(Value), Size(Size), Loc(Loc) {
- }
+ MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
+ SMLoc Loc, MCSection *Sec = nullptr)
+ : MCFragment(FT_Fill, false, Sec), Value(Value), ValueSize(VSize),
+ NumValues(NumValues), Loc(Loc) {}
- uint8_t getValue() const { return Value; }
- const MCExpr &getSize() const { return Size; }
+ uint64_t getValue() const { return Value; }
+ uint8_t getValueSize() const { return ValueSize; }
+ const MCExpr &getNumValues() const { return NumValues; }
SMLoc getLoc() const { return Loc; }
@@ -444,19 +452,19 @@ public:
};
class MCOrgFragment : public MCFragment {
- /// Offset - The offset this fragment should start at.
+ /// The offset this fragment should start at.
const MCExpr *Offset;
- /// Value - Value to use for filling bytes.
+ /// Value to use for filling bytes.
int8_t Value;
- /// Loc - Source location of the directive that this fragment was created for.
+ /// Source location of the directive that this fragment was created for.
SMLoc Loc;
public:
MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
MCSection *Sec = nullptr)
- : MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value), Loc(Loc) {}
+ : MCFragment(FT_Org, false, Sec), Offset(&Offset), Value(Value), Loc(Loc) {}
/// \name Accessors
/// @{
@@ -485,7 +493,7 @@ class MCLEBFragment : public MCFragment {
public:
MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
- : MCFragment(FT_LEB, false, 0, Sec), Value(&Value_), IsSigned(IsSigned_) {
+ : MCFragment(FT_LEB, false, Sec), Value(&Value_), IsSigned(IsSigned_) {
Contents.push_back(0);
}
@@ -520,7 +528,7 @@ class MCDwarfLineAddrFragment : public MCFragment {
public:
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
MCSection *Sec = nullptr)
- : MCFragment(FT_Dwarf, false, 0, Sec), LineDelta(LineDelta),
+ : MCFragment(FT_Dwarf, false, Sec), LineDelta(LineDelta),
AddrDelta(&AddrDelta) {
Contents.push_back(0);
}
@@ -551,7 +559,7 @@ class MCDwarfCallFrameFragment : public MCFragment {
public:
MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
- : MCFragment(FT_DwarfFrame, false, 0, Sec), AddrDelta(&AddrDelta) {
+ : MCFragment(FT_DwarfFrame, false, Sec), AddrDelta(&AddrDelta) {
Contents.push_back(0);
}
@@ -576,7 +584,7 @@ class MCSymbolIdFragment : public MCFragment {
public:
MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
- : MCFragment(FT_SymbolId, false, 0, Sec), Sym(Sym) {}
+ : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
/// \name Accessors
/// @{
@@ -610,7 +618,7 @@ public:
unsigned StartLineNum, const MCSymbol *FnStartSym,
const MCSymbol *FnEndSym,
MCSection *Sec = nullptr)
- : MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId),
+ : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
StartFileId(StartFileId), StartLineNum(StartLineNum),
FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
diff --git a/contrib/llvm/include/llvm/MC/MCInst.h b/contrib/llvm/include/llvm/MC/MCInst.h
index db28fd0fd6d9..67bb11a70387 100644
--- a/contrib/llvm/include/llvm/MC/MCInst.h
+++ b/contrib/llvm/include/llvm/MC/MCInst.h
@@ -30,7 +30,7 @@ class MCInst;
class MCInstPrinter;
class raw_ostream;
-/// \brief Instances of this class represent operands of the MCInst class.
+/// Instances of this class represent operands of the MCInst class.
/// This is a simple discriminated union.
class MCOperand {
enum MachineOperandType : unsigned char {
@@ -61,13 +61,13 @@ public:
bool isExpr() const { return Kind == kExpr; }
bool isInst() const { return Kind == kInst; }
- /// \brief Returns the register number.
+ /// Returns the register number.
unsigned getReg() const {
assert(isReg() && "This is not a register operand!");
return RegVal;
}
- /// \brief Set the register number.
+ /// Set the register number.
void setReg(unsigned Reg) {
assert(isReg() && "This is not a register operand!");
RegVal = Reg;
@@ -150,11 +150,13 @@ public:
void print(raw_ostream &OS) const;
void dump() const;
+ bool isBareSymbolRef() const;
+ bool evaluateAsConstantImm(int64_t &Imm) const;
};
template <> struct isPodLike<MCOperand> { static const bool value = true; };
-/// \brief Instances of this class represent a single low-level machine
+/// Instances of this class represent a single low-level machine
/// instruction.
class MCInst {
unsigned Opcode = 0;
@@ -201,7 +203,7 @@ public:
void print(raw_ostream &OS) const;
void dump() const;
- /// \brief Dump the MCInst as prettily as possible using the additional MC
+ /// 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 MCInstPrinter *Printer = nullptr,
diff --git a/contrib/llvm/include/llvm/MC/MCInstBuilder.h b/contrib/llvm/include/llvm/MC/MCInstBuilder.h
index 30609bdb8b27..c5c4f481e7df 100644
--- a/contrib/llvm/include/llvm/MC/MCInstBuilder.h
+++ b/contrib/llvm/include/llvm/MC/MCInstBuilder.h
@@ -23,42 +23,42 @@ class MCInstBuilder {
MCInst Inst;
public:
- /// \brief Create a new MCInstBuilder for an MCInst with a specific opcode.
+ /// Create a new MCInstBuilder for an MCInst with a specific opcode.
MCInstBuilder(unsigned Opcode) {
Inst.setOpcode(Opcode);
}
- /// \brief Add a new register operand.
+ /// Add a new register operand.
MCInstBuilder &addReg(unsigned Reg) {
Inst.addOperand(MCOperand::createReg(Reg));
return *this;
}
- /// \brief Add a new integer immediate operand.
+ /// Add a new integer immediate operand.
MCInstBuilder &addImm(int64_t Val) {
Inst.addOperand(MCOperand::createImm(Val));
return *this;
}
- /// \brief Add a new floating point immediate operand.
+ /// Add a new floating point immediate operand.
MCInstBuilder &addFPImm(double Val) {
Inst.addOperand(MCOperand::createFPImm(Val));
return *this;
}
- /// \brief Add a new MCExpr operand.
+ /// Add a new MCExpr operand.
MCInstBuilder &addExpr(const MCExpr *Val) {
Inst.addOperand(MCOperand::createExpr(Val));
return *this;
}
- /// \brief Add a new MCInst operand.
+ /// Add a new MCInst operand.
MCInstBuilder &addInst(const MCInst *Val) {
Inst.addOperand(MCOperand::createInst(Val));
return *this;
}
- /// \brief Add an operand.
+ /// Add an operand.
MCInstBuilder &addOperand(const MCOperand &Op) {
Inst.addOperand(Op);
return *this;
diff --git a/contrib/llvm/include/llvm/MC/MCInstPrinter.h b/contrib/llvm/include/llvm/MC/MCInstPrinter.h
index 069403074b31..df221e1db0e7 100644
--- a/contrib/llvm/include/llvm/MC/MCInstPrinter.h
+++ b/contrib/llvm/include/llvm/MC/MCInstPrinter.h
@@ -15,7 +15,6 @@
namespace llvm {
-template <typename T> class ArrayRef;
class MCAsmInfo;
class MCInst;
class MCInstrInfo;
@@ -36,13 +35,13 @@ enum Style {
} // end namespace HexStyle
-/// \brief This is an instance of a target assembly language printer that
+/// This is an instance of a target assembly language printer that
/// converts an MCInst to valid target assembly syntax.
class MCInstPrinter {
protected:
- /// \brief A stream that comments can be emitted to if desired. Each comment
+ /// A stream that comments can be emitted to if desired. Each comment
/// must end with a newline. This will be null if verbose assembly emission
- /// is disable.
+ /// is disabled.
raw_ostream *CommentStream = nullptr;
const MCAsmInfo &MAI;
const MCInstrInfo &MII;
@@ -66,18 +65,18 @@ public:
virtual ~MCInstPrinter();
- /// \brief Specify a stream to emit comments to.
+ /// Specify a stream to emit comments to.
void setCommentStream(raw_ostream &OS) { CommentStream = &OS; }
- /// \brief Print the specified MCInst to the specified raw_ostream.
+ /// Print the specified MCInst to the specified raw_ostream.
virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot,
const MCSubtargetInfo &STI) = 0;
- /// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or
+ /// Return the name of the specified opcode enum (e.g. "MOV32ri") or
/// empty if we can't resolve it.
StringRef getOpcodeName(unsigned Opcode) const;
- /// \brief Print the assembler register name.
+ /// Print the assembler register name.
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
bool getUseMarkup() const { return UseMarkup; }
diff --git a/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h b/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h
index dd3e1df477b4..484f03b4d854 100644
--- a/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h
+++ b/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h
@@ -22,6 +22,8 @@
namespace llvm {
+class MCRegisterInfo;
+
class MCInstrAnalysis {
protected:
friend class Target;
@@ -60,7 +62,32 @@ public:
return Info->get(Inst.getOpcode()).isTerminator();
}
- /// \brief Given a branch instruction try to get the address the branch
+ /// Returns true if at least one of the register writes performed by
+ /// \param Inst implicitly clears the upper portion of all super-registers.
+ ///
+ /// Example: on X86-64, a write to EAX implicitly clears the upper half of
+ /// RAX. Also (still on x86) an XMM write perfomed by an AVX 128-bit
+ /// instruction implicitly clears the upper portion of the correspondent
+ /// YMM register.
+ ///
+ /// This method also updates an APInt which is used as mask of register
+ /// writes. There is one bit for every explicit/implicit write performed by
+ /// the instruction. If a write implicitly clears its super-registers, then
+ /// the corresponding bit is set (vic. the corresponding bit is cleared).
+ ///
+ /// The first bits in the APint are related to explicit writes. The remaining
+ /// bits are related to implicit writes. The sequence of writes follows the
+ /// machine operand sequence. For implicit writes, the sequence is defined by
+ /// the MCInstrDesc.
+ ///
+ /// The assumption is that the bit-width of the APInt is correctly set by
+ /// the caller. The default implementation conservatively assumes that none of
+ /// the writes clears the upper portion of a super-register.
+ virtual bool clearsSuperRegisters(const MCRegisterInfo &MRI,
+ const MCInst &Inst,
+ APInt &Writes) const;
+
+ /// Given a branch instruction try to get the address the branch
/// targets. Return true on success, and the address in Target.
virtual bool
evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
diff --git a/contrib/llvm/include/llvm/MC/MCInstrDesc.h b/contrib/llvm/include/llvm/MC/MCInstrDesc.h
index ff4c756a66a1..3e000a2210e9 100644
--- a/contrib/llvm/include/llvm/MC/MCInstrDesc.h
+++ b/contrib/llvm/include/llvm/MC/MCInstrDesc.h
@@ -35,12 +35,12 @@ enum OperandConstraint {
EARLY_CLOBBER // Operand is an early clobber register operand
};
-/// \brief These are flags set on operands, but should be considered
+/// These are flags set on operands, but should be considered
/// private, all access should go through the MCOperandInfo accessors.
/// See the accessors for a description of what these are.
enum OperandFlags { LookupPtrRegClass = 0, Predicate, OptionalDef };
-/// \brief Operands are tagged with one of the values of this enum.
+/// Operands are tagged with one of the values of this enum.
enum OperandType {
OPERAND_UNKNOWN = 0,
OPERAND_IMMEDIATE = 1,
@@ -60,42 +60,39 @@ enum OperandType {
OPERAND_FIRST_TARGET = 12,
};
-enum GenericOperandType {
-};
-
}
-/// \brief This holds information about one operand of a machine instruction,
+/// This holds information about one operand of a machine instruction,
/// indicating the register class for register operands, etc.
class MCOperandInfo {
public:
- /// \brief This specifies the register class enumeration of the operand
+ /// This specifies the register class enumeration of the operand
/// if the operand is a register. If isLookupPtrRegClass is set, then this is
/// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to
/// get a dynamic register class.
int16_t RegClass;
- /// \brief These are flags from the MCOI::OperandFlags enum.
+ /// These are flags from the MCOI::OperandFlags enum.
uint8_t Flags;
- /// \brief Information about the type of the operand.
+ /// Information about the type of the operand.
uint8_t OperandType;
- /// \brief The lower 16 bits are used to specify which constraints are set.
+ /// The lower 16 bits are used to specify which constraints are set.
/// The higher 16 bits are used to specify the value of constraints (4 bits
/// each).
uint32_t Constraints;
- /// \brief Set if this operand is a pointer value and it requires a callback
+ /// Set if this operand is a pointer value and it requires a callback
/// to look up its register class.
bool isLookupPtrRegClass() const {
return Flags & (1 << MCOI::LookupPtrRegClass);
}
- /// \brief Set if this is one of the operands that made up of the predicate
+ /// Set if this is one of the operands that made up of the predicate
/// operand that controls an isPredicable() instruction.
bool isPredicate() const { return Flags & (1 << MCOI::Predicate); }
- /// \brief Set if this operand is a optional def.
+ /// Set if this operand is a optional def.
bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); }
bool isGenericType() const {
@@ -114,7 +111,7 @@ public:
//===----------------------------------------------------------------------===//
namespace MCID {
-/// \brief These should be considered private to the implementation of the
+/// These should be considered private to the implementation of the
/// MCInstrDesc class. Clients should use the predicate methods on MCInstrDesc,
/// not use these directly. These all correspond to bitfields in the
/// MCInstrDesc::Flags field.
@@ -130,6 +127,7 @@ enum Flag {
IndirectBranch,
Compare,
MoveImm,
+ MoveReg,
Bitcast,
Select,
DelaySlot,
@@ -151,11 +149,12 @@ enum Flag {
ExtractSubreg,
InsertSubreg,
Convergent,
- Add
+ Add,
+ Trap
};
}
-/// \brief Describe properties that are true of each instruction in the target
+/// Describe properties that are true of each instruction in the target
/// description file. This captures information about side effects, register
/// use and many other things. There is one instance of this struct for each
/// target instruction class, and the MachineInstr class points to this struct
@@ -177,12 +176,12 @@ public:
// deprecated due to a "complex" reason, below.
int64_t DeprecatedFeature;
- // A complex method to determine is a certain is deprecated or not, and return
- // the reason for deprecation.
+ // A complex method to determine if a certain instruction is deprecated or
+ // not, and return the reason for deprecation.
bool (*ComplexDeprecationInfo)(MCInst &, const MCSubtargetInfo &,
std::string &);
- /// \brief Returns the value of the specific constraint if
+ /// Returns the value of the specific constraint if
/// it is set. Returns -1 if it is not set.
int getOperandConstraint(unsigned OpNum,
MCOI::OperandConstraint Constraint) const {
@@ -194,15 +193,15 @@ public:
return -1;
}
- /// \brief Returns true if a certain instruction is deprecated and if so
+ /// Returns true if a certain instruction is deprecated and if so
/// returns the reason in \p Info.
bool getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI,
std::string &Info) const;
- /// \brief Return the opcode number for this descriptor.
+ /// Return the opcode number for this descriptor.
unsigned getOpcode() const { return Opcode; }
- /// \brief Return the number of declared MachineOperands for this
+ /// Return the number of declared MachineOperands for this
/// MachineInstruction. Note that variadic (isVariadic() returns true)
/// instructions may have additional operands at the end of the list, and note
/// that the machine instruction may include implicit register def/uses as
@@ -218,44 +217,50 @@ public:
return make_range(opInfo_begin(), opInfo_end());
}
- /// \brief Return the number of MachineOperands that are register
+ /// Return the number of MachineOperands that are register
/// definitions. Register definitions always occur at the start of the
/// machine operand list. This is the number of "outs" in the .td file,
/// and does not include implicit defs.
unsigned getNumDefs() const { return NumDefs; }
- /// \brief Return flags of this instruction.
+ /// Return flags of this instruction.
uint64_t getFlags() const { return Flags; }
- /// \brief Return true if this instruction can have a variable number of
+ /// Return true if this instruction can have a variable number of
/// operands. In this case, the variable operands will be after the normal
/// operands but before the implicit definitions and uses (if any are
/// present).
bool isVariadic() const { return Flags & (1ULL << MCID::Variadic); }
- /// \brief Set if this instruction has an optional definition, e.g.
+ /// Set if this instruction has an optional definition, e.g.
/// ARM instructions which can set condition code if 's' bit is set.
bool hasOptionalDef() const { return Flags & (1ULL << MCID::HasOptionalDef); }
- /// \brief Return true if this is a pseudo instruction that doesn't
+ /// Return true if this is a pseudo instruction that doesn't
/// correspond to a real machine instruction.
bool isPseudo() const { return Flags & (1ULL << MCID::Pseudo); }
- /// \brief Return true if the instruction is a return.
+ /// Return true if the instruction is a return.
bool isReturn() const { return Flags & (1ULL << MCID::Return); }
- /// \brief Return true if the instruction is an add instruction.
+ /// Return true if the instruction is an add instruction.
bool isAdd() const { return Flags & (1ULL << MCID::Add); }
- /// \brief Return true if the instruction is a call.
+ /// Return true if this instruction is a trap.
+ bool isTrap() const { return Flags & (1ULL << MCID::Trap); }
+
+ /// Return true if the instruction is a register to register move.
+ bool isMoveReg() const { return Flags & (1ULL << MCID::MoveReg); }
+
+ /// Return true if the instruction is a call.
bool isCall() const { return Flags & (1ULL << MCID::Call); }
- /// \brief Returns true if the specified instruction stops control flow
+ /// Returns true if the specified instruction stops control flow
/// from executing the instruction immediately following it. Examples include
/// unconditional branches and return instructions.
bool isBarrier() const { return Flags & (1ULL << MCID::Barrier); }
- /// \brief Returns true if this instruction part of the terminator for
+ /// Returns true if this instruction part of the terminator for
/// a basic block. Typically this is things like return and branch
/// instructions.
///
@@ -263,17 +268,17 @@ public:
/// but before control flow occurs.
bool isTerminator() const { return Flags & (1ULL << MCID::Terminator); }
- /// \brief Returns true if this is a conditional, unconditional, or
+ /// Returns true if this is a conditional, unconditional, or
/// indirect branch. Predicates below can be used to discriminate between
/// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to
/// get more information.
bool isBranch() const { return Flags & (1ULL << MCID::Branch); }
- /// \brief Return true if this is an indirect branch, such as a
+ /// Return true if this is an indirect branch, such as a
/// branch through a register.
bool isIndirectBranch() const { return Flags & (1ULL << MCID::IndirectBranch); }
- /// \brief Return true if this is a branch which may fall
+ /// Return true if this is a branch which may fall
/// through to the next instruction or may transfer control flow to some other
/// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more
/// information about this branch.
@@ -281,7 +286,7 @@ public:
return isBranch() & !isBarrier() & !isIndirectBranch();
}
- /// \brief Return true if this is a branch which always
+ /// Return true if this is a branch which always
/// transfers control flow to some other block. The
/// TargetInstrInfo::AnalyzeBranch method can be used to get more information
/// about this branch.
@@ -289,40 +294,40 @@ public:
return isBranch() & isBarrier() & !isIndirectBranch();
}
- /// \brief Return true if this is a branch or an instruction which directly
+ /// Return true if this is a branch or an instruction which directly
/// writes to the program counter. Considered 'may' affect rather than
/// 'does' affect as things like predication are not taken into account.
bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const;
- /// \brief Return true if this instruction has a predicate operand
+ /// Return true if this instruction has a predicate operand
/// that controls execution. It may be set to 'always', or may be set to other
/// values. There are various methods in TargetInstrInfo that can be used to
/// control and modify the predicate in this instruction.
bool isPredicable() const { return Flags & (1ULL << MCID::Predicable); }
- /// \brief Return true if this instruction is a comparison.
+ /// Return true if this instruction is a comparison.
bool isCompare() const { return Flags & (1ULL << MCID::Compare); }
- /// \brief Return true if this instruction is a move immediate
+ /// Return true if this instruction is a move immediate
/// (including conditional moves) instruction.
bool isMoveImmediate() const { return Flags & (1ULL << MCID::MoveImm); }
- /// \brief Return true if this instruction is a bitcast instruction.
+ /// Return true if this instruction is a bitcast instruction.
bool isBitcast() const { return Flags & (1ULL << MCID::Bitcast); }
- /// \brief Return true if this is a select instruction.
+ /// Return true if this is a select instruction.
bool isSelect() const { return Flags & (1ULL << MCID::Select); }
- /// \brief Return true if this instruction cannot be safely
+ /// Return true if this instruction cannot be safely
/// duplicated. For example, if the instruction has a unique labels attached
/// to it, duplicating it would cause multiple definition errors.
bool isNotDuplicable() const { return Flags & (1ULL << MCID::NotDuplicable); }
- /// \brief Returns true if the specified instruction has a delay slot which
+ /// Returns true if the specified instruction has a delay slot which
/// must be filled by the code generator.
bool hasDelaySlot() const { return Flags & (1ULL << MCID::DelaySlot); }
- /// \brief Return true for instructions that can be folded as memory operands
+ /// Return true for instructions that can be folded as memory operands
/// in other instructions. The most common use for this is instructions that
/// are simple loads from memory that don't modify the loaded value in any
/// way, but it can also be used for instructions that can be expressed as
@@ -331,7 +336,7 @@ public:
/// that return a value in their only virtual register definition.
bool canFoldAsLoad() const { return Flags & (1ULL << MCID::FoldableAsLoad); }
- /// \brief Return true if this instruction behaves
+ /// Return true if this instruction behaves
/// the same way as the generic REG_SEQUENCE instructions.
/// E.g., on ARM,
/// dX VMOVDRR rY, rZ
@@ -343,7 +348,7 @@ public:
/// override accordingly.
bool isRegSequenceLike() const { return Flags & (1ULL << MCID::RegSequence); }
- /// \brief Return true if this instruction behaves
+ /// Return true if this instruction behaves
/// the same way as the generic EXTRACT_SUBREG instructions.
/// E.g., on ARM,
/// rX, rY VMOVRRD dZ
@@ -358,7 +363,7 @@ public:
return Flags & (1ULL << MCID::ExtractSubreg);
}
- /// \brief Return true if this instruction behaves
+ /// Return true if this instruction behaves
/// the same way as the generic INSERT_SUBREG instructions.
/// E.g., on ARM,
/// dX = VSETLNi32 dY, rZ, Imm
@@ -371,7 +376,7 @@ public:
bool isInsertSubregLike() const { return Flags & (1ULL << MCID::InsertSubreg); }
- /// \brief Return true if this instruction is convergent.
+ /// Return true if this instruction is convergent.
///
/// Convergent instructions may not be made control-dependent on any
/// additional values.
@@ -381,18 +386,18 @@ public:
// Side Effect Analysis
//===--------------------------------------------------------------------===//
- /// \brief Return true if this instruction could possibly read memory.
+ /// Return true if this instruction could possibly read memory.
/// Instructions with this flag set are not necessarily simple load
/// instructions, they may load a value and modify it, for example.
bool mayLoad() const { return Flags & (1ULL << MCID::MayLoad); }
- /// \brief Return true if this instruction could possibly modify memory.
+ /// Return true if this instruction could possibly modify memory.
/// Instructions with this flag set are not necessarily simple store
/// instructions, they may store a modified value based on their operands, or
/// may not actually modify anything, for example.
bool mayStore() const { return Flags & (1ULL << MCID::MayStore); }
- /// \brief Return true if this instruction has side
+ /// Return true if this instruction has side
/// effects that are not modeled by other flags. This does not return true
/// for instructions whose effects are captured by:
///
@@ -412,7 +417,7 @@ public:
// Flags that indicate whether an instruction can be modified by a method.
//===--------------------------------------------------------------------===//
- /// \brief Return true if this may be a 2- or 3-address instruction (of the
+ /// Return true if this may be a 2- or 3-address instruction (of the
/// form "X = op Y, Z, ..."), which produces the same result if Y and Z are
/// exchanged. If this flag is set, then the
/// TargetInstrInfo::commuteInstruction method may be used to hack on the
@@ -424,7 +429,7 @@ public:
/// commute them.
bool isCommutable() const { return Flags & (1ULL << MCID::Commutable); }
- /// \brief Return true if this is a 2-address instruction which can be changed
+ /// Return true if this is a 2-address instruction which can be changed
/// into a 3-address instruction if needed. Doing this transformation can be
/// profitable in the register allocator, because it means that the
/// instruction can use a 2-address form if possible, but degrade into a less
@@ -442,7 +447,7 @@ public:
return Flags & (1ULL << MCID::ConvertibleTo3Addr);
}
- /// \brief Return true if this instruction requires custom insertion support
+ /// Return true if this instruction requires custom insertion support
/// when the DAG scheduler is inserting it into a machine basic block. If
/// this is true for the instruction, it basically means that it is a pseudo
/// instruction used at SelectionDAG time that is expanded out into magic code
@@ -454,13 +459,13 @@ public:
return Flags & (1ULL << MCID::UsesCustomInserter);
}
- /// \brief Return true if this instruction requires *adjustment* after
+ /// Return true if this instruction requires *adjustment* after
/// instruction selection by calling a target hook. For example, this can be
/// used to fill in ARM 's' optional operand depending on whether the
/// conditional flag register is used.
bool hasPostISelHook() const { return Flags & (1ULL << MCID::HasPostISelHook); }
- /// \brief Returns true if this instruction is a candidate for remat. This
+ /// Returns true if this instruction is a candidate for remat. This
/// flag is only used in TargetInstrInfo method isTriviallyRematerializable.
///
/// If this flag is set, the isReallyTriviallyReMaterializable()
@@ -470,7 +475,7 @@ public:
return Flags & (1ULL << MCID::Rematerializable);
}
- /// \brief Returns true if this instruction has the same cost (or less) than a
+ /// Returns true if this instruction has the same cost (or less) than a
/// move instruction. This is useful during certain types of optimizations
/// (e.g., remat during two-address conversion or machine licm) where we would
/// like to remat or hoist the instruction, but not if it costs more than
@@ -481,7 +486,7 @@ public:
/// for different subtargets.
bool isAsCheapAsAMove() const { return Flags & (1ULL << MCID::CheapAsAMove); }
- /// \brief Returns true if this instruction source operands have special
+ /// Returns true if this instruction source operands have special
/// register allocation requirements that are not captured by the operand
/// register classes. e.g. ARM::STRD's two source registers must be an even /
/// odd pair, ARM::STM registers have to be in ascending order. Post-register
@@ -491,7 +496,7 @@ public:
return Flags & (1ULL << MCID::ExtraSrcRegAllocReq);
}
- /// \brief Returns true if this instruction def operands have special register
+ /// Returns true if this instruction def operands have special register
/// allocation requirements that are not captured by the operand register
/// classes. e.g. ARM::LDRD's two def registers must be an even / odd pair,
/// ARM::LDM registers have to be in ascending order. Post-register
@@ -501,7 +506,7 @@ public:
return Flags & (1ULL << MCID::ExtraDefRegAllocReq);
}
- /// \brief Return a list of registers that are potentially read by any
+ /// Return a list of registers that are potentially read by any
/// instance of this machine instruction. For example, on X86, the "adc"
/// instruction adds two register operands and adds the carry bit in from the
/// flags register. In this case, the instruction is marked as implicitly
@@ -511,7 +516,7 @@ public:
/// This method returns null if the instruction has no implicit uses.
const MCPhysReg *getImplicitUses() const { return ImplicitUses; }
- /// \brief Return the number of implicit uses this instruction has.
+ /// Return the number of implicit uses this instruction has.
unsigned getNumImplicitUses() const {
if (!ImplicitUses)
return 0;
@@ -521,7 +526,7 @@ public:
return i;
}
- /// \brief Return a list of registers that are potentially written by any
+ /// Return a list of registers that are potentially written by any
/// instance of this machine instruction. For example, on X86, many
/// instructions implicitly set the flags register. In this case, they are
/// marked as setting the FLAGS. Likewise, many instructions always deposit
@@ -533,7 +538,7 @@ public:
/// This method returns null if the instruction has no implicit defs.
const MCPhysReg *getImplicitDefs() const { return ImplicitDefs; }
- /// \brief Return the number of implicit defs this instruct has.
+ /// Return the number of implicit defs this instruct has.
unsigned getNumImplicitDefs() const {
if (!ImplicitDefs)
return 0;
@@ -543,7 +548,7 @@ public:
return i;
}
- /// \brief Return true if this instruction implicitly
+ /// Return true if this instruction implicitly
/// uses the specified physical register.
bool hasImplicitUseOfPhysReg(unsigned Reg) const {
if (const MCPhysReg *ImpUses = ImplicitUses)
@@ -553,22 +558,22 @@ public:
return false;
}
- /// \brief Return true if this instruction implicitly
+ /// Return true if this instruction implicitly
/// defines the specified physical register.
bool hasImplicitDefOfPhysReg(unsigned Reg,
const MCRegisterInfo *MRI = nullptr) const;
- /// \brief Return the scheduling class for this instruction. The
+ /// Return the scheduling class for this instruction. The
/// scheduling class is an index into the InstrItineraryData table. This
/// returns zero if there is no known scheduling information for the
/// instruction.
unsigned getSchedClass() const { return SchedClass; }
- /// \brief Return the number of bytes in the encoding of this instruction,
+ /// Return the number of bytes in the encoding of this instruction,
/// or zero if the encoding size cannot be known from the opcode.
unsigned getSize() const { return Size; }
- /// \brief Find the index of the first operand in the
+ /// Find the index of the first operand in the
/// operand list that is used to represent the predicate. It returns -1 if
/// none is found.
int findFirstPredOperandIdx() const {
@@ -580,7 +585,7 @@ public:
return -1;
}
- /// \brief Return true if this instruction defines the specified physical
+ /// Return true if this instruction defines the specified physical
/// register, either explicitly or implicitly.
bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg,
const MCRegisterInfo &RI) const;
diff --git a/contrib/llvm/include/llvm/MC/MCInstrInfo.h b/contrib/llvm/include/llvm/MC/MCInstrInfo.h
index 80f1f320b7c2..18da87cf8929 100644
--- a/contrib/llvm/include/llvm/MC/MCInstrInfo.h
+++ b/contrib/llvm/include/llvm/MC/MCInstrInfo.h
@@ -20,7 +20,7 @@
namespace llvm {
//---------------------------------------------------------------------------
-/// \brief Interface to description of machine instruction set.
+/// Interface to description of machine instruction set.
class MCInstrInfo {
const MCInstrDesc *Desc; // Raw array to allow static init'n
const unsigned *InstrNameIndices; // Array for name indices in InstrNameData
@@ -28,7 +28,7 @@ class MCInstrInfo {
unsigned NumOpcodes; // Number of entries in the desc array
public:
- /// \brief Initialize MCInstrInfo, called by TableGen auto-generated routines.
+ /// Initialize MCInstrInfo, called by TableGen auto-generated routines.
/// *DO NOT USE*.
void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND,
unsigned NO) {
@@ -40,14 +40,14 @@ public:
unsigned getNumOpcodes() const { return NumOpcodes; }
- /// \brief Return the machine instruction descriptor that corresponds to the
+ /// Return the machine instruction descriptor that corresponds to the
/// specified instruction opcode.
const MCInstrDesc &get(unsigned Opcode) const {
assert(Opcode < NumOpcodes && "Invalid opcode!");
return Desc[Opcode];
}
- /// \brief Returns the name for the instructions with the given opcode.
+ /// Returns the name for the instructions with the given opcode.
StringRef getName(unsigned Opcode) const {
assert(Opcode < NumOpcodes && "Invalid opcode!");
return StringRef(&InstrNameData[InstrNameIndices[Opcode]]);
diff --git a/contrib/llvm/include/llvm/MC/MCInstrItineraries.h b/contrib/llvm/include/llvm/MC/MCInstrItineraries.h
index 4443dd113715..fe81376e0db7 100644
--- a/contrib/llvm/include/llvm/MC/MCInstrItineraries.h
+++ b/contrib/llvm/include/llvm/MC/MCInstrItineraries.h
@@ -67,12 +67,12 @@ struct InstrStage {
int NextCycles_; ///< Number of machine cycles to next stage
ReservationKinds Kind_; ///< Kind of the FU reservation
- /// \brief Returns the number of cycles the stage is occupied.
+ /// Returns the number of cycles the stage is occupied.
unsigned getCycles() const {
return Cycles_;
}
- /// \brief Returns the choice of FUs.
+ /// Returns the choice of FUs.
unsigned getUnits() const {
return Units_;
}
@@ -81,7 +81,7 @@ struct InstrStage {
return Kind_;
}
- /// \brief Returns the number of cycles from the start of this stage to the
+ /// Returns the number of cycles from the start of this stage to the
/// start of the next stage in the itinerary
unsigned getNextCycles() const {
return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_;
@@ -94,11 +94,11 @@ struct InstrStage {
/// cycle in which operands are read and written.
///
struct InstrItinerary {
- int NumMicroOps; ///< # of micro-ops, -1 means it's variable
- unsigned FirstStage; ///< Index of first stage in itinerary
- unsigned LastStage; ///< Index of last + 1 stage in itinerary
- unsigned FirstOperandCycle; ///< Index of first operand rd/wr
- unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr
+ int16_t NumMicroOps; ///< # of micro-ops, -1 means it's variable
+ uint16_t FirstStage; ///< Index of first stage in itinerary
+ uint16_t LastStage; ///< Index of last + 1 stage in itinerary
+ uint16_t FirstOperandCycle; ///< Index of first operand rd/wr
+ uint16_t LastOperandCycle; ///< Index of last + 1 operand rd/wr
};
//===----------------------------------------------------------------------===//
@@ -120,28 +120,28 @@ public:
: SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F),
Itineraries(SchedModel.InstrItineraries) {}
- /// \brief Returns true if there are no itineraries.
+ /// Returns true if there are no itineraries.
bool isEmpty() const { return Itineraries == nullptr; }
- /// \brief Returns true if the index is for the end marker itinerary.
+ /// Returns true if the index is for the end marker itinerary.
bool isEndMarker(unsigned ItinClassIndx) const {
- return ((Itineraries[ItinClassIndx].FirstStage == ~0U) &&
- (Itineraries[ItinClassIndx].LastStage == ~0U));
+ return ((Itineraries[ItinClassIndx].FirstStage == UINT16_MAX) &&
+ (Itineraries[ItinClassIndx].LastStage == UINT16_MAX));
}
- /// \brief Return the first stage of the itinerary.
+ /// Return the first stage of the itinerary.
const InstrStage *beginStage(unsigned ItinClassIndx) const {
unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage;
return Stages + StageIdx;
}
- /// \brief Return the last+1 stage of the itinerary.
+ /// Return the last+1 stage of the itinerary.
const InstrStage *endStage(unsigned ItinClassIndx) const {
unsigned StageIdx = Itineraries[ItinClassIndx].LastStage;
return Stages + StageIdx;
}
- /// \brief Return the total stage latency of the given class. The latency is
+ /// Return the total stage latency of the given class. The latency is
/// the maximum completion time for any stage in the itinerary. If no stages
/// exist, it defaults to one cycle.
unsigned getStageLatency(unsigned ItinClassIndx) const {
@@ -160,7 +160,7 @@ public:
return Latency;
}
- /// \brief Return the cycle for the given class and operand. Return -1 if no
+ /// Return the cycle for the given class and operand. Return -1 if no
/// cycle is specified for the operand.
int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const {
if (isEmpty())
@@ -174,7 +174,7 @@ public:
return (int)OperandCycles[FirstIdx + OperandIdx];
}
- /// \brief Return true if there is a pipeline forwarding between instructions
+ /// Return true if there is a pipeline forwarding between instructions
/// of itinerary classes DefClass and UseClasses so that value produced by an
/// instruction of itinerary class DefClass, operand index DefIdx can be
/// bypassed when it's read by an instruction of itinerary class UseClass,
@@ -197,7 +197,7 @@ public:
Forwardings[FirstUseIdx + UseIdx];
}
- /// \brief Compute and return the use operand latency of a given itinerary
+ /// Compute and return the use operand latency of a given itinerary
/// class and operand index if the value is produced by an instruction of the
/// specified itinerary class and def operand index.
int getOperandLatency(unsigned DefClass, unsigned DefIdx,
@@ -221,7 +221,7 @@ public:
return UseCycle;
}
- /// \brief Return the number of micro-ops that the given class decodes to.
+ /// Return the number of micro-ops that the given class decodes to.
/// Return -1 for classes that require dynamic lookup via TargetInstrInfo.
int getNumMicroOps(unsigned ItinClassIndx) const {
if (isEmpty())
diff --git a/contrib/llvm/include/llvm/MC/MCLabel.h b/contrib/llvm/include/llvm/MC/MCLabel.h
index b6579fd654ab..aaf70691fc01 100644
--- a/contrib/llvm/include/llvm/MC/MCLabel.h
+++ b/contrib/llvm/include/llvm/MC/MCLabel.h
@@ -18,11 +18,11 @@ namespace llvm {
class raw_ostream;
-/// \brief Instances of this class represent a label name in the MC file,
+/// Instances of this class represent a label name in the MC file,
/// and MCLabel are created and uniqued by the MCContext class. MCLabel
/// should only be constructed for valid instances in the object file.
class MCLabel {
- // \brief The instance number of this Directional Local Label.
+ // The instance number of this Directional Local Label.
unsigned Instance;
private: // MCContext creates and uniques these.
@@ -34,16 +34,16 @@ public:
MCLabel(const MCLabel &) = delete;
MCLabel &operator=(const MCLabel &) = delete;
- /// \brief Get the current instance of this Directional Local Label.
+ /// Get the current instance of this Directional Local Label.
unsigned getInstance() const { return Instance; }
- /// \brief Increment the current instance of this Directional Local Label.
+ /// Increment the current instance of this Directional Local Label.
unsigned incInstance() { return ++Instance; }
- /// \brief Print the value to the stream \p OS.
+ /// Print the value to the stream \p OS.
void print(raw_ostream &OS) const;
- /// \brief Print the value to stderr.
+ /// Print the value to stderr.
void dump() const;
};
diff --git a/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h b/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h
index 594869f74632..22fbeb72a4ec 100644
--- a/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h
+++ b/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h
@@ -26,7 +26,7 @@ namespace llvm {
class MachObjectWriter;
-class MCMachObjectTargetWriter {
+class MCMachObjectTargetWriter : public MCObjectTargetWriter {
const unsigned Is64Bit : 1;
const uint32_t CPUType;
const uint32_t CPUSubtype;
@@ -43,6 +43,11 @@ protected:
public:
virtual ~MCMachObjectTargetWriter();
+ virtual Triple::ObjectFormatType getFormat() const { return Triple::MachO; }
+ static bool classof(const MCObjectTargetWriter *W) {
+ return W->getFormat() == Triple::MachO;
+ }
+
/// \name Lifetime Management
/// @{
@@ -116,11 +121,15 @@ class MachObjectWriter : public MCObjectWriter {
MachSymbolData *findSymbolData(const MCSymbol &Sym);
+ void writeWithPadding(StringRef Str, uint64_t Size);
+
public:
MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
raw_pwrite_stream &OS, bool IsLittleEndian)
- : MCObjectWriter(OS, IsLittleEndian),
- TargetObjectWriter(std::move(MOTW)) {}
+ : TargetObjectWriter(std::move(MOTW)),
+ W(OS, IsLittleEndian ? support::little : support::big) {}
+
+ support::endian::Writer W;
const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
@@ -260,7 +269,7 @@ public:
const MCFragment &FB, bool InSet,
bool IsPCRel) const override;
- void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+ uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
};
/// Construct a new Mach-O writer instance.
diff --git a/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h b/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h
index 79bf2b97015f..3a27ef8c8fee 100644
--- a/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -14,7 +14,9 @@
#ifndef LLVM_MC_MCOBJECTFILEINFO_H
#define LLVM_MC_MCOBJECTFILEINFO_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/CodeGen.h"
namespace llvm {
@@ -79,6 +81,7 @@ protected:
MCSection *DwarfAbbrevSection;
MCSection *DwarfInfoSection;
MCSection *DwarfLineSection;
+ MCSection *DwarfLineStrSection;
MCSection *DwarfFrameSection;
MCSection *DwarfPubTypesSection;
const MCSection *DwarfDebugInlineSection;
@@ -91,11 +94,11 @@ protected:
// can be enabled by a compiler flag.
MCSection *DwarfPubNamesSection;
- /// DWARF5 Experimental Debug Info Sections
- /// DwarfAccelNamesSection, DwarfAccelObjCSection,
- /// DwarfAccelNamespaceSection, DwarfAccelTypesSection -
- /// If we use the DWARF accelerated hash tables then we want to emit these
- /// sections.
+ /// Accelerator table sections. DwarfDebugNamesSection is the DWARF v5
+ /// accelerator table, while DwarfAccelNamesSection, DwarfAccelObjCSection,
+ /// DwarfAccelNamespaceSection, DwarfAccelTypesSection are pre-DWARF v5
+ /// extensions.
+ MCSection *DwarfDebugNamesSection;
MCSection *DwarfAccelNamesSection;
MCSection *DwarfAccelObjCSection;
MCSection *DwarfAccelNamespaceSection;
@@ -113,6 +116,11 @@ protected:
/// The DWARF v5 string offset and address table sections.
MCSection *DwarfStrOffSection;
MCSection *DwarfAddrSection;
+ /// The DWARF v5 range list section.
+ MCSection *DwarfRnglistsSection;
+
+ /// The DWARF v5 range list section for fission.
+ MCSection *DwarfRnglistsDWOSection;
// These are for Fission DWP files.
MCSection *DwarfCUIndexSection;
@@ -157,6 +165,7 @@ protected:
/// Section containing metadata on function stack sizes.
MCSection *StackSizesSection;
+ mutable DenseMap<const MCSymbol *, unsigned> StackSizesUniquing;
// ELF specific sections.
MCSection *DataRelROSection;
@@ -182,6 +191,7 @@ protected:
MCSection *ConstTextCoalSection;
MCSection *ConstDataSection;
MCSection *DataCoalSection;
+ MCSection *ConstDataCoalSection;
MCSection *DataCommonSection;
MCSection *DataBSSSection;
MCSection *FourByteConstantSection;
@@ -196,6 +206,7 @@ protected:
MCSection *PDataSection;
MCSection *XDataSection;
MCSection *SXDataSection;
+ MCSection *GFIDsSection;
public:
void InitMCObjectFileInfo(const Triple &TT, bool PIC, MCContext &ctx,
@@ -233,6 +244,7 @@ public:
MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; }
MCSection *getDwarfInfoSection() const { return DwarfInfoSection; }
MCSection *getDwarfLineSection() const { return DwarfLineSection; }
+ MCSection *getDwarfLineStrSection() const { return DwarfLineStrSection; }
MCSection *getDwarfFrameSection() const { return DwarfFrameSection; }
MCSection *getDwarfPubNamesSection() const { return DwarfPubNamesSection; }
MCSection *getDwarfPubTypesSection() const { return DwarfPubTypesSection; }
@@ -249,9 +261,12 @@ public:
MCSection *getDwarfLocSection() const { return DwarfLocSection; }
MCSection *getDwarfARangesSection() const { return DwarfARangesSection; }
MCSection *getDwarfRangesSection() const { return DwarfRangesSection; }
+ MCSection *getDwarfRnglistsSection() const { return DwarfRnglistsSection; }
MCSection *getDwarfMacinfoSection() const { return DwarfMacinfoSection; }
- // DWARF5 Experimental Debug Info Sections
+ MCSection *getDwarfDebugNamesSection() const {
+ return DwarfDebugNamesSection;
+ }
MCSection *getDwarfAccelNamesSection() const {
return DwarfAccelNamesSection;
}
@@ -272,6 +287,9 @@ public:
MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; }
MCSection *getDwarfStrOffSection() const { return DwarfStrOffSection; }
MCSection *getDwarfAddrSection() const { return DwarfAddrSection; }
+ MCSection *getDwarfRnglistsDWOSection() const {
+ return DwarfRnglistsDWOSection;
+ }
MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; }
MCSection *getDwarfTUIndexSection() const { return DwarfTUIndexSection; }
MCSection *getDwarfSwiftASTSection() const { return DwarfSwiftASTSection; }
@@ -293,7 +311,7 @@ public:
MCSection *getStackMapSection() const { return StackMapSection; }
MCSection *getFaultMapSection() const { return FaultMapSection; }
- MCSection *getStackSizesSection() const { return StackSizesSection; }
+ MCSection *getStackSizesSection(const MCSection &TextSec) const;
// ELF specific sections.
MCSection *getDataRelROSection() const { return DataRelROSection; }
@@ -323,6 +341,9 @@ public:
}
const MCSection *getConstDataSection() const { return ConstDataSection; }
const MCSection *getDataCoalSection() const { return DataCoalSection; }
+ const MCSection *getConstDataCoalSection() const {
+ return ConstDataCoalSection;
+ }
const MCSection *getDataCommonSection() const { return DataCommonSection; }
MCSection *getDataBSSSection() const { return DataBSSSection; }
const MCSection *getFourByteConstantSection() const {
@@ -349,6 +370,7 @@ public:
MCSection *getPDataSection() const { return PDataSection; }
MCSection *getXDataSection() const { return XDataSection; }
MCSection *getSXDataSection() const { return SXDataSection; }
+ MCSection *getGFIDsSection() const { return GFIDsSection; }
MCSection *getEHFrameSection() {
return EHFrameSection;
diff --git a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h
index 43ed00b4a7a7..035206dce939 100644
--- a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h
+++ b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h
@@ -26,7 +26,7 @@ class MCAsmBackend;
class raw_ostream;
class raw_pwrite_stream;
-/// \brief Streaming object file generation interface.
+/// Streaming object file generation interface.
///
/// This class provides an implementation of the MCStreamer interface which is
/// suitable for use with the assembler backend. Specific object file formats
@@ -34,9 +34,6 @@ class raw_pwrite_stream;
/// to that file format or custom semantics expected by the object writer
/// implementation.
class MCObjectStreamer : public MCStreamer {
- std::unique_ptr<MCObjectWriter> ObjectWriter;
- std::unique_ptr<MCAsmBackend> TAB;
- std::unique_ptr<MCCodeEmitter> Emitter;
std::unique_ptr<MCAssembler> Assembler;
MCSection::iterator CurInsertionPoint;
bool EmitEHFrame;
@@ -51,7 +48,7 @@ class MCObjectStreamer : public MCStreamer {
protected:
MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> OW,
std::unique_ptr<MCCodeEmitter> Emitter);
~MCObjectStreamer();
@@ -76,7 +73,9 @@ public:
/// Get a data fragment to write into, creating a new one if the current
/// fragment is not a data fragment.
- MCDataFragment *getOrCreateDataFragment();
+ /// Optionally a \p STI can be passed in so that a new fragment is created
+ /// if the Subtarget differs from the current fragment.
+ MCDataFragment *getOrCreateDataFragment(const MCSubtargetInfo* STI = nullptr);
MCPaddingFragment *getOrCreatePaddingFragment();
protected:
@@ -91,8 +90,11 @@ protected:
public:
void visitUsedSymbol(const MCSymbol &Sym) override;
- MCAssembler &getAssembler() { return *Assembler; }
+ /// Create a dummy fragment to assign any pending labels.
+ void flushPendingLabels() { flushPendingLabels(nullptr); }
+ MCAssembler &getAssembler() { return *Assembler; }
+ MCAssembler *getAssemblerPtr() override;
/// \name MCStreamer Interface
/// @{
@@ -108,7 +110,7 @@ public:
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
bool = false) override;
- /// \brief Emit an instruction to a special fragment, because this instruction
+ /// Emit an instruction to a special fragment, because this instruction
/// can change its size during relaxation.
virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &);
@@ -159,7 +161,8 @@ public:
void EmitGPRel32Value(const MCExpr *Value) override;
void EmitGPRel64Value(const MCExpr *Value) override;
bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc) override;
+ const MCExpr *Expr, SMLoc Loc,
+ const MCSubtargetInfo &STI) override;
using MCStreamer::emitFill;
void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
SMLoc Loc = SMLoc()) override;
@@ -167,6 +170,9 @@ public:
SMLoc Loc = SMLoc()) override;
void EmitFileDirective(StringRef Filename) override;
+ void EmitAddrsig() override;
+ void EmitAddrsigSym(const MCSymbol *Sym) override;
+
void FinishImpl() override;
/// Emit the absolute difference between two symbols if possible.
@@ -179,6 +185,9 @@ public:
void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
unsigned Size) override;
+ void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
+ const MCSymbol *Lo) override;
+
bool mayHaveInstructions(MCSection &Sec) const override;
};
diff --git a/contrib/llvm/include/llvm/MC/MCObjectWriter.h b/contrib/llvm/include/llvm/MC/MCObjectWriter.h
index cd90690fb186..8bae2bf20083 100644
--- a/contrib/llvm/include/llvm/MC/MCObjectWriter.h
+++ b/contrib/llvm/include/llvm/MC/MCObjectWriter.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/raw_ostream.h"
@@ -36,22 +37,9 @@ class MCValue;
/// points. Once assembly is complete, the object writer is given the
/// MCAssembler instance, which contains all the symbol and section data which
/// should be emitted as part of writeObject().
-///
-/// The object writer also contains a number of helper methods for writing
-/// binary data to the output stream.
class MCObjectWriter {
- raw_pwrite_stream *OS;
-
protected:
- unsigned IsLittleEndian : 1;
-
- // Can only create subclasses.
- MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian)
- : OS(&OS), IsLittleEndian(IsLittleEndian) {}
-
- unsigned getInitialOffset() {
- return OS->tell();
- }
+ MCObjectWriter() = default;
public:
MCObjectWriter(const MCObjectWriter &) = delete;
@@ -61,11 +49,6 @@ public:
/// lifetime management
virtual void reset() {}
- bool isLittleEndian() const { return IsLittleEndian; }
-
- raw_pwrite_stream &getStream() { return *OS; }
- void setStream(raw_pwrite_stream &NewOS) { OS = &NewOS; }
-
/// \name High-Level API
/// @{
@@ -109,90 +92,31 @@ public:
bool InSet,
bool IsPCRel) const;
- /// Write the object file.
+ /// Tell the object writer to emit an address-significance table during
+ /// writeObject(). If this function is not called, all symbols are treated as
+ /// address-significant.
+ virtual void emitAddrsigSection() {}
+
+ /// Record the given symbol in the address-significance table to be written
+ /// diring writeObject().
+ virtual void addAddrsigSymbol(const MCSymbol *Sym) {}
+
+ /// Write the object file and returns the number of bytes written.
///
/// This routine is called by the assembler after layout and relaxation is
/// complete, fixups have been evaluated and applied, and relocations
/// generated.
- virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0;
+ virtual uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0;
/// @}
- /// \name Binary Output
- /// @{
-
- void write8(uint8_t Value) { *OS << char(Value); }
-
- void writeLE16(uint16_t Value) {
- support::endian::Writer<support::little>(*OS).write(Value);
- }
-
- void writeLE32(uint32_t Value) {
- support::endian::Writer<support::little>(*OS).write(Value);
- }
-
- void writeLE64(uint64_t Value) {
- support::endian::Writer<support::little>(*OS).write(Value);
- }
-
- void writeBE16(uint16_t Value) {
- support::endian::Writer<support::big>(*OS).write(Value);
- }
-
- void writeBE32(uint32_t Value) {
- support::endian::Writer<support::big>(*OS).write(Value);
- }
-
- void writeBE64(uint64_t Value) {
- support::endian::Writer<support::big>(*OS).write(Value);
- }
-
- void write16(uint16_t Value) {
- if (IsLittleEndian)
- writeLE16(Value);
- else
- writeBE16(Value);
- }
-
- void write32(uint32_t Value) {
- if (IsLittleEndian)
- writeLE32(Value);
- else
- writeBE32(Value);
- }
-
- void write64(uint64_t Value) {
- if (IsLittleEndian)
- writeLE64(Value);
- else
- writeBE64(Value);
- }
-
- void WriteZeros(unsigned N) {
- const char Zeros[16] = {0};
-
- for (unsigned i = 0, e = N / 16; i != e; ++i)
- *OS << StringRef(Zeros, 16);
-
- *OS << StringRef(Zeros, N % 16);
- }
-
- void writeBytes(const SmallVectorImpl<char> &ByteVec,
- unsigned ZeroFillSize = 0) {
- writeBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
- }
-
- void writeBytes(StringRef Str, unsigned ZeroFillSize = 0) {
- // TODO: this version may need to go away once all fragment contents are
- // converted to SmallVector<char, N>
- assert(
- (ZeroFillSize == 0 || Str.size() <= ZeroFillSize) &&
- "data size greater than fill size, unexpected large write will occur");
- *OS << Str;
- if (ZeroFillSize)
- WriteZeros(ZeroFillSize - Str.size());
- }
+};
- /// @}
+/// Base class for classes that define behaviour that is specific to both the
+/// target and the object format.
+class MCObjectTargetWriter {
+public:
+ virtual ~MCObjectTargetWriter() = default;
+ virtual Triple::ObjectFormatType getFormat() const = 0;
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h
index 7836ece2d688..10550b3370e8 100644
--- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h
+++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h
@@ -10,11 +10,9 @@
#ifndef LLVM_MC_MCPARSER_MCASMLEXER_H
#define LLVM_MC_MCPARSER_MCASMLEXER_H
-#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/SMLoc.h"
+#include "llvm/MC/MCAsmMacro.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -23,113 +21,6 @@
namespace llvm {
-/// Target independent representation for an assembler token.
-class AsmToken {
-public:
- enum TokenKind {
- // Markers
- Eof, Error,
-
- // String values.
- Identifier,
- String,
-
- // Integer values.
- Integer,
- BigNum, // larger than 64 bits
-
- // Real values.
- Real,
-
- // Comments
- Comment,
- HashDirective,
- // No-value.
- EndOfStatement,
- Colon,
- Space,
- Plus, Minus, Tilde,
- Slash, // '/'
- BackSlash, // '\'
- LParen, RParen, LBrac, RBrac, LCurly, RCurly,
- Star, Dot, Comma, Dollar, Equal, EqualEqual,
-
- Pipe, PipePipe, Caret,
- Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash,
- Less, LessEqual, LessLess, LessGreater,
- Greater, GreaterEqual, GreaterGreater, At,
-
- // MIPS unary expression operators such as %neg.
- PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi,
- PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo,
- PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi,
- PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi,
- PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi,
- PercentTprel_Lo
- };
-
-private:
- TokenKind Kind;
-
- /// A reference to the entire token contents; this is always a pointer into
- /// a memory buffer owned by the source manager.
- StringRef Str;
-
- APInt IntVal;
-
-public:
- AsmToken() = default;
- AsmToken(TokenKind Kind, StringRef Str, APInt IntVal)
- : Kind(Kind), Str(Str), IntVal(std::move(IntVal)) {}
- AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0)
- : Kind(Kind), Str(Str), IntVal(64, IntVal, true) {}
-
- TokenKind getKind() const { return Kind; }
- bool is(TokenKind K) const { return Kind == K; }
- bool isNot(TokenKind K) const { return Kind != K; }
-
- SMLoc getLoc() const;
- SMLoc getEndLoc() const;
- SMRange getLocRange() const;
-
- /// Get the contents of a string token (without quotes).
- StringRef getStringContents() const {
- assert(Kind == String && "This token isn't a string!");
- return Str.slice(1, Str.size() - 1);
- }
-
- /// Get the identifier string for the current token, which should be an
- /// identifier or a string. This gets the portion of the string which should
- /// be used as the identifier, e.g., it does not include the quotes on
- /// strings.
- StringRef getIdentifier() const {
- if (Kind == Identifier)
- return getString();
- return getStringContents();
- }
-
- /// Get the string for the current token, this includes all characters (for
- /// example, the quotes on strings) in the token.
- ///
- /// The returned StringRef points into the source manager's memory buffer, and
- /// is safe to store across calls to Lex().
- StringRef getString() const { return Str; }
-
- // FIXME: Don't compute this in advance, it makes every token larger, and is
- // also not generally what we want (it is nicer for recovery etc. to lex 123br
- // as a single token, then diagnose as an invalid number).
- int64_t getIntVal() const {
- assert(Kind == Integer && "This token isn't an integer!");
- return IntVal.getZExtValue();
- }
-
- APInt getAPIntVal() const {
- assert((Kind == Integer || Kind == BigNum) &&
- "This token isn't an integer!");
- return IntVal;
- }
-};
-
/// A callback class which is notified of each comment in an assembly file as
/// it is lexed.
class AsmCommentConsumer {
diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h
index 0f79c4777ea9..0d56f36fbae8 100644
--- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h
@@ -91,7 +91,7 @@ private:
IdKind Kind;
};
-/// \brief Generic Sema callback for assembly parser.
+/// Generic Sema callback for assembly parser.
class MCAsmParserSemaCallback {
public:
virtual ~MCAsmParserSemaCallback();
@@ -105,7 +105,7 @@ public:
unsigned &Offset) = 0;
};
-/// \brief Generic assembler parser interface, for use by target specific
+/// Generic assembler parser interface, for use by target specific
/// assembly parsers.
class MCAsmParser {
public:
@@ -153,7 +153,7 @@ public:
virtual MCContext &getContext() = 0;
- /// \brief Return the output streamer for the assembler.
+ /// Return the output streamer for the assembler.
virtual MCStreamer &getStreamer() = 0;
MCTargetAsmParser &getTargetParser() const { return *TargetParser; }
@@ -168,13 +168,13 @@ public:
void setEnablePrintSchedInfo(bool Value) { EnablePrintSchedInfo = Value; }
bool shouldPrintSchedInfo() { return EnablePrintSchedInfo; }
- /// \brief Run the parser on the input source buffer.
+ /// Run the parser on the input source buffer.
virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0;
virtual void setParsingInlineAsm(bool V) = 0;
virtual bool isParsingInlineAsm() = 0;
- /// \brief Parse MS-style inline assembly.
+ /// Parse MS-style inline assembly.
virtual bool parseMSInlineAsm(
void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
@@ -182,22 +182,22 @@ public:
SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0;
- /// \brief Emit a note at the location \p L, with the message \p Msg.
+ /// Emit a note at the location \p L, with the message \p Msg.
virtual void Note(SMLoc L, const Twine &Msg, SMRange Range = None) = 0;
- /// \brief Emit a warning at the location \p L, with the message \p Msg.
+ /// Emit a warning at the location \p L, with the message \p Msg.
///
/// \return The return value is true, if warnings are fatal.
virtual bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) = 0;
- /// \brief Return an error at the location \p L, with the message \p Msg. This
+ /// Return an error at the location \p L, with the message \p Msg. This
/// may be modified before being emitted.
///
/// \return The return value is always true, as an idiomatic convenience to
/// clients.
bool Error(SMLoc L, const Twine &Msg, SMRange Range = None);
- /// \brief Emit an error at the location \p L, with the message \p Msg.
+ /// Emit an error at the location \p L, with the message \p Msg.
///
/// \return The return value is always true, as an idiomatic convenience to
/// clients.
@@ -214,21 +214,23 @@ public:
return rv;
}
+ void clearPendingErrors() { PendingErrors.clear(); }
+
bool addErrorSuffix(const Twine &Suffix);
- /// \brief Get the next AsmToken in the stream, possibly handling file
+ /// Get the next AsmToken in the stream, possibly handling file
/// inclusion first.
virtual const AsmToken &Lex() = 0;
- /// \brief Get the current AsmToken from the stream.
+ /// Get the current AsmToken from the stream.
const AsmToken &getTok() const;
- /// \brief Report an error at the current lexer location.
+ /// Report an error at the current lexer location.
bool TokError(const Twine &Msg, SMRange Range = None);
bool parseTokenLoc(SMLoc &Loc);
bool parseToken(AsmToken::TokenKind T, const Twine &Msg = "unexpected token");
- /// \brief Attempt to parse and consume token, returning true on
+ /// Attempt to parse and consume token, returning true on
/// success.
bool parseOptionalToken(AsmToken::TokenKind T);
@@ -241,23 +243,23 @@ public:
bool check(bool P, const Twine &Msg);
bool check(bool P, SMLoc Loc, const Twine &Msg);
- /// \brief Parse an identifier or string (as a quoted identifier) and set \p
+ /// Parse an identifier or string (as a quoted identifier) and set \p
/// Res to the identifier contents.
virtual bool parseIdentifier(StringRef &Res) = 0;
- /// \brief Parse up to the end of statement and return the contents from the
+ /// Parse up to the end of statement and return the contents from the
/// current token until the end of the statement; the current token on exit
/// will be either the EndOfStatement or EOF.
virtual StringRef parseStringToEndOfStatement() = 0;
- /// \brief Parse the current token as a string which may include escaped
+ /// Parse the current token as a string which may include escaped
/// characters and return the string contents.
virtual bool parseEscapedString(std::string &Data) = 0;
- /// \brief Skip to the end of the current statement, for error recovery.
+ /// Skip to the end of the current statement, for error recovery.
virtual void eatToEndOfStatement() = 0;
- /// \brief Parse an arbitrary expression.
+ /// Parse an arbitrary expression.
///
/// \param Res - The value of the expression. The result is undefined
/// on error.
@@ -265,14 +267,14 @@ public:
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0;
bool parseExpression(const MCExpr *&Res);
- /// \brief Parse a primary expression.
+ /// Parse a primary expression.
///
/// \param Res - The value of the expression. The result is undefined
/// on error.
/// \return - False on success.
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0;
- /// \brief Parse an arbitrary expression, assuming that an initial '(' has
+ /// Parse an arbitrary expression, assuming that an initial '(' has
/// already been consumed.
///
/// \param Res - The value of the expression. The result is undefined
@@ -280,19 +282,19 @@ public:
/// \return - False on success.
virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0;
- /// \brief Parse an expression which must evaluate to an absolute value.
+ /// Parse an expression which must evaluate to an absolute value.
///
/// \param Res - The value of the absolute expression. The result is undefined
/// on error.
/// \return - False on success.
virtual bool parseAbsoluteExpression(int64_t &Res) = 0;
- /// \brief Ensure that we have a valid section set in the streamer. Otherwise,
+ /// Ensure that we have a valid section set in the streamer. Otherwise,
/// report an error and switch to .text.
/// \return - False on success.
virtual bool checkForValidSection() = 0;
- /// \brief Parse an arbitrary expression of a specified parenthesis depth,
+ /// Parse an arbitrary expression of a specified parenthesis depth,
/// assuming that the initial '(' characters have already been consumed.
///
/// \param ParenDepth - Specifies how many trailing expressions outside the
@@ -304,7 +306,7 @@ public:
SMLoc &EndLoc) = 0;
};
-/// \brief Create an MCAsmParser instance.
+/// Create an MCAsmParser instance.
MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &,
const MCAsmInfo &, unsigned CB = 0);
diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
index ffb8d7a4a26a..1a132bceddc5 100644
--- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
+++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
@@ -20,7 +20,7 @@ namespace llvm {
class Twine;
-/// \brief Generic interface for extending the MCAsmParser,
+/// Generic interface for extending the MCAsmParser,
/// which is implemented by target and object file assembly parser
/// implementations.
class MCAsmParserExtension {
@@ -45,7 +45,7 @@ public:
MCAsmParserExtension &operator=(const MCAsmParserExtension &) = delete;
virtual ~MCAsmParserExtension();
- /// \brief Initialize the extension for parsing using the given \p Parser.
+ /// Initialize the extension for parsing using the given \p Parser.
/// The extension should use the AsmParser interfaces to register its
/// parsing routines.
virtual void Initialize(MCAsmParser &Parser);
diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h
index 84173bb9cb8e..259113bc3860 100644
--- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h
+++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h
@@ -25,7 +25,7 @@ namespace MCParserUtils {
/// On success, returns false and sets the Symbol and Value output parameters.
bool parseAssignmentExpression(StringRef Name, bool allow_redef,
MCAsmParser &Parser, MCSymbol *&Symbol,
- const MCExpr *&Value);
+ const MCExpr *&Value, bool AllowExtendedExpr = false);
} // namespace MCParserUtils
diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 9f8550c3887c..2d188a6755e1 100644
--- a/contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -14,6 +14,7 @@
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/SMLoc.h"
@@ -133,6 +134,53 @@ enum OperandMatchResultTy {
MatchOperand_ParseFail // operand matched but had errors
};
+enum class DiagnosticPredicateTy {
+ Match,
+ NearMatch,
+ NoMatch,
+};
+
+// When an operand is parsed, the assembler will try to iterate through a set of
+// possible operand classes that the operand might match and call the
+// corresponding PredicateMethod to determine that.
+//
+// If there are two AsmOperands that would give a specific diagnostic if there
+// is no match, there is currently no mechanism to distinguish which operand is
+// a closer match. The DiagnosticPredicate distinguishes between 'completely
+// no match' and 'near match', so the assembler can decide whether to give a
+// specific diagnostic, or use 'InvalidOperand' and continue to find a
+// 'better matching' diagnostic.
+//
+// For example:
+// opcode opnd0, onpd1, opnd2
+//
+// where:
+// opnd2 could be an 'immediate of range [-8, 7]'
+// opnd2 could be a 'register + shift/extend'.
+//
+// If opnd2 is a valid register, but with a wrong shift/extend suffix, it makes
+// little sense to give a diagnostic that the operand should be an immediate
+// in range [-8, 7].
+//
+// This is a light-weight alternative to the 'NearMissInfo' approach
+// below which collects *all* possible diagnostics. This alternative
+// is optional and fully backward compatible with existing
+// PredicateMethods that return a 'bool' (match or no match).
+struct DiagnosticPredicate {
+ DiagnosticPredicateTy Type;
+
+ explicit DiagnosticPredicate(bool Match)
+ : Type(Match ? DiagnosticPredicateTy::Match
+ : DiagnosticPredicateTy::NearMatch) {}
+ DiagnosticPredicate(DiagnosticPredicateTy T) : Type(T) {}
+ DiagnosticPredicate(const DiagnosticPredicate &) = default;
+
+ operator bool() const { return Type == DiagnosticPredicateTy::Match; }
+ bool isMatch() const { return Type == DiagnosticPredicateTy::Match; }
+ bool isNearMatch() const { return Type == DiagnosticPredicateTy::NearMatch; }
+ bool isNoMatch() const { return Type == DiagnosticPredicateTy::NoMatch; }
+};
+
// When matching of an assembly instruction fails, there may be multiple
// encodings that are close to being a match. It's often ambiguous which one
// the programmer intended to use, so we want to report an error which mentions
@@ -271,6 +319,7 @@ class MCTargetAsmParser : public MCAsmParserExtension {
public:
enum MatchResultTy {
Match_InvalidOperand,
+ Match_InvalidTiedOperand,
Match_MissingFeature,
Match_MnemonicFail,
Match_Success,
@@ -323,6 +372,11 @@ public:
SemaCallback = Callback;
}
+ // Target-specific parsing of assembler-level variable assignment.
+ virtual bool parseAssignmentExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ return getParser().parseExpression(Res, EndLoc);
+ }
+
virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) = 0;
@@ -400,6 +454,15 @@ public:
virtual void convertToMapAndConstraints(unsigned Kind,
const OperandVector &Operands) = 0;
+ /// Returns whether two registers are equal and is used by the tied-operands
+ /// checks in the AsmMatcher. This method can be overridden allow e.g. a
+ /// sub- or super-register as the tied operand.
+ virtual bool regsEqual(const MCParsedAsmOperand &Op1,
+ const MCParsedAsmOperand &Op2) const {
+ assert(Op1.isReg() && Op2.isReg() && "Operands not all regs");
+ return Op1.getReg() == Op2.getReg();
+ }
+
// Return whether this parser uses assignment statements with equals tokens
virtual bool equalIsAsmAssignment() { return true; };
// Return whether this start of statement identifier is a label
diff --git a/contrib/llvm/include/llvm/MC/MCRegisterInfo.h b/contrib/llvm/include/llvm/MC/MCRegisterInfo.h
index c57c9ef709da..6edfc30b0aa6 100644
--- a/contrib/llvm/include/llvm/MC/MCRegisterInfo.h
+++ b/contrib/llvm/include/llvm/MC/MCRegisterInfo.h
@@ -240,7 +240,7 @@ public:
friend class MCRegUnitMaskIterator;
friend class MCRegUnitRootIterator;
- /// \brief Initialize MCRegisterInfo, called by TableGen
+ /// Initialize MCRegisterInfo, called by TableGen
/// auto-generated routines. *DO NOT USE*.
void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA,
unsigned PC,
@@ -283,7 +283,7 @@ public:
Dwarf2LRegsSize = 0;
}
- /// \brief Used to initialize LLVM register to Dwarf
+ /// Used to initialize LLVM register to Dwarf
/// register number mapping. Called by TableGen auto-generated routines.
/// *DO NOT USE*.
void mapLLVMRegsToDwarfRegs(const DwarfLLVMRegPair *Map, unsigned Size,
@@ -297,7 +297,7 @@ public:
}
}
- /// \brief Used to initialize Dwarf register to LLVM
+ /// Used to initialize Dwarf register to LLVM
/// register number mapping. Called by TableGen auto-generated routines.
/// *DO NOT USE*.
void mapDwarfRegsToLLVMRegs(const DwarfLLVMRegPair *Map, unsigned Size,
@@ -324,7 +324,7 @@ public:
L2CVRegs[LLVMReg] = CVReg;
}
- /// \brief This method should return the register where the return
+ /// This method should return the register where the return
/// address can be found.
unsigned getRARegister() const {
return RAReg;
@@ -341,86 +341,86 @@ public:
return Desc[RegNo];
}
- /// \brief Provide a get method, equivalent to [], but more useful with a
+ /// Provide a get method, equivalent to [], but more useful with a
/// pointer to this object.
const MCRegisterDesc &get(unsigned RegNo) const {
return operator[](RegNo);
}
- /// \brief Returns the physical register number of sub-register "Index"
+ /// Returns the physical register number of sub-register "Index"
/// for physical register RegNo. Return zero if the sub-register does not
/// exist.
unsigned getSubReg(unsigned Reg, unsigned Idx) const;
- /// \brief Return a super-register of the specified register
+ /// Return a super-register of the specified register
/// Reg so its sub-register of index SubIdx is Reg.
unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx,
const MCRegisterClass *RC) const;
- /// \brief For a given register pair, return the sub-register index
+ /// For a given register pair, return the sub-register index
/// if the second register is a sub-register of the first. Return zero
/// otherwise.
unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;
- /// \brief Get the size of the bit range covered by a sub-register index.
+ /// Get the size of the bit range covered by a sub-register index.
/// If the index isn't continuous, return the sum of the sizes of its parts.
/// If the index is used to access subregisters of different sizes, return -1.
unsigned getSubRegIdxSize(unsigned Idx) const;
- /// \brief Get the offset of the bit range covered by a sub-register index.
+ /// Get the offset of the bit range covered by a sub-register index.
/// If an Offset doesn't make sense (the index isn't continuous, or is used to
/// access sub-registers at different offsets), return -1.
unsigned getSubRegIdxOffset(unsigned Idx) const;
- /// \brief Return the human-readable symbolic target-specific name for the
+ /// Return the human-readable symbolic target-specific name for the
/// specified physical register.
const char *getName(unsigned RegNo) const {
return RegStrings + get(RegNo).Name;
}
- /// \brief Return the number of registers this target has (useful for
+ /// Return the number of registers this target has (useful for
/// sizing arrays holding per register information)
unsigned getNumRegs() const {
return NumRegs;
}
- /// \brief Return the number of sub-register indices
+ /// Return the number of sub-register indices
/// understood by the target. Index 0 is reserved for the no-op sub-register,
/// while 1 to getNumSubRegIndices() - 1 represent real sub-registers.
unsigned getNumSubRegIndices() const {
return NumSubRegIndices;
}
- /// \brief Return the number of (native) register units in the
+ /// Return the number of (native) register units in the
/// target. Register units are numbered from 0 to getNumRegUnits() - 1. They
/// can be accessed through MCRegUnitIterator defined below.
unsigned getNumRegUnits() const {
return NumRegUnits;
}
- /// \brief Map a target register to an equivalent dwarf register
+ /// Map a target register to an equivalent dwarf register
/// number. Returns -1 if there is no equivalent value. The second
/// parameter allows targets to use different numberings for EH info and
/// debugging info.
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- /// \brief Map a dwarf register back to a target register.
+ /// Map a dwarf register back to a target register.
int getLLVMRegNum(unsigned RegNum, bool isEH) const;
- /// \brief Map a DWARF EH register back to a target register (same as
+ /// Map a DWARF EH register back to a target register (same as
/// getLLVMRegNum(RegNum, true)) but return -1 if there is no mapping,
/// rather than asserting that there must be one.
int getLLVMRegNumFromEH(unsigned RegNum) const;
- /// \brief Map a target EH register number to an equivalent DWARF register
+ /// Map a target EH register number to an equivalent DWARF register
/// number.
int getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const;
- /// \brief Map a target register to an equivalent SEH register
+ /// Map a target register to an equivalent SEH register
/// number. Returns LLVM register number if there is no equivalent value.
int getSEHRegNum(unsigned RegNum) const;
- /// \brief Map a target register to an equivalent CodeView register
+ /// Map a target register to an equivalent CodeView register
/// number.
int getCodeViewRegNum(unsigned RegNum) const;
@@ -434,7 +434,7 @@ public:
return (unsigned)(regclass_end()-regclass_begin());
}
- /// \brief Returns the register class associated with the enumeration
+ /// Returns the register class associated with the enumeration
/// value. See class MCOperandInfo.
const MCRegisterClass& getRegClass(unsigned i) const {
assert(i < getNumRegClasses() && "Register Class ID out of range");
@@ -445,33 +445,33 @@ public:
return RegClassStrings + Class->NameIdx;
}
- /// \brief Returns the encoding for RegNo
+ /// Returns the encoding for RegNo
uint16_t getEncodingValue(unsigned RegNo) const {
assert(RegNo < NumRegs &&
"Attempting to get encoding for invalid register number!");
return RegEncodingTable[RegNo];
}
- /// \brief Returns true if RegB is a sub-register of RegA.
+ /// Returns true if RegB is a sub-register of RegA.
bool isSubRegister(unsigned RegA, unsigned RegB) const {
return isSuperRegister(RegB, RegA);
}
- /// \brief Returns true if RegB is a super-register of RegA.
+ /// Returns true if RegB is a super-register of RegA.
bool isSuperRegister(unsigned RegA, unsigned RegB) const;
- /// \brief Returns true if RegB is a sub-register of RegA or if RegB == RegA.
+ /// Returns true if RegB is a sub-register of RegA or if RegB == RegA.
bool isSubRegisterEq(unsigned RegA, unsigned RegB) const {
return isSuperRegisterEq(RegB, RegA);
}
- /// \brief Returns true if RegB is a super-register of RegA or if
+ /// Returns true if RegB is a super-register of RegA or if
/// RegB == RegA.
bool isSuperRegisterEq(unsigned RegA, unsigned RegB) const {
return RegA == RegB || isSuperRegister(RegA, RegB);
}
- /// \brief Returns true if RegB is a super-register or sub-register of RegA
+ /// Returns true if RegB is a super-register or sub-register of RegA
/// or if RegB == RegA.
bool isSuperOrSubRegisterEq(unsigned RegA, unsigned RegB) const {
return isSubRegisterEq(RegA, RegB) || isSuperRegister(RegA, RegB);
@@ -651,17 +651,17 @@ public:
Reg1 = MCRI->RegUnitRoots[RegUnit][1];
}
- /// \brief Dereference to get the current root register.
+ /// Dereference to get the current root register.
unsigned operator*() const {
return Reg0;
}
- /// \brief Check if the iterator is at the end of the list.
+ /// Check if the iterator is at the end of the list.
bool isValid() const {
return Reg0;
}
- /// \brief Preincrement to move to the next root register.
+ /// Preincrement to move to the next root register.
void operator++() {
assert(isValid() && "Cannot move off the end of the list.");
Reg0 = Reg1;
diff --git a/contrib/llvm/include/llvm/MC/MCSchedule.h b/contrib/llvm/include/llvm/MC/MCSchedule.h
index a79afe163e6c..f2f1dfb36918 100644
--- a/contrib/llvm/include/llvm/MC/MCSchedule.h
+++ b/contrib/llvm/include/llvm/MC/MCSchedule.h
@@ -15,18 +15,22 @@
#ifndef LLVM_MC_MCSCHEDULE_H
#define LLVM_MC_MCSCHEDULE_H
+#include "llvm/ADT/Optional.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
namespace llvm {
struct InstrItinerary;
+class MCSubtargetInfo;
+class MCInstrInfo;
+class MCInst;
+class InstrItineraryData;
/// Define a kind of processor resource that will be modeled by the scheduler.
struct MCProcResourceDesc {
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
const char *Name;
-#endif
unsigned NumUnits; // Number of resource of this kind
unsigned SuperIdx; // Index of the resources kind that contains this kind.
@@ -44,6 +48,11 @@ struct MCProcResourceDesc {
// an out-of-order cpus.
int BufferSize;
+ // If the resource has sub-units, a pointer to the first element of an array
+ // of `NumUnits` elements containing the ProcResourceIdx of the sub units.
+ // nullptr if the resource does not have sub-units.
+ const unsigned *SubUnitsIdxBegin;
+
bool operator==(const MCProcResourceDesc &Other) const {
return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx
&& BufferSize == Other.BufferSize;
@@ -53,8 +62,8 @@ struct MCProcResourceDesc {
/// Identify one of the processor resource kinds consumed by a particular
/// scheduling class for the specified number of cycles.
struct MCWriteProcResEntry {
- unsigned ProcResourceIdx;
- unsigned Cycles;
+ uint16_t ProcResourceIdx;
+ uint16_t Cycles;
bool operator==(const MCWriteProcResEntry &Other) const {
return ProcResourceIdx == Other.ProcResourceIdx && Cycles == Other.Cycles;
@@ -67,8 +76,8 @@ struct MCWriteProcResEntry {
/// the WriteResources of this def. When the operand expands to a sequence of
/// writes, this ID is the last write in the sequence.
struct MCWriteLatencyEntry {
- int Cycles;
- unsigned WriteResourceID;
+ int16_t Cycles;
+ uint16_t WriteResourceID;
bool operator==(const MCWriteLatencyEntry &Other) const {
return Cycles == Other.Cycles && WriteResourceID == Other.WriteResourceID;
@@ -99,21 +108,21 @@ struct MCReadAdvanceEntry {
///
/// Defined as an aggregate struct for creating tables with initializer lists.
struct MCSchedClassDesc {
- static const unsigned short InvalidNumMicroOps = UINT16_MAX;
- static const unsigned short VariantNumMicroOps = UINT16_MAX - 1;
+ static const unsigned short InvalidNumMicroOps = (1U << 14) - 1;
+ static const unsigned short VariantNumMicroOps = InvalidNumMicroOps - 1;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
const char* Name;
#endif
- unsigned short NumMicroOps;
- bool BeginGroup;
- bool EndGroup;
- unsigned WriteProcResIdx; // First index into WriteProcResTable.
- unsigned NumWriteProcResEntries;
- unsigned WriteLatencyIdx; // First index into WriteLatencyTable.
- unsigned NumWriteLatencyEntries;
- unsigned ReadAdvanceIdx; // First index into ReadAdvanceTable.
- unsigned NumReadAdvanceEntries;
+ uint16_t NumMicroOps : 14;
+ bool BeginGroup : 1;
+ bool EndGroup : 1;
+ uint16_t WriteProcResIdx; // First index into WriteProcResTable.
+ uint16_t NumWriteProcResEntries;
+ uint16_t WriteLatencyIdx; // First index into WriteLatencyTable.
+ uint16_t NumWriteLatencyEntries;
+ uint16_t ReadAdvanceIdx; // First index into ReadAdvanceTable.
+ uint16_t NumReadAdvanceEntries;
bool isValid() const {
return NumMicroOps != InvalidNumMicroOps;
@@ -123,6 +132,64 @@ struct MCSchedClassDesc {
}
};
+/// Specify the cost of a register definition in terms of number of physical
+/// register allocated at register renaming stage. For example, AMD Jaguar.
+/// natively supports 128-bit data types, and operations on 256-bit registers
+/// (i.e. YMM registers) are internally split into two COPs (complex operations)
+/// and each COP updates a physical register. Basically, on Jaguar, a YMM
+/// register write effectively consumes two physical registers. That means,
+/// the cost of a YMM write in the BtVer2 model is 2.
+struct MCRegisterCostEntry {
+ unsigned RegisterClassID;
+ unsigned Cost;
+};
+
+/// A register file descriptor.
+///
+/// This struct allows to describe processor register files. In particular, it
+/// helps describing the size of the register file, as well as the cost of
+/// allocating a register file at register renaming stage.
+/// FIXME: this struct can be extended to provide information about the number
+/// of read/write ports to the register file. A value of zero for field
+/// 'NumPhysRegs' means: this register file has an unbounded number of physical
+/// registers.
+struct MCRegisterFileDesc {
+ const char *Name;
+ uint16_t NumPhysRegs;
+ uint16_t NumRegisterCostEntries;
+ // Index of the first cost entry in MCExtraProcessorInfo::RegisterCostTable.
+ uint16_t RegisterCostEntryIdx;
+};
+
+/// Provide extra details about the machine processor.
+///
+/// This is a collection of "optional" processor information that is not
+/// normally used by the LLVM machine schedulers, but that can be consumed by
+/// external tools like llvm-mca to improve the quality of the peformance
+/// analysis.
+struct MCExtraProcessorInfo {
+ // Actual size of the reorder buffer in hardware.
+ unsigned ReorderBufferSize;
+ // Number of instructions retired per cycle.
+ unsigned MaxRetirePerCycle;
+ const MCRegisterFileDesc *RegisterFiles;
+ unsigned NumRegisterFiles;
+ const MCRegisterCostEntry *RegisterCostTable;
+ unsigned NumRegisterCostEntries;
+
+ struct PfmCountersInfo {
+ // An optional name of a performance counter that can be used to measure
+ // cycles.
+ const char *CycleCounter;
+
+ // For each MCProcResourceDesc defined by the processor, an optional list of
+ // names of performance counters that can be used to measure the resource
+ // utilization.
+ const char **IssueCounters;
+ };
+ PfmCountersInfo PfmCounters;
+};
+
/// Machine model for scheduling, bundling, and heuristics.
///
/// The machine model directly provides basic information about the
@@ -133,9 +200,62 @@ struct MCSchedClassDesc {
/// provides a detailed reservation table describing each cycle of instruction
/// execution. Subtargets may define any or all of the above categories of data
/// depending on the type of CPU and selected scheduler.
+///
+/// The machine independent properties defined here are used by the scheduler as
+/// an abstract machine model. A real micro-architecture has a number of
+/// buffers, queues, and stages. Declaring that a given machine-independent
+/// abstract property corresponds to a specific physical property across all
+/// subtargets can't be done. Nonetheless, the abstract model is
+/// useful. Futhermore, subtargets typically extend this model with processor
+/// specific resources to model any hardware features that can be exploited by
+/// sceduling heuristics and aren't sufficiently represented in the abstract.
+///
+/// The abstract pipeline is built around the notion of an "issue point". This
+/// is merely a reference point for counting machine cycles. The physical
+/// machine will have pipeline stages that delay execution. The scheduler does
+/// not model those delays because they are irrelevant as long as they are
+/// consistent. Inaccuracies arise when instructions have different execution
+/// delays relative to each other, in addition to their intrinsic latency. Those
+/// special cases can be handled by TableGen constructs such as, ReadAdvance,
+/// which reduces latency when reading data, and ResourceCycles, which consumes
+/// a processor resource when writing data for a number of abstract
+/// cycles.
+///
+/// TODO: One tool currently missing is the ability to add a delay to
+/// ResourceCycles. That would be easy to add and would likely cover all cases
+/// currently handled by the legacy itinerary tables.
+///
+/// A note on out-of-order execution and, more generally, instruction
+/// buffers. Part of the CPU pipeline is always in-order. The issue point, which
+/// is the point of reference for counting cycles, only makes sense as an
+/// in-order part of the pipeline. Other parts of the pipeline are sometimes
+/// falling behind and sometimes catching up. It's only interesting to model
+/// those other, decoupled parts of the pipeline if they may be predictably
+/// resource constrained in a way that the scheduler can exploit.
+///
+/// The LLVM machine model distinguishes between in-order constraints and
+/// out-of-order constraints so that the target's scheduling strategy can apply
+/// appropriate heuristics. For a well-balanced CPU pipeline, out-of-order
+/// resources would not typically be treated as a hard scheduling
+/// constraint. For example, in the GenericScheduler, a delay caused by limited
+/// out-of-order resources is not directly reflected in the number of cycles
+/// that the scheduler sees between issuing an instruction and its dependent
+/// instructions. In other words, out-of-order resources don't directly increase
+/// the latency between pairs of instructions. However, they can still be used
+/// to detect potential bottlenecks across a sequence of instructions and bias
+/// the scheduling heuristics appropriately.
struct MCSchedModel {
// IssueWidth is the maximum number of instructions that may be scheduled in
- // the same per-cycle group.
+ // the same per-cycle group. This is meant to be a hard in-order constraint
+ // (a.k.a. "hazard"). In the GenericScheduler strategy, no more than
+ // IssueWidth micro-ops can ever be scheduled in a particular cycle.
+ //
+ // In practice, IssueWidth is useful to model any bottleneck between the
+ // decoder (after micro-op expansion) and the out-of-order reservation
+ // stations or the decoder bandwidth itself. If the total number of
+ // reservation stations is also a bottleneck, or if any other pipeline stage
+ // has a bandwidth limitation, then that can be naturally modeled by adding an
+ // out-of-order processor resource.
unsigned IssueWidth;
static const unsigned DefaultIssueWidth = 1;
@@ -193,11 +313,21 @@ struct MCSchedModel {
friend class InstrItineraryData;
const InstrItinerary *InstrItineraries;
+ const MCExtraProcessorInfo *ExtraProcessorInfo;
+
+ bool hasExtraProcessorInfo() const { return ExtraProcessorInfo; }
+
unsigned getProcessorID() const { return ProcID; }
/// Does this machine model include instruction-level scheduling.
bool hasInstrSchedModel() const { return SchedClassTable; }
+ const MCExtraProcessorInfo &getExtraProcessorInfo() const {
+ assert(hasExtraProcessorInfo() &&
+ "No extra information available for this model");
+ return *ExtraProcessorInfo;
+ }
+
/// Return true if this machine model data for all instructions with a
/// scheduling class (itinerary class or SchedRW list).
bool isComplete() const { return CompleteModel; }
@@ -223,11 +353,31 @@ struct MCSchedModel {
return &SchedClassTable[SchedClassIdx];
}
+ /// Returns the latency value for the scheduling class.
+ static int computeInstrLatency(const MCSubtargetInfo &STI,
+ const MCSchedClassDesc &SCDesc);
+
+ int computeInstrLatency(const MCSubtargetInfo &STI, unsigned SClass) const;
+ int computeInstrLatency(const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
+ const MCInst &Inst) const;
+
+ // Returns the reciprocal throughput information from a MCSchedClassDesc.
+ static double
+ getReciprocalThroughput(const MCSubtargetInfo &STI,
+ const MCSchedClassDesc &SCDesc);
+
+ static double
+ getReciprocalThroughput(unsigned SchedClass, const InstrItineraryData &IID);
+
+ double
+ getReciprocalThroughput(const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
+ const MCInst &Inst) const;
+
/// Returns the default initialized model.
static const MCSchedModel &GetDefaultSchedModel() { return Default; }
static const MCSchedModel Default;
};
-} // End llvm namespace
+} // namespace llvm
#endif
diff --git a/contrib/llvm/include/llvm/MC/MCSection.h b/contrib/llvm/include/llvm/MC/MCSection.h
index 2771b1e67eab..ba5c60d3ba58 100644
--- a/contrib/llvm/include/llvm/MC/MCSection.h
+++ b/contrib/llvm/include/llvm/MC/MCSection.h
@@ -40,7 +40,7 @@ class MCSection {
public:
enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm };
- /// \brief Express the state of bundle locked groups while emitting code.
+ /// Express the state of bundle locked groups while emitting code.
enum BundleLockStateType {
NotBundleLocked,
BundleLocked,
@@ -65,13 +65,13 @@ private:
/// The index of this section in the layout order.
unsigned LayoutOrder;
- /// \brief Keeping track of bundle-locked state.
+ /// Keeping track of bundle-locked state.
BundleLockStateType BundleLockState = NotBundleLocked;
- /// \brief Current nesting depth of bundle_lock directives.
+ /// Current nesting depth of bundle_lock directives.
unsigned BundleLockNestingDepth = 0;
- /// \brief We've seen a bundle_lock directive but not its first instruction
+ /// We've seen a bundle_lock directive but not its first instruction
/// yet.
bool BundleGroupBeforeFirstInst : 1;
diff --git a/contrib/llvm/include/llvm/MC/MCSectionWasm.h b/contrib/llvm/include/llvm/MC/MCSectionWasm.h
index cc467ed9837a..ab4cd7b007ec 100644
--- a/contrib/llvm/include/llvm/MC/MCSectionWasm.h
+++ b/contrib/llvm/include/llvm/MC/MCSectionWasm.h
@@ -26,8 +26,6 @@ class MCSymbol;
/// This represents a section on wasm.
class MCSectionWasm final : public MCSection {
-private:
-
/// This is the name of the section. The referenced memory is owned by
/// TargetLoweringObjectFileWasm's WasmUniqueMap.
StringRef SectionName;
@@ -39,17 +37,17 @@ private:
// The offset of the MC function/data section in the wasm code/data section.
// For data relocations the offset is relative to start of the data payload
// itself and does not include the size of the section header.
- uint64_t SectionOffset;
+ uint64_t SectionOffset = 0;
- // For data sections, this is the offset of the corresponding wasm data
+ // For data sections, this is the index of of the corresponding wasm data
// segment
- uint64_t MemoryOffset;
+ uint32_t SegmentIndex = 0;
friend class MCContext;
MCSectionWasm(StringRef Section, SectionKind K, const MCSymbolWasm *group,
unsigned UniqueID, MCSymbol *Begin)
: MCSection(SV_Wasm, K, Begin), SectionName(Section), UniqueID(UniqueID),
- Group(group), SectionOffset(0) {}
+ Group(group) {}
void setSectionName(StringRef Name) { SectionName = Name; }
@@ -79,8 +77,8 @@ public:
uint64_t getSectionOffset() const { return SectionOffset; }
void setSectionOffset(uint64_t Offset) { SectionOffset = Offset; }
- uint32_t getMemoryOffset() const { return MemoryOffset; }
- void setMemoryOffset(uint32_t Offset) { MemoryOffset = Offset; }
+ uint32_t getSegmentIndex() const { return SegmentIndex; }
+ void setSegmentIndex(uint32_t Index) { SegmentIndex = Index; }
static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; }
};
diff --git a/contrib/llvm/include/llvm/MC/MCStreamer.h b/contrib/llvm/include/llvm/MC/MCStreamer.h
index 5b564e538bb2..0a5d80c6d778 100644
--- a/contrib/llvm/include/llvm/MC/MCStreamer.h
+++ b/contrib/llvm/include/llvm/MC/MCStreamer.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCDirectives.h"
@@ -23,6 +24,8 @@
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCWinEH.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/TargetParser.h"
#include <cassert>
@@ -167,7 +170,7 @@ private:
std::unique_ptr<AssemblerConstantPools> ConstantPools;
};
-/// \brief Streaming machine code generation interface.
+/// Streaming machine code generation interface.
///
/// This interface is intended to provide a programatic interface that is very
/// similar to the level that an assembler .s file provides. It has callbacks
@@ -194,11 +197,11 @@ class MCStreamer {
/// closed. Otherwise, issue an error and return null.
WinEH::FrameInfo *EnsureValidWinFrameInfo(SMLoc Loc);
- /// \brief Tracks an index to represent the order a symbol was emitted in.
+ /// Tracks an index to represent the order a symbol was emitted in.
/// Zero means we did not emit that symbol.
DenseMap<const MCSymbol *, unsigned> SymbolOrdering;
- /// \brief This is stack of current and previous section values saved by
+ /// This is stack of current and previous section values saved by
/// PushSection.
SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack;
@@ -208,6 +211,8 @@ class MCStreamer {
/// requires.
unsigned NextWinCFIID = 0;
+ bool UseAssemblerInfoForParsing;
+
protected:
MCStreamer(MCContext &Ctx);
@@ -244,6 +249,11 @@ public:
MCContext &getContext() const { return Context; }
+ virtual MCAssembler *getAssemblerPtr() { return nullptr; }
+
+ void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; }
+ bool getUseAssemblerInfoForParsing() { return UseAssemblerInfoForParsing; }
+
MCTargetStreamer *getTargetStreamer() {
return TargetStreamer.get();
}
@@ -265,19 +275,19 @@ public:
/// \name Assembly File Formatting.
/// @{
- /// \brief Return true if this streamer supports verbose assembly and if it is
+ /// Return true if this streamer supports verbose assembly and if it is
/// enabled.
virtual bool isVerboseAsm() const { return false; }
- /// \brief Return true if this asm streamer supports emitting unformatted text
+ /// Return true if this asm streamer supports emitting unformatted text
/// to the .s file with EmitRawText.
virtual bool hasRawTextSupport() const { return false; }
- /// \brief Is the integrated assembler required for this streamer to function
+ /// Is the integrated assembler required for this streamer to function
/// correctly?
virtual bool isIntegratedAssemblerRequired() const { return false; }
- /// \brief Add a textual comment.
+ /// Add a textual comment.
///
/// Typically for comments that can be emitted to the generated .s
/// file if applicable as a QoI issue to make the output of the compiler
@@ -292,22 +302,22 @@ public:
/// with a false value.
virtual void AddComment(const Twine &T, bool EOL = true) {}
- /// \brief Return a raw_ostream that comments can be written to. Unlike
+ /// Return a raw_ostream that comments can be written to. Unlike
/// AddComment, you are required to terminate comments with \n if you use this
/// method.
virtual raw_ostream &GetCommentOS();
- /// \brief Print T and prefix it with the comment string (normally #) and
+ /// Print T and prefix it with the comment string (normally #) and
/// optionally a tab. This prints the comment immediately, not at the end of
/// the current line. It is basically a safe version of EmitRawText: since it
/// only prints comments, the object streamer ignores it instead of asserting.
virtual void emitRawComment(const Twine &T, bool TabPrefix = true);
- /// \brief Add explicit comment T. T is required to be a valid
+ /// Add explicit comment T. T is required to be a valid
/// comment in the output and does not need to be escaped.
virtual void addExplicitComment(const Twine &T);
- /// \brief Emit added explicit comments.
+ /// Emit added explicit comments.
virtual void emitExplicitComments();
/// AddBlankLine - Emit a blank line to a .s file to pretty it up.
@@ -318,7 +328,7 @@ public:
/// \name Symbol & Section Management
/// @{
- /// \brief Return the current section that the streamer is emitting code to.
+ /// Return the current section that the streamer is emitting code to.
MCSectionSubPair getCurrentSection() const {
if (!SectionStack.empty())
return SectionStack.back().first;
@@ -326,32 +336,32 @@ public:
}
MCSection *getCurrentSectionOnly() const { return getCurrentSection().first; }
- /// \brief Return the previous section that the streamer is emitting code to.
+ /// Return the previous section that the streamer is emitting code to.
MCSectionSubPair getPreviousSection() const {
if (!SectionStack.empty())
return SectionStack.back().second;
return MCSectionSubPair();
}
- /// \brief Returns an index to represent the order a symbol was emitted in.
+ /// Returns an index to represent the order a symbol was emitted in.
/// (zero if we did not emit that symbol)
unsigned GetSymbolOrder(const MCSymbol *Sym) const {
return SymbolOrdering.lookup(Sym);
}
- /// \brief Update streamer for a new active section.
+ /// Update streamer for a new active section.
///
/// This is called by PopSection and SwitchSection, if the current
/// section changes.
virtual void ChangeSection(MCSection *, const MCExpr *);
- /// \brief Save the current and previous section on the section stack.
+ /// Save the current and previous section on the section stack.
void PushSection() {
SectionStack.push_back(
std::make_pair(getCurrentSection(), getPreviousSection()));
}
- /// \brief Restore the current and previous section from the section stack.
+ /// Restore the current and previous section from the section stack.
/// Calls ChangeSection as needed.
///
/// Returns false if the stack was empty.
@@ -385,7 +395,7 @@ public:
virtual void SwitchSection(MCSection *Section,
const MCExpr *Subsection = nullptr);
- /// \brief Set the current section where code is being emitted to \p Section.
+ /// Set the current section where code is being emitted to \p Section.
/// This is required to update CurSection. This version does not call
/// ChangeSection.
void SwitchSectionNoChange(MCSection *Section,
@@ -397,18 +407,18 @@ public:
SectionStack.back().first = MCSectionSubPair(Section, Subsection);
}
- /// \brief Create the default sections and set the initial one.
+ /// Create the default sections and set the initial one.
virtual void InitSections(bool NoExecStack);
MCSymbol *endSection(MCSection *Section);
- /// \brief Sets the symbol's section.
+ /// Sets the symbol's section.
///
/// Each emitted symbol will be tracked in the ordering table,
/// so we can sort on them later.
void AssignFragment(MCSymbol *Symbol, MCFragment *Fragment);
- /// \brief Emit a label for \p Symbol into the current section.
+ /// Emit a label for \p Symbol into the current section.
///
/// This corresponds to an assembler statement such as:
/// foo:
@@ -422,17 +432,17 @@ public:
virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol);
- /// \brief Note in the output the specified \p Flag.
+ /// Note in the output the specified \p Flag.
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
- /// \brief Emit the given list \p Options of strings as linker
+ /// Emit the given list \p Options of strings as linker
/// options into the output.
virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {}
- /// \brief Note in the output the specified region \p Kind.
+ /// Note in the output the specified region \p Kind.
virtual void EmitDataRegion(MCDataRegionType Kind) {}
- /// \brief Specify the Mach-O minimum deployment target version.
+ /// Specify the Mach-O minimum deployment target version.
virtual void EmitVersionMin(MCVersionMinType Type, unsigned Major,
unsigned Minor, unsigned Update) {}
@@ -443,11 +453,11 @@ public:
void EmitVersionForTarget(const Triple &Target);
- /// \brief Note in the output that the specified \p Func is a Thumb mode
+ /// Note in the output that the specified \p Func is a Thumb mode
/// function (ARM target only).
virtual void EmitThumbFunc(MCSymbol *Func);
- /// \brief Emit an assignment of \p Value to \p Symbol.
+ /// Emit an assignment of \p Value to \p Symbol.
///
/// This corresponds to an assembler statement such as:
/// symbol = value
@@ -460,7 +470,7 @@ public:
/// \param Value - The value for the symbol.
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
- /// \brief Emit an weak reference from \p Alias to \p Symbol.
+ /// Emit an weak reference from \p Alias to \p Symbol.
///
/// This corresponds to an assembler statement such as:
/// .weakref alias, symbol
@@ -469,53 +479,61 @@ public:
/// \param Symbol - The symbol being aliased.
virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
- /// \brief Add the given \p Attribute to \p Symbol.
+ /// Add the given \p Attribute to \p Symbol.
virtual bool EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) = 0;
- /// \brief Set the \p DescValue for the \p Symbol.
+ /// Set the \p DescValue for the \p Symbol.
///
/// \param Symbol - The symbol to have its n_desc field set.
/// \param DescValue - The value to set into the n_desc field.
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
- /// \brief Start emitting COFF symbol definition
+ /// Start emitting COFF symbol definition
///
/// \param Symbol - The symbol to have its External & Type fields set.
virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol);
- /// \brief Emit the storage class of the symbol.
+ /// Emit the storage class of the symbol.
///
/// \param StorageClass - The storage class the symbol should have.
virtual void EmitCOFFSymbolStorageClass(int StorageClass);
- /// \brief Emit the type of the symbol.
+ /// Emit the type of the symbol.
///
/// \param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h)
virtual void EmitCOFFSymbolType(int Type);
- /// \brief Marks the end of the symbol definition.
+ /// Marks the end of the symbol definition.
virtual void EndCOFFSymbolDef();
virtual void EmitCOFFSafeSEH(MCSymbol const *Symbol);
- /// \brief Emits a COFF section index.
+ /// Emits the symbol table index of a Symbol into the current section.
+ virtual void EmitCOFFSymbolIndex(MCSymbol const *Symbol);
+
+ /// Emits a COFF section index.
///
/// \param Symbol - Symbol the section number relocation should point to.
virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol);
- /// \brief Emits a COFF section relative relocation.
+ /// Emits a COFF section relative relocation.
///
/// \param Symbol - Symbol the section relative relocation should point to.
virtual void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset);
- /// \brief Emit an ELF .size directive.
+ /// Emits a COFF image relative relocation.
+ ///
+ /// \param Symbol - Symbol the image relative relocation should point to.
+ virtual void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset);
+
+ /// Emit an ELF .size directive.
///
/// This corresponds to an assembler statement such as:
/// .size symbol, expression
virtual void emitELFSize(MCSymbol *Symbol, const MCExpr *Value);
- /// \brief Emit an ELF .symver directive.
+ /// Emit an ELF .symver directive.
///
/// This corresponds to an assembler statement such as:
/// .symver _start, foo@@SOME_VERSION
@@ -524,11 +542,11 @@ public:
virtual void emitELFSymverDirective(StringRef AliasName,
const MCSymbol *Aliasee);
- /// \brief Emit a Linker Optimization Hint (LOH) directive.
+ /// Emit a Linker Optimization Hint (LOH) directive.
/// \param Args - Arguments of the LOH.
virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {}
- /// \brief Emit a common symbol.
+ /// Emit a common symbol.
///
/// \param Symbol - The common symbol to emit.
/// \param Size - The size of the common symbol.
@@ -537,7 +555,7 @@ public:
virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) = 0;
- /// \brief Emit a local common (.lcomm) symbol.
+ /// Emit a local common (.lcomm) symbol.
///
/// \param Symbol - The common symbol to emit.
/// \param Size - The size of the common symbol.
@@ -545,7 +563,7 @@ public:
virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment);
- /// \brief Emit the zerofill section and an optional symbol.
+ /// Emit the zerofill section and an optional symbol.
///
/// \param Section - The zerofill section to create and or to put the symbol
/// \param Symbol - The zerofill symbol to emit, if non-NULL.
@@ -553,9 +571,10 @@ public:
/// \param ByteAlignment - The alignment of the zerofill symbol if
/// non-zero. This must be a power of 2 on some targets.
virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0) = 0;
+ uint64_t Size = 0, unsigned ByteAlignment = 0,
+ SMLoc Loc = SMLoc()) = 0;
- /// \brief Emit a thread local bss (.tbss) symbol.
+ /// Emit a thread local bss (.tbss) symbol.
///
/// \param Section - The thread local common section.
/// \param Symbol - The thread local common symbol to emit.
@@ -569,7 +588,7 @@ public:
/// \name Generating Data
/// @{
- /// \brief Emit the bytes in \p Data into the output.
+ /// Emit the bytes in \p Data into the output.
///
/// This is used to implement assembler directives such as .byte, .ascii,
/// etc.
@@ -579,7 +598,7 @@ public:
/// method uses .byte directives instead of .ascii or .asciz for readability.
virtual void EmitBinaryData(StringRef Data);
- /// \brief Emit the expression \p Value into the output as a native
+ /// Emit the expression \p Value into the output as a native
/// integer of the given \p Size bytes.
///
/// This is used to implement assembler directives such as .word, .quad,
@@ -594,7 +613,7 @@ public:
void EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc = SMLoc());
- /// \brief Special case of EmitValue that avoids the client having
+ /// Special case of EmitValue that avoids the client having
/// to pass in a MCExpr for constant integers.
virtual void EmitIntValue(uint64_t Value, unsigned Size);
@@ -602,70 +621,66 @@ public:
virtual void EmitSLEB128Value(const MCExpr *Value);
- /// \brief Special case of EmitULEB128Value that avoids the client having to
+ /// Special case of EmitULEB128Value that avoids the client having to
/// pass in a MCExpr for constant integers.
void EmitULEB128IntValue(uint64_t Value);
- /// \brief Like EmitULEB128Value but pads the output to specific number of
- /// bytes.
- void EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo);
-
- /// \brief Special case of EmitSLEB128Value that avoids the client having to
+ /// Special case of EmitSLEB128Value that avoids the client having to
/// pass in a MCExpr for constant integers.
void EmitSLEB128IntValue(int64_t Value);
- /// \brief Special case of EmitValue that avoids the client having to pass in
+ /// Special case of EmitValue that avoids the client having to pass in
/// a MCExpr for MCSymbols.
void EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
bool IsSectionRelative = false);
- /// \brief Emit the expression \p Value into the output as a dtprel
+ /// Emit the expression \p Value into the output as a dtprel
/// (64-bit DTP relative) value.
///
/// This is used to implement assembler directives such as .dtpreldword on
/// targets that support them.
virtual void EmitDTPRel64Value(const MCExpr *Value);
- /// \brief Emit the expression \p Value into the output as a dtprel
+ /// Emit the expression \p Value into the output as a dtprel
/// (32-bit DTP relative) value.
///
/// This is used to implement assembler directives such as .dtprelword on
/// targets that support them.
virtual void EmitDTPRel32Value(const MCExpr *Value);
- /// \brief Emit the expression \p Value into the output as a tprel
+ /// Emit the expression \p Value into the output as a tprel
/// (64-bit TP relative) value.
///
/// This is used to implement assembler directives such as .tpreldword on
/// targets that support them.
virtual void EmitTPRel64Value(const MCExpr *Value);
- /// \brief Emit the expression \p Value into the output as a tprel
+ /// Emit the expression \p Value into the output as a tprel
/// (32-bit TP relative) value.
///
/// This is used to implement assembler directives such as .tprelword on
/// targets that support them.
virtual void EmitTPRel32Value(const MCExpr *Value);
- /// \brief Emit the expression \p Value into the output as a gprel64 (64-bit
+ /// Emit the expression \p Value into the output as a gprel64 (64-bit
/// GP relative) value.
///
/// This is used to implement assembler directives such as .gpdword on
/// targets that support them.
virtual void EmitGPRel64Value(const MCExpr *Value);
- /// \brief Emit the expression \p Value into the output as a gprel32 (32-bit
+ /// Emit the expression \p Value into the output as a gprel32 (32-bit
/// GP relative) value.
///
/// This is used to implement assembler directives such as .gprel32 on
/// targets that support them.
virtual void EmitGPRel32Value(const MCExpr *Value);
- /// \brief Emit NumBytes bytes worth of the value specified by FillValue.
+ /// Emit NumBytes bytes worth of the value specified by FillValue.
/// This implements directives such as '.space'.
void emitFill(uint64_t NumBytes, uint8_t FillValue);
- /// \brief Emit \p Size bytes worth of the value specified by \p FillValue.
+ /// Emit \p Size bytes worth of the value specified by \p FillValue.
///
/// This is used to implement assembler directives such as .space or .skip.
///
@@ -675,7 +690,7 @@ public:
virtual void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
SMLoc Loc = SMLoc());
- /// \brief Emit \p NumValues copies of \p Size bytes. Each \p Size bytes is
+ /// Emit \p NumValues copies of \p Size bytes. Each \p Size bytes is
/// taken from the lowest order 4 bytes of \p Expr expression.
///
/// This is used to implement assembler directives such as .fill.
@@ -683,15 +698,14 @@ public:
/// \param NumValues - The number of copies of \p Size bytes to emit.
/// \param Size - The size (in bytes) of each repeated value.
/// \param Expr - The expression from which \p Size bytes are used.
- virtual void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr);
virtual void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
SMLoc Loc = SMLoc());
- /// \brief Emit NumBytes worth of zeros.
+ /// Emit NumBytes worth of zeros.
/// This function properly handles data in virtual sections.
void EmitZeros(uint64_t NumBytes);
- /// \brief Emit some number of copies of \p Value until the byte alignment \p
+ /// Emit some number of copies of \p Value until the byte alignment \p
/// ByteAlignment is reached.
///
/// If the number of bytes need to emit for the alignment is not a multiple
@@ -712,7 +726,7 @@ public:
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0);
- /// \brief Emit nops until the byte alignment \p ByteAlignment is reached.
+ /// Emit nops until the byte alignment \p ByteAlignment is reached.
///
/// This used to align code where the alignment bytes may be executed. This
/// can emit different bytes for different sizes to optimize execution.
@@ -725,7 +739,7 @@ public:
virtual void EmitCodeAlignment(unsigned ByteAlignment,
unsigned MaxBytesToEmit = 0);
- /// \brief Emit some number of copies of \p Value until the byte offset \p
+ /// Emit some number of copies of \p Value until the byte offset \p
/// Offset is reached.
///
/// This is used to implement assembler directives such as .org.
@@ -744,21 +758,43 @@ public:
/// @}
- /// \brief Switch to a new logical file. This is used to implement the '.file
+ /// Switch to a new logical file. This is used to implement the '.file
/// "foo.c"' assembler directive.
virtual void EmitFileDirective(StringRef Filename);
- /// \brief Emit the "identifiers" directive. This implements the
+ /// Emit the "identifiers" directive. This implements the
/// '.ident "version foo"' assembler directive.
virtual void EmitIdent(StringRef IdentString) {}
- /// \brief Associate a filename with a specified logical file number. This
+ /// Associate a filename with a specified logical file number. This
/// implements the DWARF2 '.file 4 "foo.c"' assembler directive.
- virtual unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
- StringRef Filename,
- unsigned CUID = 0);
+ unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
+ StringRef Filename,
+ MD5::MD5Result *Checksum = nullptr,
+ Optional<StringRef> Source = None,
+ unsigned CUID = 0) {
+ return cantFail(
+ tryEmitDwarfFileDirective(FileNo, Directory, Filename, Checksum,
+ Source, CUID));
+ }
+
+ /// Associate a filename with a specified logical file number.
+ /// Also associate a directory, optional checksum, and optional source
+ /// text with the logical file. This implements the DWARF2
+ /// '.file 4 "dir/foo.c"' assembler directive, and the DWARF5
+ /// '.file 4 "dir/foo.c" md5 "..." source "..."' assembler directive.
+ virtual Expected<unsigned> tryEmitDwarfFileDirective(
+ unsigned FileNo, StringRef Directory, StringRef Filename,
+ MD5::MD5Result *Checksum = nullptr, Optional<StringRef> Source = None,
+ unsigned CUID = 0);
+
+ /// Specify the "root" file of the compilation, using the ".file 0" extension.
+ virtual void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned CUID = 0);
- /// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler
+ /// This implements the DWARF2 '.loc fileno lineno ...' assembler
/// directive.
virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
@@ -772,27 +808,27 @@ public:
ArrayRef<uint8_t> Checksum,
unsigned ChecksumKind);
- /// \brief Introduces a function id for use with .cv_loc.
+ /// Introduces a function id for use with .cv_loc.
virtual bool EmitCVFuncIdDirective(unsigned FunctionId);
- /// \brief Introduces an inline call site id for use with .cv_loc. Includes
+ /// Introduces an inline call site id for use with .cv_loc. Includes
/// extra information for inline line table generation.
virtual bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
unsigned IAFile, unsigned IALine,
unsigned IACol, SMLoc Loc);
- /// \brief This implements the CodeView '.cv_loc' assembler directive.
+ /// This implements the CodeView '.cv_loc' assembler directive.
virtual void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
StringRef FileName, SMLoc Loc);
- /// \brief This implements the CodeView '.cv_linetable' assembler directive.
+ /// This implements the CodeView '.cv_linetable' assembler directive.
virtual void EmitCVLinetableDirective(unsigned FunctionId,
const MCSymbol *FnStart,
const MCSymbol *FnEnd);
- /// \brief This implements the CodeView '.cv_inline_linetable' assembler
+ /// This implements the CodeView '.cv_inline_linetable' assembler
/// directive.
virtual void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
unsigned SourceFileId,
@@ -800,16 +836,16 @@ public:
const MCSymbol *FnStartSym,
const MCSymbol *FnEndSym);
- /// \brief This implements the CodeView '.cv_def_range' assembler
+ /// This implements the CodeView '.cv_def_range' assembler
/// directive.
virtual void EmitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
StringRef FixedSizePortion);
- /// \brief This implements the CodeView '.cv_stringtable' assembler directive.
+ /// This implements the CodeView '.cv_stringtable' assembler directive.
virtual void EmitCVStringTableDirective() {}
- /// \brief This implements the CodeView '.cv_filechecksums' assembler directive.
+ /// This implements the CodeView '.cv_filechecksums' assembler directive.
virtual void EmitCVFileChecksumsDirective() {}
/// This implements the CodeView '.cv_filechecksumoffset' assembler
@@ -825,6 +861,10 @@ public:
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
unsigned Size);
+ /// Emit the absolute difference between two symbols encoded with ULEB128.
+ virtual void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
+ const MCSymbol *Lo);
+
virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID);
virtual void EmitCFISections(bool EH, bool Debug);
void EmitCFIStartProc(bool IsSimple);
@@ -867,6 +907,9 @@ public:
SMLoc Loc = SMLoc());
virtual void EmitWinEHHandlerData(SMLoc Loc = SMLoc());
+ virtual void emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count);
+
/// Get the .pdata section used for the given section. Typically the given
/// section is either the main .text section or some other COMDAT .text
/// section, but it may be any section containing code.
@@ -877,41 +920,45 @@ public:
virtual void EmitSyntaxDirective();
- /// \brief Emit a .reloc directive.
+ /// Emit a .reloc directive.
/// Returns true if the relocation could not be emitted because Name is not
/// known.
virtual bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc) {
+ const MCExpr *Expr, SMLoc Loc,
+ const MCSubtargetInfo &STI) {
return true;
}
- /// \brief Emit the given \p Instruction into the current section.
+ virtual void EmitAddrsig() {}
+ virtual void EmitAddrsigSym(const MCSymbol *Sym) {}
+
+ /// Emit the given \p Instruction into the current section.
/// PrintSchedInfo == true then schedul comment should be added to output
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
bool PrintSchedInfo = false);
- /// \brief Set the bundle alignment mode from now on in the section.
+ /// Set the bundle alignment mode from now on in the section.
/// The argument is the power of 2 to which the alignment is set. The
/// value 0 means turn the bundle alignment off.
virtual void EmitBundleAlignMode(unsigned AlignPow2);
- /// \brief The following instructions are a bundle-locked group.
+ /// The following instructions are a bundle-locked group.
///
/// \param AlignToEnd - If true, the bundle-locked group will be aligned to
/// the end of a bundle.
virtual void EmitBundleLock(bool AlignToEnd);
- /// \brief Ends a bundle-locked group.
+ /// Ends a bundle-locked group.
virtual void EmitBundleUnlock();
- /// \brief If this file is backed by a assembly streamer, this dumps the
+ /// If this file is backed by a assembly streamer, this dumps the
/// specified string in the output .s file. This capability is indicated by
/// the hasRawTextSupport() predicate. By default this aborts.
void EmitRawText(const Twine &String);
- /// \brief Streamer specific finalization.
+ /// Streamer specific finalization.
virtual void FinishImpl();
- /// \brief Finish emission of machine code.
+ /// Finish emission of machine code.
void Finish();
virtual bool mayHaveInstructions(MCSection &Sec) const { return true; }
diff --git a/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h b/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h
index dd10881b73a8..b3ce523d9c0c 100644
--- a/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h
+++ b/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h
@@ -27,15 +27,14 @@
namespace llvm {
-class MachineInstr;
class MCInst;
//===----------------------------------------------------------------------===//
///
-/// MCSubtargetInfo - Generic base class for all target subtargets.
+/// Generic base class for all target subtargets.
///
class MCSubtargetInfo {
- Triple TargetTriple; // Target triple
+ Triple TargetTriple;
std::string CPU; // CPU being targeted.
ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list
ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions
@@ -49,7 +48,7 @@ class MCSubtargetInfo {
const InstrStage *Stages; // Instruction itinerary stages
const unsigned *OperandCycles; // Itinerary operand cycles
- const unsigned *ForwardingPaths; // Forwarding paths
+ const unsigned *ForwardingPaths;
FeatureBitset FeatureBits; // Feature bits for current CPU + FS
public:
@@ -66,22 +65,10 @@ public:
MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete;
virtual ~MCSubtargetInfo() = default;
- /// getTargetTriple - Return the target triple string.
const Triple &getTargetTriple() const { return TargetTriple; }
+ StringRef getCPU() const { return CPU; }
- /// getCPU - Return the CPU string.
- StringRef getCPU() const {
- return CPU;
- }
-
- /// getFeatureBits - Return the feature bits.
- ///
- const FeatureBitset& getFeatureBits() const {
- return FeatureBits;
- }
-
- /// setFeatureBits - Set the feature bits.
- ///
+ const FeatureBitset& getFeatureBits() const { return FeatureBits; }
void setFeatureBits(const FeatureBitset &FeatureBits_) {
FeatureBits = FeatureBits_;
}
@@ -102,16 +89,16 @@ public:
/// string.
void setDefaultFeatures(StringRef CPU, StringRef FS);
- /// ToggleFeature - Toggle a feature and returns the re-computed feature
- /// bits. This version does not change the implied bits.
+ /// Toggle a feature and return the re-computed feature bits.
+ /// This version does not change the implied bits.
FeatureBitset ToggleFeature(uint64_t FB);
- /// ToggleFeature - Toggle a feature and returns the re-computed feature
- /// bits. This version does not change the implied bits.
+ /// Toggle a feature and return the re-computed feature bits.
+ /// This version does not change the implied bits.
FeatureBitset ToggleFeature(const FeatureBitset& FB);
- /// ToggleFeature - Toggle a set of features and returns the re-computed
- /// feature bits. This version will also change all implied bits.
+ /// Toggle a set of features and return the re-computed feature bits.
+ /// This version will also change all implied bits.
FeatureBitset ToggleFeature(StringRef FS);
/// Apply a feature flag and return the re-computed feature bits, including
@@ -122,8 +109,7 @@ public:
/// the provided string, ignoring all other features.
bool checkFeatures(StringRef FS) const;
- /// getSchedModelForCPU - Get the machine model of a CPU.
- ///
+ /// Get the machine model of a CPU.
const MCSchedModel &getSchedModelForCPU(StringRef CPU) const;
/// Get the machine model for this subtarget's CPU.
@@ -167,13 +153,19 @@ public:
return 0;
}
- /// getInstrItineraryForCPU - Get scheduling itinerary of a CPU.
- ///
+ /// Get scheduling itinerary of a CPU.
InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const;
/// Initialize an InstrItineraryData instance.
void initInstrItins(InstrItineraryData &InstrItins) const;
+ /// Resolve a variant scheduling class for the given MCInst and CPU.
+ virtual unsigned
+ resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI,
+ unsigned CPUID) const {
+ return 0;
+ }
+
/// Check whether the CPU string is valid.
bool isCPUStringValid(StringRef CPU) const {
auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU);
@@ -181,10 +173,6 @@ public:
}
/// Returns string representation of scheduler comment
- virtual std::string getSchedInfoStr(const MachineInstr &MI) const {
- return {};
- }
-
virtual std::string getSchedInfoStr(MCInst const &MCI) const {
return {};
}
diff --git a/contrib/llvm/include/llvm/MC/MCSymbol.h b/contrib/llvm/include/llvm/MC/MCSymbol.h
index 9b1cc6e7d7e8..4681a1be60c4 100644
--- a/contrib/llvm/include/llvm/MC/MCSymbol.h
+++ b/contrib/llvm/include/llvm/MC/MCSymbol.h
@@ -85,7 +85,7 @@ protected:
/// "Lfoo" or ".foo".
unsigned IsTemporary : 1;
- /// \brief True if this symbol can be redefined.
+ /// True if this symbol can be redefined.
unsigned IsRedefinable : 1;
/// IsUsed - True if this symbol has been used.
@@ -141,7 +141,7 @@ protected:
friend class MCExpr;
friend class MCContext;
- /// \brief The name for a symbol.
+ /// The name for a symbol.
/// MCSymbol contains a uint64_t so is probably aligned to 8. On a 32-bit
/// system, the name is a pointer so isn't going to satisfy the 8 byte
/// alignment of uint64_t. Account for that here.
@@ -168,24 +168,24 @@ protected:
private:
void operator delete(void *);
- /// \brief Placement delete - required by std, but never called.
+ /// Placement delete - required by std, but never called.
void operator delete(void*, unsigned) {
llvm_unreachable("Constructor throws?");
}
- /// \brief Placement delete - required by std, but never called.
+ /// Placement delete - required by std, but never called.
void operator delete(void*, unsigned, bool) {
llvm_unreachable("Constructor throws?");
}
- MCSection *getSectionPtr(bool SetUsed = true) const {
- if (MCFragment *F = getFragment(SetUsed)) {
+ MCSection *getSectionPtr() const {
+ if (MCFragment *F = getFragment()) {
assert(F != AbsolutePseudoFragment);
return F->getParent();
}
return nullptr;
}
- /// \brief Get a reference to the name field. Requires that we have a name
+ /// Get a reference to the name field. Requires that we have a name
const StringMapEntry<bool> *&getNameEntryPtr() {
assert(FragmentAndHasName.getInt() && "Name is required");
NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this);
@@ -221,13 +221,12 @@ public:
/// isUsed - Check if this is used.
bool isUsed() const { return IsUsed; }
- void setUsed(bool Value) const { IsUsed |= Value; }
- /// \brief Check if this symbol is redefinable.
+ /// Check if this symbol is redefinable.
bool isRedefinable() const { return IsRedefinable; }
- /// \brief Mark this symbol as redefinable.
+ /// Mark this symbol as redefinable.
void setRedefinable(bool Value) { IsRedefinable = Value; }
- /// \brief Prepare this symbol to be redefined.
+ /// Prepare this symbol to be redefined.
void redefineIfPossible() {
if (IsRedefinable) {
if (SymbolContents == SymContentsVariable) {
@@ -246,28 +245,28 @@ public:
/// isDefined - Check if this symbol is defined (i.e., it has an address).
///
/// Defined symbols are either absolute or in some section.
- bool isDefined(bool SetUsed = true) const {
- return getFragment(SetUsed) != nullptr;
- }
+ bool isDefined() const { return !isUndefined(); }
/// isInSection - Check if this symbol is defined in some section (i.e., it
/// is defined but not absolute).
- bool isInSection(bool SetUsed = true) const {
- return isDefined(SetUsed) && !isAbsolute(SetUsed);
+ bool isInSection() const {
+ return isDefined() && !isAbsolute();
}
/// isUndefined - Check if this symbol undefined (i.e., implicitly defined).
- bool isUndefined(bool SetUsed = true) const { return !isDefined(SetUsed); }
+ bool isUndefined(bool SetUsed = true) const {
+ return getFragment(SetUsed) == nullptr;
+ }
/// isAbsolute - Check if this is an absolute symbol.
- bool isAbsolute(bool SetUsed = true) const {
- return getFragment(SetUsed) == AbsolutePseudoFragment;
+ bool isAbsolute() const {
+ return getFragment() == AbsolutePseudoFragment;
}
/// Get the section associated with a defined, non-absolute symbol.
- MCSection &getSection(bool SetUsed = true) const {
- assert(isInSection(SetUsed) && "Invalid accessor!");
- return *getSectionPtr(SetUsed);
+ MCSection &getSection() const {
+ assert(isInSection() && "Invalid accessor!");
+ return *getSectionPtr();
}
/// Mark the symbol as defined in the fragment \p F.
@@ -317,6 +316,8 @@ public:
Index = Value;
}
+ bool isUnset() const { return SymbolContents == SymContentsUnset; }
+
uint64_t getOffset() const {
assert((SymbolContents == SymContentsUnset ||
SymbolContents == SymContentsOffset) &&
diff --git a/contrib/llvm/include/llvm/MC/MCSymbolMachO.h b/contrib/llvm/include/llvm/MC/MCSymbolMachO.h
index 25220e4a8109..6125c2050976 100644
--- a/contrib/llvm/include/llvm/MC/MCSymbolMachO.h
+++ b/contrib/llvm/include/llvm/MC/MCSymbolMachO.h
@@ -14,7 +14,7 @@
namespace llvm {
class MCSymbolMachO : public MCSymbol {
- /// \brief We store the value for the 'desc' symbol field in the
+ /// We store the value for the 'desc' symbol field in the
/// lowest 16 bits of the implementation defined flags.
enum MachOSymbolFlags : uint16_t { // See <mach-o/nlist.h>.
SF_DescFlagsMask = 0xFFFF,
@@ -104,7 +104,7 @@ public:
setFlags(Value & SF_DescFlagsMask);
}
- /// \brief Get the encoded value of the flags as they will be emitted in to
+ /// Get the encoded value of the flags as they will be emitted in to
/// the MachO binary
uint16_t getEncodedFlags(bool EncodeAsAltEntry) const {
uint16_t Flags = getFlags();
diff --git a/contrib/llvm/include/llvm/MC/MCSymbolWasm.h b/contrib/llvm/include/llvm/MC/MCSymbolWasm.h
index 309ebf96d1b0..e043453dc732 100644
--- a/contrib/llvm/include/llvm/MC/MCSymbolWasm.h
+++ b/contrib/llvm/include/llvm/MC/MCSymbolWasm.h
@@ -15,15 +15,17 @@
namespace llvm {
class MCSymbolWasm : public MCSymbol {
-private:
- bool IsFunction = false;
+ wasm::WasmSymbolType Type = wasm::WASM_SYMBOL_TYPE_DATA;
bool IsWeak = false;
bool IsHidden = false;
+ bool IsComdat = false;
std::string ModuleName;
SmallVector<wasm::ValType, 1> Returns;
SmallVector<wasm::ValType, 4> Params;
+ wasm::WasmGlobalType GlobalType;
bool ParamsSet = false;
bool ReturnsSet = false;
+ bool GlobalTypeSet = false;
/// An expression describing how to calculate the size of a symbol. If a
/// symbol has no size this field will be NULL.
@@ -40,8 +42,12 @@ public:
const MCExpr *getSize() const { return SymbolSize; }
void setSize(const MCExpr *SS) { SymbolSize = SS; }
- bool isFunction() const { return IsFunction; }
- void setIsFunction(bool isFunc) { IsFunction = isFunc; }
+ bool isFunction() const { return Type == wasm::WASM_SYMBOL_TYPE_FUNCTION; }
+ bool isData() const { return Type == wasm::WASM_SYMBOL_TYPE_DATA; }
+ bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; }
+ bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; }
+ wasm::WasmSymbolType getType() const { return Type; }
+ void setType(wasm::WasmSymbolType type) { Type = type; }
bool isWeak() const { return IsWeak; }
void setWeak(bool isWeak) { IsWeak = isWeak; }
@@ -49,7 +55,11 @@ public:
bool isHidden() const { return IsHidden; }
void setHidden(bool isHidden) { IsHidden = isHidden; }
+ bool isComdat() const { return IsComdat; }
+ void setComdat(bool isComdat) { IsComdat = isComdat; }
+
const StringRef getModuleName() const { return ModuleName; }
+ void setModuleName(StringRef Name) { ModuleName = Name; }
const SmallVector<wasm::ValType, 1> &getReturns() const {
assert(ReturnsSet);
@@ -70,6 +80,16 @@ public:
ParamsSet = true;
Params = std::move(Pars);
}
+
+ const wasm::WasmGlobalType &getGlobalType() const {
+ assert(GlobalTypeSet);
+ return GlobalType;
+ }
+
+ void setGlobalType(wasm::WasmGlobalType GT) {
+ GlobalTypeSet = true;
+ GlobalType = GT;
+ }
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/MC/MCTargetOptions.h b/contrib/llvm/include/llvm/MC/MCTargetOptions.h
index 5509bb3bdc7c..f5d330fbeb22 100644
--- a/contrib/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/contrib/llvm/include/llvm/MC/MCTargetOptions.h
@@ -21,6 +21,7 @@ enum class ExceptionHandling {
SjLj, /// setjmp/longjmp based exceptions
ARM, /// ARM EHABI
WinEH, /// Windows Exception Handling
+ Wasm, /// WebAssembly Exception Handling
};
enum class DebugCompressionType {
diff --git a/contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.def b/contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.inc
index 5172fa44511f..5172fa44511f 100644
--- a/contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.def
+++ b/contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.inc
diff --git a/contrib/llvm/include/llvm/MC/MCValue.h b/contrib/llvm/include/llvm/MC/MCValue.h
index ff223f70303b..11f5082ed3f4 100644
--- a/contrib/llvm/include/llvm/MC/MCValue.h
+++ b/contrib/llvm/include/llvm/MC/MCValue.h
@@ -23,7 +23,7 @@ namespace llvm {
class MCAsmInfo;
class raw_ostream;
-/// \brief This represents an "assembler immediate".
+/// This represents an "assembler immediate".
///
/// In its most general form, this can hold ":Kind:(SymbolA - SymbolB +
/// imm64)". Not all targets supports relocations of this general form, but we
@@ -49,13 +49,13 @@ public:
const MCSymbolRefExpr *getSymB() const { return SymB; }
uint32_t getRefKind() const { return RefKind; }
- /// \brief Is this an absolute (as opposed to relocatable) value.
+ /// Is this an absolute (as opposed to relocatable) value.
bool isAbsolute() const { return !SymA && !SymB; }
- /// \brief Print the value to the stream \p OS.
+ /// Print the value to the stream \p OS.
void print(raw_ostream &OS) const;
- /// \brief Print the value to stderr.
+ /// Print the value to stderr.
void dump() const;
MCSymbolRefExpr::VariantKind getAccessVariant() const;
diff --git a/contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h b/contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h
index a4d5eb857b39..e45030f302ff 100644
--- a/contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h
+++ b/contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h
@@ -10,18 +10,16 @@
#ifndef LLVM_MC_MCWASMOBJECTWRITER_H
#define LLVM_MC_MCWASMOBJECTWRITER_H
-#include "llvm/ADT/Triple.h"
-#include "llvm/BinaryFormat/Wasm.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include <memory>
namespace llvm {
class MCFixup;
-class MCObjectWriter;
class MCValue;
class raw_pwrite_stream;
-class MCWasmObjectTargetWriter {
+class MCWasmObjectTargetWriter : public MCObjectTargetWriter {
const unsigned Is64Bit : 1;
protected:
@@ -30,6 +28,11 @@ protected:
public:
virtual ~MCWasmObjectTargetWriter();
+ virtual Triple::ObjectFormatType getFormat() const { return Triple::Wasm; }
+ static bool classof(const MCObjectTargetWriter *W) {
+ return W->getFormat() == Triple::Wasm;
+ }
+
virtual unsigned getRelocType(const MCValue &Target,
const MCFixup &Fixup) const = 0;
@@ -39,7 +42,7 @@ public:
/// @}
};
-/// \brief Construct a new Wasm writer instance.
+/// Construct a new Wasm writer instance.
///
/// \param MOTW - The target specific Wasm writer subclass.
/// \param OS - The stream to write to.
diff --git a/contrib/llvm/include/llvm/MC/MCWasmStreamer.h b/contrib/llvm/include/llvm/MC/MCWasmStreamer.h
index c0d45451a9ab..01e6a4379287 100644
--- a/contrib/llvm/include/llvm/MC/MCWasmStreamer.h
+++ b/contrib/llvm/include/llvm/MC/MCWasmStreamer.h
@@ -15,6 +15,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/DataTypes.h"
@@ -27,8 +28,10 @@ class raw_ostream;
class MCWasmStreamer : public MCObjectStreamer {
public:
MCWasmStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
- raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter)
- : MCObjectStreamer(Context, std::move(TAB), OS, std::move(Emitter)),
+ std::unique_ptr<MCObjectWriter> OW,
+ std::unique_ptr<MCCodeEmitter> Emitter)
+ : MCObjectStreamer(Context, std::move(TAB), std::move(OW),
+ std::move(Emitter)),
SeenIdent(false) {}
~MCWasmStreamer() override;
@@ -57,7 +60,8 @@ public:
unsigned ByteAlignment) override;
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0) override;
+ uint64_t Size = 0, unsigned ByteAlignment = 0,
+ SMLoc Loc = SMLoc()) override;
void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment = 0) override;
void EmitValueImpl(const MCExpr *Value, unsigned Size,
@@ -73,7 +77,7 @@ private:
void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override;
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
- /// \brief Merge the content of the fragment \p EF into the fragment \p DF.
+ /// Merge the content of the fragment \p EF into the fragment \p DF.
void mergeFragment(MCDataFragment *, MCDataFragment *);
bool SeenIdent;
diff --git a/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h b/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h
index 3234bd93cad0..c1d35ea1f6ba 100644
--- a/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h
+++ b/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h
@@ -10,6 +10,7 @@
#ifndef LLVM_MC_MCWINCOFFOBJECTWRITER_H
#define LLVM_MC_MCWINCOFFOBJECTWRITER_H
+#include "llvm/MC/MCObjectWriter.h"
#include <memory>
namespace llvm {
@@ -17,11 +18,10 @@ namespace llvm {
class MCAsmBackend;
class MCContext;
class MCFixup;
-class MCObjectWriter;
class MCValue;
class raw_pwrite_stream;
- class MCWinCOFFObjectTargetWriter {
+ class MCWinCOFFObjectTargetWriter : public MCObjectTargetWriter {
virtual void anchor();
const unsigned Machine;
@@ -32,6 +32,11 @@ class raw_pwrite_stream;
public:
virtual ~MCWinCOFFObjectTargetWriter() = default;
+ virtual Triple::ObjectFormatType getFormat() const { return Triple::COFF; }
+ static bool classof(const MCObjectTargetWriter *W) {
+ return W->getFormat() == Triple::COFF;
+ }
+
unsigned getMachine() const { return Machine; }
virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsCrossSection,
@@ -39,7 +44,7 @@ class raw_pwrite_stream;
virtual bool recordRelocation(const MCFixup &) const { return true; }
};
- /// \brief Construct a new Win COFF writer instance.
+ /// Construct a new Win COFF writer instance.
///
/// \param MOTW - The target specific WinCOFF writer subclass.
/// \param OS - The stream to write to.
diff --git a/contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h b/contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h
index a2500c06efa1..0049d04b4b3f 100644
--- a/contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h
+++ b/contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h
@@ -28,7 +28,8 @@ class raw_pwrite_stream;
class MCWinCOFFStreamer : public MCObjectStreamer {
public:
MCWinCOFFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
- std::unique_ptr<MCCodeEmitter> CE, raw_pwrite_stream &OS);
+ std::unique_ptr<MCCodeEmitter> CE,
+ std::unique_ptr<MCObjectWriter> OW);
/// state management
void reset() override {
@@ -50,14 +51,16 @@ public:
void EmitCOFFSymbolType(int Type) override;
void EndCOFFSymbolDef() override;
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
+ void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
+ void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) override;
+ unsigned ByteAlignment, SMLoc Loc = SMLoc()) override;
void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
void EmitIdent(StringRef IdentString) override;
diff --git a/contrib/llvm/include/llvm/MC/StringTableBuilder.h b/contrib/llvm/include/llvm/MC/StringTableBuilder.h
index 0df3fcd63723..265260fcee4d 100644
--- a/contrib/llvm/include/llvm/MC/StringTableBuilder.h
+++ b/contrib/llvm/include/llvm/MC/StringTableBuilder.h
@@ -20,10 +20,10 @@ namespace llvm {
class raw_ostream;
-/// \brief Utility for building string tables with deduplicated suffixes.
+/// Utility for building string tables with deduplicated suffixes.
class StringTableBuilder {
public:
- enum Kind { ELF, WinCOFF, MachO, RAW };
+ enum Kind { ELF, WinCOFF, MachO, RAW, DWARF };
private:
DenseMap<CachedHashStringRef, size_t> StringIndexMap;
@@ -39,13 +39,13 @@ public:
StringTableBuilder(Kind K, unsigned Alignment = 1);
~StringTableBuilder();
- /// \brief Add a string to the builder. Returns the position of S in the
+ /// Add a string to the builder. Returns the position of S in the
/// table. The position will be changed if finalize is used.
/// Can only be used before the table is finalized.
size_t add(CachedHashStringRef S);
size_t add(StringRef S) { return add(CachedHashStringRef(S)); }
- /// \brief Analyze the strings and build the final table. No more strings can
+ /// Analyze the strings and build the final table. No more strings can
/// be added after this point.
void finalize();
@@ -53,7 +53,7 @@ public:
/// returned by add will still be valid.
void finalizeInOrder();
- /// \brief Get the offest of a string in the string table. Can only be used
+ /// Get the offest of a string in the string table. Can only be used
/// after the table is finalized.
size_t getOffset(CachedHashStringRef S) const;
size_t getOffset(StringRef S) const {
diff --git a/contrib/llvm/include/llvm/Object/Archive.h b/contrib/llvm/include/llvm/Object/Archive.h
index 5a1512bb9d36..9ef1e4875191 100644
--- a/contrib/llvm/include/llvm/Object/Archive.h
+++ b/contrib/llvm/include/llvm/Object/Archive.h
@@ -91,9 +91,9 @@ public:
const Archive *Parent;
ArchiveMemberHeader Header;
- /// \brief Includes header but not padding byte.
+ /// Includes header but not padding byte.
StringRef Data;
- /// \brief Offset from Data to the start of the file.
+ /// Offset from Data to the start of the file.
uint16_t StartOfFile;
Expected<bool> isThinMember() const;
diff --git a/contrib/llvm/include/llvm/Object/Binary.h b/contrib/llvm/include/llvm/Object/Binary.h
index 5e93691d1fd2..99745e24b8c8 100644
--- a/contrib/llvm/include/llvm/Object/Binary.h
+++ b/contrib/llvm/include/llvm/Object/Binary.h
@@ -156,7 +156,7 @@ public:
}
};
-/// @brief Create a Binary from Source, autodetecting the file type.
+/// Create a Binary from Source, autodetecting the file type.
///
/// @param Source The data to create the Binary from.
Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
diff --git a/contrib/llvm/include/llvm/Object/COFF.h b/contrib/llvm/include/llvm/Object/COFF.h
index b072dd5ba7d9..6caadea0175b 100644
--- a/contrib/llvm/include/llvm/Object/COFF.h
+++ b/contrib/llvm/include/llvm/Object/COFF.h
@@ -16,9 +16,9 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/Binary.h"
+#include "llvm/Object/CVDebugRecord.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/BinaryByteStream.h"
@@ -276,6 +276,7 @@ struct coff_symbol_generic {
};
struct coff_aux_section_definition;
+struct coff_aux_weak_external;
class COFFSymbolRef {
public:
@@ -360,6 +361,13 @@ public:
return getAux<coff_aux_section_definition>();
}
+ const coff_aux_weak_external *getWeakExternal() const {
+ if (!getNumberOfAuxSymbols() ||
+ getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
+ return nullptr;
+ return getAux<coff_aux_weak_external>();
+ }
+
bool isAbsolute() const {
return getSectionNumber() == -1;
}
@@ -452,11 +460,12 @@ struct coff_section {
if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD)
return 1;
- // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1.
+ // Bit [20:24] contains section alignment. 0 means use a default alignment
+ // of 16.
uint32_t Shift = (Characteristics >> 20) & 0xF;
if (Shift > 0)
return 1U << (Shift - 1);
- return 1;
+ return 16;
}
};
@@ -927,6 +936,7 @@ public:
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
Triple::ArchType getArch() const override;
+ Expected<uint64_t> getStartAddress() const override;
SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
import_directory_iterator import_directory_begin() const;
@@ -963,6 +973,8 @@ public:
std::error_code getDataDirectory(uint32_t index,
const data_directory *&Res) const;
std::error_code getSection(int32_t index, const coff_section *&Res) const;
+ std::error_code getSection(StringRef SectionName,
+ const coff_section *&Res) const;
template <typename coff_symbol_type>
std::error_code getSymbol(uint32_t Index,
@@ -1012,8 +1024,7 @@ public:
llvm_unreachable("null symbol table pointer!");
}
- iterator_range<const coff_relocation *>
- getRelocations(const coff_section *Sec) const;
+ ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const;
std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
uint64_t getSectionSize(const coff_section *Sec) const;
diff --git a/contrib/llvm/include/llvm/Object/COFFImportFile.h b/contrib/llvm/include/llvm/Object/COFFImportFile.h
index 4b284de679b3..0a4556ad8884 100644
--- a/contrib/llvm/include/llvm/Object/COFFImportFile.h
+++ b/contrib/llvm/include/llvm/Object/COFFImportFile.h
@@ -74,6 +74,7 @@ struct COFFShortExport {
std::string Name;
std::string ExtName;
std::string SymbolName;
+ std::string AliasTarget;
uint16_t Ordinal = 0;
bool Noname = false;
@@ -81,10 +82,6 @@ struct COFFShortExport {
bool Private = false;
bool Constant = false;
- bool isWeak() {
- return ExtName.size() && ExtName != Name;
- }
-
friend bool operator==(const COFFShortExport &L, const COFFShortExport &R) {
return L.Name == R.Name && L.ExtName == R.ExtName &&
L.Ordinal == R.Ordinal && L.Noname == R.Noname &&
@@ -98,7 +95,7 @@ struct COFFShortExport {
Error writeImportLibrary(StringRef ImportName, StringRef Path,
ArrayRef<COFFShortExport> Exports,
- COFF::MachineTypes Machine, bool MakeWeakAliases);
+ COFF::MachineTypes Machine, bool MinGW);
} // namespace object
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVDebugRecord.h b/contrib/llvm/include/llvm/Object/CVDebugRecord.h
index 5a0bb4266ba2..faad72c0df29 100644
--- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVDebugRecord.h
+++ b/contrib/llvm/include/llvm/Object/CVDebugRecord.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEBUGINFO_CODEVIEW_CVDEBUGRECORD_H
-#define LLVM_DEBUGINFO_CODEVIEW_CVDEBUGRECORD_H
+#ifndef LLVM_OBJECT_CVDEBUGRECORD_H
+#define LLVM_OBJECT_CVDEBUGRECORD_H
#include "llvm/Support/Endian.h"
diff --git a/contrib/llvm/include/llvm/Object/Decompressor.h b/contrib/llvm/include/llvm/Object/Decompressor.h
index c8e888d285e4..2a77d2ffbf68 100644
--- a/contrib/llvm/include/llvm/Object/Decompressor.h
+++ b/contrib/llvm/include/llvm/Object/Decompressor.h
@@ -17,10 +17,10 @@
namespace llvm {
namespace object {
-/// @brief Decompressor helps to handle decompression of compressed sections.
+/// Decompressor helps to handle decompression of compressed sections.
class Decompressor {
public:
- /// @brief Create decompressor object.
+ /// Create decompressor object.
/// @param Name Section name.
/// @param Data Section content.
/// @param IsLE Flag determines if Data is in little endian form.
@@ -28,27 +28,27 @@ public:
static Expected<Decompressor> create(StringRef Name, StringRef Data,
bool IsLE, bool Is64Bit);
- /// @brief Resize the buffer and uncompress section data into it.
+ /// Resize the buffer and uncompress section data into it.
/// @param Out Destination buffer.
template <class T> Error resizeAndDecompress(T &Out) {
Out.resize(DecompressedSize);
return decompress({Out.data(), (size_t)DecompressedSize});
}
- /// @brief Uncompress section data to raw buffer provided.
+ /// Uncompress section data to raw buffer provided.
/// @param Buffer Destination buffer.
Error decompress(MutableArrayRef<char> Buffer);
- /// @brief Return memory buffer size required for decompression.
+ /// Return memory buffer size required for decompression.
uint64_t getDecompressedSize() { return DecompressedSize; }
- /// @brief Return true if section is compressed, including gnu-styled case.
+ /// Return true if section is compressed, including gnu-styled case.
static bool isCompressed(const object::SectionRef &Section);
- /// @brief Return true if section is a ELF compressed one.
+ /// Return true if section is a ELF compressed one.
static bool isCompressedELFSection(uint64_t Flags, StringRef Name);
- /// @brief Return true if section name matches gnu style compressed one.
+ /// Return true if section name matches gnu style compressed one.
static bool isGnuStyle(StringRef Name);
private:
diff --git a/contrib/llvm/include/llvm/Object/ELF.h b/contrib/llvm/include/llvm/Object/ELF.h
index 45c98233dec0..752d468fd25b 100644
--- a/contrib/llvm/include/llvm/Object/ELF.h
+++ b/contrib/llvm/include/llvm/Object/ELF.h
@@ -32,6 +32,7 @@ namespace llvm {
namespace object {
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type);
+uint32_t getELFRelrRelocationType(uint32_t Machine);
StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type);
// Subclasses of ELFFile may need this for template instantiation
@@ -60,6 +61,7 @@ public:
using Elf_Phdr = typename ELFT::Phdr;
using Elf_Rel = typename ELFT::Rel;
using Elf_Rela = typename ELFT::Rela;
+ using Elf_Relr = typename ELFT::Relr;
using Elf_Verdef = typename ELFT::Verdef;
using Elf_Verdaux = typename ELFT::Verdaux;
using Elf_Verneed = typename ELFT::Verneed;
@@ -67,11 +69,15 @@ public:
using Elf_Versym = typename ELFT::Versym;
using Elf_Hash = typename ELFT::Hash;
using Elf_GnuHash = typename ELFT::GnuHash;
+ using Elf_Nhdr = typename ELFT::Nhdr;
+ using Elf_Note = typename ELFT::Note;
+ using Elf_Note_Iterator = typename ELFT::NoteIterator;
using Elf_Dyn_Range = typename ELFT::DynRange;
using Elf_Shdr_Range = typename ELFT::ShdrRange;
using Elf_Sym_Range = typename ELFT::SymRange;
using Elf_Rel_Range = typename ELFT::RelRange;
using Elf_Rela_Range = typename ELFT::RelaRange;
+ using Elf_Relr_Range = typename ELFT::RelrRange;
using Elf_Phdr_Range = typename ELFT::PhdrRange;
const uint8_t *base() const {
@@ -107,8 +113,12 @@ public:
StringRef getRelocationTypeName(uint32_t Type) const;
void getRelocationTypeName(uint32_t Type,
SmallVectorImpl<char> &Result) const;
+ uint32_t getRelrRelocationType() const;
- /// \brief Get the symbol for a given relocation.
+ const char *getDynamicTagAsString(unsigned Arch, uint64_t Type) const;
+ const char *getDynamicTagAsString(uint64_t Type) const;
+
+ /// Get the symbol for a given relocation.
Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel,
const Elf_Shdr *SymTab) const;
@@ -126,6 +136,10 @@ public:
Expected<Elf_Shdr_Range> sections() const;
+ Expected<Elf_Dyn_Range> dynamicEntries() const;
+
+ Expected<const uint8_t *> toMappedAddr(uint64_t VAddr) const;
+
Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const {
if (!Sec)
return makeArrayRef<Elf_Sym>(nullptr, nullptr);
@@ -140,9 +154,15 @@ public:
return getSectionContentsAsArray<Elf_Rel>(Sec);
}
+ Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const {
+ return getSectionContentsAsArray<Elf_Relr>(Sec);
+ }
+
+ Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const;
+
Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const;
- /// \brief Iterate over program header table.
+ /// Iterate over program header table.
Expected<Elf_Phdr_Range> program_headers() const {
if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr))
return createError("invalid e_phentsize");
@@ -155,6 +175,73 @@ public:
return makeArrayRef(Begin, Begin + getHeader()->e_phnum);
}
+ /// Get an iterator over notes in a program header.
+ ///
+ /// The program header must be of type \c PT_NOTE.
+ ///
+ /// \param Phdr the program header to iterate over.
+ /// \param Err [out] an error to support fallible iteration, which should
+ /// be checked after iteration ends.
+ Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const {
+ if (Phdr.p_type != ELF::PT_NOTE) {
+ Err = createError("attempt to iterate notes of non-note program header");
+ return Elf_Note_Iterator(Err);
+ }
+ if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) {
+ Err = createError("invalid program header offset/size");
+ return Elf_Note_Iterator(Err);
+ }
+ return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err);
+ }
+
+ /// Get an iterator over notes in a section.
+ ///
+ /// The section must be of type \c SHT_NOTE.
+ ///
+ /// \param Shdr the section to iterate over.
+ /// \param Err [out] an error to support fallible iteration, which should
+ /// be checked after iteration ends.
+ Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const {
+ if (Shdr.sh_type != ELF::SHT_NOTE) {
+ Err = createError("attempt to iterate notes of non-note section");
+ return Elf_Note_Iterator(Err);
+ }
+ if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) {
+ Err = createError("invalid section offset/size");
+ return Elf_Note_Iterator(Err);
+ }
+ return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err);
+ }
+
+ /// Get the end iterator for notes.
+ Elf_Note_Iterator notes_end() const {
+ return Elf_Note_Iterator();
+ }
+
+ /// Get an iterator range over notes of a program header.
+ ///
+ /// The program header must be of type \c PT_NOTE.
+ ///
+ /// \param Phdr the program header to iterate over.
+ /// \param Err [out] an error to support fallible iteration, which should
+ /// be checked after iteration ends.
+ iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr,
+ Error &Err) const {
+ return make_range(notes_begin(Phdr, Err), notes_end());
+ }
+
+ /// Get an iterator range over notes of a section.
+ ///
+ /// The section must be of type \c SHT_NOTE.
+ ///
+ /// \param Shdr the section to iterate over.
+ /// \param Err [out] an error to support fallible iteration, which should
+ /// be checked after iteration ends.
+ iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr,
+ Error &Err) const {
+ return make_range(notes_begin(Shdr, Err), notes_end());
+ }
+
Expected<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const;
Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms,
ArrayRef<Elf_Word> ShndxTable) const;
@@ -165,6 +252,7 @@ public:
Elf_Sym_Range Symtab,
ArrayRef<Elf_Word> ShndxTable) const;
Expected<const Elf_Shdr *> getSection(uint32_t Index) const;
+ Expected<const Elf_Shdr *> getSection(const StringRef SectionName) const;
Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec,
uint32_t Index) const;
@@ -177,10 +265,10 @@ public:
Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const;
};
-using ELF32LEFile = ELFFile<ELFType<support::little, false>>;
-using ELF64LEFile = ELFFile<ELFType<support::little, true>>;
-using ELF32BEFile = ELFFile<ELFType<support::big, false>>;
-using ELF64BEFile = ELFFile<ELFType<support::big, true>>;
+using ELF32LEFile = ELFFile<ELF32LE>;
+using ELF64LEFile = ELFFile<ELF64LE>;
+using ELF32BEFile = ELFFile<ELF32BE>;
+using ELF64BEFile = ELFFile<ELF64BE>;
template <class ELFT>
inline Expected<const typename ELFT::Shdr *>
@@ -327,6 +415,11 @@ void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
}
template <class ELFT>
+uint32_t ELFFile<ELFT>::getRelrRelocationType() const {
+ return getELFRelrRelocationType(getHeader()->e_machine);
+}
+
+template <class ELFT>
Expected<const typename ELFT::Sym *>
ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,
const Elf_Shdr *SymTab) const {
@@ -429,6 +522,22 @@ ELFFile<ELFT>::getSection(uint32_t Index) const {
}
template <class ELFT>
+Expected<const typename ELFT::Shdr *>
+ELFFile<ELFT>::getSection(const StringRef SectionName) const {
+ auto TableOrErr = sections();
+ if (!TableOrErr)
+ return TableOrErr.takeError();
+ for (auto &Sec : *TableOrErr) {
+ auto SecNameOrErr = getSectionName(&Sec);
+ if (!SecNameOrErr)
+ return SecNameOrErr.takeError();
+ if (*SecNameOrErr == SectionName)
+ return &Sec;
+ }
+ return createError("invalid section name");
+}
+
+template <class ELFT>
Expected<StringRef>
ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const {
if (Section->sh_type != ELF::SHT_STRTAB)
diff --git a/contrib/llvm/include/llvm/Object/ELFObjectFile.h b/contrib/llvm/include/llvm/Object/ELFObjectFile.h
index 40503cb6bb9d..2c0905d545a7 100644
--- a/contrib/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/contrib/llvm/include/llvm/Object/ELFObjectFile.h
@@ -15,6 +15,7 @@
#define LLVM_OBJECT_ELFOBJECTFILE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
@@ -67,6 +68,9 @@ public:
virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0;
+ /// Returns platform-specific object flags, if any.
+ virtual unsigned getPlatformFlags() const = 0;
+
elf_symbol_iterator_range symbols() const;
static bool classof(const Binary *v) { return v->isELF(); }
@@ -77,7 +81,11 @@ public:
SubtargetFeatures getARMFeatures() const;
+ SubtargetFeatures getRISCVFeatures() const;
+
void setARMSubArch(Triple &TheTriple) const override;
+
+ virtual uint16_t getEType() const = 0;
};
class ELFSectionRef : public SectionRef {
@@ -195,19 +203,20 @@ ELFObjectFileBase::symbols() const {
template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
uint16_t getEMachine() const override;
+ uint16_t getEType() const override;
uint64_t getSymbolSize(DataRefImpl Sym) const override;
public:
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
- using uintX_t = typename ELFFile<ELFT>::uintX_t;
+ using uintX_t = typename ELFT::uint;
- using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym;
- using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr;
- using Elf_Ehdr = typename ELFFile<ELFT>::Elf_Ehdr;
- using Elf_Rel = typename ELFFile<ELFT>::Elf_Rel;
- using Elf_Rela = typename ELFFile<ELFT>::Elf_Rela;
- using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn;
+ using Elf_Sym = typename ELFT::Sym;
+ using Elf_Shdr = typename ELFT::Shdr;
+ using Elf_Ehdr = typename ELFT::Ehdr;
+ using Elf_Rel = typename ELFT::Rel;
+ using Elf_Rela = typename ELFT::Rela;
+ using Elf_Dyn = typename ELFT::Dyn;
private:
ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF,
@@ -251,6 +260,7 @@ protected:
bool isSectionVirtual(DataRefImpl Sec) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
+ std::vector<SectionRef> dynamic_relocation_sections() const override;
section_iterator getRelocatedSection(DataRefImpl Sec) const override;
void moveRelocationNext(DataRefImpl &Rel) const override;
@@ -265,7 +275,7 @@ protected:
uint64_t getSectionOffset(DataRefImpl Sec) const override;
StringRef getRelocationTypeName(uint32_t Type) const;
- /// \brief Get the relocation section that contains \a Rel.
+ /// Get the relocation section that contains \a Rel.
const Elf_Shdr *getRelSection(DataRefImpl Rel) const {
auto RelSecOrErr = EF.getSection(Rel.d.a);
if (!RelSecOrErr)
@@ -363,11 +373,9 @@ public:
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
Triple::ArchType getArch() const override;
+ Expected<uint64_t> getStartAddress() const override;
- std::error_code getPlatformFlags(unsigned &Result) const override {
- Result = EF.getHeader()->e_flags;
- return std::error_code();
- }
+ unsigned getPlatformFlags() const override { return EF.getHeader()->e_flags; }
std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const override {
auto SectionsOrErr = EF.sections();
@@ -404,10 +412,10 @@ public:
bool isRelocatableObject() const override;
};
-using ELF32LEObjectFile = ELFObjectFile<ELFType<support::little, false>>;
-using ELF64LEObjectFile = ELFObjectFile<ELFType<support::little, true>>;
-using ELF32BEObjectFile = ELFObjectFile<ELFType<support::big, false>>;
-using ELF64BEObjectFile = ELFObjectFile<ELFType<support::big, true>>;
+using ELF32LEObjectFile = ELFObjectFile<ELF32LE>;
+using ELF64LEObjectFile = ELFObjectFile<ELF64LE>;
+using ELF32BEObjectFile = ELFObjectFile<ELF32BE>;
+using ELF64BEObjectFile = ELFObjectFile<ELF64BE>;
template <class ELFT>
void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const {
@@ -505,6 +513,10 @@ uint16_t ELFObjectFile<ELFT>::getEMachine() const {
return EF.getHeader()->e_machine;
}
+template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const {
+ return EF.getHeader()->e_type;
+}
+
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const {
return getSymbol(Sym)->st_size;
@@ -698,8 +710,9 @@ bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const {
const Elf_Shdr *EShdr = getSection(Sec);
- return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
- EShdr->sh_type == ELF::SHT_PROGBITS;
+ return EShdr->sh_type == ELF::SHT_PROGBITS &&
+ EShdr->sh_flags & ELF::SHF_ALLOC &&
+ !(EShdr->sh_flags & ELF::SHF_EXECINSTR);
}
template <class ELFT>
@@ -710,6 +723,35 @@ bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const {
}
template <class ELFT>
+std::vector<SectionRef>
+ELFObjectFile<ELFT>::dynamic_relocation_sections() const {
+ std::vector<SectionRef> Res;
+ std::vector<uintptr_t> Offsets;
+
+ auto SectionsOrErr = EF.sections();
+ if (!SectionsOrErr)
+ return Res;
+
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ if (Sec.sh_type != ELF::SHT_DYNAMIC)
+ continue;
+ Elf_Dyn *Dynamic =
+ reinterpret_cast<Elf_Dyn *>((uintptr_t)base() + Sec.sh_offset);
+ for (; Dynamic->d_tag != ELF::DT_NULL; Dynamic++) {
+ if (Dynamic->d_tag == ELF::DT_REL || Dynamic->d_tag == ELF::DT_RELA ||
+ Dynamic->d_tag == ELF::DT_JMPREL) {
+ Offsets.push_back(Dynamic->d_un.d_val);
+ }
+ }
+ }
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ if (is_contained(Offsets, Sec.sh_offset))
+ Res.emplace_back(toDRI(&Sec), this);
+ }
+ return Res;
+}
+
+template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
return getSection(Sec)->sh_type == ELF::SHT_NOBITS;
}
@@ -790,8 +832,6 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
- assert(EF.getHeader()->e_type == ELF::ET_REL &&
- "Only relocatable object files have relocation offsets");
const Elf_Shdr *sec = getRelSection(Rel);
if (sec->sh_type == ELF::SHT_REL)
return getRel(Rel)->r_offset;
@@ -986,8 +1026,6 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
case ELF::EM_SPARC:
case ELF::EM_SPARC32PLUS:
return "ELF32-sparc";
- case ELF::EM_WEBASSEMBLY:
- return "ELF32-wasm";
case ELF::EM_AMDGPU:
return "ELF32-amdgpu";
default:
@@ -1011,8 +1049,6 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF64-sparc";
case ELF::EM_MIPS:
return "ELF64-mips";
- case ELF::EM_WEBASSEMBLY:
- return "ELF64-wasm";
case ELF::EM_AMDGPU:
return "ELF64-amdgpu";
case ELF::EM_BPF:
@@ -1074,26 +1110,20 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
return IsLittleEndian ? Triple::sparcel : Triple::sparc;
case ELF::EM_SPARCV9:
return Triple::sparcv9;
- case ELF::EM_WEBASSEMBLY:
- switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) {
- case ELF::ELFCLASS32: return Triple::wasm32;
- case ELF::ELFCLASS64: return Triple::wasm64;
- default: return Triple::UnknownArch;
- }
case ELF::EM_AMDGPU: {
if (!IsLittleEndian)
return Triple::UnknownArch;
- unsigned EFlags = EF.getHeader()->e_flags;
- switch (EFlags & ELF::EF_AMDGPU_ARCH) {
- case ELF::EF_AMDGPU_ARCH_R600:
+ unsigned MACH = EF.getHeader()->e_flags & ELF::EF_AMDGPU_MACH;
+ if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST &&
+ MACH <= ELF::EF_AMDGPU_MACH_R600_LAST)
return Triple::r600;
- case ELF::EF_AMDGPU_ARCH_GCN:
+ if (MACH >= ELF::EF_AMDGPU_MACH_AMDGCN_FIRST &&
+ MACH <= ELF::EF_AMDGPU_MACH_AMDGCN_LAST)
return Triple::amdgcn;
- default:
- return Triple::UnknownArch;
- }
+
+ return Triple::UnknownArch;
}
case ELF::EM_BPF:
@@ -1105,6 +1135,11 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
}
template <class ELFT>
+Expected<uint64_t> ELFObjectFile<ELFT>::getStartAddress() const {
+ return EF.getHeader()->e_entry;
+}
+
+template <class ELFT>
ELFObjectFileBase::elf_symbol_iterator_range
ELFObjectFile<ELFT>::getDynamicSymbolIterators() const {
return make_range(dynamic_symbol_begin(), dynamic_symbol_end());
diff --git a/contrib/llvm/include/llvm/Object/ELFTypes.h b/contrib/llvm/include/llvm/Object/ELFTypes.h
index 83b688548fdc..fb386120e34d 100644
--- a/contrib/llvm/include/llvm/Object/ELFTypes.h
+++ b/contrib/llvm/include/llvm/Object/ELFTypes.h
@@ -40,11 +40,15 @@ template <class ELFT> struct Elf_Versym_Impl;
template <class ELFT> struct Elf_Hash_Impl;
template <class ELFT> struct Elf_GnuHash_Impl;
template <class ELFT> struct Elf_Chdr_Impl;
+template <class ELFT> struct Elf_Nhdr_Impl;
+template <class ELFT> class Elf_Note_Impl;
+template <class ELFT> class Elf_Note_Iterator_Impl;
+template <class ELFT> struct Elf_CGProfile_Impl;
template <endianness E, bool Is64> struct ELFType {
private:
template <typename Ty>
- using packed = support::detail::packed_endian_specific_integral<Ty, E, 2>;
+ using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>;
public:
static const endianness TargetEndianness = E;
@@ -58,6 +62,7 @@ public:
using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>;
using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>;
using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>;
+ using Relr = packed<uint>;
using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>;
using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>;
using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>;
@@ -66,11 +71,16 @@ public:
using Hash = Elf_Hash_Impl<ELFType<E, Is64>>;
using GnuHash = Elf_GnuHash_Impl<ELFType<E, Is64>>;
using Chdr = Elf_Chdr_Impl<ELFType<E, Is64>>;
+ using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>;
+ using Note = Elf_Note_Impl<ELFType<E, Is64>>;
+ using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>;
+ using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>;
using DynRange = ArrayRef<Dyn>;
using ShdrRange = ArrayRef<Shdr>;
using SymRange = ArrayRef<Sym>;
using RelRange = ArrayRef<Rel>;
using RelaRange = ArrayRef<Rela>;
+ using RelrRange = ArrayRef<Relr>;
using PhdrRange = ArrayRef<Phdr>;
using Half = packed<uint16_t>;
@@ -90,46 +100,7 @@ using ELF64BE = ELFType<support::big, true>;
// Use an alignment of 2 for the typedefs since that is the worst case for
// ELF files in archives.
-// Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
-template <endianness target_endianness> struct ELFDataTypeTypedefHelperCommon {
- using Elf_Half = support::detail::packed_endian_specific_integral<
- uint16_t, target_endianness, 2>;
- using Elf_Word = support::detail::packed_endian_specific_integral<
- uint32_t, target_endianness, 2>;
- using Elf_Sword = support::detail::packed_endian_specific_integral<
- int32_t, target_endianness, 2>;
- using Elf_Xword = support::detail::packed_endian_specific_integral<
- uint64_t, target_endianness, 2>;
- using Elf_Sxword = support::detail::packed_endian_specific_integral<
- int64_t, target_endianness, 2>;
-};
-
-template <class ELFT> struct ELFDataTypeTypedefHelper;
-
-/// ELF 32bit types.
-template <endianness TargetEndianness>
-struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, false>>
- : ELFDataTypeTypedefHelperCommon<TargetEndianness> {
- using value_type = uint32_t;
- using Elf_Addr = support::detail::packed_endian_specific_integral<
- value_type, TargetEndianness, 2>;
- using Elf_Off = support::detail::packed_endian_specific_integral<
- value_type, TargetEndianness, 2>;
-};
-
-/// ELF 64bit types.
-template <endianness TargetEndianness>
-struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>>
- : ELFDataTypeTypedefHelperCommon<TargetEndianness> {
- using value_type = uint64_t;
- using Elf_Addr = support::detail::packed_endian_specific_integral<
- value_type, TargetEndianness, 2>;
- using Elf_Off = support::detail::packed_endian_specific_integral<
- value_type, TargetEndianness, 2>;
-};
-
// I really don't like doing this, but the alternative is copypasta.
-
#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \
using Elf_Addr = typename ELFT::Addr; \
using Elf_Off = typename ELFT::Off; \
@@ -139,9 +110,9 @@ struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>>
using Elf_Xword = typename ELFT::Xword; \
using Elf_Sxword = typename ELFT::Sxword;
-#define LLD_ELF_COMMA ,
+#define LLVM_ELF_COMMA ,
#define LLVM_ELF_IMPORT_TYPES(E, W) \
- LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLD_ELF_COMMA W>)
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLVM_ELF_COMMA W>)
// Section header.
template <class ELFT> struct Elf_Shdr_Base;
@@ -181,7 +152,7 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> {
using Elf_Shdr_Base<ELFT>::sh_entsize;
using Elf_Shdr_Base<ELFT>::sh_size;
- /// @brief Get the number of entities this section contains if it has any.
+ /// Get the number of entities this section contains if it has any.
unsigned getEntityCount() const {
if (sh_entsize == 0)
return 0;
@@ -590,6 +561,134 @@ struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> {
Elf_Xword ch_addralign;
};
+/// Note header
+template <class ELFT>
+struct Elf_Nhdr_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ Elf_Word n_namesz;
+ Elf_Word n_descsz;
+ Elf_Word n_type;
+
+ /// The alignment of the name and descriptor.
+ ///
+ /// Implementations differ from the specification here: in practice all
+ /// variants align both the name and descriptor to 4-bytes.
+ static const unsigned int Align = 4;
+
+ /// Get the size of the note, including name, descriptor, and padding.
+ size_t getSize() const {
+ return sizeof(*this) + alignTo<Align>(n_namesz) + alignTo<Align>(n_descsz);
+ }
+};
+
+/// An ELF note.
+///
+/// Wraps a note header, providing methods for accessing the name and
+/// descriptor safely.
+template <class ELFT>
+class Elf_Note_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+
+ const Elf_Nhdr_Impl<ELFT> &Nhdr;
+
+ template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl;
+
+ Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {}
+
+public:
+ /// Get the note's name, excluding the terminating null byte.
+ StringRef getName() const {
+ if (!Nhdr.n_namesz)
+ return StringRef();
+ return StringRef(reinterpret_cast<const char *>(&Nhdr) + sizeof(Nhdr),
+ Nhdr.n_namesz - 1);
+ }
+
+ /// Get the note's descriptor.
+ ArrayRef<Elf_Word> getDesc() const {
+ if (!Nhdr.n_descsz)
+ return ArrayRef<Elf_Word>();
+ return ArrayRef<Elf_Word>(
+ reinterpret_cast<const Elf_Word *>(
+ reinterpret_cast<const uint8_t *>(&Nhdr) + sizeof(Nhdr) +
+ alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Nhdr.n_namesz)),
+ Nhdr.n_descsz);
+ }
+
+ /// Get the note's type.
+ Elf_Word getType() const { return Nhdr.n_type; }
+};
+
+template <class ELFT>
+class Elf_Note_Iterator_Impl
+ : std::iterator<std::forward_iterator_tag, Elf_Note_Impl<ELFT>> {
+ // Nhdr being a nullptr marks the end of iteration.
+ const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr;
+ size_t RemainingSize = 0u;
+ Error *Err = nullptr;
+
+ template <class ELFFileELFT> friend class ELFFile;
+
+ // Stop iteration and indicate an overflow.
+ void stopWithOverflowError() {
+ Nhdr = nullptr;
+ *Err = make_error<StringError>("ELF note overflows container",
+ object_error::parse_failed);
+ }
+
+ // Advance Nhdr by NoteSize bytes, starting from NhdrPos.
+ //
+ // Assumes NoteSize <= RemainingSize. Ensures Nhdr->getSize() <= RemainingSize
+ // upon returning. Handles stopping iteration when reaching the end of the
+ // container, either cleanly or with an overflow error.
+ void advanceNhdr(const uint8_t *NhdrPos, size_t NoteSize) {
+ RemainingSize -= NoteSize;
+ if (RemainingSize == 0u)
+ Nhdr = nullptr;
+ else if (sizeof(*Nhdr) > RemainingSize)
+ stopWithOverflowError();
+ else {
+ Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize);
+ if (Nhdr->getSize() > RemainingSize)
+ stopWithOverflowError();
+ }
+ }
+
+ Elf_Note_Iterator_Impl() {}
+ explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {}
+ Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, Error &Err)
+ : RemainingSize(Size), Err(&Err) {
+ assert(Start && "ELF note iterator starting at NULL");
+ advanceNhdr(Start, 0u);
+ }
+
+public:
+ Elf_Note_Iterator_Impl &operator++() {
+ assert(Nhdr && "incremented ELF note end iterator");
+ const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr);
+ size_t NoteSize = Nhdr->getSize();
+ advanceNhdr(NhdrPos, NoteSize);
+ return *this;
+ }
+ bool operator==(Elf_Note_Iterator_Impl Other) const {
+ return Nhdr == Other.Nhdr;
+ }
+ bool operator!=(Elf_Note_Iterator_Impl Other) const {
+ return !(*this == Other);
+ }
+ Elf_Note_Impl<ELFT> operator*() const {
+ assert(Nhdr && "dereferenced ELF note end iterator");
+ return Elf_Note_Impl<ELFT>(*Nhdr);
+ }
+};
+
+template <class ELFT> struct Elf_CGProfile_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ Elf_Word cgp_from;
+ Elf_Word cgp_to;
+ Elf_Xword cgp_weight;
+};
+
// MIPS .reginfo section
template <class ELFT>
struct Elf_Mips_RegInfo;
diff --git a/contrib/llvm/include/llvm/Object/IRObjectFile.h b/contrib/llvm/include/llvm/Object/IRObjectFile.h
index 6c271b1a1f44..993359b766a1 100644
--- a/contrib/llvm/include/llvm/Object/IRObjectFile.h
+++ b/contrib/llvm/include/llvm/Object/IRObjectFile.h
@@ -50,11 +50,22 @@ public:
return v->isIR();
}
- /// \brief Finds and returns bitcode embedded in the given object file, or an
+ using module_iterator =
+ pointee_iterator<std::vector<std::unique_ptr<Module>>::const_iterator,
+ const Module>;
+
+ module_iterator module_begin() const { return module_iterator(Mods.begin()); }
+ module_iterator module_end() const { return module_iterator(Mods.end()); }
+
+ iterator_range<module_iterator> modules() const {
+ return make_range(module_begin(), module_end());
+ }
+
+ /// Finds and returns bitcode embedded in the given object file, or an
/// error code if not found.
static Expected<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj);
- /// \brief Finds and returns bitcode in the given memory buffer (which may
+ /// Finds and returns bitcode in the given memory buffer (which may
/// be either a bitcode file or a native object file with embedded bitcode),
/// or an error code if not found.
static Expected<MemoryBufferRef>
diff --git a/contrib/llvm/include/llvm/Object/MachO.h b/contrib/llvm/include/llvm/Object/MachO.h
index d0cc40da4293..531b3d249035 100644
--- a/contrib/llvm/include/llvm/Object/MachO.h
+++ b/contrib/llvm/include/llvm/Object/MachO.h
@@ -304,6 +304,8 @@ public:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ Expected<SectionRef> getSection(unsigned SectionIndex) const;
+ Expected<SectionRef> getSection(StringRef SectionName) const;
bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
@@ -463,7 +465,7 @@ public:
// In a MachO file, sections have a segment name. This is used in the .o
// files. They have a single segment, but this field specifies which segment
- // a section should be put in in the final object.
+ // a section should be put in the final object.
StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
// Names are stored as 16 bytes. These returns the raw 16 bytes without
diff --git a/contrib/llvm/include/llvm/Object/MachOUniversal.h b/contrib/llvm/include/llvm/Object/MachOUniversal.h
index 72837d0970c4..9e70b0bc30c0 100644
--- a/contrib/llvm/include/llvm/Object/MachOUniversal.h
+++ b/contrib/llvm/include/llvm/Object/MachOUniversal.h
@@ -34,9 +34,9 @@ class MachOUniversalBinary : public Binary {
public:
class ObjectForArch {
const MachOUniversalBinary *Parent;
- /// \brief Index of object in the universal binary.
+ /// Index of object in the universal binary.
uint32_t Index;
- /// \brief Descriptor of the object.
+ /// Descriptor of the object.
MachO::fat_arch Header;
MachO::fat_arch_64 Header64;
diff --git a/contrib/llvm/include/llvm/Object/ModuleSymbolTable.h b/contrib/llvm/include/llvm/Object/ModuleSymbolTable.h
index 9e9322885388..c3cbc27998e5 100644
--- a/contrib/llvm/include/llvm/Object/ModuleSymbolTable.h
+++ b/contrib/llvm/include/llvm/Object/ModuleSymbolTable.h
@@ -57,6 +57,15 @@ public:
static void CollectAsmSymbols(
const Module &M,
function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol);
+
+ /// Parse inline ASM and collect the symvers directives that are defined in
+ /// the current module.
+ ///
+ /// For each found symbol, call \p AsmSymver with the name of the symbol and
+ /// its alias.
+ static void
+ CollectAsmSymvers(const Module &M,
+ function_ref<void(StringRef, StringRef)> AsmSymver);
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Object/ObjectFile.h b/contrib/llvm/include/llvm/Object/ObjectFile.h
index 079a59468156..02d62e8e4879 100644
--- a/contrib/llvm/include/llvm/Object/ObjectFile.h
+++ b/contrib/llvm/include/llvm/Object/ObjectFile.h
@@ -65,7 +65,7 @@ public:
symbol_iterator getSymbol() const;
uint64_t getType() const;
- /// @brief Get a string that represents the type of this relocation.
+ /// Get a string that represents the type of this relocation.
///
/// This is for display purposes only.
void getTypeName(SmallVectorImpl<char> &Result) const;
@@ -100,7 +100,7 @@ public:
uint64_t getSize() const;
std::error_code getContents(StringRef &Result) const;
- /// @brief Get the alignment of this section as the actual value (not log 2).
+ /// Get the alignment of this section as the actual value (not log 2).
uint64_t getAlignment() const;
bool isCompressed() const;
@@ -154,12 +154,12 @@ public:
/// offset or a virtual address.
uint64_t getValue() const;
- /// @brief Get the alignment of this symbol as the actual value (not log 2).
+ /// Get the alignment of this symbol as the actual value (not log 2).
uint32_t getAlignment() const;
uint64_t getCommonSize() const;
Expected<SymbolRef::Type> getType() const;
- /// @brief Get section this symbol is defined in reference to. Result is
+ /// Get section this symbol is defined in reference to. Result is
/// end_sections() if it is undefined or is an absolute symbol.
Expected<section_iterator> getSection() const;
@@ -262,6 +262,10 @@ public:
return getCommonSymbolSizeImpl(Symb);
}
+ virtual std::vector<SectionRef> dynamic_relocation_sections() const {
+ return std::vector<SectionRef>();
+ }
+
using symbol_iterator_range = iterator_range<symbol_iterator>;
symbol_iterator_range symbols() const {
return symbol_iterator_range(symbol_begin(), symbol_end());
@@ -275,7 +279,7 @@ public:
return section_iterator_range(section_begin(), section_end());
}
- /// @brief The number of bytes used to represent an address in this object
+ /// The number of bytes used to represent an address in this object
/// file format.
virtual uint8_t getBytesInAddress() const = 0;
@@ -283,16 +287,13 @@ public:
virtual Triple::ArchType getArch() const = 0;
virtual SubtargetFeatures getFeatures() const = 0;
virtual void setARMSubArch(Triple &TheTriple) const { }
+ virtual Expected<uint64_t> getStartAddress() const {
+ return errorCodeToError(object_error::parse_failed);
+ };
- /// @brief Create a triple from the data in this object file.
+ /// Create a triple from the data in this object file.
Triple makeTriple() const;
- /// Returns platform-specific object flags, if any.
- virtual std::error_code getPlatformFlags(unsigned &Result) const {
- Result = 0;
- return object_error::invalid_file_type;
- }
-
virtual std::error_code
getBuildAttributes(ARMAttributeParser &Attributes) const {
return std::error_code();
@@ -307,7 +308,7 @@ public:
/// @returns Pointer to ObjectFile subclass to handle this type of object.
/// @param ObjectPath The path to the object file. ObjectPath.isObject must
/// return true.
- /// @brief Create ObjectFile from path.
+ /// Create ObjectFile from path.
static Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath);
diff --git a/contrib/llvm/include/llvm/Object/RelocVisitor.h b/contrib/llvm/include/llvm/Object/RelocVisitor.h
index 2d0e938f06fd..008e109f6679 100644
--- a/contrib/llvm/include/llvm/Object/RelocVisitor.h
+++ b/contrib/llvm/include/llvm/Object/RelocVisitor.h
@@ -23,6 +23,7 @@
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/Wasm.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <cstdint>
@@ -31,7 +32,7 @@
namespace llvm {
namespace object {
-/// @brief Base class for object file relocation visitors.
+/// Base class for object file relocation visitors.
class RelocVisitor {
public:
explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
@@ -46,6 +47,8 @@ public:
return visitCOFF(Rel, R, Value);
if (isa<MachOObjectFile>(ObjToVisit))
return visitMachO(Rel, R, Value);
+ if (isa<WasmObjectFile>(ObjToVisit))
+ return visitWasm(Rel, R, Value);
HasError = true;
return 0;
@@ -316,6 +319,27 @@ private:
HasError = true;
return 0;
}
+
+ uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (ObjToVisit.getArch() == Triple::wasm32) {
+ switch (Rel) {
+ case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
+ // For wasm section, its offset at 0 -- ignoring Value
+ return 0;
+ }
+ }
+ HasError = true;
+ return 0;
+ }
};
} // end namespace object
diff --git a/contrib/llvm/include/llvm/Object/Wasm.h b/contrib/llvm/include/llvm/Object/Wasm.h
index 71951d83f3cc..fd34e45feb62 100644
--- a/contrib/llvm/include/llvm/Object/Wasm.h
+++ b/contrib/llvm/include/llvm/Object/Wasm.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
@@ -34,61 +35,49 @@ namespace object {
class WasmSymbol {
public:
- enum class SymbolType {
- FUNCTION_IMPORT,
- FUNCTION_EXPORT,
- GLOBAL_IMPORT,
- GLOBAL_EXPORT,
- DEBUG_FUNCTION_NAME,
- };
-
- WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section,
- uint32_t ElementIndex, uint32_t FunctionType = 0)
- : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex),
- FunctionType(FunctionType) {}
+ WasmSymbol(const wasm::WasmSymbolInfo &Info,
+ const wasm::WasmSignature *FunctionType,
+ const wasm::WasmGlobalType *GlobalType)
+ : Info(Info), FunctionType(FunctionType), GlobalType(GlobalType) {}
- StringRef Name;
- SymbolType Type;
- uint32_t Section;
- uint32_t Flags = 0;
+ const wasm::WasmSymbolInfo &Info;
+ const wasm::WasmSignature *FunctionType;
+ const wasm::WasmGlobalType *GlobalType;
- // Index into either the function or global index space.
- uint32_t ElementIndex;
-
- // For function, the type index
- uint32_t FunctionType;
+ bool isTypeFunction() const {
+ return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
+ }
- // Symbols can be both exported and imported (in the case of the weakly
- // defined symbol). In this the import index is stored as AltIndex.
- uint32_t AltIndex = 0;
- bool HasAltIndex = false;
+ bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
- void setAltIndex(uint32_t Index) {
- HasAltIndex = true;
- AltIndex = Index;
+ bool isTypeGlobal() const {
+ return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
}
- bool isFunction() const {
- return Type == WasmSymbol::SymbolType::FUNCTION_IMPORT ||
- Type == WasmSymbol::SymbolType::FUNCTION_EXPORT ||
- Type == WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME;
+ bool isTypeSection() const {
+ return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
}
+ bool isDefined() const { return !isUndefined(); }
- bool isWeak() const {
+ bool isUndefined() const {
+ return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
+ }
+
+ bool isBindingWeak() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
}
- bool isGlobal() const {
+ bool isBindingGlobal() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
}
- bool isLocal() const {
+ bool isBindingLocal() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
}
unsigned getBinding() const {
- return Flags & wasm::WASM_SYMBOL_BINDING_MASK;
+ return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
}
bool isHidden() const {
@@ -96,16 +85,13 @@ public:
}
unsigned getVisibility() const {
- return Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
+ return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
}
- void print(raw_ostream &Out) const {
- Out << "Name=" << Name << ", Type=" << static_cast<int>(Type)
- << ", Flags=" << Flags << " ElemIndex=" << ElementIndex;
- }
+ void print(raw_ostream &Out) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
+ LLVM_DUMP_METHOD void dump() const;
#endif
};
@@ -144,12 +130,16 @@ public:
ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
ArrayRef<wasm::WasmExport> exports() const { return Exports; }
+ ArrayRef<WasmSymbol> syms() const { return Symbols; }
const wasm::WasmLinkingData& linkingData() const { return LinkingData; }
uint32_t getNumberOfSymbols() const { return Symbols.size(); }
ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
+ ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
uint32_t startFunction() const { return StartFunction; }
+ uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
+ uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -203,39 +193,50 @@ public:
SubtargetFeatures getFeatures() const override;
bool isRelocatableObject() const override;
+ struct ReadContext {
+ const uint8_t *Start;
+ const uint8_t *Ptr;
+ const uint8_t *End;
+ };
+
private:
bool isValidFunctionIndex(uint32_t Index) const;
+ bool isDefinedFunctionIndex(uint32_t Index) const;
+ bool isValidGlobalIndex(uint32_t Index) const;
+ bool isDefinedGlobalIndex(uint32_t Index) const;
+ bool isValidFunctionSymbol(uint32_t Index) const;
+ bool isValidGlobalSymbol(uint32_t Index) const;
+ bool isValidDataSymbol(uint32_t Index) const;
+ bool isValidSectionSymbol(uint32_t Index) const;
+ wasm::WasmFunction &getDefinedFunction(uint32_t Index);
+ wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
+
const WasmSection &getWasmSection(DataRefImpl Ref) const;
const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
- WasmSection* findCustomSectionByName(StringRef Name);
- WasmSection* findSectionByType(uint32_t Type);
-
const uint8_t *getPtr(size_t Offset) const;
Error parseSection(WasmSection &Sec);
- Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr,
- const uint8_t *End);
+ Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
// Standard section types
- Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseImportSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseTableSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End);
- Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseExportSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseStartSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseElemSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseDataSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseTypeSection(ReadContext &Ctx);
+ Error parseImportSection(ReadContext &Ctx);
+ Error parseFunctionSection(ReadContext &Ctx);
+ Error parseTableSection(ReadContext &Ctx);
+ Error parseMemorySection(ReadContext &Ctx);
+ Error parseGlobalSection(ReadContext &Ctx);
+ Error parseExportSection(ReadContext &Ctx);
+ Error parseStartSection(ReadContext &Ctx);
+ Error parseElemSection(ReadContext &Ctx);
+ Error parseCodeSection(ReadContext &Ctx);
+ Error parseDataSection(ReadContext &Ctx);
// Custom section types
- Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
- Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
- const uint8_t *End);
-
- void populateSymbolTable();
+ Error parseNameSection(ReadContext &Ctx);
+ Error parseLinkingSection(ReadContext &Ctx);
+ Error parseLinkingSectionSymtab(ReadContext &Ctx);
+ Error parseLinkingSectionComdat(ReadContext &Ctx);
+ Error parseRelocSection(StringRef Name, ReadContext &Ctx);
wasm::WasmObjectHeader Header;
std::vector<WasmSection> Sections;
@@ -250,15 +251,15 @@ private:
std::vector<WasmSegment> DataSegments;
std::vector<wasm::WasmFunction> Functions;
std::vector<WasmSymbol> Symbols;
+ std::vector<wasm::WasmFunctionName> DebugNames;
uint32_t StartFunction = -1;
bool HasLinkingSection = false;
wasm::WasmLinkingData LinkingData;
uint32_t NumImportedGlobals = 0;
uint32_t NumImportedFunctions = 0;
- uint32_t ImportSection = 0;
- uint32_t ExportSection = 0;
-
- StringMap<uint32_t> SymbolMap;
+ uint32_t CodeSection = 0;
+ uint32_t DataSection = 0;
+ uint32_t GlobalSection = 0;
};
} // end namespace object
diff --git a/contrib/llvm/include/llvm/Object/WasmTraits.h b/contrib/llvm/include/llvm/Object/WasmTraits.h
new file mode 100644
index 000000000000..ebcd00b15227
--- /dev/null
+++ b/contrib/llvm/include/llvm/Object/WasmTraits.h
@@ -0,0 +1,63 @@
+//===- WasmTraits.h - DenseMap traits for the Wasm structures ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides llvm::DenseMapInfo traits for the Wasm structures.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_WASMTRAITS_H
+#define LLVM_OBJECT_WASMTRAITS_H
+
+#include "llvm/ADT/Hashing.h"
+#include "llvm/BinaryFormat/Wasm.h"
+
+namespace llvm {
+
+template <typename T> struct DenseMapInfo;
+
+// Traits for using WasmSignature in a DenseMap.
+template <> struct DenseMapInfo<wasm::WasmSignature> {
+ static wasm::WasmSignature getEmptyKey() {
+ return wasm::WasmSignature{{}, 1};
+ }
+ static wasm::WasmSignature getTombstoneKey() {
+ return wasm::WasmSignature{{}, 2};
+ }
+ static unsigned getHashValue(const wasm::WasmSignature &Sig) {
+ unsigned H = hash_value(Sig.ReturnType);
+ for (int32_t Param : Sig.ParamTypes)
+ H = hash_combine(H, Param);
+ return H;
+ }
+ static bool isEqual(const wasm::WasmSignature &LHS,
+ const wasm::WasmSignature &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Traits for using WasmGlobalType in a DenseMap
+template <> struct DenseMapInfo<wasm::WasmGlobalType> {
+ static wasm::WasmGlobalType getEmptyKey() {
+ return wasm::WasmGlobalType{1, true};
+ }
+ static wasm::WasmGlobalType getTombstoneKey() {
+ return wasm::WasmGlobalType{2, true};
+ }
+ static unsigned getHashValue(const wasm::WasmGlobalType &GlobalType) {
+ return hash_combine(GlobalType.Type, GlobalType.Mutable);
+ }
+ static bool isEqual(const wasm::WasmGlobalType &LHS,
+ const wasm::WasmGlobalType &RHS) {
+ return LHS == RHS;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_WASMTRAITS_H
diff --git a/contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h b/contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h
index 8794eaa6d59a..78f021fc0386 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h
@@ -67,6 +67,7 @@ struct Section {
yaml::BinaryRef SectionData;
std::vector<CodeViewYAML::YAMLDebugSubsection> DebugS;
std::vector<CodeViewYAML::LeafRecord> DebugT;
+ std::vector<CodeViewYAML::LeafRecord> DebugP;
Optional<CodeViewYAML::DebugHSection> DebugH;
std::vector<Relocation> Relocations;
StringRef Name;
diff --git a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h
index 4f0d9efb963b..344966fe6891 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h
@@ -32,10 +32,10 @@ namespace CodeViewYAML {
struct GlobalHash {
GlobalHash() = default;
explicit GlobalHash(StringRef S) : Hash(S) {
- assert(S.size() == 20 && "Invalid hash size!");
+ assert(S.size() == 8 && "Invalid hash size!");
}
explicit GlobalHash(ArrayRef<uint8_t> S) : Hash(S) {
- assert(S.size() == 20 && "Invalid hash size!");
+ assert(S.size() == 8 && "Invalid hash size!");
}
yaml::BinaryRef Hash;
};
@@ -47,7 +47,7 @@ struct DebugHSection {
std::vector<GlobalHash> Hashes;
};
-DebugHSection fromDebugH(ArrayRef<uint8_t> DebugT);
+DebugHSection fromDebugH(ArrayRef<uint8_t> DebugH);
ArrayRef<uint8_t> toDebugH(const DebugHSection &DebugH,
BumpPtrAllocator &Alloc);
diff --git a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
index bc3b5567c2f9..1b1306df4f53 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
@@ -51,8 +51,10 @@ struct LeafRecord {
static Expected<LeafRecord> fromCodeViewRecord(codeview::CVType Type);
};
-std::vector<LeafRecord> fromDebugT(ArrayRef<uint8_t> DebugT);
-ArrayRef<uint8_t> toDebugT(ArrayRef<LeafRecord>, BumpPtrAllocator &Alloc);
+std::vector<LeafRecord> fromDebugT(ArrayRef<uint8_t> DebugTorP,
+ StringRef SectionName);
+ArrayRef<uint8_t> toDebugT(ArrayRef<LeafRecord>, BumpPtrAllocator &Alloc,
+ StringRef SectionName);
} // end namespace CodeViewYAML
diff --git a/contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h b/contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h
index 0d7d8b4efbdf..ce3227421930 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief Common declarations for yaml2obj
+/// Common declarations for yaml2obj
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECTYAML_DWARFEMITTER_H
@@ -39,11 +39,12 @@ void EmitDebugInfo(raw_ostream &OS, const Data &DI);
void EmitDebugLine(raw_ostream &OS, const Data &DI);
Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
-EmitDebugSections(StringRef YAMLString,
+EmitDebugSections(StringRef YAMLString, bool ApplyFixups = false,
bool IsLittleEndian = sys::IsLittleEndianHost);
+StringMap<std::unique_ptr<MemoryBuffer>>
+EmitDebugSections(llvm::DWARFYAML::Data &DI, bool ApplyFixups);
} // end namespace DWARFYAML
-
} // end namespace llvm
#endif // LLVM_OBJECTYAML_DWARFEMITTER_H
diff --git a/contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h
index 2162f0fef852..705c88778945 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file declares classes for handling the YAML representation
+/// This file declares classes for handling the YAML representation
/// of DWARF Debug Info.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h b/contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 7ba83967330e..6fc69735f1c7 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file declares classes for handling the YAML representation
+/// This file declares classes for handling the YAML representation
/// of ELF.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h b/contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h
index 1fa8f92e516a..cec4f86185f0 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file declares classes for handling the YAML representation
+/// This file declares classes for handling the YAML representation
/// of Mach-O.
///
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h b/contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h
index 188ce8e44491..8cd08e520560 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file declares classes for handling the YAML representation
+/// This file declares classes for handling the YAML representation
/// of wasm binaries.
///
//===----------------------------------------------------------------------===//
@@ -28,15 +28,17 @@ namespace llvm {
namespace WasmYAML {
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionType)
-LLVM_YAML_STRONG_TYPEDEF(int32_t, ValueType)
-LLVM_YAML_STRONG_TYPEDEF(int32_t, TableType)
-LLVM_YAML_STRONG_TYPEDEF(int32_t, SignatureForm)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, ValueType)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, TableType)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, SignatureForm)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportKind)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, Opcode)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolFlags)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolKind)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SegmentFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, LimitFlags)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, ComdatKind)
struct FileHeader {
yaml::Hex32 Version;
@@ -66,6 +68,7 @@ struct ElemSegment {
};
struct Global {
+ uint32_t Index;
ValueType Type;
bool Mutable;
wasm::WasmInitExpr InitExpr;
@@ -89,6 +92,7 @@ struct LocalDecl {
};
struct Function {
+ uint32_t Index;
std::vector<LocalDecl> Locals;
yaml::BinaryRef Body;
};
@@ -127,13 +131,29 @@ struct Signature {
};
struct SymbolInfo {
+ uint32_t Index;
StringRef Name;
+ SymbolKind Kind;
SymbolFlags Flags;
+ union {
+ uint32_t ElementIndex;
+ wasm::WasmDataReference DataRef;
+ };
};
struct InitFunction {
uint32_t Priority;
- uint32_t FunctionIndex;
+ uint32_t Symbol;
+};
+
+struct ComdatEntry {
+ ComdatKind Kind;
+ uint32_t Index;
+};
+
+struct Comdat {
+ StringRef Name;
+ std::vector<ComdatEntry> Entries;
};
struct Section {
@@ -175,10 +195,11 @@ struct LinkingSection : CustomSection {
return C && C->Name == "linking";
}
- uint32_t DataSize;
- std::vector<SymbolInfo> SymbolInfos;
+ uint32_t Version;
+ std::vector<SymbolInfo> SymbolTable;
std::vector<SegmentInfo> SegmentInfos;
std::vector<InitFunction> InitFunctions;
+ std::vector<Comdat> Comdats;
};
struct TypeSection : Section {
@@ -316,6 +337,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ComdatEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Comdat)
namespace llvm {
namespace yaml {
@@ -352,6 +375,10 @@ template <> struct ScalarBitSetTraits<WasmYAML::SymbolFlags> {
static void bitset(IO &IO, WasmYAML::SymbolFlags &Value);
};
+template <> struct ScalarEnumerationTraits<WasmYAML::SymbolKind> {
+ static void enumeration(IO &IO, WasmYAML::SymbolKind &Kind);
+};
+
template <> struct ScalarBitSetTraits<WasmYAML::SegmentFlags> {
static void bitset(IO &IO, WasmYAML::SegmentFlags &Value);
};
@@ -412,6 +439,18 @@ template <> struct MappingTraits<WasmYAML::InitFunction> {
static void mapping(IO &IO, WasmYAML::InitFunction &Init);
};
+template <> struct ScalarEnumerationTraits<WasmYAML::ComdatKind> {
+ static void enumeration(IO &IO, WasmYAML::ComdatKind &Kind);
+};
+
+template <> struct MappingTraits<WasmYAML::ComdatEntry> {
+ static void mapping(IO &IO, WasmYAML::ComdatEntry &ComdatEntry);
+};
+
+template <> struct MappingTraits<WasmYAML::Comdat> {
+ static void mapping(IO &IO, WasmYAML::Comdat &Comdat);
+};
+
template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
static void enumeration(IO &IO, WasmYAML::ValueType &Type);
};
diff --git a/contrib/llvm/include/llvm/ObjectYAML/YAML.h b/contrib/llvm/include/llvm/ObjectYAML/YAML.h
index 93266dd67f1a..163cd8dfcf08 100644
--- a/contrib/llvm/include/llvm/ObjectYAML/YAML.h
+++ b/contrib/llvm/include/llvm/ObjectYAML/YAML.h
@@ -21,7 +21,7 @@ class raw_ostream;
namespace yaml {
-/// \brief Specialized YAMLIO scalar type for representing a binary blob.
+/// Specialized YAMLIO scalar type for representing a binary blob.
///
/// A typical use case would be to represent the content of a section in a
/// binary file.
@@ -64,11 +64,11 @@ namespace yaml {
class BinaryRef {
friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS);
- /// \brief Either raw binary data, or a string of hex bytes (must always
+ /// Either raw binary data, or a string of hex bytes (must always
/// be an even number of characters).
ArrayRef<uint8_t> Data;
- /// \brief Discriminator between the two states of the `Data` member.
+ /// Discriminator between the two states of the `Data` member.
bool DataIsHexString = true;
public:
@@ -77,7 +77,7 @@ public:
BinaryRef(StringRef Data)
: Data(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()) {}
- /// \brief The number of bytes that are represented by this BinaryRef.
+ /// The number of bytes that are represented by this BinaryRef.
/// This is the number of bytes that writeAsBinary() will write.
ArrayRef<uint8_t>::size_type binary_size() const {
if (DataIsHexString)
@@ -85,11 +85,11 @@ public:
return Data.size();
}
- /// \brief Write the contents (regardless of whether it is binary or a
+ /// Write the contents (regardless of whether it is binary or a
/// hex string) as binary to the given raw_ostream.
void writeAsBinary(raw_ostream &OS) const;
- /// \brief Write the contents (regardless of whether it is binary or a
+ /// Write the contents (regardless of whether it is binary or a
/// hex string) as hex to the given raw_ostream.
///
/// For example, a possible output could be `DEADBEEFCAFEBABE`.
diff --git a/contrib/llvm/include/llvm/Option/Arg.h b/contrib/llvm/include/llvm/Option/Arg.h
index c519a4a824c5..d0086bb6d611 100644
--- a/contrib/llvm/include/llvm/Option/Arg.h
+++ b/contrib/llvm/include/llvm/Option/Arg.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the llvm::Arg class for parsed arguments.
+/// Defines the llvm::Arg class for parsed arguments.
///
//===----------------------------------------------------------------------===//
@@ -28,35 +28,35 @@ namespace opt {
class ArgList;
-/// \brief A concrete instance of a particular driver option.
+/// A concrete instance of a particular driver option.
///
/// The Arg class encodes just enough information to be able to
/// derive the argument values efficiently.
class Arg {
private:
- /// \brief The option this argument is an instance of.
+ /// The option this argument is an instance of.
const Option Opt;
- /// \brief The argument this argument was derived from (during tool chain
+ /// The argument this argument was derived from (during tool chain
/// argument translation), if any.
const Arg *BaseArg;
- /// \brief How this instance of the option was spelled.
+ /// How this instance of the option was spelled.
StringRef Spelling;
- /// \brief The index at which this argument appears in the containing
+ /// The index at which this argument appears in the containing
/// ArgList.
unsigned Index;
- /// \brief Was this argument used to effect compilation?
+ /// Was this argument used to effect compilation?
///
/// This is used for generating "argument unused" diagnostics.
mutable unsigned Claimed : 1;
- /// \brief Does this argument own its values?
+ /// Does this argument own its values?
mutable unsigned OwnsValues : 1;
- /// \brief The argument values, as C strings.
+ /// The argument values, as C strings.
SmallVector<const char *, 2> Values;
public:
@@ -74,7 +74,7 @@ public:
StringRef getSpelling() const { return Spelling; }
unsigned getIndex() const { return Index; }
- /// \brief Return the base argument which generated this arg.
+ /// Return the base argument which generated this arg.
///
/// This is either the argument itself or the argument it was
/// derived from during tool chain specific argument translation.
@@ -88,7 +88,7 @@ public:
bool isClaimed() const { return getBaseArg().Claimed; }
- /// \brief Set the Arg claimed bit.
+ /// Set the Arg claimed bit.
void claim() const { getBaseArg().Claimed = true; }
unsigned getNumValues() const { return Values.size(); }
@@ -107,10 +107,10 @@ public:
return false;
}
- /// \brief Append the argument onto the given array as strings.
+ /// Append the argument onto the given array as strings.
void render(const ArgList &Args, ArgStringList &Output) const;
- /// \brief Append the argument, render as an input, onto the given
+ /// Append the argument, render as an input, onto the given
/// array as strings.
///
/// The distinction is that some options only render their values
@@ -120,7 +120,7 @@ public:
void print(raw_ostream &O) const;
void dump() const;
- /// \brief Return a formatted version of the argument and
+ /// Return a formatted version of the argument and
/// its values, for debugging and diagnostics.
std::string getAsString(const ArgList &Args) const;
};
diff --git a/contrib/llvm/include/llvm/Option/ArgList.h b/contrib/llvm/include/llvm/Option/ArgList.h
index aaea68bf8e27..687c8cbb02f9 100644
--- a/contrib/llvm/include/llvm/Option/ArgList.h
+++ b/contrib/llvm/include/llvm/Option/ArgList.h
@@ -85,9 +85,6 @@ public:
SkipToNextArg();
}
- // FIXME: This conversion function makes no sense.
- operator const Arg*() { return *Current; }
-
reference operator*() const { return *Current; }
pointer operator->() const { return Current; }
@@ -356,7 +353,7 @@ public:
return MakeArgStringRef(Str.toStringRef(Buf));
}
- /// \brief Create an arg string for (\p LHS + \p RHS), reusing the
+ /// Create an arg string for (\p LHS + \p RHS), reusing the
/// string at \p Index if possible.
const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS,
StringRef RHS) const;
@@ -390,6 +387,8 @@ private:
void releaseMemory();
public:
+ InputArgList() : NumInputArgStrings(0) {}
+
InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
InputArgList(InputArgList &&RHS)
diff --git a/contrib/llvm/include/llvm/Option/OptTable.h b/contrib/llvm/include/llvm/Option/OptTable.h
index 57a6954f4878..743c4772c98c 100644
--- a/contrib/llvm/include/llvm/Option/OptTable.h
+++ b/contrib/llvm/include/llvm/Option/OptTable.h
@@ -29,7 +29,7 @@ class ArgList;
class InputArgList;
class Option;
-/// \brief Provide access to the Option info table.
+/// Provide access to the Option info table.
///
/// The OptTable class provides a layer of indirection which allows Option
/// instance to be created lazily. In the common case, only a few options will
@@ -38,7 +38,7 @@ class Option;
/// parts of the driver still use Option instances where convenient.
class OptTable {
public:
- /// \brief Entry for a single option instance in the option data table.
+ /// Entry for a single option instance in the option data table.
struct Info {
/// A null terminated array of prefix strings to apply to name while
/// matching.
@@ -57,7 +57,7 @@ public:
};
private:
- /// \brief The option information table.
+ /// The option information table.
std::vector<Info> OptionInfos;
bool IgnoreCase;
@@ -86,36 +86,36 @@ protected:
public:
~OptTable();
- /// \brief Return the total number of option classes.
+ /// Return the total number of option classes.
unsigned getNumOptions() const { return OptionInfos.size(); }
- /// \brief Get the given Opt's Option instance, lazily creating it
+ /// Get the given Opt's Option instance, lazily creating it
/// if necessary.
///
/// \return The option, or null for the INVALID option id.
const Option getOption(OptSpecifier Opt) const;
- /// \brief Lookup the name of the given option.
+ /// Lookup the name of the given option.
const char *getOptionName(OptSpecifier id) const {
return getInfo(id).Name;
}
- /// \brief Get the kind of the given option.
+ /// Get the kind of the given option.
unsigned getOptionKind(OptSpecifier id) const {
return getInfo(id).Kind;
}
- /// \brief Get the group id for the given option.
+ /// Get the group id for the given option.
unsigned getOptionGroupID(OptSpecifier id) const {
return getInfo(id).GroupID;
}
- /// \brief Get the help text to use to describe this option.
+ /// Get the help text to use to describe this option.
const char *getOptionHelpText(OptSpecifier id) const {
return getInfo(id).HelpText;
}
- /// \brief Get the meta-variable name to use when describing
+ /// Get the meta-variable name to use when describing
/// this options values in the help text.
const char *getOptionMetaVar(OptSpecifier id) const {
return getInfo(id).MetaVar;
@@ -143,6 +143,26 @@ public:
std::vector<std::string> findByPrefix(StringRef Cur,
unsigned short DisableFlags) const;
+ /// Find the OptTable option that most closely matches the given string.
+ ///
+ /// \param [in] Option - A string, such as "-stdlibs=l", that represents user
+ /// input of an option that may not exist in the OptTable. Note that the
+ /// string includes prefix dashes "-" as well as values "=l".
+ /// \param [out] NearestString - The nearest option string found in the
+ /// OptTable.
+ /// \param [in] FlagsToInclude - Only find options with any of these flags.
+ /// Zero is the default, which includes all flags.
+ /// \param [in] FlagsToExclude - Don't find options with this flag. Zero
+ /// is the default, and means exclude nothing.
+ /// \param [in] MinimumLength - Don't find options shorter than this length.
+ /// For example, a minimum length of 3 prevents "-x" from being considered
+ /// near to "-S".
+ ///
+ /// \return The edit distance of the nearest string found.
+ unsigned findNearest(StringRef Option, std::string &NearestString,
+ unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0,
+ unsigned MinimumLength = 4) const;
+
/// Add Values to Option's Values class
///
/// \param [in] Option - Prefix + Name of the flag which Values will be
@@ -154,7 +174,7 @@ public:
/// \return true in success, and false in fail.
bool addValues(const char *Option, const char *Values);
- /// \brief Parse a single argument; returning the new argument and
+ /// Parse a single argument; returning the new argument and
/// updating Index.
///
/// \param [in,out] Index - The current parsing position in the argument
@@ -172,7 +192,7 @@ public:
unsigned FlagsToInclude = 0,
unsigned FlagsToExclude = 0) const;
- /// \brief Parse an list of arguments into an InputArgList.
+ /// Parse an list of arguments into an InputArgList.
///
/// The resulting InputArgList will reference the strings in [\p ArgBegin,
/// \p ArgEnd), and their lifetime should extend past that of the returned
@@ -194,7 +214,7 @@ public:
unsigned &MissingArgCount, unsigned FlagsToInclude = 0,
unsigned FlagsToExclude = 0) const;
- /// \brief Render the help text for an option table.
+ /// Render the help text for an option table.
///
/// \param OS - The stream to write the help text to.
/// \param Name - The name to use in the usage line.
diff --git a/contrib/llvm/include/llvm/Option/Option.h b/contrib/llvm/include/llvm/Option/Option.h
index d9aebd5b0757..b09f6043b7a9 100644
--- a/contrib/llvm/include/llvm/Option/Option.h
+++ b/contrib/llvm/include/llvm/Option/Option.h
@@ -95,7 +95,7 @@ public:
return OptionClass(Info->Kind);
}
- /// \brief Get the name of this option without any prefix.
+ /// Get the name of this option without any prefix.
StringRef getName() const {
assert(Info && "Must have a valid info!");
return Info->Name;
@@ -113,7 +113,7 @@ public:
return Owner->getOption(Info->AliasID);
}
- /// \brief Get the alias arguments as a \0 separated list.
+ /// Get the alias arguments as a \0 separated list.
/// E.g. ["foo", "bar"] would be returned as "foo\0bar\0".
const char *getAliasArgs() const {
assert(Info && "Must have a valid info!");
@@ -123,13 +123,13 @@ public:
return Info->AliasArgs;
}
- /// \brief Get the default prefix for this option.
+ /// Get the default prefix for this option.
StringRef getPrefix() const {
const char *Prefix = *Info->Prefixes;
return Prefix ? Prefix : StringRef();
}
- /// \brief Get the name of this option with the default prefix.
+ /// Get the name of this option with the default prefix.
std::string getPrefixedName() const {
std::string Ret = getPrefix();
Ret += getName();
diff --git a/contrib/llvm/include/llvm/Pass.h b/contrib/llvm/include/llvm/Pass.h
index a29b3771abb4..d65347d611ea 100644
--- a/contrib/llvm/include/llvm/Pass.h
+++ b/contrib/llvm/include/llvm/Pass.h
@@ -353,18 +353,18 @@ protected:
/// If the user specifies the -time-passes argument on an LLVM tool command line
/// then the value of this boolean will be true, otherwise false.
-/// @brief This is the storage for the -time-passes option.
+/// This is the storage for the -time-passes option.
extern bool TimePassesIsEnabled;
/// isFunctionInPrintList - returns true if a function should be printed via
// debugging options like -print-after-all/-print-before-all.
-// @brief Tells if the function IR should be printed by PrinterPass.
+// Tells if the function IR should be printed by PrinterPass.
extern bool isFunctionInPrintList(StringRef FunctionName);
/// forcePrintModuleIR - returns true if IR printing passes should
// be printing module IR (even for local-pass printers e.g. function-pass)
// to provide more context, as enabled by debugging option -print-module-scope
-// @brief Tells if IR printer should be printing module IR
+// Tells if IR printer should be printing module IR
extern bool forcePrintModuleIR();
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/PassAnalysisSupport.h b/contrib/llvm/include/llvm/PassAnalysisSupport.h
index b109605355bf..118718747659 100644
--- a/contrib/llvm/include/llvm/PassAnalysisSupport.h
+++ b/contrib/llvm/include/llvm/PassAnalysisSupport.h
@@ -174,7 +174,7 @@ public:
AnalysisImpls.push_back(pir);
}
- /// Clear cache that is used to connect a pass to the the analysis (PassInfo).
+ /// Clear cache that is used to connect a pass to the analysis (PassInfo).
void clearAnalysisImpls() {
AnalysisImpls.clear();
}
diff --git a/contrib/llvm/include/llvm/Passes/PassBuilder.h b/contrib/llvm/include/llvm/Passes/PassBuilder.h
index b69988826253..24a93bc76af5 100644
--- a/contrib/llvm/include/llvm/Passes/PassBuilder.h
+++ b/contrib/llvm/include/llvm/Passes/PassBuilder.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include <vector>
@@ -26,6 +27,7 @@ namespace llvm {
class StringRef;
class AAManager;
class TargetMachine;
+class ModuleSummaryIndex;
/// A struct capturing PGO tunables.
struct PGOOptions {
@@ -47,7 +49,7 @@ struct PGOOptions {
bool SamplePGOSupport;
};
-/// \brief This class provides access to building LLVM's passes.
+/// This class provides access to building LLVM's passes.
///
/// It's members provide the baseline state available to passes during their
/// construction. The \c PassRegistry.def file specifies how to construct all
@@ -58,7 +60,7 @@ class PassBuilder {
Optional<PGOOptions> PGOOpt;
public:
- /// \brief A struct to capture parsed pass pipeline names.
+ /// A struct to capture parsed pass pipeline names.
///
/// A pipeline is defined as a series of names, each of which may in itself
/// recursively contain a nested pipeline. A name is either the name of a pass
@@ -71,7 +73,7 @@ public:
std::vector<PipelineElement> InnerPipeline;
};
- /// \brief ThinLTO phase.
+ /// ThinLTO phase.
///
/// This enumerates the LLVM ThinLTO optimization phases.
enum class ThinLTOPhase {
@@ -83,7 +85,7 @@ public:
PostLink
};
- /// \brief LLVM-provided high-level optimization levels.
+ /// LLVM-provided high-level optimization levels.
///
/// This enumerates the LLVM-provided high-level optimization levels. Each
/// level has a specific goal and rationale.
@@ -173,7 +175,7 @@ public:
Optional<PGOOptions> PGOOpt = None)
: TM(TM), PGOOpt(PGOOpt) {}
- /// \brief Cross register the analysis managers through their proxies.
+ /// Cross register the analysis managers through their proxies.
///
/// This is an interface that can be used to cross register each
// AnalysisManager with all the others analysis managers.
@@ -182,7 +184,7 @@ public:
CGSCCAnalysisManager &CGAM,
ModuleAnalysisManager &MAM);
- /// \brief Registers all available module analysis passes.
+ /// Registers all available module analysis passes.
///
/// This is an interface that can be used to populate a \c
/// ModuleAnalysisManager with all registered module analyses. Callers can
@@ -190,7 +192,7 @@ public:
/// pre-register analyses and this will not override those.
void registerModuleAnalyses(ModuleAnalysisManager &MAM);
- /// \brief Registers all available CGSCC analysis passes.
+ /// Registers all available CGSCC analysis passes.
///
/// This is an interface that can be used to populate a \c CGSCCAnalysisManager
/// with all registered CGSCC analyses. Callers can still manually register any
@@ -198,7 +200,7 @@ public:
/// not override those.
void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM);
- /// \brief Registers all available function analysis passes.
+ /// Registers all available function analysis passes.
///
/// This is an interface that can be used to populate a \c
/// FunctionAnalysisManager with all registered function analyses. Callers can
@@ -206,7 +208,7 @@ public:
/// pre-register analyses and this will not override those.
void registerFunctionAnalyses(FunctionAnalysisManager &FAM);
- /// \brief Registers all available loop analysis passes.
+ /// Registers all available loop analysis passes.
///
/// This is an interface that can be used to populate a \c LoopAnalysisManager
/// with all registered loop analyses. Callers can still manually register any
@@ -309,8 +311,9 @@ public:
/// only intended for use when attempting to optimize code. If frontends
/// require some transformations for semantic reasons, they should explicitly
/// build them.
- ModulePassManager buildThinLTODefaultPipeline(OptimizationLevel Level,
- bool DebugLogging = false);
+ ModulePassManager
+ buildThinLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging,
+ const ModuleSummaryIndex *ImportSummary);
/// Build a pre-link, LTO-targeting default optimization pipeline to a pass
/// manager.
@@ -339,13 +342,14 @@ public:
/// require some transformations for semantic reasons, they should explicitly
/// build them.
ModulePassManager buildLTODefaultPipeline(OptimizationLevel Level,
- bool DebugLogging = false);
+ bool DebugLogging,
+ ModuleSummaryIndex *ExportSummary);
/// Build the default `AAManager` with the default alias analysis pipeline
/// registered.
AAManager buildDefaultAAPipeline();
- /// \brief Parse a textual pass pipeline description into a \c
+ /// Parse a textual pass pipeline description into a \c
/// ModulePassManager.
///
/// The format of the textual pass pipeline description looks something like:
@@ -409,7 +413,7 @@ public:
/// returns false.
bool parseAAPipeline(AAManager &AA, StringRef PipelineText);
- /// \brief Register a callback for a default optimizer pipeline extension
+ /// Register a callback for a default optimizer pipeline extension
/// point
///
/// This extension point allows adding passes that perform peephole
@@ -420,7 +424,7 @@ public:
PeepholeEPCallbacks.push_back(C);
}
- /// \brief Register a callback for a default optimizer pipeline extension
+ /// Register a callback for a default optimizer pipeline extension
/// point
///
/// This extension point allows adding late loop canonicalization and
@@ -434,7 +438,7 @@ public:
LateLoopOptimizationsEPCallbacks.push_back(C);
}
- /// \brief Register a callback for a default optimizer pipeline extension
+ /// Register a callback for a default optimizer pipeline extension
/// point
///
/// This extension point allows adding loop passes to the end of the loop
@@ -444,7 +448,7 @@ public:
LoopOptimizerEndEPCallbacks.push_back(C);
}
- /// \brief Register a callback for a default optimizer pipeline extension
+ /// Register a callback for a default optimizer pipeline extension
/// point
///
/// This extension point allows adding optimization passes after most of the
@@ -454,7 +458,7 @@ public:
ScalarOptimizerLateEPCallbacks.push_back(C);
}
- /// \brief Register a callback for a default optimizer pipeline extension
+ /// Register a callback for a default optimizer pipeline extension
/// point
///
/// This extension point allows adding CallGraphSCC passes at the end of the
@@ -465,7 +469,7 @@ public:
CGSCCOptimizerLateEPCallbacks.push_back(C);
}
- /// \brief Register a callback for a default optimizer pipeline extension
+ /// Register a callback for a default optimizer pipeline extension
/// point
///
/// This extension point allows adding optimization passes before the
@@ -476,7 +480,17 @@ public:
VectorizerStartEPCallbacks.push_back(C);
}
- /// \brief Register a callback for parsing an AliasAnalysis Name to populate
+ /// Register a callback for a default optimizer pipeline extension point.
+ ///
+ /// This extension point allows adding optimization once at the start of the
+ /// pipeline. This does not apply to 'backend' compiles (LTO and ThinLTO
+ /// link-time pipelines).
+ void registerPipelineStartEPCallback(
+ const std::function<void(ModulePassManager &)> &C) {
+ PipelineStartEPCallbacks.push_back(C);
+ }
+
+ /// Register a callback for parsing an AliasAnalysis Name to populate
/// the given AAManager \p AA
void registerParseAACallback(
const std::function<bool(StringRef Name, AAManager &AA)> &C) {
@@ -530,7 +544,7 @@ public:
}
/// @}}
- /// \brief Register a callback for a top-level pipeline entry.
+ /// Register a callback for a top-level pipeline entry.
///
/// If the PassManager type is not given at the top level of the pipeline
/// text, this Callback should be used to determine the appropriate stack of
@@ -589,6 +603,8 @@ private:
SmallVector<std::function<void(FunctionPassManager &, OptimizationLevel)>, 2>
VectorizerStartEPCallbacks;
// Module callbacks
+ SmallVector<std::function<void(ModulePassManager &)>, 2>
+ PipelineStartEPCallbacks;
SmallVector<std::function<void(ModuleAnalysisManager &)>, 2>
ModuleAnalysisRegistrationCallbacks;
SmallVector<std::function<bool(StringRef, ModulePassManager &,
diff --git a/contrib/llvm/include/llvm/Passes/PassPlugin.h b/contrib/llvm/include/llvm/Passes/PassPlugin.h
new file mode 100644
index 000000000000..af8f11a7a352
--- /dev/null
+++ b/contrib/llvm/include/llvm/Passes/PassPlugin.h
@@ -0,0 +1,114 @@
+//===- llvm/Passes/PassPlugin.h - Public Plugin API -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines the public entry point for new-PM pass plugins.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PASSES_PASSPLUGIN_H
+#define LLVM_PASSES_PASSPLUGIN_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <string>
+
+namespace llvm {
+class PassBuilder;
+
+/// \macro LLVM_PLUGIN_API_VERSION
+/// Identifies the API version understood by this plugin.
+///
+/// When a plugin is loaded, the driver will check it's supported plugin version
+/// against that of the plugin. A mismatch is an error. The supported version
+/// will be incremented for ABI-breaking changes to the \c PassPluginLibraryInfo
+/// struct, i.e. when callbacks are added, removed, or reordered.
+#define LLVM_PLUGIN_API_VERSION 1
+
+extern "C" {
+/// Information about the plugin required to load its passes
+///
+/// This struct defines the core interface for pass plugins and is supposed to
+/// be filled out by plugin implementors. LLVM-side users of a plugin are
+/// expected to use the \c PassPlugin class below to interface with it.
+struct PassPluginLibraryInfo {
+ /// The API version understood by this plugin, usually \c
+ /// LLVM_PLUGIN_API_VERSION
+ uint32_t APIVersion;
+ /// A meaningful name of the plugin.
+ const char *PluginName;
+ /// The version of the plugin.
+ const char *PluginVersion;
+
+ /// The callback for registering plugin passes with a \c PassBuilder
+ /// instance
+ void (*RegisterPassBuilderCallbacks)(PassBuilder &);
+};
+}
+
+/// A loaded pass plugin.
+///
+/// An instance of this class wraps a loaded pass plugin and gives access to
+/// its interface defined by the \c PassPluginLibraryInfo it exposes.
+class PassPlugin {
+public:
+ /// Attempts to load a pass plugin from a given file.
+ ///
+ /// \returns Returns an error if either the library cannot be found or loaded,
+ /// there is no public entry point, or the plugin implements the wrong API
+ /// version.
+ static Expected<PassPlugin> Load(const std::string &Filename);
+
+ /// Get the filename of the loaded plugin.
+ StringRef getFilename() const { return Filename; }
+
+ /// Get the plugin name
+ StringRef getPluginName() const { return Info.PluginName; }
+
+ /// Get the plugin version
+ StringRef getPluginVersion() const { return Info.PluginVersion; }
+
+ /// Get the plugin API version
+ uint32_t getAPIVersion() const { return Info.APIVersion; }
+
+ /// Invoke the PassBuilder callback registration
+ void registerPassBuilderCallbacks(PassBuilder &PB) const {
+ Info.RegisterPassBuilderCallbacks(PB);
+ }
+
+private:
+ PassPlugin(const std::string &Filename, const sys::DynamicLibrary &Library)
+ : Filename(Filename), Library(Library), Info() {}
+
+ std::string Filename;
+ sys::DynamicLibrary Library;
+ PassPluginLibraryInfo Info;
+};
+}
+
+/// The public entry point for a pass plugin.
+///
+/// When a plugin is loaded by the driver, it will call this entry point to
+/// obtain information about this plugin and about how to register its passes.
+/// This function needs to be implemented by the plugin, see the example below:
+///
+/// ```
+/// extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+/// llvmGetPassPluginInfo() {
+/// return {
+/// LLVM_PLUGIN_API_VERSION, "MyPlugin", "v0.1", [](PassBuilder &PB) { ... }
+/// };
+/// }
+/// ```
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+llvmGetPassPluginInfo();
+
+#endif /* LLVM_PASSES_PASSPLUGIN_H */
diff --git a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 5a4098cf666c..1ca56dcaf9c5 100644
--- a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/StringRef.h"
@@ -506,7 +507,7 @@ public:
/// This is the main interface to get coverage information, using a profile to
/// fill out execution counts.
class CoverageMapping {
- StringSet<> FunctionNames;
+ DenseMap<size_t, DenseSet<size_t>> RecordProvenance;
std::vector<FunctionRecord> Functions;
std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
std::vector<std::pair<std::string, uint64_t>> FuncCounterMismatches;
diff --git a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index 633e51565cd2..c88c71a6d6f4 100644
--- a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -32,7 +32,7 @@ namespace coverage {
class CoverageMappingReader;
-/// \brief Coverage mapping information for a single function.
+/// Coverage mapping information for a single function.
struct CoverageMappingRecord {
StringRef FunctionName;
uint64_t FunctionHash;
@@ -41,7 +41,7 @@ struct CoverageMappingRecord {
ArrayRef<CounterMappingRegion> MappingRegions;
};
-/// \brief A file format agnostic iterator over coverage mapping data.
+/// A file format agnostic iterator over coverage mapping data.
class CoverageMappingIterator
: public std::iterator<std::input_iterator_tag, CoverageMappingRecord> {
CoverageMappingReader *Reader;
@@ -101,7 +101,7 @@ public:
CoverageMappingIterator end() { return CoverageMappingIterator(); }
};
-/// \brief Base class for the raw coverage mapping and filenames data readers.
+/// Base class for the raw coverage mapping and filenames data readers.
class RawCoverageReader {
protected:
StringRef Data;
@@ -114,7 +114,7 @@ protected:
Error readString(StringRef &Result);
};
-/// \brief Reader for the raw coverage filenames.
+/// Reader for the raw coverage filenames.
class RawCoverageFilenamesReader : public RawCoverageReader {
std::vector<StringRef> &Filenames;
@@ -128,7 +128,7 @@ public:
Error read();
};
-/// \brief Checks if the given coverage mapping data is exported for
+/// Checks if the given coverage mapping data is exported for
/// an unused function.
class RawCoverageMappingDummyChecker : public RawCoverageReader {
public:
@@ -138,7 +138,7 @@ public:
Expected<bool> isDummy();
};
-/// \brief Reader for the raw coverage mapping data.
+/// Reader for the raw coverage mapping data.
class RawCoverageMappingReader : public RawCoverageReader {
ArrayRef<StringRef> TranslationUnitFilenames;
std::vector<StringRef> &Filenames;
@@ -169,7 +169,7 @@ private:
unsigned InferredFileID, size_t NumFileIDs);
};
-/// \brief Reader for the coverage mapping data that is emitted by the
+/// Reader for the coverage mapping data that is emitted by the
/// frontend and stored in an object file.
class BinaryCoverageReader : public CoverageMappingReader {
public:
diff --git a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
index b6f864ab3de3..86fb1bdf1773 100644
--- a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
+++ b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
@@ -25,7 +25,7 @@ class raw_ostream;
namespace coverage {
-/// \brief Writer of the filenames section for the instrumentation
+/// Writer of the filenames section for the instrumentation
/// based code coverage.
class CoverageFilenamesSectionWriter {
ArrayRef<StringRef> Filenames;
@@ -34,11 +34,11 @@ public:
CoverageFilenamesSectionWriter(ArrayRef<StringRef> Filenames)
: Filenames(Filenames) {}
- /// \brief Write encoded filenames to the given output stream.
+ /// Write encoded filenames to the given output stream.
void write(raw_ostream &OS);
};
-/// \brief Writer for instrumentation based coverage mapping data.
+/// Writer for instrumentation based coverage mapping data.
class CoverageMappingWriter {
ArrayRef<unsigned> VirtualFileMapping;
ArrayRef<CounterExpression> Expressions;
@@ -51,7 +51,7 @@ public:
: VirtualFileMapping(VirtualFileMapping), Expressions(Expressions),
MappingRegions(MappingRegions) {}
- /// \brief Write encoded coverage mapping data to the given output stream.
+ /// Write encoded coverage mapping data to the given output stream.
void write(raw_ostream &OS);
};
diff --git a/contrib/llvm/include/llvm/ProfileData/GCOV.h b/contrib/llvm/include/llvm/ProfileData/GCOV.h
index 497f80b87b26..8500401e44ad 100644
--- a/contrib/llvm/include/llvm/ProfileData/GCOV.h
+++ b/contrib/llvm/include/llvm/ProfileData/GCOV.h
@@ -41,7 +41,7 @@ namespace GCOV {
enum GCOVVersion { V402, V404, V704 };
-/// \brief A struct for passing gcov options between functions.
+/// A struct for passing gcov options between functions.
struct Options {
Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
: AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
@@ -376,6 +376,7 @@ private:
};
class FileInfo {
+protected:
// It is unlikely--but possible--for multiple functions to be on the same
// line.
// Therefore this typedef allows LineData.Functions to store multiple
@@ -428,7 +429,7 @@ public:
void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
StringRef GCDAFile);
-private:
+protected:
std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
diff --git a/contrib/llvm/include/llvm/ProfileData/InstrProf.h b/contrib/llvm/include/llvm/ProfileData/InstrProf.h
index b08b78cd593c..206142b3565a 100644
--- a/contrib/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/contrib/llvm/include/llvm/ProfileData/InstrProf.h
@@ -425,9 +425,20 @@ private:
// A map from function runtime address to function name MD5 hash.
// This map is only populated and used by raw instr profile reader.
AddrHashMap AddrToMD5Map;
+ bool Sorted = false;
+
+ static StringRef getExternalSymbol() {
+ return "** External Symbol **";
+ }
+
+ // If the symtab is created by a series of calls to \c addFuncName, \c
+ // finalizeSymtab needs to be called before looking up function names.
+ // This is required because the underlying map is a vector (for space
+ // efficiency) which needs to be sorted.
+ inline void finalizeSymtab();
public:
- InstrProfSymtab() = default;
+ InstrProfSymtab() = default;
/// Create InstrProfSymtab from an object file section which
/// contains function PGO names. When section may contain raw
@@ -456,21 +467,17 @@ public:
/// \p IterRange. This interface is used by IndexedProfReader.
template <typename NameIterRange> Error create(const NameIterRange &IterRange);
- // If the symtab is created by a series of calls to \c addFuncName, \c
- // finalizeSymtab needs to be called before looking up function names.
- // This is required because the underlying map is a vector (for space
- // efficiency) which needs to be sorted.
- inline void finalizeSymtab();
-
/// Update the symtab by adding \p FuncName to the table. This interface
/// is used by the raw and text profile readers.
Error addFuncName(StringRef FuncName) {
if (FuncName.empty())
return make_error<InstrProfError>(instrprof_error::malformed);
auto Ins = NameTab.insert(FuncName);
- if (Ins.second)
+ if (Ins.second) {
MD5NameMap.push_back(std::make_pair(
IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey()));
+ Sorted = false;
+ }
return Error::success();
}
@@ -480,7 +487,8 @@ public:
AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val));
}
- AddrHashMap &getAddrHashMap() { return AddrToMD5Map; }
+ /// Return a function's hash, or 0, if the function isn't in this SymTab.
+ uint64_t getFunctionHashFromAddress(uint64_t Address);
/// Return function's PGO name from the function name's symbol
/// address in the object file. If an error occurs, return
@@ -491,6 +499,16 @@ public:
/// If not found, return an empty string.
inline StringRef getFuncName(uint64_t FuncMD5Hash);
+ /// Just like getFuncName, except that it will return a non-empty StringRef
+ /// if the function is external to this symbol table. All such cases
+ /// will be represented using the same StringRef value.
+ inline StringRef getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash);
+
+ /// True if Symbol is the value used to represent external symbols.
+ static bool isExternalSymbol(const StringRef &Symbol) {
+ return Symbol == InstrProfSymtab::getExternalSymbol();
+ }
+
/// Return function from the name's md5 hash. Return nullptr if not found.
inline Function *getFunction(uint64_t FuncMD5Hash);
@@ -524,14 +542,25 @@ Error InstrProfSymtab::create(const NameIterRange &IterRange) {
}
void InstrProfSymtab::finalizeSymtab() {
- std::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first());
- std::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first());
- std::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first());
+ if (Sorted)
+ return;
+ llvm::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first());
+ llvm::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first());
+ llvm::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first());
AddrToMD5Map.erase(std::unique(AddrToMD5Map.begin(), AddrToMD5Map.end()),
AddrToMD5Map.end());
+ Sorted = true;
+}
+
+StringRef InstrProfSymtab::getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash) {
+ StringRef ret = getFuncName(FuncMD5Hash);
+ if (ret.empty())
+ return InstrProfSymtab::getExternalSymbol();
+ return ret;
}
StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) {
+ finalizeSymtab();
auto Result =
std::lower_bound(MD5NameMap.begin(), MD5NameMap.end(), FuncMD5Hash,
[](const std::pair<uint64_t, std::string> &LHS,
@@ -542,6 +571,7 @@ StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) {
}
Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) {
+ finalizeSymtab();
auto Result =
std::lower_bound(MD5FuncMap.begin(), MD5FuncMap.end(), FuncMD5Hash,
[](const std::pair<uint64_t, Function*> &LHS,
@@ -614,8 +644,6 @@ struct InstrProfRecord {
return *this;
}
- using ValueMapType = std::vector<std::pair<uint64_t, uint64_t>>;
-
/// Return the number of value profile kinds with non-zero number
/// of profile sites.
inline uint32_t getNumValueKinds() const;
@@ -649,7 +677,7 @@ struct InstrProfRecord {
/// Add ValueData for ValueKind at value Site.
void addValueData(uint32_t ValueKind, uint32_t Site,
InstrProfValueData *VData, uint32_t N,
- ValueMapType *ValueMap);
+ InstrProfSymtab *SymTab);
/// Merge the counts in \p Other into this one.
/// Optionally scale merged counts by \p Weight.
@@ -723,7 +751,7 @@ private:
// Map indirect call target name hash to name string.
uint64_t remapValue(uint64_t Value, uint32_t ValueKind,
- ValueMapType *HashKeys);
+ InstrProfSymtab *SymTab);
// Merge Value Profile data from Src record to this record for ValueKind.
// Scale merged value counts by \p Weight.
@@ -993,7 +1021,7 @@ template <> inline uint64_t getMagic<uint32_t>() {
// compiler-rt/lib/profile/InstrProfiling.h.
// It should also match the synthesized type in
// Transforms/Instrumentation/InstrProfiling.cpp:getOrCreateRegionCounters.
-template <class IntPtrT> struct LLVM_ALIGNAS(8) ProfileData {
+template <class IntPtrT> struct alignas(8) ProfileData {
#define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Type Name;
#include "llvm/ProfileData/InstrProfData.inc"
};
diff --git a/contrib/llvm/include/llvm/ProfileData/InstrProfData.inc b/contrib/llvm/include/llvm/ProfileData/InstrProfData.inc
index 6a98dc7b9b85..454620ed997a 100644
--- a/contrib/llvm/include/llvm/ProfileData/InstrProfData.inc
+++ b/contrib/llvm/include/llvm/ProfileData/InstrProfData.inc
@@ -178,7 +178,7 @@ VALUE_PROF_FUNC_PARAM(uint64_t, LargeValue, Type::getInt64Ty(Ctx))
* functions are profiled by the instrumented code. The target addresses are
* written in the raw profile data and converted to target function name's MD5
* hash by the profile reader during deserialization. Typically, this happens
- * when the the raw profile data is read during profile merging.
+ * when the raw profile data is read during profile merging.
*
* For this remapping the ProfData is used. ProfData contains both the function
* name hash and the function address.
@@ -308,14 +308,14 @@ typedef struct ValueProfRecord {
#ifdef __cplusplus
/*!
- * \brief Return the number of value sites.
+ * Return the number of value sites.
*/
uint32_t getNumValueSites() const { return NumValueSites; }
/*!
- * \brief Read data from this record and save it to Record.
+ * Read data from this record and save it to Record.
*/
void deserializeTo(InstrProfRecord &Record,
- InstrProfRecord::ValueMapType *VMap);
+ InstrProfSymtab *SymTab);
/*
* In-place byte swap:
* Do byte swap for this instance. \c Old is the original order before
@@ -393,7 +393,7 @@ typedef struct ValueProfData {
* Read data from this data and save it to \c Record.
*/
void deserializeTo(InstrProfRecord &Record,
- InstrProfRecord::ValueMapType *VMap);
+ InstrProfSymtab *SymTab);
void operator delete(void *ptr) { ::operator delete(ptr); }
#endif
} ValueProfData;
@@ -458,7 +458,7 @@ getValueProfRecordHeaderSize(uint32_t NumValueSites);
#endif
/*!
- * \brief Return the \c ValueProfRecord header size including the
+ * Return the \c ValueProfRecord header size including the
* padding bytes.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
@@ -471,7 +471,7 @@ uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) {
}
/*!
- * \brief Return the total size of the value profile record including the
+ * Return the total size of the value profile record including the
* header and the value data.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
@@ -482,7 +482,7 @@ uint32_t getValueProfRecordSize(uint32_t NumValueSites,
}
/*!
- * \brief Return the pointer to the start of value data array.
+ * Return the pointer to the start of value data array.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
@@ -491,7 +491,7 @@ InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
}
/*!
- * \brief Return the total number of value data for \c This record.
+ * Return the total number of value data for \c This record.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
@@ -503,7 +503,7 @@ uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
}
/*!
- * \brief Use this method to advance to the next \c This \c ValueProfRecord.
+ * Use this method to advance to the next \c This \c ValueProfRecord.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
@@ -514,7 +514,7 @@ ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
}
/*!
- * \brief Return the first \c ValueProfRecord instance.
+ * Return the first \c ValueProfRecord instance.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) {
diff --git a/contrib/llvm/include/llvm/ProfileData/InstrProfReader.h b/contrib/llvm/include/llvm/ProfileData/InstrProfReader.h
index aa58ead1eda1..efc22dcd0d9a 100644
--- a/contrib/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/contrib/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -101,7 +101,7 @@ protected:
return make_error<InstrProfError>(Err);
}
- Error error(Error E) { return error(InstrProfError::take(std::move(E))); }
+ Error error(Error &&E) { return error(InstrProfError::take(std::move(E))); }
/// Clear the current error and return a successful one.
Error success() { return error(instrprof_error::success); }
@@ -199,8 +199,6 @@ private:
uint32_t ValueKindLast;
uint32_t CurValueDataSize;
- InstrProfRecord::ValueMapType FunctionPtrToNameMap;
-
public:
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)) {}
diff --git a/contrib/llvm/include/llvm/ProfileData/ProfileCommon.h b/contrib/llvm/include/llvm/ProfileData/ProfileCommon.h
index 51b065bcdb70..087588f06340 100644
--- a/contrib/llvm/include/llvm/ProfileData/ProfileCommon.h
+++ b/contrib/llvm/include/llvm/ProfileData/ProfileCommon.h
@@ -61,7 +61,7 @@ protected:
void computeDetailedSummary();
public:
- /// \brief A vector of useful cutoff values for detailed summary.
+ /// A vector of useful cutoff values for detailed summary.
static const ArrayRef<uint32_t> DefaultCutoffs;
};
diff --git a/contrib/llvm/include/llvm/ProfileData/SampleProf.h b/contrib/llvm/include/llvm/ProfileData/SampleProf.h
index 641631cc4ec9..0cd6dd2c2c0e 100644
--- a/contrib/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/contrib/llvm/include/llvm/ProfileData/SampleProf.h
@@ -78,11 +78,29 @@ struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {};
namespace llvm {
namespace sampleprof {
-static inline uint64_t SPMagic() {
+enum SampleProfileFormat {
+ SPF_None = 0,
+ SPF_Text = 0x1,
+ SPF_Compact_Binary = 0x2,
+ SPF_GCC = 0x3,
+ SPF_Binary = 0xff
+};
+
+static inline uint64_t SPMagic(SampleProfileFormat Format = SPF_Binary) {
return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) |
uint64_t('R') << (64 - 24) | uint64_t('O') << (64 - 32) |
uint64_t('F') << (64 - 40) | uint64_t('4') << (64 - 48) |
- uint64_t('2') << (64 - 56) | uint64_t(0xff);
+ uint64_t('2') << (64 - 56) | uint64_t(Format);
+}
+
+// Get the proper representation of a string in the input Format.
+static inline StringRef getRepInFormat(StringRef Name,
+ SampleProfileFormat Format,
+ std::string &GUIDBuf) {
+ if (Name.empty())
+ return Name;
+ GUIDBuf = std::to_string(Function::getGUID(Name));
+ return (Format == SPF_Compact_Binary) ? StringRef(GUIDBuf) : Name;
}
static inline uint64_t SPVersion() { return 103; }
@@ -359,7 +377,7 @@ public:
/// GUID to \p S. Also traverse the BodySamples to add hot CallTarget's GUID
/// to \p S.
void findInlinedFunctions(DenseSet<GlobalValue::GUID> &S, const Module *M,
- uint64_t Threshold) const {
+ uint64_t Threshold, bool isCompact) const {
if (TotalSamples <= Threshold)
return;
S.insert(Function::getGUID(Name));
@@ -370,11 +388,12 @@ public:
if (TS.getValue() > Threshold) {
Function *Callee = M->getFunction(TS.getKey());
if (!Callee || !Callee->getSubprogram())
- S.insert(Function::getGUID(TS.getKey()));
+ S.insert(isCompact ? std::stol(TS.getKey().data())
+ : Function::getGUID(TS.getKey()));
}
for (const auto &CS : CallsiteSamples)
for (const auto &NameFS : CS.second)
- NameFS.second.findInlinedFunctions(S, M, Threshold);
+ NameFS.second.findInlinedFunctions(S, M, Threshold, isCompact);
}
/// Set the name of the function.
@@ -383,6 +402,21 @@ public:
/// Return the function name.
const StringRef &getName() const { return Name; }
+ /// Returns the line offset to the start line of the subprogram.
+ /// We assume that a single function will not exceed 65535 LOC.
+ static unsigned getOffset(const DILocation *DIL);
+
+ /// Get the FunctionSamples of the inline instance where DIL originates
+ /// from.
+ ///
+ /// The FunctionSamples of the instruction (Machine or IR) associated to
+ /// \p DIL is the inlined instance in which that instruction is coming from.
+ /// We traverse the inline stack of that instruction, and match it with the
+ /// tree nodes in the profile.
+ ///
+ /// \returns the FunctionSamples pointer to the inlined instance.
+ const FunctionSamples *findFunctionSamples(const DILocation *DIL) const;
+
private:
/// Mangled name of the function.
StringRef Name;
diff --git a/contrib/llvm/include/llvm/ProfileData/SampleProfReader.h b/contrib/llvm/include/llvm/ProfileData/SampleProfReader.h
index 0e9ab2dc60ee..0617b05e8d4f 100644
--- a/contrib/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/contrib/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -235,7 +235,7 @@ class raw_ostream;
namespace sampleprof {
-/// \brief Sample-based profile reader.
+/// Sample-based profile reader.
///
/// Each profile contains sample counts for all the functions
/// executed. Inside each function, statements are annotated with the
@@ -264,105 +264,113 @@ namespace sampleprof {
/// compact and I/O efficient. They can both be used interchangeably.
class SampleProfileReader {
public:
- SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
- : Profiles(0), Ctx(C), Buffer(std::move(B)) {}
+ SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
+ SampleProfileFormat Format = SPF_None)
+ : Profiles(0), Ctx(C), Buffer(std::move(B)), Format(Format) {}
virtual ~SampleProfileReader() = default;
- /// \brief Read and validate the file header.
+ /// Read and validate the file header.
virtual std::error_code readHeader() = 0;
- /// \brief Read sample profiles from the associated file.
+ /// Read sample profiles from the associated file.
virtual std::error_code read() = 0;
- /// \brief Print the profile for \p FName on stream \p OS.
+ /// Print the profile for \p FName on stream \p OS.
void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs());
- /// \brief Print all the profiles on stream \p OS.
+ /// Print all the profiles on stream \p OS.
void dump(raw_ostream &OS = dbgs());
- /// \brief Return the samples collected for function \p F.
+ /// Return the samples collected for function \p F.
FunctionSamples *getSamplesFor(const Function &F) {
// The function name may have been updated by adding suffix. In sample
// profile, the function names are all stripped, so we need to strip
// the function name suffix before matching with profile.
- if (Profiles.count(F.getName().split('.').first))
- return &Profiles[(F.getName().split('.').first)];
+ StringRef Fname = F.getName().split('.').first;
+ std::string FGUID;
+ Fname = getRepInFormat(Fname, getFormat(), FGUID);
+ if (Profiles.count(Fname))
+ return &Profiles[Fname];
return nullptr;
}
- /// \brief Return all the profiles.
+ /// Return all the profiles.
StringMap<FunctionSamples> &getProfiles() { return Profiles; }
- /// \brief Report a parse error message.
+ /// Report a parse error message.
void reportError(int64_t LineNumber, Twine Msg) const {
Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(),
LineNumber, Msg));
}
- /// \brief Create a sample profile reader appropriate to the file format.
+ /// Create a sample profile reader appropriate to the file format.
static ErrorOr<std::unique_ptr<SampleProfileReader>>
create(const Twine &Filename, LLVMContext &C);
- /// \brief Create a sample profile reader from the supplied memory buffer.
+ /// Create a sample profile reader from the supplied memory buffer.
static ErrorOr<std::unique_ptr<SampleProfileReader>>
create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C);
- /// \brief Return the profile summary.
+ /// Return the profile summary.
ProfileSummary &getSummary() { return *(Summary.get()); }
+ /// \brief Return the profile format.
+ SampleProfileFormat getFormat() { return Format; }
+
protected:
- /// \brief Map every function to its associated profile.
+ /// Map every function to its associated profile.
///
/// The profile of every function executed at runtime is collected
/// in the structure FunctionSamples. This maps function objects
/// to their corresponding profiles.
StringMap<FunctionSamples> Profiles;
- /// \brief LLVM context used to emit diagnostics.
+ /// LLVM context used to emit diagnostics.
LLVMContext &Ctx;
- /// \brief Memory buffer holding the profile file.
+ /// Memory buffer holding the profile file.
std::unique_ptr<MemoryBuffer> Buffer;
- /// \brief Profile summary information.
+ /// Profile summary information.
std::unique_ptr<ProfileSummary> Summary;
- /// \brief Compute summary for this profile.
+ /// Compute summary for this profile.
void computeSummary();
+
+ /// \brief The format of sample.
+ SampleProfileFormat Format = SPF_None;
};
class SampleProfileReaderText : public SampleProfileReader {
public:
SampleProfileReaderText(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
- : SampleProfileReader(std::move(B), C) {}
+ : SampleProfileReader(std::move(B), C, SPF_Text) {}
- /// \brief Read and validate the file header.
+ /// Read and validate the file header.
std::error_code readHeader() override { return sampleprof_error::success; }
- /// \brief Read sample profiles from the associated file.
+ /// Read sample profiles from the associated file.
std::error_code read() override;
- /// \brief Return true if \p Buffer is in the format supported by this class.
+ /// Return true if \p Buffer is in the format supported by this class.
static bool hasFormat(const MemoryBuffer &Buffer);
};
class SampleProfileReaderBinary : public SampleProfileReader {
public:
- SampleProfileReaderBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
- : SampleProfileReader(std::move(B), C) {}
+ SampleProfileReaderBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
+ SampleProfileFormat Format = SPF_None)
+ : SampleProfileReader(std::move(B), C, Format) {}
- /// \brief Read and validate the file header.
+ /// Read and validate the file header.
std::error_code readHeader() override;
- /// \brief Read sample profiles from the associated file.
+ /// Read sample profiles from the associated file.
std::error_code read() override;
- /// \brief Return true if \p Buffer is in the format supported by this class.
- static bool hasFormat(const MemoryBuffer &Buffer);
-
protected:
- /// \brief Read a numeric value of type T from the profile.
+ /// Read a numeric value of type T from the profile.
///
/// If an error occurs during decoding, a diagnostic message is emitted and
/// EC is set.
@@ -370,7 +378,7 @@ protected:
/// \returns the read value.
template <typename T> ErrorOr<T> readNumber();
- /// \brief Read a string from the profile.
+ /// Read a string from the profile.
///
/// If an error occurs during decoding, a diagnostic message is emitted and
/// EC is set.
@@ -378,29 +386,68 @@ protected:
/// \returns the read value.
ErrorOr<StringRef> readString();
- /// Read a string indirectly via the name table.
- ErrorOr<StringRef> readStringFromTable();
+ /// Read the string index and check whether it overflows the table.
+ template <typename T> inline ErrorOr<uint32_t> readStringIndex(T &Table);
- /// \brief Return true if we've reached the end of file.
+ /// Return true if we've reached the end of file.
bool at_eof() const { return Data >= End; }
/// Read the contents of the given profile instance.
std::error_code readProfile(FunctionSamples &FProfile);
- /// \brief Points to the current location in the buffer.
+ /// Points to the current location in the buffer.
const uint8_t *Data = nullptr;
- /// \brief Points to the end of the buffer.
+ /// Points to the end of the buffer.
const uint8_t *End = nullptr;
+private:
+ std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
+ virtual std::error_code verifySPMagic(uint64_t Magic) = 0;
+
+ /// Read profile summary.
+ std::error_code readSummary();
+
+ /// Read the whole name table.
+ virtual std::error_code readNameTable() = 0;
+
+ /// Read a string indirectly via the name table.
+ virtual ErrorOr<StringRef> readStringFromTable() = 0;
+};
+
+class SampleProfileReaderRawBinary : public SampleProfileReaderBinary {
+private:
/// Function name table.
std::vector<StringRef> NameTable;
+ virtual std::error_code verifySPMagic(uint64_t Magic) override;
+ virtual std::error_code readNameTable() override;
+ /// Read a string indirectly via the name table.
+ virtual ErrorOr<StringRef> readStringFromTable() override;
+
+public:
+ SampleProfileReaderRawBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
+ : SampleProfileReaderBinary(std::move(B), C, SPF_Binary) {}
+
+ /// \brief Return true if \p Buffer is in the format supported by this class.
+ static bool hasFormat(const MemoryBuffer &Buffer);
+};
+class SampleProfileReaderCompactBinary : public SampleProfileReaderBinary {
private:
- std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
+ /// Function name table.
+ std::vector<std::string> NameTable;
+ virtual std::error_code verifySPMagic(uint64_t Magic) override;
+ virtual std::error_code readNameTable() override;
+ /// Read a string indirectly via the name table.
+ virtual ErrorOr<StringRef> readStringFromTable() override;
- /// \brief Read profile summary.
- std::error_code readSummary();
+public:
+ SampleProfileReaderCompactBinary(std::unique_ptr<MemoryBuffer> B,
+ LLVMContext &C)
+ : SampleProfileReaderBinary(std::move(B), C, SPF_Compact_Binary) {}
+
+ /// \brief Return true if \p Buffer is in the format supported by this class.
+ static bool hasFormat(const MemoryBuffer &Buffer);
};
using InlineCallStack = SmallVector<FunctionSamples *, 10>;
@@ -421,15 +468,16 @@ enum HistType {
class SampleProfileReaderGCC : public SampleProfileReader {
public:
SampleProfileReaderGCC(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
- : SampleProfileReader(std::move(B), C), GcovBuffer(Buffer.get()) {}
+ : SampleProfileReader(std::move(B), C, SPF_GCC),
+ GcovBuffer(Buffer.get()) {}
- /// \brief Read and validate the file header.
+ /// Read and validate the file header.
std::error_code readHeader() override;
- /// \brief Read sample profiles from the associated file.
+ /// Read sample profiles from the associated file.
std::error_code read() override;
- /// \brief Return true if \p Buffer is in the format supported by this class.
+ /// Return true if \p Buffer is in the format supported by this class.
static bool hasFormat(const MemoryBuffer &Buffer);
protected:
@@ -441,7 +489,7 @@ protected:
template <typename T> ErrorOr<T> readNumber();
ErrorOr<StringRef> readString();
- /// \brief Read the section tag and check that it's the same as \p Expected.
+ /// Read the section tag and check that it's the same as \p Expected.
std::error_code readSectionTag(uint32_t Expected);
/// GCOV buffer containing the profile.
diff --git a/contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h b/contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h
index 86af1038d74e..74dc839ff049 100644
--- a/contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h
+++ b/contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h
@@ -23,14 +23,13 @@
#include <algorithm>
#include <cstdint>
#include <memory>
+#include <set>
#include <system_error>
namespace llvm {
namespace sampleprof {
-enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC };
-
-/// \brief Sample-based profile writer. Base class.
+/// Sample-based profile writer. Base class.
class SampleProfileWriter {
public:
virtual ~SampleProfileWriter() = default;
@@ -62,21 +61,21 @@ protected:
SampleProfileWriter(std::unique_ptr<raw_ostream> &OS)
: OutputStream(std::move(OS)) {}
- /// \brief Write a file header for the profile file.
+ /// Write a file header for the profile file.
virtual std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) = 0;
- /// \brief Output stream where to emit the profile to.
+ /// Output stream where to emit the profile to.
std::unique_ptr<raw_ostream> OutputStream;
- /// \brief Profile summary.
+ /// Profile summary.
std::unique_ptr<ProfileSummary> Summary;
- /// \brief Compute summary for this profile.
+ /// Compute summary for this profile.
void computeSummary(const StringMap<FunctionSamples> &ProfileMap);
};
-/// \brief Sample-based profile writer (text format).
+/// Sample-based profile writer (text format).
class SampleProfileWriterText : public SampleProfileWriter {
public:
std::error_code write(const FunctionSamples &S) override;
@@ -101,32 +100,49 @@ private:
SampleProfileFormat Format);
};
-/// \brief Sample-based profile writer (binary format).
+/// Sample-based profile writer (binary format).
class SampleProfileWriterBinary : public SampleProfileWriter {
public:
std::error_code write(const FunctionSamples &S) override;
-
-protected:
SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
: SampleProfileWriter(OS) {}
- std::error_code
- writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
+protected:
+ virtual std::error_code writeNameTable() = 0;
+ virtual std::error_code writeMagicIdent() = 0;
+ std::error_code writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
std::error_code writeSummary();
std::error_code writeNameIdx(StringRef FName);
std::error_code writeBody(const FunctionSamples &S);
+ inline void stablizeNameTable(std::set<StringRef> &V);
+
+ MapVector<StringRef, uint32_t> NameTable;
private:
void addName(StringRef FName);
void addNames(const FunctionSamples &S);
- MapVector<StringRef, uint32_t> NameTable;
-
friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
SampleProfileFormat Format);
};
+class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
+ using SampleProfileWriterBinary::SampleProfileWriterBinary;
+
+protected:
+ virtual std::error_code writeNameTable() override;
+ virtual std::error_code writeMagicIdent() override;
+};
+
+class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary {
+ using SampleProfileWriterBinary::SampleProfileWriterBinary;
+
+protected:
+ virtual std::error_code writeNameTable() override;
+ virtual std::error_code writeMagicIdent() override;
+};
+
} // end namespace sampleprof
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Support/AArch64TargetParser.def b/contrib/llvm/include/llvm/Support/AArch64TargetParser.def
index 30c7924ea5f1..6772e5f9b734 100644
--- a/contrib/llvm/include/llvm/Support/AArch64TargetParser.def
+++ b/contrib/llvm/include/llvm/Support/AArch64TargetParser.def
@@ -35,6 +35,11 @@ AARCH64_ARCH("armv8.3-a", ARMV8_3A, "8.3-A", "v8.3a",
(AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
AArch64::AEK_RDM | AArch64::AEK_RCPC))
+AARCH64_ARCH("armv8.4-a", ARMV8_4A, "8.4-A", "v8.4a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD))
#undef AARCH64_ARCH
#ifndef AARCH64_ARCH_EXT_NAME
@@ -47,6 +52,10 @@ AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc")
AARCH64_ARCH_EXT_NAME("lse", AArch64::AEK_LSE, "+lse", "-lse")
AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm")
AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto")
+AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4")
+AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3")
+AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2")
+AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes")
AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod")
AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8")
AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon")
@@ -82,6 +91,8 @@ AARCH64_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC))
AARCH64_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC))
+AARCH64_CPU_NAME("exynos-m4", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("falkor", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC | AArch64::AEK_RDM))
AARCH64_CPU_NAME("saphira", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false,
diff --git a/contrib/llvm/include/llvm/Support/AMDGPUKernelDescriptor.h b/contrib/llvm/include/llvm/Support/AMDGPUKernelDescriptor.h
deleted file mode 100644
index ce2c0c1c959e..000000000000
--- a/contrib/llvm/include/llvm/Support/AMDGPUKernelDescriptor.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//===--- AMDGPUKernelDescriptor.h -------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file
-/// \brief AMDGPU kernel descriptor definitions. For more information, visit
-/// https://llvm.org/docs/AMDGPUUsage.html#kernel-descriptor-for-gfx6-gfx9
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_AMDGPUKERNELDESCRIPTOR_H
-#define LLVM_SUPPORT_AMDGPUKERNELDESCRIPTOR_H
-
-#include <cstdint>
-
-// Creates enumeration entries used for packing bits into integers. Enumeration
-// entries include bit shift amount, bit width, and bit mask.
-#define AMDGPU_BITS_ENUM_ENTRY(name, shift, width) \
- name ## _SHIFT = (shift), \
- name ## _WIDTH = (width), \
- name = (((1 << (width)) - 1) << (shift)) \
-
-// Gets bits for specified bit mask from specified source.
-#define AMDGPU_BITS_GET(src, mask) \
- ((src & mask) >> mask ## _SHIFT) \
-
-// Sets bits for specified bit mask in specified destination.
-#define AMDGPU_BITS_SET(dst, mask, val) \
- dst &= (~(1 << mask ## _SHIFT) & ~mask); \
- dst |= (((val) << mask ## _SHIFT) & mask) \
-
-namespace llvm {
-namespace AMDGPU {
-namespace HSAKD {
-
-/// \brief Floating point rounding modes.
-enum : uint8_t {
- AMDGPU_FLOAT_ROUND_MODE_NEAR_EVEN = 0,
- AMDGPU_FLOAT_ROUND_MODE_PLUS_INFINITY = 1,
- AMDGPU_FLOAT_ROUND_MODE_MINUS_INFINITY = 2,
- AMDGPU_FLOAT_ROUND_MODE_ZERO = 3,
-};
-
-/// \brief Floating point denorm modes.
-enum : uint8_t {
- AMDGPU_FLOAT_DENORM_MODE_FLUSH_SRC_DST = 0,
- AMDGPU_FLOAT_DENORM_MODE_FLUSH_DST = 1,
- AMDGPU_FLOAT_DENORM_MODE_FLUSH_SRC = 2,
- AMDGPU_FLOAT_DENORM_MODE_FLUSH_NONE = 3,
-};
-
-/// \brief System VGPR workitem IDs.
-enum : uint8_t {
- AMDGPU_SYSTEM_VGPR_WORKITEM_ID_X = 0,
- AMDGPU_SYSTEM_VGPR_WORKITEM_ID_X_Y = 1,
- AMDGPU_SYSTEM_VGPR_WORKITEM_ID_X_Y_Z = 2,
- AMDGPU_SYSTEM_VGPR_WORKITEM_ID_UNDEFINED = 3,
-};
-
-/// \brief Compute program resource register one layout.
-enum ComputePgmRsrc1 {
- AMDGPU_BITS_ENUM_ENTRY(GRANULATED_WORKITEM_VGPR_COUNT, 0, 6),
- AMDGPU_BITS_ENUM_ENTRY(GRANULATED_WAVEFRONT_SGPR_COUNT, 6, 4),
- AMDGPU_BITS_ENUM_ENTRY(PRIORITY, 10, 2),
- AMDGPU_BITS_ENUM_ENTRY(FLOAT_ROUND_MODE_32, 12, 2),
- AMDGPU_BITS_ENUM_ENTRY(FLOAT_ROUND_MODE_16_64, 14, 2),
- AMDGPU_BITS_ENUM_ENTRY(FLOAT_DENORM_MODE_32, 16, 2),
- AMDGPU_BITS_ENUM_ENTRY(FLOAT_DENORM_MODE_16_64, 18, 2),
- AMDGPU_BITS_ENUM_ENTRY(PRIV, 20, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_DX10_CLAMP, 21, 1),
- AMDGPU_BITS_ENUM_ENTRY(DEBUG_MODE, 22, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_IEEE_MODE, 23, 1),
- AMDGPU_BITS_ENUM_ENTRY(BULKY, 24, 1),
- AMDGPU_BITS_ENUM_ENTRY(CDBG_USER, 25, 1),
- AMDGPU_BITS_ENUM_ENTRY(FP16_OVFL, 26, 1),
- AMDGPU_BITS_ENUM_ENTRY(RESERVED0, 27, 5),
-};
-
-/// \brief Compute program resource register two layout.
-enum ComputePgmRsrc2 {
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_PRIVATE_SEGMENT_WAVE_OFFSET, 0, 1),
- AMDGPU_BITS_ENUM_ENTRY(USER_SGPR_COUNT, 1, 5),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_TRAP_HANDLER, 6, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_WORKGROUP_ID_X, 7, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_WORKGROUP_ID_Y, 8, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_WORKGROUP_ID_Z, 9, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_WORKGROUP_INFO, 10, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_VGPR_WORKITEM_ID, 11, 2),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_ADDRESS_WATCH, 13, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_MEMORY, 14, 1),
- AMDGPU_BITS_ENUM_ENTRY(GRANULATED_LDS_SIZE, 15, 9),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, 24, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, 25, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, 26, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, 27, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, 28, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, 29, 1),
- AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, 30, 1),
- AMDGPU_BITS_ENUM_ENTRY(RESERVED1, 31, 1),
-};
-
-/// \brief Kernel descriptor layout. This layout should be kept backwards
-/// compatible as it is consumed by the command processor.
-struct KernelDescriptor final {
- uint32_t GroupSegmentFixedSize;
- uint32_t PrivateSegmentFixedSize;
- uint32_t MaxFlatWorkGroupSize;
- uint64_t IsDynamicCallStack : 1;
- uint64_t IsXNACKEnabled : 1;
- uint64_t Reserved0 : 30;
- int64_t KernelCodeEntryByteOffset;
- uint64_t Reserved1[3];
- uint32_t ComputePgmRsrc1;
- uint32_t ComputePgmRsrc2;
- uint64_t EnableSGPRPrivateSegmentBuffer : 1;
- uint64_t EnableSGPRDispatchPtr : 1;
- uint64_t EnableSGPRQueuePtr : 1;
- uint64_t EnableSGPRKernargSegmentPtr : 1;
- uint64_t EnableSGPRDispatchID : 1;
- uint64_t EnableSGPRFlatScratchInit : 1;
- uint64_t EnableSGPRPrivateSegmentSize : 1;
- uint64_t EnableSGPRGridWorkgroupCountX : 1;
- uint64_t EnableSGPRGridWorkgroupCountY : 1;
- uint64_t EnableSGPRGridWorkgroupCountZ : 1;
- uint64_t Reserved2 : 54;
-
- KernelDescriptor() = default;
-};
-
-} // end namespace HSAKD
-} // end namespace AMDGPU
-} // end namespace llvm
-
-#endif // LLVM_SUPPORT_AMDGPUKERNELDESCRIPTOR_H
diff --git a/contrib/llvm/include/llvm/Support/AMDGPUMetadata.h b/contrib/llvm/include/llvm/Support/AMDGPUMetadata.h
index 00039a75c51d..667fb3f3da43 100644
--- a/contrib/llvm/include/llvm/Support/AMDGPUMetadata.h
+++ b/contrib/llvm/include/llvm/Support/AMDGPUMetadata.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief AMDGPU metadata definitions and in-memory representations.
+/// AMDGPU metadata definitions and in-memory representations.
///
//
//===----------------------------------------------------------------------===//
@@ -29,17 +29,17 @@ namespace AMDGPU {
//===----------------------------------------------------------------------===//
namespace HSAMD {
-/// \brief HSA metadata major version.
+/// HSA metadata major version.
constexpr uint32_t VersionMajor = 1;
-/// \brief HSA metadata minor version.
+/// HSA metadata minor version.
constexpr uint32_t VersionMinor = 0;
-/// \brief HSA metadata beginning assembler directive.
+/// HSA metadata beginning assembler directive.
constexpr char AssemblerDirectiveBegin[] = ".amd_amdgpu_hsa_metadata";
-/// \brief HSA metadata ending assembler directive.
+/// HSA metadata ending assembler directive.
constexpr char AssemblerDirectiveEnd[] = ".end_amd_amdgpu_hsa_metadata";
-/// \brief Access qualifiers.
+/// Access qualifiers.
enum class AccessQualifier : uint8_t {
Default = 0,
ReadOnly = 1,
@@ -48,7 +48,7 @@ enum class AccessQualifier : uint8_t {
Unknown = 0xff
};
-/// \brief Address space qualifiers.
+/// Address space qualifiers.
enum class AddressSpaceQualifier : uint8_t {
Private = 0,
Global = 1,
@@ -59,7 +59,7 @@ enum class AddressSpaceQualifier : uint8_t {
Unknown = 0xff
};
-/// \brief Value kinds.
+/// Value kinds.
enum class ValueKind : uint8_t {
ByValue = 0,
GlobalBuffer = 1,
@@ -78,7 +78,7 @@ enum class ValueKind : uint8_t {
Unknown = 0xff
};
-/// \brief Value types.
+/// Value types.
enum class ValueType : uint8_t {
Struct = 0,
I8 = 1,
@@ -106,29 +106,29 @@ namespace Kernel {
namespace Attrs {
namespace Key {
-/// \brief Key for Kernel::Attr::Metadata::mReqdWorkGroupSize.
+/// Key for Kernel::Attr::Metadata::mReqdWorkGroupSize.
constexpr char ReqdWorkGroupSize[] = "ReqdWorkGroupSize";
-/// \brief Key for Kernel::Attr::Metadata::mWorkGroupSizeHint.
+/// Key for Kernel::Attr::Metadata::mWorkGroupSizeHint.
constexpr char WorkGroupSizeHint[] = "WorkGroupSizeHint";
-/// \brief Key for Kernel::Attr::Metadata::mVecTypeHint.
+/// Key for Kernel::Attr::Metadata::mVecTypeHint.
constexpr char VecTypeHint[] = "VecTypeHint";
-/// \brief Key for Kernel::Attr::Metadata::mRuntimeHandle.
+/// Key for Kernel::Attr::Metadata::mRuntimeHandle.
constexpr char RuntimeHandle[] = "RuntimeHandle";
} // end namespace Key
-/// \brief In-memory representation of kernel attributes metadata.
+/// In-memory representation of kernel attributes metadata.
struct Metadata final {
- /// \brief 'reqd_work_group_size' attribute. Optional.
+ /// 'reqd_work_group_size' attribute. Optional.
std::vector<uint32_t> mReqdWorkGroupSize = std::vector<uint32_t>();
- /// \brief 'work_group_size_hint' attribute. Optional.
+ /// 'work_group_size_hint' attribute. Optional.
std::vector<uint32_t> mWorkGroupSizeHint = std::vector<uint32_t>();
- /// \brief 'vec_type_hint' attribute. Optional.
+ /// 'vec_type_hint' attribute. Optional.
std::string mVecTypeHint = std::string();
- /// \brief External symbol created by runtime to store the kernel address
+ /// External symbol created by runtime to store the kernel address
/// for enqueued blocks.
std::string mRuntimeHandle = std::string();
- /// \brief Default constructor.
+ /// Default constructor.
Metadata() = default;
/// \returns True if kernel attributes metadata is empty, false otherwise.
@@ -151,68 +151,68 @@ struct Metadata final {
namespace Arg {
namespace Key {
-/// \brief Key for Kernel::Arg::Metadata::mName.
+/// Key for Kernel::Arg::Metadata::mName.
constexpr char Name[] = "Name";
-/// \brief Key for Kernel::Arg::Metadata::mTypeName.
+/// Key for Kernel::Arg::Metadata::mTypeName.
constexpr char TypeName[] = "TypeName";
-/// \brief Key for Kernel::Arg::Metadata::mSize.
+/// Key for Kernel::Arg::Metadata::mSize.
constexpr char Size[] = "Size";
-/// \brief Key for Kernel::Arg::Metadata::mAlign.
+/// Key for Kernel::Arg::Metadata::mAlign.
constexpr char Align[] = "Align";
-/// \brief Key for Kernel::Arg::Metadata::mValueKind.
+/// Key for Kernel::Arg::Metadata::mValueKind.
constexpr char ValueKind[] = "ValueKind";
-/// \brief Key for Kernel::Arg::Metadata::mValueType.
+/// Key for Kernel::Arg::Metadata::mValueType.
constexpr char ValueType[] = "ValueType";
-/// \brief Key for Kernel::Arg::Metadata::mPointeeAlign.
+/// Key for Kernel::Arg::Metadata::mPointeeAlign.
constexpr char PointeeAlign[] = "PointeeAlign";
-/// \brief Key for Kernel::Arg::Metadata::mAddrSpaceQual.
+/// Key for Kernel::Arg::Metadata::mAddrSpaceQual.
constexpr char AddrSpaceQual[] = "AddrSpaceQual";
-/// \brief Key for Kernel::Arg::Metadata::mAccQual.
+/// Key for Kernel::Arg::Metadata::mAccQual.
constexpr char AccQual[] = "AccQual";
-/// \brief Key for Kernel::Arg::Metadata::mActualAccQual.
+/// Key for Kernel::Arg::Metadata::mActualAccQual.
constexpr char ActualAccQual[] = "ActualAccQual";
-/// \brief Key for Kernel::Arg::Metadata::mIsConst.
+/// Key for Kernel::Arg::Metadata::mIsConst.
constexpr char IsConst[] = "IsConst";
-/// \brief Key for Kernel::Arg::Metadata::mIsRestrict.
+/// Key for Kernel::Arg::Metadata::mIsRestrict.
constexpr char IsRestrict[] = "IsRestrict";
-/// \brief Key for Kernel::Arg::Metadata::mIsVolatile.
+/// Key for Kernel::Arg::Metadata::mIsVolatile.
constexpr char IsVolatile[] = "IsVolatile";
-/// \brief Key for Kernel::Arg::Metadata::mIsPipe.
+/// Key for Kernel::Arg::Metadata::mIsPipe.
constexpr char IsPipe[] = "IsPipe";
} // end namespace Key
-/// \brief In-memory representation of kernel argument metadata.
+/// In-memory representation of kernel argument metadata.
struct Metadata final {
- /// \brief Name. Optional.
+ /// Name. Optional.
std::string mName = std::string();
- /// \brief Type name. Optional.
+ /// Type name. Optional.
std::string mTypeName = std::string();
- /// \brief Size in bytes. Required.
+ /// Size in bytes. Required.
uint32_t mSize = 0;
- /// \brief Alignment in bytes. Required.
+ /// Alignment in bytes. Required.
uint32_t mAlign = 0;
- /// \brief Value kind. Required.
+ /// Value kind. Required.
ValueKind mValueKind = ValueKind::Unknown;
- /// \brief Value type. Required.
+ /// Value type. Required.
ValueType mValueType = ValueType::Unknown;
- /// \brief Pointee alignment in bytes. Optional.
+ /// Pointee alignment in bytes. Optional.
uint32_t mPointeeAlign = 0;
- /// \brief Address space qualifier. Optional.
+ /// Address space qualifier. Optional.
AddressSpaceQualifier mAddrSpaceQual = AddressSpaceQualifier::Unknown;
- /// \brief Access qualifier. Optional.
+ /// Access qualifier. Optional.
AccessQualifier mAccQual = AccessQualifier::Unknown;
- /// \brief Actual access qualifier. Optional.
+ /// Actual access qualifier. Optional.
AccessQualifier mActualAccQual = AccessQualifier::Unknown;
- /// \brief True if 'const' qualifier is specified. Optional.
+ /// True if 'const' qualifier is specified. Optional.
bool mIsConst = false;
- /// \brief True if 'restrict' qualifier is specified. Optional.
+ /// True if 'restrict' qualifier is specified. Optional.
bool mIsRestrict = false;
- /// \brief True if 'volatile' qualifier is specified. Optional.
+ /// True if 'volatile' qualifier is specified. Optional.
bool mIsVolatile = false;
- /// \brief True if 'pipe' qualifier is specified. Optional.
+ /// True if 'pipe' qualifier is specified. Optional.
bool mIsPipe = false;
- /// \brief Default constructor.
+ /// Default constructor.
Metadata() = default;
};
@@ -224,67 +224,67 @@ struct Metadata final {
namespace CodeProps {
namespace Key {
-/// \brief Key for Kernel::CodeProps::Metadata::mKernargSegmentSize.
+/// Key for Kernel::CodeProps::Metadata::mKernargSegmentSize.
constexpr char KernargSegmentSize[] = "KernargSegmentSize";
-/// \brief Key for Kernel::CodeProps::Metadata::mGroupSegmentFixedSize.
+/// Key for Kernel::CodeProps::Metadata::mGroupSegmentFixedSize.
constexpr char GroupSegmentFixedSize[] = "GroupSegmentFixedSize";
-/// \brief Key for Kernel::CodeProps::Metadata::mPrivateSegmentFixedSize.
+/// Key for Kernel::CodeProps::Metadata::mPrivateSegmentFixedSize.
constexpr char PrivateSegmentFixedSize[] = "PrivateSegmentFixedSize";
-/// \brief Key for Kernel::CodeProps::Metadata::mKernargSegmentAlign.
+/// Key for Kernel::CodeProps::Metadata::mKernargSegmentAlign.
constexpr char KernargSegmentAlign[] = "KernargSegmentAlign";
-/// \brief Key for Kernel::CodeProps::Metadata::mWavefrontSize.
+/// Key for Kernel::CodeProps::Metadata::mWavefrontSize.
constexpr char WavefrontSize[] = "WavefrontSize";
-/// \brief Key for Kernel::CodeProps::Metadata::mNumSGPRs.
+/// Key for Kernel::CodeProps::Metadata::mNumSGPRs.
constexpr char NumSGPRs[] = "NumSGPRs";
-/// \brief Key for Kernel::CodeProps::Metadata::mNumVGPRs.
+/// Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char NumVGPRs[] = "NumVGPRs";
-/// \brief Key for Kernel::CodeProps::Metadata::mMaxFlatWorkGroupSize.
+/// Key for Kernel::CodeProps::Metadata::mMaxFlatWorkGroupSize.
constexpr char MaxFlatWorkGroupSize[] = "MaxFlatWorkGroupSize";
-/// \brief Key for Kernel::CodeProps::Metadata::mIsDynamicCallStack.
+/// Key for Kernel::CodeProps::Metadata::mIsDynamicCallStack.
constexpr char IsDynamicCallStack[] = "IsDynamicCallStack";
-/// \brief Key for Kernel::CodeProps::Metadata::mIsXNACKEnabled.
+/// Key for Kernel::CodeProps::Metadata::mIsXNACKEnabled.
constexpr char IsXNACKEnabled[] = "IsXNACKEnabled";
-/// \brief Key for Kernel::CodeProps::Metadata::mNumSpilledSGPRs.
+/// Key for Kernel::CodeProps::Metadata::mNumSpilledSGPRs.
constexpr char NumSpilledSGPRs[] = "NumSpilledSGPRs";
-/// \brief Key for Kernel::CodeProps::Metadata::mNumSpilledVGPRs.
+/// Key for Kernel::CodeProps::Metadata::mNumSpilledVGPRs.
constexpr char NumSpilledVGPRs[] = "NumSpilledVGPRs";
} // end namespace Key
-/// \brief In-memory representation of kernel code properties metadata.
+/// In-memory representation of kernel code properties metadata.
struct Metadata final {
- /// \brief Size in bytes of the kernarg segment memory. Kernarg segment memory
+ /// Size in bytes of the kernarg segment memory. Kernarg segment memory
/// holds the values of the arguments to the kernel. Required.
uint64_t mKernargSegmentSize = 0;
- /// \brief Size in bytes of the group segment memory required by a workgroup.
+ /// Size in bytes of the group segment memory required by a workgroup.
/// This value does not include any dynamically allocated group segment memory
/// that may be added when the kernel is dispatched. Required.
uint32_t mGroupSegmentFixedSize = 0;
- /// \brief Size in bytes of the private segment memory required by a workitem.
+ /// Size in bytes of the private segment memory required by a workitem.
/// Private segment memory includes arg, spill and private segments. Required.
uint32_t mPrivateSegmentFixedSize = 0;
- /// \brief Maximum byte alignment of variables used by the kernel in the
+ /// Maximum byte alignment of variables used by the kernel in the
/// kernarg memory segment. Required.
uint32_t mKernargSegmentAlign = 0;
- /// \brief Wavefront size. Required.
+ /// Wavefront size. Required.
uint32_t mWavefrontSize = 0;
- /// \brief Total number of SGPRs used by a wavefront. Optional.
+ /// Total number of SGPRs used by a wavefront. Optional.
uint16_t mNumSGPRs = 0;
- /// \brief Total number of VGPRs used by a workitem. Optional.
+ /// Total number of VGPRs used by a workitem. Optional.
uint16_t mNumVGPRs = 0;
- /// \brief Maximum flat work-group size supported by the kernel. Optional.
+ /// Maximum flat work-group size supported by the kernel. Optional.
uint32_t mMaxFlatWorkGroupSize = 0;
- /// \brief True if the generated machine code is using a dynamically sized
+ /// True if the generated machine code is using a dynamically sized
/// call stack. Optional.
bool mIsDynamicCallStack = false;
- /// \brief True if the generated machine code is capable of supporting XNACK.
+ /// True if the generated machine code is capable of supporting XNACK.
/// Optional.
bool mIsXNACKEnabled = false;
- /// \brief Number of SGPRs spilled by a wavefront. Optional.
+ /// Number of SGPRs spilled by a wavefront. Optional.
uint16_t mNumSpilledSGPRs = 0;
- /// \brief Number of VGPRs spilled by a workitem. Optional.
+ /// Number of VGPRs spilled by a workitem. Optional.
uint16_t mNumSpilledVGPRs = 0;
- /// \brief Default constructor.
+ /// Default constructor.
Metadata() = default;
/// \returns True if kernel code properties metadata is empty, false
@@ -308,40 +308,40 @@ struct Metadata final {
namespace DebugProps {
namespace Key {
-/// \brief Key for Kernel::DebugProps::Metadata::mDebuggerABIVersion.
+/// Key for Kernel::DebugProps::Metadata::mDebuggerABIVersion.
constexpr char DebuggerABIVersion[] = "DebuggerABIVersion";
-/// \brief Key for Kernel::DebugProps::Metadata::mReservedNumVGPRs.
+/// Key for Kernel::DebugProps::Metadata::mReservedNumVGPRs.
constexpr char ReservedNumVGPRs[] = "ReservedNumVGPRs";
-/// \brief Key for Kernel::DebugProps::Metadata::mReservedFirstVGPR.
+/// Key for Kernel::DebugProps::Metadata::mReservedFirstVGPR.
constexpr char ReservedFirstVGPR[] = "ReservedFirstVGPR";
-/// \brief Key for Kernel::DebugProps::Metadata::mPrivateSegmentBufferSGPR.
+/// Key for Kernel::DebugProps::Metadata::mPrivateSegmentBufferSGPR.
constexpr char PrivateSegmentBufferSGPR[] = "PrivateSegmentBufferSGPR";
-/// \brief Key for
+/// Key for
/// Kernel::DebugProps::Metadata::mWavefrontPrivateSegmentOffsetSGPR.
constexpr char WavefrontPrivateSegmentOffsetSGPR[] =
"WavefrontPrivateSegmentOffsetSGPR";
} // end namespace Key
-/// \brief In-memory representation of kernel debug properties metadata.
+/// In-memory representation of kernel debug properties metadata.
struct Metadata final {
- /// \brief Debugger ABI version. Optional.
+ /// Debugger ABI version. Optional.
std::vector<uint32_t> mDebuggerABIVersion = std::vector<uint32_t>();
- /// \brief Consecutive number of VGPRs reserved for debugger use. Must be 0 if
+ /// Consecutive number of VGPRs reserved for debugger use. Must be 0 if
/// mDebuggerABIVersion is not set. Optional.
uint16_t mReservedNumVGPRs = 0;
- /// \brief First fixed VGPR reserved. Must be uint16_t(-1) if
+ /// First fixed VGPR reserved. Must be uint16_t(-1) if
/// mDebuggerABIVersion is not set or mReservedFirstVGPR is 0. Optional.
uint16_t mReservedFirstVGPR = uint16_t(-1);
- /// \brief Fixed SGPR of the first of 4 SGPRs used to hold the scratch V# used
+ /// Fixed SGPR of the first of 4 SGPRs used to hold the scratch V# used
/// for the entire kernel execution. Must be uint16_t(-1) if
/// mDebuggerABIVersion is not set or SGPR not used or not known. Optional.
uint16_t mPrivateSegmentBufferSGPR = uint16_t(-1);
- /// \brief Fixed SGPR used to hold the wave scratch offset for the entire
+ /// Fixed SGPR used to hold the wave scratch offset for the entire
/// kernel execution. Must be uint16_t(-1) if mDebuggerABIVersion is not set
/// or SGPR is not used or not known. Optional.
uint16_t mWavefrontPrivateSegmentOffsetSGPR = uint16_t(-1);
- /// \brief Default constructor.
+ /// Default constructor.
Metadata() = default;
/// \returns True if kernel debug properties metadata is empty, false
@@ -360,75 +360,75 @@ struct Metadata final {
} // end namespace DebugProps
namespace Key {
-/// \brief Key for Kernel::Metadata::mName.
+/// Key for Kernel::Metadata::mName.
constexpr char Name[] = "Name";
-/// \brief Key for Kernel::Metadata::mSymbolName.
+/// Key for Kernel::Metadata::mSymbolName.
constexpr char SymbolName[] = "SymbolName";
-/// \brief Key for Kernel::Metadata::mLanguage.
+/// Key for Kernel::Metadata::mLanguage.
constexpr char Language[] = "Language";
-/// \brief Key for Kernel::Metadata::mLanguageVersion.
+/// Key for Kernel::Metadata::mLanguageVersion.
constexpr char LanguageVersion[] = "LanguageVersion";
-/// \brief Key for Kernel::Metadata::mAttrs.
+/// Key for Kernel::Metadata::mAttrs.
constexpr char Attrs[] = "Attrs";
-/// \brief Key for Kernel::Metadata::mArgs.
+/// Key for Kernel::Metadata::mArgs.
constexpr char Args[] = "Args";
-/// \brief Key for Kernel::Metadata::mCodeProps.
+/// Key for Kernel::Metadata::mCodeProps.
constexpr char CodeProps[] = "CodeProps";
-/// \brief Key for Kernel::Metadata::mDebugProps.
+/// Key for Kernel::Metadata::mDebugProps.
constexpr char DebugProps[] = "DebugProps";
} // end namespace Key
-/// \brief In-memory representation of kernel metadata.
+/// In-memory representation of kernel metadata.
struct Metadata final {
- /// \brief Kernel source name. Required.
+ /// Kernel source name. Required.
std::string mName = std::string();
- /// \brief Kernel descriptor name. Required.
+ /// Kernel descriptor name. Required.
std::string mSymbolName = std::string();
- /// \brief Language. Optional.
+ /// Language. Optional.
std::string mLanguage = std::string();
- /// \brief Language version. Optional.
+ /// Language version. Optional.
std::vector<uint32_t> mLanguageVersion = std::vector<uint32_t>();
- /// \brief Attributes metadata. Optional.
+ /// Attributes metadata. Optional.
Attrs::Metadata mAttrs = Attrs::Metadata();
- /// \brief Arguments metadata. Optional.
+ /// Arguments metadata. Optional.
std::vector<Arg::Metadata> mArgs = std::vector<Arg::Metadata>();
- /// \brief Code properties metadata. Optional.
+ /// Code properties metadata. Optional.
CodeProps::Metadata mCodeProps = CodeProps::Metadata();
- /// \brief Debug properties metadata. Optional.
+ /// Debug properties metadata. Optional.
DebugProps::Metadata mDebugProps = DebugProps::Metadata();
- /// \brief Default constructor.
+ /// Default constructor.
Metadata() = default;
};
} // end namespace Kernel
namespace Key {
-/// \brief Key for HSA::Metadata::mVersion.
+/// Key for HSA::Metadata::mVersion.
constexpr char Version[] = "Version";
-/// \brief Key for HSA::Metadata::mPrintf.
+/// Key for HSA::Metadata::mPrintf.
constexpr char Printf[] = "Printf";
-/// \brief Key for HSA::Metadata::mKernels.
+/// Key for HSA::Metadata::mKernels.
constexpr char Kernels[] = "Kernels";
} // end namespace Key
-/// \brief In-memory representation of HSA metadata.
+/// In-memory representation of HSA metadata.
struct Metadata final {
- /// \brief HSA metadata version. Required.
+ /// HSA metadata version. Required.
std::vector<uint32_t> mVersion = std::vector<uint32_t>();
- /// \brief Printf metadata. Optional.
+ /// Printf metadata. Optional.
std::vector<std::string> mPrintf = std::vector<std::string>();
- /// \brief Kernels metadata. Required.
+ /// Kernels metadata. Required.
std::vector<Kernel::Metadata> mKernels = std::vector<Kernel::Metadata>();
- /// \brief Default constructor.
+ /// Default constructor.
Metadata() = default;
};
-/// \brief Converts \p String to \p HSAMetadata.
+/// Converts \p String to \p HSAMetadata.
std::error_code fromString(std::string String, Metadata &HSAMetadata);
-/// \brief Converts \p HSAMetadata to \p String.
+/// Converts \p HSAMetadata to \p String.
std::error_code toString(Metadata HSAMetadata, std::string &String);
} // end namespace HSAMD
@@ -438,10 +438,10 @@ std::error_code toString(Metadata HSAMetadata, std::string &String);
//===----------------------------------------------------------------------===//
namespace PALMD {
-/// \brief PAL metadata assembler directive.
+/// PAL metadata assembler directive.
constexpr char AssemblerDirective[] = ".amd_amdgpu_pal_metadata";
-/// \brief PAL metadata keys.
+/// PAL metadata keys.
enum Key : uint32_t {
LS_NUM_USED_VGPRS = 0x10000021,
HS_NUM_USED_VGPRS = 0x10000022,
@@ -468,10 +468,10 @@ enum Key : uint32_t {
CS_SCRATCH_SIZE = 0x1000004a
};
-/// \brief PAL metadata represented as a vector.
+/// PAL metadata represented as a vector.
typedef std::vector<uint32_t> Metadata;
-/// \brief Converts \p PALMetadata to \p String.
+/// Converts \p PALMetadata to \p String.
std::error_code toString(const Metadata &PALMetadata, std::string &String);
} // end namespace PALMD
diff --git a/contrib/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h b/contrib/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h
new file mode 100644
index 000000000000..751699e3a19f
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h
@@ -0,0 +1,185 @@
+//===--- AMDHSAKernelDescriptor.h -----------------------------*- C++ -*---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// AMDHSA kernel descriptor definitions. For more information, visit
+/// https://llvm.org/docs/AMDGPUUsage.html#kernel-descriptor
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H
+#define LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H
+
+#include <cstddef>
+#include <cstdint>
+
+// Gets offset of specified member in specified type.
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
+#endif // offsetof
+
+// Creates enumeration entries used for packing bits into integers. Enumeration
+// entries include bit shift amount, bit width, and bit mask.
+#ifndef AMDHSA_BITS_ENUM_ENTRY
+#define AMDHSA_BITS_ENUM_ENTRY(NAME, SHIFT, WIDTH) \
+ NAME ## _SHIFT = (SHIFT), \
+ NAME ## _WIDTH = (WIDTH), \
+ NAME = (((1 << (WIDTH)) - 1) << (SHIFT))
+#endif // AMDHSA_BITS_ENUM_ENTRY
+
+// Gets bits for specified bit mask from specified source.
+#ifndef AMDHSA_BITS_GET
+#define AMDHSA_BITS_GET(SRC, MSK) ((SRC & MSK) >> MSK ## _SHIFT)
+#endif // AMDHSA_BITS_GET
+
+// Sets bits for specified bit mask in specified destination.
+#ifndef AMDHSA_BITS_SET
+#define AMDHSA_BITS_SET(DST, MSK, VAL) \
+ DST &= ~MSK; \
+ DST |= ((VAL << MSK ## _SHIFT) & MSK)
+#endif // AMDHSA_BITS_SET
+
+namespace llvm {
+namespace amdhsa {
+
+// Floating point rounding modes. Must match hardware definition.
+enum : uint8_t {
+ FLOAT_ROUND_MODE_NEAR_EVEN = 0,
+ FLOAT_ROUND_MODE_PLUS_INFINITY = 1,
+ FLOAT_ROUND_MODE_MINUS_INFINITY = 2,
+ FLOAT_ROUND_MODE_ZERO = 3,
+};
+
+// Floating point denorm modes. Must match hardware definition.
+enum : uint8_t {
+ FLOAT_DENORM_MODE_FLUSH_SRC_DST = 0,
+ FLOAT_DENORM_MODE_FLUSH_DST = 1,
+ FLOAT_DENORM_MODE_FLUSH_SRC = 2,
+ FLOAT_DENORM_MODE_FLUSH_NONE = 3,
+};
+
+// System VGPR workitem IDs. Must match hardware definition.
+enum : uint8_t {
+ SYSTEM_VGPR_WORKITEM_ID_X = 0,
+ SYSTEM_VGPR_WORKITEM_ID_X_Y = 1,
+ SYSTEM_VGPR_WORKITEM_ID_X_Y_Z = 2,
+ SYSTEM_VGPR_WORKITEM_ID_UNDEFINED = 3,
+};
+
+// Compute program resource register 1. Must match hardware definition.
+#define COMPUTE_PGM_RSRC1(NAME, SHIFT, WIDTH) \
+ AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC1_ ## NAME, SHIFT, WIDTH)
+enum : int32_t {
+ COMPUTE_PGM_RSRC1(GRANULATED_WORKITEM_VGPR_COUNT, 0, 6),
+ COMPUTE_PGM_RSRC1(GRANULATED_WAVEFRONT_SGPR_COUNT, 6, 4),
+ COMPUTE_PGM_RSRC1(PRIORITY, 10, 2),
+ COMPUTE_PGM_RSRC1(FLOAT_ROUND_MODE_32, 12, 2),
+ COMPUTE_PGM_RSRC1(FLOAT_ROUND_MODE_16_64, 14, 2),
+ COMPUTE_PGM_RSRC1(FLOAT_DENORM_MODE_32, 16, 2),
+ COMPUTE_PGM_RSRC1(FLOAT_DENORM_MODE_16_64, 18, 2),
+ COMPUTE_PGM_RSRC1(PRIV, 20, 1),
+ COMPUTE_PGM_RSRC1(ENABLE_DX10_CLAMP, 21, 1),
+ COMPUTE_PGM_RSRC1(DEBUG_MODE, 22, 1),
+ COMPUTE_PGM_RSRC1(ENABLE_IEEE_MODE, 23, 1),
+ COMPUTE_PGM_RSRC1(BULKY, 24, 1),
+ COMPUTE_PGM_RSRC1(CDBG_USER, 25, 1),
+ COMPUTE_PGM_RSRC1(FP16_OVFL, 26, 1), // GFX9+
+ COMPUTE_PGM_RSRC1(RESERVED0, 27, 5),
+};
+#undef COMPUTE_PGM_RSRC1
+
+// Compute program resource register 2. Must match hardware definition.
+#define COMPUTE_PGM_RSRC2(NAME, SHIFT, WIDTH) \
+ AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC2_ ## NAME, SHIFT, WIDTH)
+enum : int32_t {
+ COMPUTE_PGM_RSRC2(ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET, 0, 1),
+ COMPUTE_PGM_RSRC2(USER_SGPR_COUNT, 1, 5),
+ COMPUTE_PGM_RSRC2(ENABLE_TRAP_HANDLER, 6, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_X, 7, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_Y, 8, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_Z, 9, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_INFO, 10, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_VGPR_WORKITEM_ID, 11, 2),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_ADDRESS_WATCH, 13, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_MEMORY, 14, 1),
+ COMPUTE_PGM_RSRC2(GRANULATED_LDS_SIZE, 15, 9),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, 24, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, 25, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, 26, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, 27, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, 28, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, 29, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, 30, 1),
+ COMPUTE_PGM_RSRC2(RESERVED0, 31, 1),
+};
+#undef COMPUTE_PGM_RSRC2
+
+// Kernel code properties. Must be kept backwards compatible.
+#define KERNEL_CODE_PROPERTY(NAME, SHIFT, WIDTH) \
+ AMDHSA_BITS_ENUM_ENTRY(KERNEL_CODE_PROPERTY_ ## NAME, SHIFT, WIDTH)
+enum : int32_t {
+ KERNEL_CODE_PROPERTY(ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, 0, 1),
+ KERNEL_CODE_PROPERTY(ENABLE_SGPR_DISPATCH_PTR, 1, 1),
+ KERNEL_CODE_PROPERTY(ENABLE_SGPR_QUEUE_PTR, 2, 1),
+ KERNEL_CODE_PROPERTY(ENABLE_SGPR_KERNARG_SEGMENT_PTR, 3, 1),
+ KERNEL_CODE_PROPERTY(ENABLE_SGPR_DISPATCH_ID, 4, 1),
+ KERNEL_CODE_PROPERTY(ENABLE_SGPR_FLAT_SCRATCH_INIT, 5, 1),
+ KERNEL_CODE_PROPERTY(ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, 6, 1),
+ KERNEL_CODE_PROPERTY(RESERVED0, 7, 9),
+};
+#undef KERNEL_CODE_PROPERTY
+
+// Kernel descriptor. Must be kept backwards compatible.
+struct kernel_descriptor_t {
+ uint32_t group_segment_fixed_size;
+ uint32_t private_segment_fixed_size;
+ uint8_t reserved0[8];
+ int64_t kernel_code_entry_byte_offset;
+ uint8_t reserved1[24];
+ uint32_t compute_pgm_rsrc1;
+ uint32_t compute_pgm_rsrc2;
+ uint16_t kernel_code_properties;
+ uint8_t reserved2[6];
+};
+
+static_assert(
+ sizeof(kernel_descriptor_t) == 64,
+ "invalid size for kernel_descriptor_t");
+static_assert(
+ offsetof(kernel_descriptor_t, group_segment_fixed_size) == 0,
+ "invalid offset for group_segment_fixed_size");
+static_assert(
+ offsetof(kernel_descriptor_t, private_segment_fixed_size) == 4,
+ "invalid offset for private_segment_fixed_size");
+static_assert(
+ offsetof(kernel_descriptor_t, reserved0) == 8,
+ "invalid offset for reserved0");
+static_assert(
+ offsetof(kernel_descriptor_t, kernel_code_entry_byte_offset) == 16,
+ "invalid offset for kernel_code_entry_byte_offset");
+static_assert(
+ offsetof(kernel_descriptor_t, reserved1) == 24,
+ "invalid offset for reserved1");
+static_assert(
+ offsetof(kernel_descriptor_t, compute_pgm_rsrc1) == 48,
+ "invalid offset for compute_pgm_rsrc1");
+static_assert(
+ offsetof(kernel_descriptor_t, compute_pgm_rsrc2) == 52,
+ "invalid offset for compute_pgm_rsrc2");
+static_assert(
+ offsetof(kernel_descriptor_t, kernel_code_properties) == 56,
+ "invalid offset for kernel_code_properties");
+static_assert(
+ offsetof(kernel_descriptor_t, reserved2) == 58,
+ "invalid offset for reserved2");
+
+} // end namespace amdhsa
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H
diff --git a/contrib/llvm/include/llvm/Support/ARMTargetParser.def b/contrib/llvm/include/llvm/Support/ARMTargetParser.def
index 6c8eff1a8f84..78f5410fb733 100644
--- a/contrib/llvm/include/llvm/Support/ARMTargetParser.def
+++ b/contrib/llvm/include/llvm/Support/ARMTargetParser.def
@@ -101,6 +101,11 @@ ARM_ARCH("armv8.3-a", ARMV8_3A, "8.3-A", "v8.3a",
ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS))
+ARM_ARCH("armv8.4-a", ARMV8_4A, "8.4-A", "v8.4a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS |
+ ARM::AEK_DOTPROD))
ARM_ARCH("armv8-r", ARMV8R, "8-R", "v8r", ARMBuildAttrs::CPUArch::v8_R,
FK_NEON_FP_ARMV8,
(ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
@@ -130,6 +135,8 @@ ARM_ARCH_EXT_NAME("invalid", ARM::AEK_INVALID, nullptr, nullptr)
ARM_ARCH_EXT_NAME("none", ARM::AEK_NONE, nullptr, nullptr)
ARM_ARCH_EXT_NAME("crc", ARM::AEK_CRC, "+crc", "-crc")
ARM_ARCH_EXT_NAME("crypto", ARM::AEK_CRYPTO, "+crypto","-crypto")
+ARM_ARCH_EXT_NAME("sha2", ARM::AEK_SHA2, "+sha2", "-sha2")
+ARM_ARCH_EXT_NAME("aes", ARM::AEK_AES, "+aes", "-aes")
ARM_ARCH_EXT_NAME("dotprod", ARM::AEK_DOTPROD, "+dotprod","-dotprod")
ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp")
ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, nullptr, nullptr)
@@ -253,6 +260,7 @@ ARM_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m1", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("exynos-m4", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("kryo", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
// Non-standard Arch names.
ARM_CPU_NAME("iwmmxt", IWMMXT, FK_NONE, true, ARM::AEK_NONE)
diff --git a/contrib/llvm/include/llvm/Support/AlignOf.h b/contrib/llvm/include/llvm/Support/AlignOf.h
index abd19afa22f0..9e7a62b85e34 100644
--- a/contrib/llvm/include/llvm/Support/AlignOf.h
+++ b/contrib/llvm/include/llvm/Support/AlignOf.h
@@ -20,7 +20,7 @@
namespace llvm {
/// \struct AlignedCharArray
-/// \brief Helper for building an aligned character array type.
+/// Helper for building an aligned character array type.
///
/// This template is used to explicitly build up a collection of aligned
/// character array types. We have to build these up using a macro and explicit
@@ -34,12 +34,12 @@ namespace llvm {
template<std::size_t Alignment, std::size_t Size>
struct AlignedCharArray {
- LLVM_ALIGNAS(Alignment) char buffer[Size];
+ alignas(Alignment) char buffer[Size];
};
#else // _MSC_VER
-/// \brief Create a type with an aligned char buffer.
+/// Create a type with an aligned char buffer.
template<std::size_t Alignment, std::size_t Size>
struct AlignedCharArray;
@@ -124,7 +124,7 @@ union SizerImpl {
};
} // end namespace detail
-/// \brief This union template exposes a suitably aligned and sized character
+/// This union template exposes a suitably aligned and sized character
/// array member which can hold elements of any of up to ten types.
///
/// These types may be arrays, structs, or any other types. The goal is to
diff --git a/contrib/llvm/include/llvm/Support/Allocator.h b/contrib/llvm/include/llvm/Support/Allocator.h
index a94aa8fb1f2a..184ac491b1f1 100644
--- a/contrib/llvm/include/llvm/Support/Allocator.h
+++ b/contrib/llvm/include/llvm/Support/Allocator.h
@@ -23,7 +23,9 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemAlloc.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -35,7 +37,7 @@
namespace llvm {
-/// \brief CRTP base class providing obvious overloads for the core \c
+/// CRTP base class providing obvious overloads for the core \c
/// Allocate() methods of LLVM-style allocators.
///
/// This base class both documents the full public interface exposed by all
@@ -43,7 +45,7 @@ namespace llvm {
/// set of methods which the derived class must define.
template <typename DerivedT> class AllocatorBase {
public:
- /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method
+ /// Allocate \a Size bytes of \a Alignment aligned memory. This method
/// must be implemented by \c DerivedT.
void *Allocate(size_t Size, size_t Alignment) {
#ifdef __clang__
@@ -57,7 +59,7 @@ public:
return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
}
- /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this
+ /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
/// allocator.
void Deallocate(const void *Ptr, size_t Size) {
#ifdef __clang__
@@ -74,12 +76,12 @@ public:
// The rest of these methods are helpers that redirect to one of the above
// core methods.
- /// \brief Allocate space for a sequence of objects without constructing them.
+ /// Allocate space for a sequence of objects without constructing them.
template <typename T> T *Allocate(size_t Num = 1) {
return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
}
- /// \brief Deallocate space for a sequence of objects without constructing them.
+ /// Deallocate space for a sequence of objects without constructing them.
template <typename T>
typename std::enable_if<
!std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type
@@ -94,7 +96,7 @@ public:
LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
size_t /*Alignment*/) {
- return malloc(Size);
+ return safe_malloc(Size);
}
// Pull in base class overloads.
@@ -119,7 +121,7 @@ void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
} // end namespace detail
-/// \brief Allocate memory in an ever growing pool, as if by bump-pointer.
+/// Allocate memory in an ever growing pool, as if by bump-pointer.
///
/// This isn't strictly a bump-pointer allocator as it uses backing slabs of
/// memory rather than relying on a boundless contiguous heap. However, it has
@@ -187,7 +189,7 @@ public:
return *this;
}
- /// \brief Deallocate all but the current slab and reset the current pointer
+ /// Deallocate all but the current slab and reset the current pointer
/// to the beginning of it, freeing all memory allocated so far.
void Reset() {
// Deallocate all but the first slab, and deallocate all custom-sized slabs.
@@ -207,7 +209,7 @@ public:
Slabs.erase(std::next(Slabs.begin()), Slabs.end());
}
- /// \brief Allocate space at the specified alignment.
+ /// Allocate space at the specified alignment.
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
Allocate(size_t Size, size_t Alignment) {
assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
@@ -302,30 +304,30 @@ public:
}
private:
- /// \brief The current pointer into the current slab.
+ /// The current pointer into the current slab.
///
/// This points to the next free byte in the slab.
char *CurPtr = nullptr;
- /// \brief The end of the current slab.
+ /// The end of the current slab.
char *End = nullptr;
- /// \brief The slabs allocated so far.
+ /// The slabs allocated so far.
SmallVector<void *, 4> Slabs;
- /// \brief Custom-sized slabs allocated for too-large allocation requests.
+ /// Custom-sized slabs allocated for too-large allocation requests.
SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs;
- /// \brief How many bytes we've allocated.
+ /// How many bytes we've allocated.
///
/// Used so that we can compute how much space was wasted.
size_t BytesAllocated = 0;
- /// \brief The number of bytes to put between allocations when running under
+ /// The number of bytes to put between allocations when running under
/// a sanitizer.
size_t RedZoneSize = 1;
- /// \brief The allocator instance we use to get slabs of memory.
+ /// The allocator instance we use to get slabs of memory.
AllocatorT Allocator;
static size_t computeSlabSize(unsigned SlabIdx) {
@@ -336,7 +338,7 @@ private:
return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128));
}
- /// \brief Allocate a new slab and move the bump pointers over into the new
+ /// Allocate a new slab and move the bump pointers over into the new
/// slab, modifying CurPtr and End.
void StartNewSlab() {
size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
@@ -351,7 +353,7 @@ private:
End = ((char *)NewSlab) + AllocatedSlabSize;
}
- /// \brief Deallocate a sequence of slabs.
+ /// Deallocate a sequence of slabs.
void DeallocateSlabs(SmallVectorImpl<void *>::iterator I,
SmallVectorImpl<void *>::iterator E) {
for (; I != E; ++I) {
@@ -361,7 +363,7 @@ private:
}
}
- /// \brief Deallocate all memory for custom sized slabs.
+ /// Deallocate all memory for custom sized slabs.
void DeallocateCustomSizedSlabs() {
for (auto &PtrAndSize : CustomSizedSlabs) {
void *Ptr = PtrAndSize.first;
@@ -373,11 +375,11 @@ private:
template <typename T> friend class SpecificBumpPtrAllocator;
};
-/// \brief The standard BumpPtrAllocator which just uses the default template
+/// The standard BumpPtrAllocator which just uses the default template
/// parameters.
typedef BumpPtrAllocatorImpl<> BumpPtrAllocator;
-/// \brief A BumpPtrAllocator that allows only elements of a specific type to be
+/// A BumpPtrAllocator that allows only elements of a specific type to be
/// allocated.
///
/// This allows calling the destructor in DestroyAll() and when the allocator is
@@ -430,7 +432,7 @@ public:
Allocator.Reset();
}
- /// \brief Allocate space for an array of objects without constructing them.
+ /// Allocate space for an array of objects without constructing them.
T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); }
};
diff --git a/contrib/llvm/include/llvm/Support/AtomicOrdering.h b/contrib/llvm/include/llvm/Support/AtomicOrdering.h
index e93b755aa63b..a679ab30243e 100644
--- a/contrib/llvm/include/llvm/Support/AtomicOrdering.h
+++ b/contrib/llvm/include/llvm/Support/AtomicOrdering.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Atomic ordering constants.
+/// Atomic ordering constants.
///
/// These values are used by LLVM to represent atomic ordering for C++11's
/// memory model and more, as detailed in docs/Atomics.rst.
diff --git a/contrib/llvm/include/llvm/Support/BinaryByteStream.h b/contrib/llvm/include/llvm/Support/BinaryByteStream.h
index db1ccba1398b..9808d3b72157 100644
--- a/contrib/llvm/include/llvm/Support/BinaryByteStream.h
+++ b/contrib/llvm/include/llvm/Support/BinaryByteStream.h
@@ -25,7 +25,7 @@
namespace llvm {
-/// \brief An implementation of BinaryStream which holds its entire data set
+/// An implementation of BinaryStream which holds its entire data set
/// in a single contiguous buffer. BinaryByteStream guarantees that no read
/// operation will ever incur a copy. Note that BinaryByteStream does not
/// own the underlying buffer.
@@ -69,7 +69,7 @@ protected:
ArrayRef<uint8_t> Data;
};
-/// \brief An implementation of BinaryStream whose data is backed by an llvm
+/// An implementation of BinaryStream whose data is backed by an llvm
/// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
/// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
/// will never cause a copy.
@@ -83,7 +83,7 @@ public:
std::unique_ptr<MemoryBuffer> MemBuffer;
};
-/// \brief An implementation of BinaryStream which holds its entire data set
+/// An implementation of BinaryStream which holds its entire data set
/// in a single contiguous buffer. As with BinaryByteStream, the mutable
/// version also guarantees that no read operation will ever incur a copy,
/// and similarly it does not own the underlying buffer.
@@ -131,7 +131,7 @@ private:
BinaryByteStream ImmutableStream;
};
-/// \brief An implementation of WritableBinaryStream which can write at its end
+/// An implementation of WritableBinaryStream which can write at its end
/// causing the underlying data to grow. This class owns the underlying data.
class AppendingBinaryByteStream : public WritableBinaryStream {
std::vector<uint8_t> Data;
@@ -193,7 +193,7 @@ public:
Error commit() override { return Error::success(); }
- /// \brief Return the properties of this stream.
+ /// Return the properties of this stream.
virtual BinaryStreamFlags getFlags() const override {
return BSF_Write | BSF_Append;
}
@@ -201,7 +201,7 @@ public:
MutableArrayRef<uint8_t> data() { return Data; }
};
-/// \brief An implementation of WritableBinaryStream backed by an llvm
+/// An implementation of WritableBinaryStream backed by an llvm
/// FileOutputBuffer.
class FileBufferByteStream : public WritableBinaryStream {
private:
@@ -222,6 +222,12 @@ private:
return Error::success();
}
+ /// Returns a pointer to the start of the buffer.
+ uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
+
+ /// Returns a pointer to the end of the buffer.
+ uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
+
private:
std::unique_ptr<FileOutputBuffer> FileBuffer;
};
@@ -253,6 +259,12 @@ public:
Error commit() override { return Impl.commit(); }
+ /// Returns a pointer to the start of the buffer.
+ uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
+
+ /// Returns a pointer to the end of the buffer.
+ uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
+
private:
StreamImpl Impl;
};
diff --git a/contrib/llvm/include/llvm/Support/BinaryStream.h b/contrib/llvm/include/llvm/Support/BinaryStream.h
index d69a03eccfdb..7677214e48ee 100644
--- a/contrib/llvm/include/llvm/Support/BinaryStream.h
+++ b/contrib/llvm/include/llvm/Support/BinaryStream.h
@@ -26,7 +26,7 @@ enum BinaryStreamFlags {
LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ BSF_Append)
};
-/// \brief An interface for accessing data in a stream-like format, but which
+/// An interface for accessing data in a stream-like format, but which
/// discourages copying. Instead of specifying a buffer in which to copy
/// data on a read, the API returns an ArrayRef to data owned by the stream's
/// implementation. Since implementations may not necessarily store data in a
@@ -39,21 +39,21 @@ public:
virtual llvm::support::endianness getEndian() const = 0;
- /// \brief Given an offset into the stream and a number of bytes, attempt to
+ /// Given an offset into the stream and a number of bytes, attempt to
/// read the bytes and set the output ArrayRef to point to data owned by the
/// stream.
virtual Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) = 0;
- /// \brief Given an offset into the stream, read as much as possible without
+ /// Given an offset into the stream, read as much as possible without
/// copying any data.
virtual Error readLongestContiguousChunk(uint32_t Offset,
ArrayRef<uint8_t> &Buffer) = 0;
- /// \brief Return the number of bytes of data in this stream.
+ /// Return the number of bytes of data in this stream.
virtual uint32_t getLength() = 0;
- /// \brief Return the properties of this stream.
+ /// Return the properties of this stream.
virtual BinaryStreamFlags getFlags() const { return BSF_None; }
protected:
@@ -66,7 +66,7 @@ protected:
}
};
-/// \brief A BinaryStream which can be read from as well as written to. Note
+/// A BinaryStream which can be read from as well as written to. Note
/// that writing to a BinaryStream always necessitates copying from the input
/// buffer to the stream's backing store. Streams are assumed to be buffered
/// so that to be portable it is necessary to call commit() on the stream when
@@ -75,15 +75,15 @@ class WritableBinaryStream : public BinaryStream {
public:
~WritableBinaryStream() override = default;
- /// \brief Attempt to write the given bytes into the stream at the desired
+ /// Attempt to write the given bytes into the stream at the desired
/// offset. This will always necessitate a copy. Cannot shrink or grow the
/// stream, only writes into existing allocated space.
virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0;
- /// \brief For buffered streams, commits changes to the backing store.
+ /// For buffered streams, commits changes to the backing store.
virtual Error commit() = 0;
- /// \brief Return the properties of this stream.
+ /// Return the properties of this stream.
BinaryStreamFlags getFlags() const override { return BSF_Write; }
protected:
diff --git a/contrib/llvm/include/llvm/Support/BinaryStreamArray.h b/contrib/llvm/include/llvm/Support/BinaryStreamArray.h
index 3f5562ba7519..d1571cb37fc6 100644
--- a/contrib/llvm/include/llvm/Support/BinaryStreamArray.h
+++ b/contrib/llvm/include/llvm/Support/BinaryStreamArray.h
@@ -111,7 +111,7 @@ public:
bool empty() const { return Stream.getLength() == 0; }
- /// \brief given an offset into the array's underlying stream, return an
+ /// given an offset into the array's underlying stream, return an
/// iterator to the record at that offset. This is considered unsafe
/// since the behavior is undefined if \p Offset does not refer to the
/// beginning of a valid record.
diff --git a/contrib/llvm/include/llvm/Support/BinaryStreamReader.h b/contrib/llvm/include/llvm/Support/BinaryStreamReader.h
index ae5ebb2c3628..fe77b550c453 100644
--- a/contrib/llvm/include/llvm/Support/BinaryStreamReader.h
+++ b/contrib/llvm/include/llvm/Support/BinaryStreamReader.h
@@ -24,7 +24,7 @@
namespace llvm {
-/// \brief Provides read only access to a subclass of `BinaryStream`. Provides
+/// Provides read only access to a subclass of `BinaryStream`. Provides
/// bounds checking and helpers for writing certain common data types such as
/// null-terminated strings, integers in various flavors of endianness, etc.
/// Can be subclassed to provide reading of custom datatypes, although no
diff --git a/contrib/llvm/include/llvm/Support/BinaryStreamRef.h b/contrib/llvm/include/llvm/Support/BinaryStreamRef.h
index 5cf355be6fe9..d8dc1392c01c 100644
--- a/contrib/llvm/include/llvm/Support/BinaryStreamRef.h
+++ b/contrib/llvm/include/llvm/Support/BinaryStreamRef.h
@@ -147,7 +147,7 @@ protected:
Optional<uint32_t> Length;
};
-/// \brief BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It
+/// BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It
/// provides copy-semantics and read only access to a "window" of the underlying
/// BinaryStream. Note that BinaryStreamRef is *not* a BinaryStream. That is to
/// say, it does not inherit and override the methods of BinaryStream. In
@@ -266,7 +266,7 @@ public:
/// Conver this WritableBinaryStreamRef to a read-only BinaryStreamRef.
operator BinaryStreamRef() const;
- /// \brief For buffered streams, commits changes to the backing store.
+ /// For buffered streams, commits changes to the backing store.
Error commit();
};
diff --git a/contrib/llvm/include/llvm/Support/BinaryStreamWriter.h b/contrib/llvm/include/llvm/Support/BinaryStreamWriter.h
index a4495a1ce27d..6e8a68a30474 100644
--- a/contrib/llvm/include/llvm/Support/BinaryStreamWriter.h
+++ b/contrib/llvm/include/llvm/Support/BinaryStreamWriter.h
@@ -24,7 +24,7 @@
namespace llvm {
-/// \brief Provides write only access to a subclass of `WritableBinaryStream`.
+/// Provides write only access to a subclass of `WritableBinaryStream`.
/// Provides bounds checking and helpers for writing certain common data types
/// such as null-terminated strings, integers in various flavors of endianness,
/// etc. Can be subclassed to provide reading and writing of custom datatypes,
@@ -56,7 +56,7 @@ public:
/// otherwise returns an appropriate error code.
Error writeBytes(ArrayRef<uint8_t> Buffer);
- /// Write the the integer \p Value to the underlying stream in the
+ /// Write the integer \p Value to the underlying stream in the
/// specified endianness. On success, updates the offset so that
/// subsequent writes occur at the next unwritten position.
///
@@ -80,7 +80,7 @@ public:
return writeInteger<U>(static_cast<U>(Num));
}
- /// Write the the string \p Str to the underlying stream followed by a null
+ /// Write the string \p Str to the underlying stream followed by a null
/// terminator. On success, updates the offset so that subsequent writes
/// occur at the next unwritten position. \p Str need not be null terminated
/// on input.
@@ -89,7 +89,7 @@ public:
/// otherwise returns an appropriate error code.
Error writeCString(StringRef Str);
- /// Write the the string \p Str to the underlying stream without a null
+ /// Write the string \p Str to the underlying stream without a null
/// terminator. On success, updates the offset so that subsequent writes
/// occur at the next unwritten position.
///
diff --git a/contrib/llvm/include/llvm/Support/BlockFrequency.h b/contrib/llvm/include/llvm/Support/BlockFrequency.h
index 2e75cbdd29c1..4b468f7acb32 100644
--- a/contrib/llvm/include/llvm/Support/BlockFrequency.h
+++ b/contrib/llvm/include/llvm/Support/BlockFrequency.h
@@ -28,32 +28,32 @@ class BlockFrequency {
public:
BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { }
- /// \brief Returns the maximum possible frequency, the saturation value.
+ /// Returns the maximum possible frequency, the saturation value.
static uint64_t getMaxFrequency() { return -1ULL; }
- /// \brief Returns the frequency as a fixpoint number scaled by the entry
+ /// Returns the frequency as a fixpoint number scaled by the entry
/// frequency.
uint64_t getFrequency() const { return Frequency; }
- /// \brief Multiplies with a branch probability. The computation will never
+ /// Multiplies with a branch probability. The computation will never
/// overflow.
BlockFrequency &operator*=(BranchProbability Prob);
BlockFrequency operator*(BranchProbability Prob) const;
- /// \brief Divide by a non-zero branch probability using saturating
+ /// Divide by a non-zero branch probability using saturating
/// arithmetic.
BlockFrequency &operator/=(BranchProbability Prob);
BlockFrequency operator/(BranchProbability Prob) const;
- /// \brief Adds another block frequency using saturating arithmetic.
+ /// Adds another block frequency using saturating arithmetic.
BlockFrequency &operator+=(BlockFrequency Freq);
BlockFrequency operator+(BlockFrequency Freq) const;
- /// \brief Subtracts another block frequency using saturating arithmetic.
+ /// Subtracts another block frequency using saturating arithmetic.
BlockFrequency &operator-=(BlockFrequency Freq);
BlockFrequency operator-(BlockFrequency Freq) const;
- /// \brief Shift block frequency to the right by count digits saturating to 1.
+ /// Shift block frequency to the right by count digits saturating to 1.
BlockFrequency &operator>>=(const unsigned count);
bool operator<(BlockFrequency RHS) const {
diff --git a/contrib/llvm/include/llvm/Support/BranchProbability.h b/contrib/llvm/include/llvm/Support/BranchProbability.h
index b403d7fbf117..3a88e71c2480 100644
--- a/contrib/llvm/include/llvm/Support/BranchProbability.h
+++ b/contrib/llvm/include/llvm/Support/BranchProbability.h
@@ -73,7 +73,7 @@ public:
void dump() const;
- /// \brief Scale a large integer.
+ /// Scale a large integer.
///
/// Scales \c Num. Guarantees full precision. Returns the floor of the
/// result.
@@ -81,7 +81,7 @@ public:
/// \return \c Num times \c this.
uint64_t scale(uint64_t Num) const;
- /// \brief Scale a large integer by the inverse.
+ /// Scale a large integer by the inverse.
///
/// Scales \c Num by the inverse of \c this. Guarantees full precision.
/// Returns the floor of the result.
diff --git a/contrib/llvm/include/llvm/Support/CachePruning.h b/contrib/llvm/include/llvm/Support/CachePruning.h
index 327c7df4570f..cf3f8ec67a52 100644
--- a/contrib/llvm/include/llvm/Support/CachePruning.h
+++ b/contrib/llvm/include/llvm/Support/CachePruning.h
@@ -37,7 +37,7 @@ struct CachePruningPolicy {
std::chrono::seconds Expiration = std::chrono::hours(7 * 24); // 1w
/// The maximum size for the cache directory, in terms of percentage of the
- /// available space on the the disk. Set to 100 to indicate no limit, 50 to
+ /// available space on the disk. Set to 100 to indicate no limit, 50 to
/// indicate that the cache size will not be left over half the available disk
/// space. A value over 100 will be reduced to 100. A value of 0 disables the
/// percentage size-based pruning.
@@ -52,9 +52,11 @@ struct CachePruningPolicy {
/// the number of files based pruning.
///
/// This defaults to 1000000 because with that many files there are
- /// diminishing returns on the effectiveness of the cache, and some file
- /// systems have a limit on how many files can be contained in a directory
- /// (notably ext4, which is limited to around 6000000 files).
+ /// diminishing returns on the effectiveness of the cache. Some systems have a
+ /// limit on total number of files, and some also limit the number of files
+ /// per directory, such as Linux ext4, with the default setting (block size is
+ /// 4096 and large_dir disabled), there is a per-directory entry limit of
+ /// 508*510*floor(4096/(40+8))~=20M for average filename length of 40.
uint64_t MaxSizeFiles = 1000000;
};
@@ -66,7 +68,7 @@ struct CachePruningPolicy {
Expected<CachePruningPolicy> parseCachePruningPolicy(StringRef PolicyStr);
/// Peform pruning using the supplied policy, returns true if pruning
-/// occured, i.e. if Policy.Interval was expired.
+/// occurred, i.e. if Policy.Interval was expired.
///
/// As a safeguard against data loss if the user specifies the wrong directory
/// as their cache directory, this function will ignore files not matching the
diff --git a/contrib/llvm/include/llvm/Support/Casting.h b/contrib/llvm/include/llvm/Support/Casting.h
index baa2a814e9a1..3f21e0f9ebc3 100644
--- a/contrib/llvm/include/llvm/Support/Casting.h
+++ b/contrib/llvm/include/llvm/Support/Casting.h
@@ -60,7 +60,7 @@ struct isa_impl {
}
};
-/// \brief Always allow upcasts, and perform no dynamic check for them.
+/// Always allow upcasts, and perform no dynamic check for them.
template <typename To, typename From>
struct isa_impl<
To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> {
diff --git a/contrib/llvm/include/llvm/Support/CheckedArithmetic.h b/contrib/llvm/include/llvm/Support/CheckedArithmetic.h
new file mode 100644
index 000000000000..039c374136ff
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/CheckedArithmetic.h
@@ -0,0 +1,104 @@
+//==-- llvm/Support/CheckedArithmetic.h - Safe arithmetical operations *- C++ //
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains generic functions for operating on integers which
+// give the indication on whether the operation has overflown.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CHECKEDARITHMETIC_H
+#define LLVM_SUPPORT_CHECKEDARITHMETIC_H
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Optional.h"
+
+#include <type_traits>
+
+namespace {
+
+/// Utility function to apply a given method of \c APInt \p F to \p LHS and
+/// \p RHS.
+/// \return Empty optional if the operation overflows, or result otherwise.
+template <typename T, typename F>
+typename std::enable_if<std::is_integral<T>::value && sizeof(T) * 8 <= 64,
+ llvm::Optional<T>>::type
+checkedOp(T LHS, T RHS, F Op, bool Signed = true) {
+ llvm::APInt ALHS(/*BitSize=*/sizeof(T) * 8, LHS, Signed);
+ llvm::APInt ARHS(/*BitSize=*/sizeof(T) * 8, RHS, Signed);
+ bool Overflow;
+ llvm::APInt Out = (ALHS.*Op)(ARHS, Overflow);
+ if (Overflow)
+ return llvm::None;
+ return Signed ? Out.getSExtValue() : Out.getZExtValue();
+}
+}
+
+namespace llvm {
+
+/// Add two signed integers \p LHS and \p RHS.
+/// \return Optional of sum if no signed overflow occurred,
+/// \c None otherwise.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+checkedAdd(T LHS, T RHS) {
+ return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
+}
+
+/// Multiply two signed integers \p LHS and \p RHS.
+/// \return Optional of product if no signed overflow occurred,
+/// \c None otherwise.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+checkedMul(T LHS, T RHS) {
+ return checkedOp(LHS, RHS, &llvm::APInt::smul_ov);
+}
+
+/// Multiply A and B, and add C to the resulting product.
+/// \return Optional of result if no signed overflow occurred,
+/// \c None otherwise.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+checkedMulAdd(T A, T B, T C) {
+ if (auto Product = checkedMul(A, B))
+ return checkedAdd(*Product, C);
+ return llvm::None;
+}
+
+/// Add two unsigned integers \p LHS and \p RHS.
+/// \return Optional of sum if no unsigned overflow occurred,
+/// \c None otherwise.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+checkedAddUnsigned(T LHS, T RHS) {
+ return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false);
+}
+
+/// Multiply two unsigned integers \p LHS and \p RHS.
+/// \return Optional of product if no unsigned overflow occurred,
+/// \c None otherwise.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+checkedMulUnsigned(T LHS, T RHS) {
+ return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false);
+}
+
+/// Multiply unsigned integers A and B, and add C to the resulting product.
+/// \return Optional of result if no unsigned overflow occurred,
+/// \c None otherwise.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+checkedMulAddUnsigned(T A, T B, T C) {
+ if (auto Product = checkedMulUnsigned(A, B))
+ return checkedAddUnsigned(*Product, C);
+ return llvm::None;
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/include/llvm/Support/CodeGenCoverage.h b/contrib/llvm/include/llvm/Support/CodeGenCoverage.h
index d5bd837bff28..c863be35b822 100644
--- a/contrib/llvm/include/llvm/Support/CodeGenCoverage.h
+++ b/contrib/llvm/include/llvm/Support/CodeGenCoverage.h
@@ -23,15 +23,18 @@ protected:
BitVector RuleCoverage;
public:
+ using const_covered_iterator = BitVector::const_set_bits_iterator;
+
CodeGenCoverage();
void setCovered(uint64_t RuleID);
- bool isCovered(uint64_t RuleID);
+ bool isCovered(uint64_t RuleID) const;
+ iterator_range<const_covered_iterator> covered() const;
bool parse(MemoryBuffer &Buffer, StringRef BackendName);
bool emit(StringRef FilePrefix, StringRef BackendName) const;
void reset();
};
-} // end namespace llvm
+} // namespace llvm
#endif // ifndef LLVM_SUPPORT_CODEGENCOVERAGE_H
diff --git a/contrib/llvm/include/llvm/Support/CommandLine.h b/contrib/llvm/include/llvm/Support/CommandLine.h
index f043c112861b..799b41fbf8b0 100644
--- a/contrib/llvm/include/llvm/Support/CommandLine.h
+++ b/contrib/llvm/include/llvm/Support/CommandLine.h
@@ -30,6 +30,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <climits>
#include <cstddef>
@@ -94,7 +95,7 @@ void PrintOptionValues();
// 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.
+/// 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
@@ -362,7 +363,10 @@ public:
bool MultiArg = false);
// Prints option name followed by message. Always returns true.
- bool error(const Twine &Message, StringRef ArgName = StringRef());
+ bool error(const Twine &Message, StringRef ArgName = StringRef(), raw_ostream &Errs = llvm::errs());
+ bool error(const Twine &Message, raw_ostream &Errs) {
+ return error(Message, StringRef(), Errs);
+ }
inline int getNumOccurrences() const { return NumOccurrences; }
inline void reset() { NumOccurrences = 0; }
@@ -1770,7 +1774,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
// Public interface for accessing registered options.
//
-/// \brief Use this to get a StringMap to all registered named options
+/// Use this to get a StringMap to all registered named options
/// (e.g. -help). Note \p Map Should be an empty StringMap.
///
/// \return A reference to the StringMap used by the cl APIs to parse options.
@@ -1799,7 +1803,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
/// than just handing around a global list.
StringMap<Option *> &getRegisteredOptions(SubCommand &Sub = *TopLevelSubCommand);
-/// \brief Use this to get all registered SubCommands from the provided parser.
+/// Use this to get all registered SubCommands from the provided parser.
///
/// \return A range of all SubCommand pointers registered with the parser.
///
@@ -1825,7 +1829,7 @@ getRegisteredSubcommands();
// Standalone command line processing utilities.
//
-/// \brief Tokenizes a command line that can contain escapes and quotes.
+/// Tokenizes a command line that can contain escapes and quotes.
//
/// The quoting rules match those used by GCC and other tools that use
/// libiberty's buildargv() or expandargv() utilities, and do not match bash.
@@ -1841,7 +1845,7 @@ void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver,
SmallVectorImpl<const char *> &NewArgv,
bool MarkEOLs = false);
-/// \brief Tokenizes a Windows command line which may contain quotes and escaped
+/// Tokenizes a Windows command line which may contain quotes and escaped
/// quotes.
///
/// See MSDN docs for CommandLineToArgvW for information on the quoting rules.
@@ -1856,7 +1860,7 @@ void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver,
SmallVectorImpl<const char *> &NewArgv,
bool MarkEOLs = false);
-/// \brief String tokenization function type. Should be compatible with either
+/// String tokenization function type. Should be compatible with either
/// Windows or Unix command line tokenizers.
using TokenizerCallback = void (*)(StringRef Source, StringSaver &Saver,
SmallVectorImpl<const char *> &NewArgv,
@@ -1889,7 +1893,7 @@ void tokenizeConfigFile(StringRef Source, StringSaver &Saver,
bool readConfigFile(StringRef CfgFileName, StringSaver &Saver,
SmallVectorImpl<const char *> &Argv);
-/// \brief Expand response files on a command line recursively using the given
+/// Expand response files on a command line recursively using the given
/// StringSaver and tokenization strategy. Argv should contain the command line
/// before expansion and will be modified in place. If requested, Argv will
/// also be populated with nullptrs indicating where each response file line
@@ -1909,7 +1913,7 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv,
bool MarkEOLs = false, bool RelativeNames = false);
-/// \brief Mark all options not part of this category as cl::ReallyHidden.
+/// Mark all options not part of this category as cl::ReallyHidden.
///
/// \param Category the category of options to keep displaying
///
@@ -1919,7 +1923,7 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
void HideUnrelatedOptions(cl::OptionCategory &Category,
SubCommand &Sub = *TopLevelSubCommand);
-/// \brief Mark all options not part of the categories as cl::ReallyHidden.
+/// Mark all options not part of the categories as cl::ReallyHidden.
///
/// \param Categories the categories of options to keep displaying.
///
@@ -1929,12 +1933,12 @@ void HideUnrelatedOptions(cl::OptionCategory &Category,
void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
SubCommand &Sub = *TopLevelSubCommand);
-/// \brief Reset all command line options to a state that looks as if they have
+/// Reset all command line options to a state that looks as if they have
/// never appeared on the command line. This is useful for being able to parse
/// a command line multiple times (especially useful for writing tests).
void ResetAllOptionOccurrences();
-/// \brief Reset the command line parser back to its initial state. This
+/// Reset the command line parser back to its initial state. This
/// removes
/// all options, categories, and subcommands and returns the parser to a state
/// where no options are supported.
diff --git a/contrib/llvm/include/llvm/Support/Compiler.h b/contrib/llvm/include/llvm/Support/Compiler.h
index b19e37235df5..4de815fe61d7 100644
--- a/contrib/llvm/include/llvm/Support/Compiler.h
+++ b/contrib/llvm/include/llvm/Support/Compiler.h
@@ -17,6 +17,9 @@
#include "llvm/Config/llvm-config.h"
+#include <new>
+#include <stddef.h>
+
#if defined(_MSC_VER)
#include <sal.h>
#endif
@@ -42,7 +45,7 @@
#endif
/// \macro LLVM_GNUC_PREREQ
-/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't
+/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't
/// available.
#ifndef LLVM_GNUC_PREREQ
# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
@@ -58,7 +61,7 @@
#endif
/// \macro LLVM_MSC_PREREQ
-/// \brief Is the compiler MSVC of at least the specified version?
+/// Is the compiler MSVC of at least the specified version?
/// The common \param version values to check for are:
/// * 1900: Microsoft Visual Studio 2015 / 14.0
#ifdef _MSC_VER
@@ -73,7 +76,7 @@
#define LLVM_MSC_PREREQ(version) 0
#endif
-/// \brief Does the compiler support ref-qualifiers for *this?
+/// Does the compiler support ref-qualifiers for *this?
///
/// Sadly, this is separate from just rvalue reference support because GCC
/// and MSVC implemented this later than everything else.
@@ -99,7 +102,7 @@
/// functions, making them private to any shared library they are linked into.
/// On PE/COFF targets, library visibility is the default, so this isn't needed.
#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
- !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)
+ !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32)
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
#else
#define LLVM_LIBRARY_VISIBILITY
@@ -146,7 +149,7 @@
// FIXME: Provide this for PE/COFF targets.
#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
- (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32))
+ (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32))
#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__))
#else
#define LLVM_ATTRIBUTE_WEAK
@@ -303,7 +306,7 @@
#endif
/// \macro LLVM_ASSUME_ALIGNED
-/// \brief Returns a pointer with an assumed alignment.
+/// Returns a pointer with an assumed alignment.
#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0)
# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
#elif defined(LLVM_BUILTIN_UNREACHABLE)
@@ -315,7 +318,7 @@
#endif
/// \macro LLVM_ALIGNAS
-/// \brief Used to specify a minimum alignment for a structure or variable.
+/// Used to specify a minimum alignment for a structure or variable.
#if __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 1)
# define LLVM_ALIGNAS(x) __attribute__((aligned(x)))
#else
@@ -323,7 +326,7 @@
#endif
/// \macro LLVM_PACKED
-/// \brief Used to specify a packed structure.
+/// Used to specify a packed structure.
/// LLVM_PACKED(
/// struct A {
/// int i;
@@ -351,7 +354,7 @@
#endif
/// \macro LLVM_PTR_SIZE
-/// \brief A constant integer equivalent to the value of sizeof(void*).
+/// A constant integer equivalent to the value of sizeof(void*).
/// Generally used in combination with LLVM_ALIGNAS or when doing computation in
/// the preprocessor.
#ifdef __SIZEOF_POINTER__
@@ -367,7 +370,7 @@
#endif
/// \macro LLVM_MEMORY_SANITIZER_BUILD
-/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation.
+/// Whether LLVM itself is built with MemorySanitizer instrumentation.
#if __has_feature(memory_sanitizer)
# define LLVM_MEMORY_SANITIZER_BUILD 1
# include <sanitizer/msan_interface.h>
@@ -378,7 +381,7 @@
#endif
/// \macro LLVM_ADDRESS_SANITIZER_BUILD
-/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation.
+/// Whether LLVM itself is built with AddressSanitizer instrumentation.
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
# define LLVM_ADDRESS_SANITIZER_BUILD 1
# include <sanitizer/asan_interface.h>
@@ -389,7 +392,7 @@
#endif
/// \macro LLVM_THREAD_SANITIZER_BUILD
-/// \brief Whether LLVM itself is built with ThreadSanitizer instrumentation.
+/// Whether LLVM itself is built with ThreadSanitizer instrumentation.
#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
# define LLVM_THREAD_SANITIZER_BUILD 1
#else
@@ -432,14 +435,14 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#endif
/// \macro LLVM_NO_SANITIZE
-/// \brief Disable a particular sanitizer for a function.
+/// Disable a particular sanitizer for a function.
#if __has_attribute(no_sanitize)
#define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND)))
#else
#define LLVM_NO_SANITIZE(KIND)
#endif
-/// \brief Mark debug helper function definitions like dump() that should not be
+/// Mark debug helper function definitions like dump() that should not be
/// stripped from debug builds.
/// Note that you should also surround dump() functions with
/// `#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)` so they do always
@@ -452,7 +455,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#endif
/// \macro LLVM_PRETTY_FUNCTION
-/// \brief Gets a user-friendly looking function signature for the current scope
+/// Gets a user-friendly looking function signature for the current scope
/// using the best available method on each platform. The exact format of the
/// resulting string is implementation specific and non-portable, so this should
/// only be used, for example, for logging or diagnostics.
@@ -465,7 +468,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#endif
/// \macro LLVM_THREAD_LOCAL
-/// \brief A thread-local storage specifier which can be used with globals,
+/// 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
@@ -494,7 +497,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#endif
/// \macro LLVM_ENABLE_EXCEPTIONS
-/// \brief Whether LLVM is built with exception support.
+/// Whether LLVM is built with exception support.
#if __has_feature(cxx_exceptions)
#define LLVM_ENABLE_EXCEPTIONS 1
#elif defined(__GNUC__) && defined(__EXCEPTIONS)
@@ -503,4 +506,46 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#define LLVM_ENABLE_EXCEPTIONS 1
#endif
+namespace llvm {
+
+/// Allocate a buffer of memory with the given size and alignment.
+///
+/// When the compiler supports aligned operator new, this will use it to to
+/// handle even over-aligned allocations.
+///
+/// However, this doesn't make any attempt to leverage the fancier techniques
+/// like posix_memalign due to portability. It is mostly intended to allow
+/// compatibility with platforms that, after aligned allocation was added, use
+/// reduced default alignment.
+inline void *allocate_buffer(size_t Size, size_t Alignment) {
+ return ::operator new(Size
+#if __cpp_aligned_new
+ ,
+ std::align_val_t(Alignment)
+#endif
+ );
+}
+
+/// Deallocate a buffer of memory with the given size and alignment.
+///
+/// If supported, this will used the sized delete operator. Also if supported,
+/// this will pass the alignment to the delete operator.
+///
+/// The pointer must have been allocated with the corresponding new operator,
+/// most likely using the above helper.
+inline void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
+ ::operator delete(Ptr
+#if __cpp_sized_deallocation
+ ,
+ Size
+#endif
+#if __cpp_aligned_new
+ ,
+ std::align_val_t(Alignment)
+#endif
+ );
+}
+
+} // End namespace llvm
+
#endif
diff --git a/contrib/llvm/include/llvm/Support/ConvertUTF.h b/contrib/llvm/include/llvm/Support/ConvertUTF.h
index 99ae171aeabb..6ae56c2470bb 100644
--- a/contrib/llvm/include/llvm/Support/ConvertUTF.h
+++ b/contrib/llvm/include/llvm/Support/ConvertUTF.h
@@ -92,6 +92,7 @@
#include <cstddef>
#include <string>
+#include <system_error>
// Wrap everything in namespace llvm so that programs can link with llvm and
// their own version of the unicode libraries.
@@ -286,6 +287,21 @@ bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out);
bool convertUTF8ToUTF16String(StringRef SrcUTF8,
SmallVectorImpl<UTF16> &DstUTF16);
+#if defined(_WIN32)
+namespace sys {
+namespace windows {
+std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16);
+/// Convert to UTF16 from the current code page used in the system
+std::error_code CurCPToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16);
+std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
+ SmallVectorImpl<char> &utf8);
+/// Convert from UTF16 to the current code page used in the system
+std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
+ SmallVectorImpl<char> &utf8);
+} // namespace windows
+} // namespace sys
+#endif
+
} /* end namespace llvm */
#endif
diff --git a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h
index 6cbc331d2731..7b3fd4f882e4 100644
--- a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h
+++ b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h
@@ -15,7 +15,7 @@
namespace llvm {
class CrashRecoveryContextCleanup;
-/// \brief Crash recovery helper object.
+/// Crash recovery helper object.
///
/// This class implements support for running operations in a safe context so
/// that crashes (memory errors, stack overflow, assertion violations) can be
@@ -27,6 +27,7 @@ class CrashRecoveryContextCleanup;
/// CrashRecoveryContext::Enable(), and then executing unsafe operations via a
/// CrashRecoveryContext object. For example:
///
+/// \code
/// void actual_work(void *);
///
/// void foo() {
@@ -38,6 +39,11 @@ class CrashRecoveryContextCleanup;
///
/// ... no crash was detected ...
/// }
+/// \endcode
+///
+/// To assist recovery the class allows specifying set of actions that will be
+/// executed in any case, whether crash occurs or not. These actions may be used
+/// to reclaim resources in the case of crash.
class CrashRecoveryContext {
void *Impl;
CrashRecoveryContextCleanup *head;
@@ -46,24 +52,27 @@ public:
CrashRecoveryContext() : Impl(nullptr), head(nullptr) {}
~CrashRecoveryContext();
+ /// Register cleanup handler, which is used when the recovery context is
+ /// finished.
+ /// The recovery context owns the handler.
void registerCleanup(CrashRecoveryContextCleanup *cleanup);
+
void unregisterCleanup(CrashRecoveryContextCleanup *cleanup);
- /// \brief Enable crash recovery.
+ /// Enable crash recovery.
static void Enable();
- /// \brief Disable crash recovery.
+ /// Disable crash recovery.
static void Disable();
- /// \brief Return the active context, if the code is currently executing in a
+ /// Return the active context, if the code is currently executing in a
/// thread which is in a protected context.
static CrashRecoveryContext *GetCurrent();
- /// \brief Return true if the current thread is recovering from a
- /// crash.
+ /// Return true if the current thread is recovering from a crash.
static bool isRecoveringFromCrash();
- /// \brief Execute the provide callback function (with the given arguments) in
+ /// Execute the provided callback function (with the given arguments) in
/// a protected context.
///
/// \return True if the function completed successfully, and false if the
@@ -75,7 +84,7 @@ public:
return RunSafely([&]() { Fn(UserData); });
}
- /// \brief Execute the provide callback function (with the given arguments) in
+ /// Execute the provide callback function (with the given arguments) in
/// a protected context which is run in another thread (optionally with a
/// requested stack size).
///
@@ -89,11 +98,18 @@ public:
return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize);
}
- /// \brief Explicitly trigger a crash recovery in the current process, and
+ /// Explicitly trigger a crash recovery in the current process, and
/// return failure from RunSafely(). This function does not return.
void HandleCrash();
};
+/// Abstract base class of cleanup handlers.
+///
+/// Derived classes override method recoverResources, which makes actual work on
+/// resource recovery.
+///
+/// Cleanup handlers are stored in a double list, which is owned and managed by
+/// a crash recovery context.
class CrashRecoveryContextCleanup {
protected:
CrashRecoveryContext *context;
@@ -115,7 +131,18 @@ private:
CrashRecoveryContextCleanup *prev, *next;
};
-template<typename DERIVED, typename T>
+/// Base class of cleanup handler that controls recovery of resources of the
+/// given type.
+///
+/// \tparam Derived Class that uses this class as a base.
+/// \tparam T Type of controlled resource.
+///
+/// This class serves as a base for its template parameter as implied by
+/// Curiously Recurring Template Pattern.
+///
+/// This class factors out creation of a cleanup handler. The latter requires
+/// knowledge of the current recovery context, which is provided by this class.
+template<typename Derived, typename T>
class CrashRecoveryContextCleanupBase : public CrashRecoveryContextCleanup {
protected:
T *resource;
@@ -123,15 +150,20 @@ protected:
: CrashRecoveryContextCleanup(context), resource(resource) {}
public:
- static DERIVED *create(T *x) {
+ /// Creates cleanup handler.
+ /// \param x Pointer to the resource recovered by this handler.
+ /// \return New handler or null if the method was called outside a recovery
+ /// context.
+ static Derived *create(T *x) {
if (x) {
if (CrashRecoveryContext *context = CrashRecoveryContext::GetCurrent())
- return new DERIVED(context, x);
+ return new Derived(context, x);
}
return nullptr;
}
};
+/// Cleanup handler that reclaims resource by calling destructor on it.
template <typename T>
class CrashRecoveryContextDestructorCleanup : public
CrashRecoveryContextCleanupBase<CrashRecoveryContextDestructorCleanup<T>, T> {
@@ -146,6 +178,7 @@ public:
}
};
+/// Cleanup handler that reclaims resource by calling 'delete' on it.
template <typename T>
class CrashRecoveryContextDeleteCleanup : public
CrashRecoveryContextCleanupBase<CrashRecoveryContextDeleteCleanup<T>, T> {
@@ -157,10 +190,10 @@ public:
void recoverResources() override { delete this->resource; }
};
+/// Cleanup handler that reclaims resource by calling its method 'Release'.
template <typename T>
class CrashRecoveryContextReleaseRefCleanup : public
- CrashRecoveryContextCleanupBase<CrashRecoveryContextReleaseRefCleanup<T>, T>
-{
+ CrashRecoveryContextCleanupBase<CrashRecoveryContextReleaseRefCleanup<T>, T> {
public:
CrashRecoveryContextReleaseRefCleanup(CrashRecoveryContext *context,
T *resource)
@@ -170,6 +203,37 @@ public:
void recoverResources() override { this->resource->Release(); }
};
+/// Helper class for managing resource cleanups.
+///
+/// \tparam T Type of resource been reclaimed.
+/// \tparam Cleanup Class that defines how the resource is reclaimed.
+///
+/// Clients create objects of this type in the code executed in a crash recovery
+/// context to ensure that the resource will be reclaimed even in the case of
+/// crash. For example:
+///
+/// \code
+/// void actual_work(void *) {
+/// ...
+/// std::unique_ptr<Resource> R(new Resource());
+/// CrashRecoveryContextCleanupRegistrar D(R.get());
+/// ...
+/// }
+///
+/// void foo() {
+/// CrashRecoveryContext CRC;
+///
+/// if (!CRC.RunSafely(actual_work, 0)) {
+/// ... a crash was detected, report error to user ...
+/// }
+/// \endcode
+///
+/// If the code of `actual_work` in the example above does not crash, the
+/// destructor of CrashRecoveryContextCleanupRegistrar removes cleanup code from
+/// the current CrashRecoveryContext and the resource is reclaimed by the
+/// destructor of std::unique_ptr. If crash happens, destructors are not called
+/// and the resource is reclaimed by cleanup object registered in the recovery
+/// context by the constructor of CrashRecoveryContextCleanupRegistrar.
template <typename T, typename Cleanup = CrashRecoveryContextDeleteCleanup<T> >
class CrashRecoveryContextCleanupRegistrar {
CrashRecoveryContextCleanup *cleanup;
diff --git a/contrib/llvm/include/llvm/Support/DJB.h b/contrib/llvm/include/llvm/Support/DJB.h
new file mode 100644
index 000000000000..e03111473362
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/DJB.h
@@ -0,0 +1,33 @@
+//===-- llvm/Support/DJB.h ---DJB Hash --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for the DJ Bernstein hash function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_DJB_H
+#define LLVM_SUPPORT_DJB_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+/// The Bernstein hash function used by the DWARF accelerator tables.
+inline uint32_t djbHash(StringRef Buffer, uint32_t H = 5381) {
+ for (unsigned char C : Buffer.bytes())
+ H = (H << 5) + H + C;
+ return H;
+}
+
+/// Computes the Bernstein hash after folding the input according to the Dwarf 5
+/// standard case folding rules.
+uint32_t caseFoldingDjbHash(StringRef Buffer, uint32_t H = 5381);
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_DJB_H
diff --git a/contrib/llvm/include/llvm/Support/DataExtractor.h b/contrib/llvm/include/llvm/Support/DataExtractor.h
index 31447882a919..3a6ada6c77df 100644
--- a/contrib/llvm/include/llvm/Support/DataExtractor.h
+++ b/contrib/llvm/include/llvm/Support/DataExtractor.h
@@ -51,13 +51,13 @@ public:
DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
: Data(Data), IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {}
- /// \brief Get the data pointed to by this extractor.
+ /// Get the data pointed to by this extractor.
StringRef getData() const { return Data; }
- /// \brief Get the endianness for this extractor.
+ /// Get the endianness for this extractor.
bool isLittleEndian() const { return IsLittleEndian; }
- /// \brief Get the address size for this extractor.
+ /// Get the address size for this extractor.
uint8_t getAddressSize() const { return AddressSize; }
- /// \brief Set the address size for this extractor.
+ /// Set the address size for this extractor.
void setAddressSize(uint8_t Size) { AddressSize = Size; }
/// Extract a C string from \a *offset_ptr.
diff --git a/contrib/llvm/include/llvm/Support/DataTypes.h b/contrib/llvm/include/llvm/Support/DataTypes.h
new file mode 100644
index 000000000000..ad60a5b3f300
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/DataTypes.h
@@ -0,0 +1,17 @@
+//===-- llvm/Support/DataTypes.h - Define fixed size types ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Due to layering constraints (Support depends on llvm-c) this is a thin
+// wrapper around the implementation that lives in llvm-c, though most clients
+// can/should think of this as being provided by Support for simplicity (not
+// many clients are aware of their dependency on llvm-c).
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/DataTypes.h"
diff --git a/contrib/llvm/include/llvm/Support/Debug.h b/contrib/llvm/include/llvm/Support/Debug.h
index 48e9e1bc167d..980abfb0e8da 100644
--- a/contrib/llvm/include/llvm/Support/Debug.h
+++ b/contrib/llvm/include/llvm/Support/Debug.h
@@ -11,17 +11,18 @@
// code, without it being enabled all of the time, and without having to add
// command line options to enable it.
//
-// In particular, just wrap your code with the DEBUG() macro, and it will be
-// enabled automatically if you specify '-debug' on the command-line.
-// DEBUG() requires the DEBUG_TYPE macro to be defined. Set it to "foo" specify
-// that your debug code belongs to class "foo". Be careful that you only do
-// this after including Debug.h and not around any #include of headers. Headers
-// should define and undef the macro acround the code that needs to use the
-// DEBUG() macro. Then, on the command line, you can specify '-debug-only=foo'
-// to enable JUST the debug information for the foo class.
+// In particular, just wrap your code with the LLVM_DEBUG() macro, and it will
+// be enabled automatically if you specify '-debug' on the command-line.
+// LLVM_DEBUG() requires the DEBUG_TYPE macro to be defined. Set it to "foo"
+// specify that your debug code belongs to class "foo". Be careful that you only
+// do this after including Debug.h and not around any #include of headers.
+// Headers should define and undef the macro acround the code that needs to use
+// the LLVM_DEBUG() macro. Then, on the command line, you can specify
+// '-debug-only=foo' to enable JUST the debug information for the foo class.
//
// When compiling without assertions, the -debug-* options and all code in
-// DEBUG() statements disappears, so it does not affect the runtime of the code.
+// LLVM_DEBUG() statements disappears, so it does not affect the runtime of the
+// code.
//
//===----------------------------------------------------------------------===//
@@ -113,9 +114,9 @@ raw_ostream &dbgs();
// debug build, then the code specified as the option to the macro will be
// executed. Otherwise it will not be. Example:
//
-// DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n");
+// LLVM_DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n");
//
-#define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X)
+#define LLVM_DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X)
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Support/DebugCounter.h b/contrib/llvm/include/llvm/Support/DebugCounter.h
index 52e1bd71a2f2..250fc6bb1f5c 100644
--- a/contrib/llvm/include/llvm/Support/DebugCounter.h
+++ b/contrib/llvm/include/llvm/Support/DebugCounter.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file provides an implementation of debug counters. Debug
+/// This file provides an implementation of debug counters. Debug
/// counters are a tool that let you narrow down a miscompilation to a specific
/// thing happening.
///
@@ -55,7 +55,7 @@ namespace llvm {
class DebugCounter {
public:
- /// \brief Returns a reference to the singleton instance.
+ /// Returns a reference to the singleton instance.
static DebugCounter &instance();
// Used by the command line option parser to push a new value it parsed.
@@ -77,23 +77,19 @@ public:
auto &Us = instance();
auto Result = Us.Counters.find(CounterName);
if (Result != Us.Counters.end()) {
- auto &CounterPair = Result->second;
- // We only execute while the skip (first) is zero and the count (second)
- // is non-zero.
+ auto &CounterInfo = Result->second;
+ ++CounterInfo.Count;
+
+ // We only execute while the Skip is not smaller than Count,
+ // and the StopAfter + Skip is larger than Count.
// Negative counters always execute.
- if (CounterPair.first < 0)
+ if (CounterInfo.Skip < 0)
return true;
- if (CounterPair.first != 0) {
- --CounterPair.first;
+ if (CounterInfo.Skip >= CounterInfo.Count)
return false;
- }
- if (CounterPair.second < 0)
- return true;
- if (CounterPair.second != 0) {
- --CounterPair.second;
+ if (CounterInfo.StopAfter < 0)
return true;
- }
- return false;
+ return CounterInfo.StopAfter + CounterInfo.Skip >= CounterInfo.Count;
}
// Didn't find the counter, should we warn?
return true;
@@ -104,21 +100,21 @@ public:
// the command line). This will return true even if those values are
// currently in a state where the counter will always execute.
static bool isCounterSet(unsigned ID) {
- return instance().Counters.count(ID);
+ return instance().Counters[ID].IsSet;
}
- // Return the skip and count for a counter. This only works for set counters.
- static std::pair<int, int> getCounterValue(unsigned ID) {
+ // Return the Count for a counter. This only works for set counters.
+ static int64_t getCounterValue(unsigned ID) {
auto &Us = instance();
auto Result = Us.Counters.find(ID);
assert(Result != Us.Counters.end() && "Asking about a non-set counter");
- return Result->second;
+ return Result->second.Count;
}
- // Set a registered counter to a given value.
- static void setCounterValue(unsigned ID, const std::pair<int, int> &Val) {
+ // Set a registered counter to a given Count value.
+ static void setCounterValue(unsigned ID, int64_t Count) {
auto &Us = instance();
- Us.Counters[ID] = Val;
+ Us.Counters[ID].Count = Count;
}
// Dump or print the current counter set into llvm::dbgs().
@@ -136,7 +132,7 @@ public:
// Return the name and description of the counter with the given ID.
std::pair<std::string, std::string> getCounterInfo(unsigned ID) const {
- return std::make_pair(RegisteredCounters[ID], CounterDesc.lookup(ID));
+ return std::make_pair(RegisteredCounters[ID], Counters.lookup(ID).Desc);
}
// Iterate through the registered counters
@@ -149,11 +145,19 @@ public:
private:
unsigned addCounter(const std::string &Name, const std::string &Desc) {
unsigned Result = RegisteredCounters.insert(Name);
- CounterDesc[Result] = Desc;
+ Counters[Result] = {};
+ Counters[Result].Desc = Desc;
return Result;
}
- DenseMap<unsigned, std::pair<long, long>> Counters;
- DenseMap<unsigned, std::string> CounterDesc;
+ // Struct to store counter info.
+ struct CounterInfo {
+ int64_t Count = 0;
+ int64_t Skip = 0;
+ int64_t StopAfter = -1;
+ bool IsSet = false;
+ std::string Desc;
+ };
+ DenseMap<unsigned, CounterInfo> Counters;
CounterVector RegisteredCounters;
};
diff --git a/contrib/llvm/include/llvm/Support/DynamicLibrary.h b/contrib/llvm/include/llvm/Support/DynamicLibrary.h
index 469d5dfad062..9563b483f6d5 100644
--- a/contrib/llvm/include/llvm/Support/DynamicLibrary.h
+++ b/contrib/llvm/include/llvm/Support/DynamicLibrary.h
@@ -64,7 +64,7 @@ namespace sys {
/// if the library fails to load.
///
/// It is safe to call this function multiple times for the same library.
- /// @brief Open a dynamic library permanently.
+ /// Open a dynamic library permanently.
static DynamicLibrary getPermanentLibrary(const char *filename,
std::string *errMsg = nullptr);
@@ -110,10 +110,10 @@ namespace sys {
/// search permanently loaded libraries (getPermanentLibrary()) as well
/// as explicitly registered symbols (AddSymbol()).
/// @throws std::string on error.
- /// @brief Search through libraries for address of a symbol
+ /// Search through libraries for address of a symbol
static void *SearchForAddressOfSymbol(const char *symbolName);
- /// @brief Convenience function for C++ophiles.
+ /// Convenience function for C++ophiles.
static void *SearchForAddressOfSymbol(const std::string &symbolName) {
return SearchForAddressOfSymbol(symbolName.c_str());
}
@@ -121,7 +121,7 @@ namespace sys {
/// This functions permanently adds the symbol \p symbolName with the
/// value \p symbolValue. These symbols are searched before any
/// libraries.
- /// @brief Add searchable symbol/value pair.
+ /// Add searchable symbol/value pair.
static void AddSymbol(StringRef symbolName, void *symbolValue);
class HandleSet;
diff --git a/contrib/llvm/include/llvm/Support/Endian.h b/contrib/llvm/include/llvm/Support/Endian.h
index f50d9b502daf..a4d3f4ff793d 100644
--- a/contrib/llvm/include/llvm/Support/Endian.h
+++ b/contrib/llvm/include/llvm/Support/Endian.h
@@ -34,7 +34,7 @@ enum {aligned = 0, unaligned = 1};
namespace detail {
-/// \brief ::value is either alignment, or alignof(T) if alignment is 0.
+/// ::value is either alignment, or alignof(T) if alignment is 0.
template<class T, int alignment>
struct PickAlignment {
enum { value = alignment == 0 ? alignof(T) : alignment };
diff --git a/contrib/llvm/include/llvm/Support/EndianStream.h b/contrib/llvm/include/llvm/Support/EndianStream.h
index 43ecd4a5c97e..9742e253ad3e 100644
--- a/contrib/llvm/include/llvm/Support/EndianStream.h
+++ b/contrib/llvm/include/llvm/Support/EndianStream.h
@@ -23,44 +23,44 @@ namespace llvm {
namespace support {
namespace endian {
-/// Adapter to write values to a stream in a particular byte order.
-template <endianness endian> struct Writer {
- raw_ostream &OS;
- Writer(raw_ostream &OS) : OS(OS) {}
- template <typename value_type> void write(ArrayRef<value_type> Vals) {
- for (value_type V : Vals)
- write(V);
- }
- template <typename value_type> void write(value_type Val) {
- Val = byte_swap<value_type, endian>(Val);
- OS.write((const char *)&Val, sizeof(value_type));
- }
-};
-template <>
-template <>
-inline void Writer<little>::write<float>(float Val) {
- write(FloatToBits(Val));
+template <typename value_type>
+inline void write(raw_ostream &os, value_type value, endianness endian) {
+ value = byte_swap<value_type>(value, endian);
+ os.write((const char *)&value, sizeof(value_type));
}
template <>
-template <>
-inline void Writer<little>::write<double>(double Val) {
- write(DoubleToBits(Val));
+inline void write<float>(raw_ostream &os, float value, endianness endian) {
+ write(os, FloatToBits(value), endian);
}
template <>
-template <>
-inline void Writer<big>::write<float>(float Val) {
- write(FloatToBits(Val));
+inline void write<double>(raw_ostream &os, double value,
+ endianness endian) {
+ write(os, DoubleToBits(value), endian);
}
-template <>
-template <>
-inline void Writer<big>::write<double>(double Val) {
- write(DoubleToBits(Val));
+template <typename value_type>
+inline void write(raw_ostream &os, ArrayRef<value_type> vals,
+ endianness endian) {
+ for (value_type v : vals)
+ write(os, v, endian);
}
+/// Adapter to write values to a stream in a particular byte order.
+struct Writer {
+ raw_ostream &OS;
+ endianness Endian;
+ Writer(raw_ostream &OS, endianness Endian) : OS(OS), Endian(Endian) {}
+ template <typename value_type> void write(ArrayRef<value_type> Val) {
+ endian::write(OS, Val, Endian);
+ }
+ template <typename value_type> void write(value_type Val) {
+ endian::write(OS, Val, Endian);
+ }
+};
+
} // end namespace endian
} // end namespace support
diff --git a/contrib/llvm/include/llvm/Support/Errc.h b/contrib/llvm/include/llvm/Support/Errc.h
index 80bfe2ac2ee5..dce42782a0d3 100644
--- a/contrib/llvm/include/llvm/Support/Errc.h
+++ b/contrib/llvm/include/llvm/Support/Errc.h
@@ -63,6 +63,7 @@ enum class errc {
no_such_process = int(std::errc::no_such_process),
not_a_directory = int(std::errc::not_a_directory),
not_enough_memory = int(std::errc::not_enough_memory),
+ not_supported = int(std::errc::not_supported),
operation_not_permitted = int(std::errc::operation_not_permitted),
permission_denied = int(std::errc::permission_denied),
read_only_file_system = int(std::errc::read_only_file_system),
diff --git a/contrib/llvm/include/llvm/Support/Errno.h b/contrib/llvm/include/llvm/Support/Errno.h
index 35dc1ea7cf84..8069c3639df3 100644
--- a/contrib/llvm/include/llvm/Support/Errno.h
+++ b/contrib/llvm/include/llvm/Support/Errno.h
@@ -34,9 +34,10 @@ template <typename FailT, typename Fun, typename... Args>
inline auto RetryAfterSignal(const FailT &Fail, const Fun &F,
const Args &... As) -> decltype(F(As...)) {
decltype(F(As...)) Res;
- do
+ do {
+ errno = 0;
Res = F(As...);
- while (Res == Fail && errno == EINTR);
+ } while (Res == Fail && errno == EINTR);
return Res;
}
diff --git a/contrib/llvm/include/llvm/Support/Error.h b/contrib/llvm/include/llvm/Support/Error.h
index 8567af392fb0..8015cab45a06 100644
--- a/contrib/llvm/include/llvm/Support/Error.h
+++ b/contrib/llvm/include/llvm/Support/Error.h
@@ -24,6 +24,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -302,6 +303,14 @@ private:
return Tmp;
}
+ friend raw_ostream &operator<<(raw_ostream &OS, const Error &E) {
+ if (auto P = E.getPtr())
+ P->log(OS);
+ else
+ OS << "success";
+ return OS;
+ }
+
ErrorInfoBase *Payload = nullptr;
};
@@ -421,7 +430,7 @@ template <class T> class LLVM_NODISCARD Expected {
static const bool isRef = std::is_reference<T>::value;
- using wrap = ReferenceStorage<typename std::remove_reference<T>::type>;
+ using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
using error_type = std::unique_ptr<ErrorInfoBase>;
@@ -505,7 +514,7 @@ public:
getErrorStorage()->~error_type();
}
- /// \brief Return false if there is an error.
+ /// Return false if there is an error.
explicit operator bool() {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
Unchecked = HasError;
@@ -513,24 +522,24 @@ public:
return !HasError;
}
- /// \brief Returns a reference to the stored T value.
+ /// Returns a reference to the stored T value.
reference get() {
assertIsChecked();
return *getStorage();
}
- /// \brief Returns a const reference to the stored T value.
+ /// Returns a const reference to the stored T value.
const_reference get() const {
assertIsChecked();
return const_cast<Expected<T> *>(this)->get();
}
- /// \brief Check that this Expected<T> is an error of type ErrT.
+ /// Check that this Expected<T> is an error of type ErrT.
template <typename ErrT> bool errorIsA() const {
return HasError && (*getErrorStorage())->template isA<ErrT>();
}
- /// \brief Take ownership of the stored error.
+ /// Take ownership of the stored error.
/// After calling this the Expected<T> is in an indeterminate state that can
/// only be safely destructed. No further calls (beside the destructor) should
/// be made on the Expected<T> vaule.
@@ -541,25 +550,25 @@ public:
return HasError ? Error(std::move(*getErrorStorage())) : Error::success();
}
- /// \brief Returns a pointer to the stored T value.
+ /// Returns a pointer to the stored T value.
pointer operator->() {
assertIsChecked();
return toPointer(getStorage());
}
- /// \brief Returns a const pointer to the stored T value.
+ /// Returns a const pointer to the stored T value.
const_pointer operator->() const {
assertIsChecked();
return toPointer(getStorage());
}
- /// \brief Returns a reference to the stored T value.
+ /// Returns a reference to the stored T value.
reference operator*() {
assertIsChecked();
return *getStorage();
}
- /// \brief Returns a const reference to the stored T value.
+ /// Returns a const reference to the stored T value.
const_reference operator*() const {
assertIsChecked();
return *getStorage();
@@ -882,16 +891,16 @@ Error handleErrors(Error E, HandlerTs &&... Hs) {
return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
}
-/// Behaves the same as handleErrors, except that it requires that all
-/// errors be handled by the given handlers. If any unhandled error remains
-/// after the handlers have run, report_fatal_error() will be called.
+/// Behaves the same as handleErrors, except that by contract all errors
+/// *must* be handled by the given handlers (i.e. there must be no remaining
+/// errors after running the handlers, or llvm_unreachable is called).
template <typename... HandlerTs>
void handleAllErrors(Error E, HandlerTs &&... Handlers) {
cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...));
}
/// Check that E is a non-error, then drop it.
-/// If E is an error report_fatal_error will be called.
+/// If E is an error, llvm_unreachable will be called.
inline void handleAllErrors(Error E) {
cantFail(std::move(E));
}
@@ -963,6 +972,18 @@ inline void consumeError(Error Err) {
handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
}
+/// Helper for converting an Error to a bool.
+///
+/// This method returns true if Err is in an error state, or false if it is
+/// in a success state. Puts Err in a checked state in both cases (unlike
+/// Error::operator bool(), which only does this for success states).
+inline bool errorToBool(Error Err) {
+ bool IsError = static_cast<bool>(Err);
+ if (IsError)
+ consumeError(std::move(Err));
+ return IsError;
+}
+
/// Helper for Errors used as out-parameters.
///
/// This helper is for use with the Error-as-out-parameter idiom, where an error
@@ -1101,6 +1122,18 @@ private:
std::error_code EC;
};
+/// Create formatted StringError object.
+template <typename... Ts>
+Error createStringError(std::error_code EC, char const *Fmt,
+ const Ts &... Vals) {
+ std::string Buffer;
+ raw_string_ostream Stream(Buffer);
+ Stream << format(Fmt, Vals...);
+ return make_error<StringError>(Stream.str(), EC);
+}
+
+Error createStringError(std::error_code EC, char const *Msg);
+
/// Helper for check-and-exit error handling.
///
/// For tool use only. NOT FOR USE IN LIBRARY CODE.
diff --git a/contrib/llvm/include/llvm/Support/ErrorHandling.h b/contrib/llvm/include/llvm/Support/ErrorHandling.h
index b45f6348390e..39cbfed2436a 100644
--- a/contrib/llvm/include/llvm/Support/ErrorHandling.h
+++ b/contrib/llvm/include/llvm/Support/ErrorHandling.h
@@ -100,6 +100,8 @@ void install_bad_alloc_error_handler(fatal_error_handler_t handler,
/// Restores default bad alloc error handling behavior.
void remove_bad_alloc_error_handler();
+void install_out_of_memory_new_handler();
+
/// Reports a bad alloc error, calling any user defined bad alloc
/// error handler. In contrast to the generic 'report_fatal_error'
/// functions, this function is expected to return, e.g. the user
@@ -110,7 +112,7 @@ void remove_bad_alloc_error_handler();
/// in the unwind chain.
///
/// If no error handler is installed (default), then a bad_alloc exception
-/// is thrown if LLVM is compiled with exception support, otherwise an assertion
+/// is thrown, if LLVM is compiled with exception support, otherwise an assertion
/// is called.
void report_bad_alloc_error(const char *Reason, bool GenCrashDiag = true);
diff --git a/contrib/llvm/include/llvm/Support/ErrorOr.h b/contrib/llvm/include/llvm/Support/ErrorOr.h
index 061fb65db465..e6ce764ad822 100644
--- a/contrib/llvm/include/llvm/Support/ErrorOr.h
+++ b/contrib/llvm/include/llvm/Support/ErrorOr.h
@@ -24,19 +24,7 @@
namespace llvm {
-/// \brief Stores a reference that can be changed.
-template <typename T>
-class ReferenceStorage {
- T *Storage;
-
-public:
- ReferenceStorage(T &Ref) : Storage(&Ref) {}
-
- operator T &() const { return *Storage; }
- T &get() const { return *Storage; }
-};
-
-/// \brief Represents either an error or a value T.
+/// Represents either an error or a value T.
///
/// ErrorOr<T> is a pointer-like class that represents the result of an
/// operation. The result is either an error, or a value of type T. This is
@@ -71,7 +59,7 @@ class ErrorOr {
static const bool isRef = std::is_reference<T>::value;
- using wrap = ReferenceStorage<typename std::remove_reference<T>::type>;
+ using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
public:
using storage_type = typename std::conditional<isRef, wrap, T>::type;
@@ -161,7 +149,7 @@ public:
getStorage()->~storage_type();
}
- /// \brief Return false if there is an error.
+ /// Return false if there is an error.
explicit operator bool() const {
return !HasError;
}
diff --git a/contrib/llvm/include/llvm/Support/FileOutputBuffer.h b/contrib/llvm/include/llvm/Support/FileOutputBuffer.h
index 6aed423a01e3..ee8cbb730878 100644
--- a/contrib/llvm/include/llvm/Support/FileOutputBuffer.h
+++ b/contrib/llvm/include/llvm/Support/FileOutputBuffer.h
@@ -30,13 +30,25 @@ namespace llvm {
/// not committed, the file will be deleted in the FileOutputBuffer destructor.
class FileOutputBuffer {
public:
- enum {
- F_executable = 1 /// set the 'x' bit on the resulting file
+ enum {
+ /// set the 'x' bit on the resulting file
+ F_executable = 1,
+
+ /// the contents of the new file are initialized from the file that exists
+ /// at the location (if present). This allows in-place modification of an
+ /// existing file.
+ F_modify = 2
};
/// Factory method to create an OutputBuffer object which manages a read/write
/// buffer of the specified size. When committed, the buffer will be written
/// to the file at the specified path.
+ ///
+ /// When F_modify is specified and \p FilePath refers to an existing on-disk
+ /// file \p Size may be set to -1, in which case the entire file is used.
+ /// Otherwise, the file shrinks or grows as necessary based on the value of
+ /// \p Size. It is an error to specify F_modify and Size=-1 if \p FilePath
+ /// does not exist.
static Expected<std::unique_ptr<FileOutputBuffer>>
create(StringRef FilePath, size_t Size, unsigned Flags = 0);
diff --git a/contrib/llvm/include/llvm/Support/FileSystem.h b/contrib/llvm/include/llvm/Support/FileSystem.h
index b1683ba5ddb3..02db4596bf1c 100644
--- a/contrib/llvm/include/llvm/Support/FileSystem.h
+++ b/contrib/llvm/include/llvm/Support/FileSystem.h
@@ -30,6 +30,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
@@ -53,6 +54,15 @@ namespace llvm {
namespace sys {
namespace fs {
+#if defined(_WIN32)
+// A Win32 HANDLE is a typedef of void*
+using file_t = void *;
+#else
+using file_t = int;
+#endif
+
+extern const file_t kInvalidFile;
+
/// An enumeration for the file system's view of the type.
enum class file_type {
status_error,
@@ -153,7 +163,7 @@ protected:
uid_t fs_st_uid = 0;
gid_t fs_st_gid = 0;
off_t fs_st_size = 0;
- #elif defined (LLVM_ON_WIN32)
+ #elif defined (_WIN32)
uint32_t LastAccessedTimeHigh = 0;
uint32_t LastAccessedTimeLow = 0;
uint32_t LastWriteTimeHigh = 0;
@@ -174,7 +184,7 @@ public:
uid_t UID, gid_t GID, off_t Size)
: fs_st_atime(ATime), fs_st_mtime(MTime), fs_st_uid(UID), fs_st_gid(GID),
fs_st_size(Size), Type(Type), Perms(Perms) {}
-#elif defined(LLVM_ON_WIN32)
+#elif defined(_WIN32)
basic_file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh,
uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
uint32_t LastWriteTimeLow, uint32_t FileSizeHigh,
@@ -196,7 +206,7 @@ public:
uint32_t getUser() const { return fs_st_uid; }
uint32_t getGroup() const { return fs_st_gid; }
uint64_t getSize() const { return fs_st_size; }
- #elif defined (LLVM_ON_WIN32)
+ #elif defined (_WIN32)
uint32_t getUser() const {
return 9999; // Not applicable to Windows, so...
}
@@ -223,7 +233,7 @@ class file_status : public basic_file_status {
dev_t fs_st_dev = 0;
nlink_t fs_st_nlinks = 0;
ino_t fs_st_ino = 0;
- #elif defined (LLVM_ON_WIN32)
+ #elif defined (_WIN32)
uint32_t NumLinks = 0;
uint32_t VolumeSerialNumber = 0;
uint32_t FileIndexHigh = 0;
@@ -240,7 +250,7 @@ public:
time_t ATime, time_t MTime, uid_t UID, gid_t GID, off_t Size)
: basic_file_status(Type, Perms, ATime, MTime, UID, GID, Size),
fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {}
- #elif defined(LLVM_ON_WIN32)
+ #elif defined(_WIN32)
file_status(file_type Type, perms Perms, uint32_t LinkCount,
uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow,
uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow,
@@ -262,7 +272,7 @@ public:
/// @name Physical Operators
/// @{
-/// @brief Make \a path an absolute path.
+/// Make \a path an absolute path.
///
/// Makes \a path absolute using the \a current_directory if it is not already.
/// An empty \a path will result in the \a current_directory.
@@ -276,7 +286,7 @@ public:
std::error_code make_absolute(const Twine &current_directory,
SmallVectorImpl<char> &path);
-/// @brief Make \a path an absolute path.
+/// Make \a path an absolute path.
///
/// Makes \a path absolute using the current directory if it is not already. An
/// empty \a path will result in the current directory.
@@ -289,7 +299,7 @@ std::error_code make_absolute(const Twine &current_directory,
/// platform-specific error_code.
std::error_code make_absolute(SmallVectorImpl<char> &path);
-/// @brief Create all the non-existent directories in path.
+/// Create all the non-existent directories in path.
///
/// @param path Directories to create.
/// @returns errc::success if is_directory(path), otherwise a platform
@@ -299,7 +309,7 @@ std::error_code create_directories(const Twine &path,
bool IgnoreExisting = true,
perms Perms = owner_all | group_all);
-/// @brief Create the directory in path.
+/// Create the directory in path.
///
/// @param path Directory to create.
/// @returns errc::success if is_directory(path), otherwise a platform
@@ -308,7 +318,7 @@ std::error_code create_directories(const Twine &path,
std::error_code create_directory(const Twine &path, bool IgnoreExisting = true,
perms Perms = owner_all | group_all);
-/// @brief Create a link from \a from to \a to.
+/// Create a link from \a from to \a to.
///
/// The link may be a soft or a hard link, depending on the platform. The caller
/// may not assume which one. Currently on windows it creates a hard link since
@@ -329,7 +339,7 @@ std::error_code create_link(const Twine &to, const Twine &from);
/// specific error_code.
std::error_code create_hard_link(const Twine &to, const Twine &from);
-/// @brief Collapse all . and .. patterns, resolve all symlinks, and optionally
+/// Collapse all . and .. patterns, resolve all symlinks, and optionally
/// expand ~ expressions to the user's home directory.
///
/// @param path The path to resolve.
@@ -339,21 +349,21 @@ std::error_code create_hard_link(const Twine &to, const Twine &from);
std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output,
bool expand_tilde = false);
-/// @brief Get the current path.
+/// Get the current path.
///
/// @param result Holds the current path on return.
/// @returns errc::success if the current path has been stored in result,
/// otherwise a platform-specific error_code.
std::error_code current_path(SmallVectorImpl<char> &result);
-/// @brief Set the current path.
+/// Set the current path.
///
/// @param path The path to set.
/// @returns errc::success if the current path was successfully set,
/// otherwise a platform-specific error_code.
std::error_code set_current_path(const Twine &path);
-/// @brief Remove path. Equivalent to POSIX remove().
+/// Remove path. Equivalent to POSIX remove().
///
/// @param path Input path.
/// @returns errc::success if path has been removed or didn't exist, otherwise a
@@ -361,14 +371,14 @@ std::error_code set_current_path(const Twine &path);
/// returns error if the file didn't exist.
std::error_code remove(const Twine &path, bool IgnoreNonExisting = true);
-/// @brief Recursively delete a directory.
+/// Recursively delete a directory.
///
/// @param path Input path.
/// @returns errc::success if path has been removed or didn't exist, otherwise a
/// platform-specific error code.
std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true);
-/// @brief Rename \a from to \a to.
+/// Rename \a from to \a to.
///
/// Files are renamed as if by POSIX rename(), except that on Windows there may
/// be a short interval of time during which the destination file does not
@@ -378,13 +388,19 @@ std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true);
/// @param to The path to rename to. This is created.
std::error_code rename(const Twine &from, const Twine &to);
-/// @brief Copy the contents of \a From to \a To.
+/// Copy the contents of \a From to \a To.
///
/// @param From The path to copy from.
/// @param To The path to copy to. This is created.
std::error_code copy_file(const Twine &From, const Twine &To);
-/// @brief Resize path to size. File is resized as if by POSIX truncate().
+/// Copy the contents of \a From to \a To.
+///
+/// @param From The path to copy from.
+/// @param ToFD The open file descriptor of the destination file.
+std::error_code copy_file(const Twine &From, int ToFD);
+
+/// Resize path to size. File is resized as if by POSIX truncate().
///
/// @param FD Input file descriptor.
/// @param Size Size to resize to.
@@ -392,21 +408,21 @@ std::error_code copy_file(const Twine &From, const Twine &To);
/// platform-specific error_code.
std::error_code resize_file(int FD, uint64_t Size);
-/// @brief Compute an MD5 hash of a file's contents.
+/// Compute an MD5 hash of a file's contents.
///
/// @param FD Input file descriptor.
/// @returns An MD5Result with the hash computed, if successful, otherwise a
/// std::error_code.
ErrorOr<MD5::MD5Result> md5_contents(int FD);
-/// @brief Version of compute_md5 that doesn't require an open file descriptor.
+/// Version of compute_md5 that doesn't require an open file descriptor.
ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path);
/// @}
/// @name Physical Observers
/// @{
-/// @brief Does file exist?
+/// Does file exist?
///
/// @param status A basic_file_status previously returned from stat.
/// @returns True if the file represented by status exists, false if it does
@@ -415,14 +431,14 @@ bool exists(const basic_file_status &status);
enum class AccessMode { Exist, Write, Execute };
-/// @brief Can the file be accessed?
+/// Can the file be accessed?
///
/// @param Path Input path.
/// @returns errc::success if the path can be accessed, otherwise a
/// platform-specific error_code.
std::error_code access(const Twine &Path, AccessMode Mode);
-/// @brief Does file exist?
+/// Does file exist?
///
/// @param Path Input path.
/// @returns True if it exists, false otherwise.
@@ -430,13 +446,13 @@ inline bool exists(const Twine &Path) {
return !access(Path, AccessMode::Exist);
}
-/// @brief Can we execute this file?
+/// Can we execute this file?
///
/// @param Path Input path.
/// @returns True if we can execute it, false otherwise.
bool can_execute(const Twine &Path);
-/// @brief Can we write this file?
+/// Can we write this file?
///
/// @param Path Input path.
/// @returns True if we can write to it, false otherwise.
@@ -444,7 +460,7 @@ inline bool can_write(const Twine &Path) {
return !access(Path, AccessMode::Write);
}
-/// @brief Do file_status's represent the same thing?
+/// Do file_status's represent the same thing?
///
/// @param A Input file_status.
/// @param B Input file_status.
@@ -455,7 +471,7 @@ inline bool can_write(const Twine &Path) {
/// otherwise.
bool equivalent(file_status A, file_status B);
-/// @brief Do paths represent the same thing?
+/// Do paths represent the same thing?
///
/// assert(status_known(A) || status_known(B));
///
@@ -467,14 +483,14 @@ bool equivalent(file_status A, file_status B);
/// platform-specific error_code.
std::error_code equivalent(const Twine &A, const Twine &B, bool &result);
-/// @brief Simpler version of equivalent for clients that don't need to
+/// Simpler version of equivalent for clients that don't need to
/// differentiate between an error and false.
inline bool equivalent(const Twine &A, const Twine &B) {
bool result;
return !equivalent(A, B, result) && result;
}
-/// @brief Is the file mounted on a local filesystem?
+/// Is the file mounted on a local filesystem?
///
/// @param path Input path.
/// @param result Set to true if \a path is on fixed media such as a hard disk,
@@ -483,24 +499,24 @@ inline bool equivalent(const Twine &A, const Twine &B) {
/// platform specific error_code.
std::error_code is_local(const Twine &path, bool &result);
-/// @brief Version of is_local accepting an open file descriptor.
+/// Version of is_local accepting an open file descriptor.
std::error_code is_local(int FD, bool &result);
-/// @brief Simpler version of is_local for clients that don't need to
+/// Simpler version of is_local for clients that don't need to
/// differentiate between an error and false.
inline bool is_local(const Twine &Path) {
bool Result;
return !is_local(Path, Result) && Result;
}
-/// @brief Simpler version of is_local accepting an open file descriptor for
+/// Simpler version of is_local accepting an open file descriptor for
/// clients that don't need to differentiate between an error and false.
inline bool is_local(int FD) {
bool Result;
return !is_local(FD, Result) && Result;
}
-/// @brief Does status represent a directory?
+/// Does status represent a directory?
///
/// @param Path The path to get the type of.
/// @param Follow For symbolic links, indicates whether to return the file type
@@ -508,13 +524,13 @@ inline bool is_local(int FD) {
/// @returns A value from the file_type enumeration indicating the type of file.
file_type get_file_type(const Twine &Path, bool Follow = true);
-/// @brief Does status represent a directory?
+/// Does status represent a directory?
///
/// @param status A basic_file_status previously returned from status.
/// @returns status.type() == file_type::directory_file.
bool is_directory(const basic_file_status &status);
-/// @brief Is path a directory?
+/// Is path a directory?
///
/// @param path Input path.
/// @param result Set to true if \a path is a directory (after following
@@ -523,20 +539,20 @@ bool is_directory(const basic_file_status &status);
/// platform-specific error_code.
std::error_code is_directory(const Twine &path, bool &result);
-/// @brief Simpler version of is_directory for clients that don't need to
+/// Simpler version of is_directory for clients that don't need to
/// differentiate between an error and false.
inline bool is_directory(const Twine &Path) {
bool Result;
return !is_directory(Path, Result) && Result;
}
-/// @brief Does status represent a regular file?
+/// Does status represent a regular file?
///
/// @param status A basic_file_status previously returned from status.
/// @returns status_known(status) && status.type() == file_type::regular_file.
bool is_regular_file(const basic_file_status &status);
-/// @brief Is path a regular file?
+/// Is path a regular file?
///
/// @param path Input path.
/// @param result Set to true if \a path is a regular file (after following
@@ -545,7 +561,7 @@ bool is_regular_file(const basic_file_status &status);
/// platform-specific error_code.
std::error_code is_regular_file(const Twine &path, bool &result);
-/// @brief Simpler version of is_regular_file for clients that don't need to
+/// Simpler version of is_regular_file for clients that don't need to
/// differentiate between an error and false.
inline bool is_regular_file(const Twine &Path) {
bool Result;
@@ -554,13 +570,13 @@ inline bool is_regular_file(const Twine &Path) {
return Result;
}
-/// @brief Does status represent a symlink file?
+/// Does status represent a symlink file?
///
/// @param status A basic_file_status previously returned from status.
/// @returns status_known(status) && status.type() == file_type::symlink_file.
bool is_symlink_file(const basic_file_status &status);
-/// @brief Is path a symlink file?
+/// Is path a symlink file?
///
/// @param path Input path.
/// @param result Set to true if \a path is a symlink file, false if it is not.
@@ -569,7 +585,7 @@ bool is_symlink_file(const basic_file_status &status);
/// platform-specific error_code.
std::error_code is_symlink_file(const Twine &path, bool &result);
-/// @brief Simpler version of is_symlink_file for clients that don't need to
+/// Simpler version of is_symlink_file for clients that don't need to
/// differentiate between an error and false.
inline bool is_symlink_file(const Twine &Path) {
bool Result;
@@ -578,14 +594,14 @@ inline bool is_symlink_file(const Twine &Path) {
return Result;
}
-/// @brief Does this status represent something that exists but is not a
+/// Does this status represent something that exists but is not a
/// directory or regular file?
///
/// @param status A basic_file_status previously returned from status.
/// @returns exists(s) && !is_regular_file(s) && !is_directory(s)
bool is_other(const basic_file_status &status);
-/// @brief Is path something that exists but is not a directory,
+/// Is path something that exists but is not a directory,
/// regular file, or symlink?
///
/// @param path Input path.
@@ -595,7 +611,7 @@ bool is_other(const basic_file_status &status);
/// platform-specific error_code.
std::error_code is_other(const Twine &path, bool &result);
-/// @brief Get file status as if by POSIX stat().
+/// Get file status as if by POSIX stat().
///
/// @param path Input path.
/// @param result Set to the file status.
@@ -606,10 +622,10 @@ std::error_code is_other(const Twine &path, bool &result);
std::error_code status(const Twine &path, file_status &result,
bool follow = true);
-/// @brief A version for when a file descriptor is already available.
+/// A version for when a file descriptor is already available.
std::error_code status(int FD, file_status &Result);
-/// @brief Set file permissions.
+/// Set file permissions.
///
/// @param Path File to set permissions on.
/// @param Permissions New file permissions.
@@ -620,7 +636,7 @@ std::error_code status(int FD, file_status &Result);
/// Otherwise, the file will be marked as read-only.
std::error_code setPermissions(const Twine &Path, perms Permissions);
-/// @brief Get file permissions.
+/// Get file permissions.
///
/// @param Path File to get permissions from.
/// @returns the permissions if they were successfully retrieved, otherwise a
@@ -630,7 +646,7 @@ std::error_code setPermissions(const Twine &Path, perms Permissions);
/// will be returned.
ErrorOr<perms> getPermissions(const Twine &Path);
-/// @brief Get file size.
+/// Get file size.
///
/// @param Path Input path.
/// @param Result Set to the size of the file in \a Path.
@@ -645,20 +661,20 @@ inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
return std::error_code();
}
-/// @brief Set the file modification and access time.
+/// Set the file modification and access time.
///
/// @returns errc::success if the file times were successfully set, otherwise a
/// platform-specific error_code or errc::function_not_supported on
/// platforms where the functionality isn't available.
std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time);
-/// @brief Is status available?
+/// Is status available?
///
/// @param s Input file status.
/// @returns True if status() != status_error.
bool status_known(const basic_file_status &s);
-/// @brief Is status available?
+/// Is status available?
///
/// @param path Input path.
/// @param result Set to true if status() != status_error.
@@ -666,30 +682,58 @@ bool status_known(const basic_file_status &s);
/// platform-specific error_code.
std::error_code status_known(const Twine &path, bool &result);
-enum OpenFlags : unsigned {
- F_None = 0,
+enum CreationDisposition : unsigned {
+ /// CD_CreateAlways - When opening a file:
+ /// * If it already exists, truncate it.
+ /// * If it does not already exist, create a new file.
+ CD_CreateAlways = 0,
+
+ /// CD_CreateNew - When opening a file:
+ /// * If it already exists, fail.
+ /// * If it does not already exist, create a new file.
+ CD_CreateNew = 1,
+
+ /// CD_OpenAlways - When opening a file:
+ /// * If it already exists, open the file with the offset set to 0.
+ /// * If it does not already exist, fail.
+ CD_OpenExisting = 2,
- /// F_Excl - When opening a file, this flag makes raw_fd_ostream
- /// report an error if the file already exists.
- F_Excl = 1,
+ /// CD_OpenAlways - When opening a file:
+ /// * If it already exists, open the file with the offset set to 0.
+ /// * If it does not already exist, create a new file.
+ CD_OpenAlways = 3,
+};
- /// F_Append - When opening a file, if it already exists append to the
- /// existing file instead of returning an error. This may not be specified
- /// with F_Excl.
- F_Append = 2,
+enum FileAccess : unsigned {
+ FA_Read = 1,
+ FA_Write = 2,
+};
+
+enum OpenFlags : unsigned {
+ OF_None = 0,
+ F_None = 0, // For compatibility
/// The file should be opened in text mode on platforms that make this
/// distinction.
- F_Text = 4,
+ OF_Text = 1,
+ F_Text = 1, // For compatibility
- /// Open the file for read and write.
- F_RW = 8,
+ /// The file should be opened in append mode.
+ OF_Append = 2,
+ F_Append = 2, // For compatibility
/// Delete the file on close. Only makes a difference on windows.
- F_Delete = 16
+ OF_Delete = 4,
+
+ /// When a child process is launched, this file should remain open in the
+ /// child process.
+ OF_ChildInherit = 8,
+
+ /// Force files Atime to be updated on access. Only makes a difference on windows.
+ OF_UpdateAtime = 16,
};
-/// @brief Create a uniquely named file.
+/// Create a uniquely named file.
///
/// Generates a unique path suitable for a temporary file and then opens it as a
/// file. The name is based on \a model with '%' replaced by a random char in
@@ -712,12 +756,13 @@ enum OpenFlags : unsigned {
/// otherwise a platform-specific error_code.
std::error_code createUniqueFile(const Twine &Model, int &ResultFD,
SmallVectorImpl<char> &ResultPath,
- unsigned Mode = all_read | all_write,
- sys::fs::OpenFlags Flags = sys::fs::F_RW);
+ unsigned Mode = all_read | all_write);
-/// @brief Simpler version for clients that don't want an open file.
+/// Simpler version for clients that don't want an open file. An empty
+/// file will still be created.
std::error_code createUniqueFile(const Twine &Model,
- SmallVectorImpl<char> &ResultPath);
+ SmallVectorImpl<char> &ResultPath,
+ unsigned Mode = all_read | all_write);
/// Represents a temporary file.
///
@@ -757,7 +802,7 @@ public:
~TempFile();
};
-/// @brief Create a file in the system temporary directory.
+/// Create a file in the system temporary directory.
///
/// The filename is of the form prefix-random_chars.suffix. Since the directory
/// is not know to the caller, Prefix and Suffix cannot have path separators.
@@ -767,16 +812,38 @@ public:
/// running the assembler.
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
int &ResultFD,
- SmallVectorImpl<char> &ResultPath,
- sys::fs::OpenFlags Flags = sys::fs::F_RW);
+ SmallVectorImpl<char> &ResultPath);
-/// @brief Simpler version for clients that don't want an open file.
+/// Simpler version for clients that don't want an open file. An empty
+/// file will still be created.
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
SmallVectorImpl<char> &ResultPath);
std::error_code createUniqueDirectory(const Twine &Prefix,
SmallVectorImpl<char> &ResultPath);
+/// Get a unique name, not currently exisiting in the filesystem. Subject
+/// to race conditions, prefer to use createUniqueFile instead.
+///
+/// Similar to createUniqueFile, but instead of creating a file only
+/// checks if it exists. This function is subject to race conditions, if you
+/// want to use the returned name to actually create a file, use
+/// createUniqueFile instead.
+std::error_code getPotentiallyUniqueFileName(const Twine &Model,
+ SmallVectorImpl<char> &ResultPath);
+
+/// Get a unique temporary file name, not currently exisiting in the
+/// filesystem. Subject to race conditions, prefer to use createTemporaryFile
+/// instead.
+///
+/// Similar to createTemporaryFile, but instead of creating a file only
+/// checks if it exists. This function is subject to race conditions, if you
+/// want to use the returned name to actually create a file, use
+/// createTemporaryFile instead.
+std::error_code
+getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
+ SmallVectorImpl<char> &ResultPath);
+
inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
return OpenFlags(unsigned(A) | unsigned(B));
}
@@ -786,15 +853,181 @@ inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
return A;
}
-std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
- OpenFlags Flags, unsigned Mode = 0666);
+inline FileAccess operator|(FileAccess A, FileAccess B) {
+ return FileAccess(unsigned(A) | unsigned(B));
+}
+inline FileAccess &operator|=(FileAccess &A, FileAccess B) {
+ A = A | B;
+ return A;
+}
+
+/// @brief Opens a file with the specified creation disposition, access mode,
+/// and flags and returns a file descriptor.
+///
+/// The caller is responsible for closing the file descriptor once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param ResultFD If the file could be opened successfully, its descriptor
+/// is stored in this location. Otherwise, this is set to -1.
+/// @param Disp Value specifying the existing-file behavior.
+/// @param Access Value specifying whether to open the file in read, write, or
+/// read-write mode.
+/// @param Flags Additional flags.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+std::error_code openFile(const Twine &Name, int &ResultFD,
+ CreationDisposition Disp, FileAccess Access,
+ OpenFlags Flags, unsigned Mode = 0666);
+
+/// @brief Opens a file with the specified creation disposition, access mode,
+/// and flags and returns a platform-specific file object.
+///
+/// The caller is responsible for closing the file object once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param Disp Value specifying the existing-file behavior.
+/// @param Access Value specifying whether to open the file in read, write, or
+/// read-write mode.
+/// @param Flags Additional flags.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp,
+ FileAccess Access, OpenFlags Flags,
+ unsigned Mode = 0666);
+
+/// @brief Opens the file with the given name in a write-only or read-write
+/// mode, returning its open file descriptor. If the file does not exist, it
+/// is created.
+///
+/// The caller is responsible for closing the file descriptor once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param ResultFD If the file could be opened successfully, its descriptor
+/// is stored in this location. Otherwise, this is set to -1.
+/// @param Flags Additional flags used to determine whether the file should be
+/// opened in, for example, read-write or in write-only mode.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+inline std::error_code
+openFileForWrite(const Twine &Name, int &ResultFD,
+ CreationDisposition Disp = CD_CreateAlways,
+ OpenFlags Flags = OF_None, unsigned Mode = 0666) {
+ return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode);
+}
+
+/// @brief Opens the file with the given name in a write-only or read-write
+/// mode, returning its open file descriptor. If the file does not exist, it
+/// is created.
+///
+/// The caller is responsible for closing the freeing the file once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param Flags Additional flags used to determine whether the file should be
+/// opened in, for example, read-write or in write-only mode.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns a platform-specific file descriptor if \a Name has been opened,
+/// otherwise an error object.
+inline Expected<file_t> openNativeFileForWrite(const Twine &Name,
+ CreationDisposition Disp,
+ OpenFlags Flags,
+ unsigned Mode = 0666) {
+ return openNativeFile(Name, Disp, FA_Write, Flags, Mode);
+}
+
+/// @brief Opens the file with the given name in a write-only or read-write
+/// mode, returning its open file descriptor. If the file does not exist, it
+/// is created.
+///
+/// The caller is responsible for closing the file descriptor once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param ResultFD If the file could be opened successfully, its descriptor
+/// is stored in this location. Otherwise, this is set to -1.
+/// @param Flags Additional flags used to determine whether the file should be
+/// opened in, for example, read-write or in write-only mode.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+inline std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
+ CreationDisposition Disp,
+ OpenFlags Flags,
+ unsigned Mode = 0666) {
+ return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode);
+}
+
+/// @brief Opens the file with the given name in a write-only or read-write
+/// mode, returning its open file descriptor. If the file does not exist, it
+/// is created.
+///
+/// The caller is responsible for closing the freeing the file once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param Flags Additional flags used to determine whether the file should be
+/// opened in, for example, read-write or in write-only mode.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns a platform-specific file descriptor if \a Name has been opened,
+/// otherwise an error object.
+inline Expected<file_t> openNativeFileForReadWrite(const Twine &Name,
+ CreationDisposition Disp,
+ OpenFlags Flags,
+ unsigned Mode = 0666) {
+ return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode);
+}
+
+/// @brief Opens the file with the given name in a read-only mode, returning
+/// its open file descriptor.
+///
+/// The caller is responsible for closing the file descriptor once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param ResultFD If the file could be opened successfully, its descriptor
+/// is stored in this location. Otherwise, this is set to -1.
+/// @param RealPath If nonnull, extra work is done to determine the real path
+/// of the opened file, and that path is stored in this
+/// location.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+ OpenFlags Flags = OF_None,
SmallVectorImpl<char> *RealPath = nullptr);
+/// @brief Opens the file with the given name in a read-only mode, returning
+/// its open file descriptor.
+///
+/// The caller is responsible for closing the freeing the file once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param RealPath If nonnull, extra work is done to determine the real path
+/// of the opened file, and that path is stored in this
+/// location.
+/// @returns a platform-specific file descriptor if \a Name has been opened,
+/// otherwise an error object.
+Expected<file_t>
+openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None,
+ SmallVectorImpl<char> *RealPath = nullptr);
+
+/// @brief Close the file object. This should be used instead of ::close for
+/// portability.
+///
+/// @param F On input, this is the file to close. On output, the file is
+/// set to kInvalidFile.
+void closeFile(file_t &F);
+
std::error_code getUniqueID(const Twine Path, UniqueID &Result);
-/// @brief Get disk space usage information.
+/// Get disk space usage information.
///
/// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug.
/// Note: Windows reports results according to the quota allocated to the user.
@@ -819,6 +1052,10 @@ private:
/// Platform-specific mapping state.
size_t Size;
void *Mapping;
+#ifdef _WIN32
+ void *FileHandle;
+#endif
+ mapmode Mode;
std::error_code init(int FD, uint64_t Offset, mapmode Mode);
@@ -924,14 +1161,16 @@ public:
SmallString<128> path_storage;
ec = detail::directory_iterator_construct(
*State, path.toStringRef(path_storage), FollowSymlinks);
+ update_error_code_for_current_entry(ec);
}
explicit directory_iterator(const directory_entry &de, std::error_code &ec,
bool follow_symlinks = true)
: FollowSymlinks(follow_symlinks) {
State = std::make_shared<detail::DirIterState>();
- ec =
- detail::directory_iterator_construct(*State, de.path(), FollowSymlinks);
+ ec = detail::directory_iterator_construct(
+ *State, de.path(), FollowSymlinks);
+ update_error_code_for_current_entry(ec);
}
/// Construct end iterator.
@@ -940,6 +1179,7 @@ public:
// No operator++ because we need error_code.
directory_iterator &increment(std::error_code &ec) {
ec = directory_iterator_increment(*State);
+ update_error_code_for_current_entry(ec);
return *this;
}
@@ -961,6 +1201,24 @@ public:
}
// Other members as required by
// C++ Std, 24.1.1 Input iterators [input.iterators]
+
+private:
+ // Checks if current entry is valid and populates error code. For example,
+ // current entry may not exist due to broken symbol links.
+ void update_error_code_for_current_entry(std::error_code &ec) {
+ // Bail out if error has already occured earlier to avoid overwriting it.
+ if (ec)
+ return;
+
+ // Empty directory entry is used to mark the end of an interation, it's not
+ // an error.
+ if (State->CurrentEntry == directory_entry())
+ return;
+
+ ErrorOr<basic_file_status> status = State->CurrentEntry.status();
+ if (!status)
+ ec = status.getError();
+ }
};
namespace detail {
@@ -998,11 +1256,9 @@ public:
if (State->HasNoPushRequest)
State->HasNoPushRequest = false;
else {
- ErrorOr<basic_file_status> st = State->Stack.top()->status();
- if (!st) return *this;
- if (is_directory(*st)) {
+ ErrorOr<basic_file_status> status = State->Stack.top()->status();
+ if (status && is_directory(*status)) {
State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
- if (ec) return *this;
if (State->Stack.top() != end_itr) {
++State->Level;
return *this;
diff --git a/contrib/llvm/include/llvm/Support/FormatAdapters.h b/contrib/llvm/include/llvm/Support/FormatAdapters.h
index 197beb7363df..8320eaad39a9 100644
--- a/contrib/llvm/include/llvm/Support/FormatAdapters.h
+++ b/contrib/llvm/include/llvm/Support/FormatAdapters.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FormatCommon.h"
#include "llvm/Support/FormatVariadicDetails.h"
#include "llvm/Support/raw_ostream.h"
@@ -19,7 +20,7 @@
namespace llvm {
template <typename T> class FormatAdapter : public detail::format_adapter {
protected:
- explicit FormatAdapter(T &&Item) : Item(Item) {}
+ explicit FormatAdapter(T &&Item) : Item(std::forward<T>(Item)) {}
T Item;
};
@@ -71,6 +72,14 @@ public:
}
}
};
+
+class ErrorAdapter : public FormatAdapter<Error> {
+public:
+ ErrorAdapter(Error &&Item) : FormatAdapter(std::move(Item)) {}
+ ErrorAdapter(ErrorAdapter &&) = default;
+ ~ErrorAdapter() { consumeError(std::move(Item)); }
+ void format(llvm::raw_ostream &Stream, StringRef Style) { Stream << Item; }
+};
}
template <typename T>
@@ -88,6 +97,13 @@ template <typename T>
detail::RepeatAdapter<T> fmt_repeat(T &&Item, size_t Count) {
return detail::RepeatAdapter<T>(std::forward<T>(Item), Count);
}
+
+// llvm::Error values must be consumed before being destroyed.
+// Wrapping an error in fmt_consume explicitly indicates that the formatv_object
+// should take ownership and consume it.
+inline detail::ErrorAdapter fmt_consume(Error &&Item) {
+ return detail::ErrorAdapter(std::move(Item));
+}
}
#endif
diff --git a/contrib/llvm/include/llvm/Support/FormatVariadic.h b/contrib/llvm/include/llvm/Support/FormatVariadic.h
index 8c08a7d9488f..b0f582513e07 100644
--- a/contrib/llvm/include/llvm/Support/FormatVariadic.h
+++ b/contrib/llvm/include/llvm/Support/FormatVariadic.h
@@ -118,7 +118,7 @@ public:
auto W = Adapters[R.Index];
- FmtAlign Align(*W, R.Where, R.Align);
+ FmtAlign Align(*W, R.Where, R.Align, R.Pad);
Align.format(S, R.Options);
}
}
@@ -168,7 +168,7 @@ public:
}
};
-// \brief Format text given a format string and replacement parameters.
+// Format text given a format string and replacement parameters.
//
// ===General Description===
//
@@ -237,6 +237,8 @@ public:
// for type T containing a method whose signature is:
// void format(const T &Obj, raw_ostream &Stream, StringRef Options)
// Then this method is invoked as described in Step 1.
+// 3. If an appropriate operator<< for raw_ostream exists, it will be used.
+// For this to work, (raw_ostream& << const T&) must return raw_ostream&.
//
// If a match cannot be found through either of the above methods, a compiler
// error is generated.
@@ -258,13 +260,6 @@ inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object<decltype(
std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
}
-// Allow a formatv_object to be formatted (no options supported).
-template <typename T> struct format_provider<formatv_object<T>> {
- static void format(const formatv_object<T> &V, raw_ostream &OS, StringRef) {
- OS << V;
- }
-};
-
} // end namespace llvm
#endif // LLVM_SUPPORT_FORMATVARIADIC_H
diff --git a/contrib/llvm/include/llvm/Support/FormatVariadicDetails.h b/contrib/llvm/include/llvm/Support/FormatVariadicDetails.h
index 9b60462209dc..56dda430efda 100644
--- a/contrib/llvm/include/llvm/Support/FormatVariadicDetails.h
+++ b/contrib/llvm/include/llvm/Support/FormatVariadicDetails.h
@@ -17,6 +17,7 @@
namespace llvm {
template <typename T, typename Enable = void> struct format_provider {};
+class Error;
namespace detail {
class format_adapter {
@@ -38,6 +39,17 @@ public:
}
};
+template <typename T>
+class stream_operator_format_adapter : public format_adapter {
+ T Item;
+
+public:
+ explicit stream_operator_format_adapter(T &&Item)
+ : Item(std::forward<T>(Item)) {}
+
+ void format(llvm::raw_ostream &S, StringRef Options) override { S << Item; }
+};
+
template <typename T> class missing_format_adapter;
// Test if format_provider<T> is defined on T and contains a member function
@@ -59,6 +71,23 @@ public:
(sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1);
};
+// Test if raw_ostream& << T -> raw_ostream& is findable via ADL.
+template <class T> class has_StreamOperator {
+public:
+ using ConstRefT = const typename std::decay<T>::type &;
+
+ template <typename U>
+ static char test(typename std::enable_if<
+ std::is_same<decltype(std::declval<llvm::raw_ostream &>()
+ << std::declval<U>()),
+ llvm::raw_ostream &>::value,
+ int *>::type);
+
+ template <typename U> static double test(...);
+
+ static bool const value = (sizeof(test<ConstRefT>(nullptr)) == 1);
+};
+
// Simple template that decides whether a type T should use the member-function
// based format() invocation.
template <typename T>
@@ -77,15 +106,24 @@ struct uses_format_provider
bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> {
};
+// Simple template that decides whether a type T should use the operator<<
+// based format() invocation. This takes last priority.
+template <typename T>
+struct uses_stream_operator
+ : public std::integral_constant<bool, !uses_format_member<T>::value &&
+ !uses_format_provider<T>::value &&
+ has_StreamOperator<T>::value> {};
+
// Simple template that decides whether a type T has neither a member-function
// nor format_provider based implementation that it can use. Mostly used so
// that the compiler spits out a nice diagnostic when a type with no format
// implementation can be located.
template <typename T>
struct uses_missing_provider
- : public std::integral_constant<bool,
- !uses_format_member<T>::value &&
- !uses_format_provider<T>::value> {};
+ : public std::integral_constant<bool, !uses_format_member<T>::value &&
+ !uses_format_provider<T>::value &&
+ !uses_stream_operator<T>::value> {
+};
template <typename T>
typename std::enable_if<uses_format_member<T>::value, T>::type
@@ -101,6 +139,19 @@ build_format_adapter(T &&Item) {
}
template <typename T>
+typename std::enable_if<uses_stream_operator<T>::value,
+ stream_operator_format_adapter<T>>::type
+build_format_adapter(T &&Item) {
+ // If the caller passed an Error by value, then stream_operator_format_adapter
+ // would be responsible for consuming it.
+ // Make the caller opt into this by calling fmt_consume().
+ static_assert(
+ !std::is_same<llvm::Error, typename std::remove_cv<T>::type>::value,
+ "llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
+ return stream_operator_format_adapter<T>(std::forward<T>(Item));
+}
+
+template <typename T>
typename std::enable_if<uses_missing_provider<T>::value,
missing_format_adapter<T>>::type
build_format_adapter(T &&Item) {
diff --git a/contrib/llvm/include/llvm/Support/GenericDomTree.h b/contrib/llvm/include/llvm/Support/GenericDomTree.h
index 635c87a106f0..115abc23e2c6 100644
--- a/contrib/llvm/include/llvm/Support/GenericDomTree.h
+++ b/contrib/llvm/include/llvm/Support/GenericDomTree.h
@@ -50,9 +50,9 @@ template <typename DomTreeT>
struct SemiNCAInfo;
} // namespace DomTreeBuilder
-/// \brief Base class for the actual dominator tree node.
+/// Base class for the actual dominator tree node.
template <class NodeT> class DomTreeNodeBase {
- friend struct PostDominatorTree;
+ friend class PostDominatorTree;
friend class DominatorTreeBase<NodeT, false>;
friend class DominatorTreeBase<NodeT, true>;
friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase<NodeT, false>>;
@@ -234,10 +234,10 @@ void ApplyUpdates(DomTreeT &DT,
ArrayRef<typename DomTreeT::UpdateType> Updates);
template <typename DomTreeT>
-bool Verify(const DomTreeT &DT);
+bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL);
} // namespace DomTreeBuilder
-/// \brief Core dominator tree base class.
+/// 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.
@@ -259,7 +259,9 @@ class DominatorTreeBase {
static constexpr UpdateKind Insert = UpdateKind::Insert;
static constexpr UpdateKind Delete = UpdateKind::Delete;
- protected:
+ enum class VerificationLevel { Fast, Basic, Full };
+
+protected:
// Dominators always have a single root, postdominators can have more.
SmallVector<NodeT *, IsPostDom ? 4 : 1> Roots;
@@ -316,6 +318,12 @@ class DominatorTreeBase {
bool compare(const DominatorTreeBase &Other) const {
if (Parent != Other.Parent) return true;
+ if (Roots.size() != Other.Roots.size())
+ return true;
+
+ if (!std::is_permutation(Roots.begin(), Roots.end(), Other.Roots.begin()))
+ return true;
+
const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes;
if (DomTreeNodes.size() != OtherDomTreeNodes.size())
return true;
@@ -343,7 +351,7 @@ class DominatorTreeBase {
/// block. This is the same as using operator[] on this class. The result
/// may (but is not required to) be null for a forward (backwards)
/// statically unreachable block.
- DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
+ DomTreeNodeBase<NodeT> *getNode(const NodeT *BB) const {
auto I = DomTreeNodes.find(BB);
if (I != DomTreeNodes.end())
return I->second.get();
@@ -351,7 +359,9 @@ class DominatorTreeBase {
}
/// See getNode.
- DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { return getNode(BB); }
+ DomTreeNodeBase<NodeT> *operator[](const 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,
@@ -750,10 +760,25 @@ public:
DomTreeBuilder::Calculate(*this);
}
- /// verify - check parent and sibling property
- bool verify() const { return DomTreeBuilder::Verify(*this); }
+ /// verify - checks if the tree is correct. There are 3 level of verification:
+ /// - Full -- verifies if the tree is correct by making sure all the
+ /// properties (including the parent and the sibling property)
+ /// hold.
+ /// Takes O(N^3) time.
+ ///
+ /// - Basic -- checks if the tree is correct, but compares it to a freshly
+ /// constructed tree instead of checking the sibling property.
+ /// Takes O(N^2) time.
+ ///
+ /// - Fast -- checks basic tree structure and compares it with a freshly
+ /// constructed tree.
+ /// Takes O(N^2) time worst case, but is faster in practise (same
+ /// as tree construction).
+ bool verify(VerificationLevel VL = VerificationLevel::Full) const {
+ return DomTreeBuilder::Verify(*this, VL);
+ }
- protected:
+protected:
void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
void reset() {
@@ -835,7 +860,7 @@ public:
return IDom != nullptr;
}
- /// \brief Wipe this tree's state without releasing any resources.
+ /// 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.
diff --git a/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h
index 9438c9e08850..103ff8ca476a 100644
--- a/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h
@@ -82,8 +82,8 @@ struct SemiNCAInfo {
// Note that these children are from the future relative to what the
// DominatorTree knows about -- using them to gets us some snapshot of the
// CFG from the past (relative to the state of the CFG).
- DenseMap<NodePtr, SmallDenseSet<NodePtrAndKind, 4>> FutureSuccessors;
- DenseMap<NodePtr, SmallDenseSet<NodePtrAndKind, 4>> FuturePredecessors;
+ DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FutureSuccessors;
+ DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FuturePredecessors;
// Remembers if the whole tree was recalculated at some point during the
// current batch update.
bool IsRecalculated = false;
@@ -146,15 +146,15 @@ struct SemiNCAInfo {
assert(llvm::find(Res, Child) != Res.end()
&& "Expected child not found in the CFG");
Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end());
- DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> "
- << BlockNamePrinter(Child) << "\n");
+ LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> "
+ << BlockNamePrinter(Child) << "\n");
} else {
// If there's an deletion in the future, it means that the edge cannot
// exist in the current CFG, but existed in it before.
assert(llvm::find(Res, Child) == Res.end() &&
"Unexpected child found in the CFG");
- DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N)
- << " -> " << BlockNamePrinter(Child) << "\n");
+ LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N)
+ << " -> " << BlockNamePrinter(Child) << "\n");
Res.push_back(Child);
}
}
@@ -387,7 +387,7 @@ struct SemiNCAInfo {
SNCA.addVirtualRoot();
unsigned Num = 1;
- DEBUG(dbgs() << "\t\tLooking for trivial roots\n");
+ LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n");
// Step #1: Find all the trivial roots that are going to will definitely
// remain tree roots.
@@ -404,14 +404,14 @@ struct SemiNCAInfo {
Roots.push_back(N);
// Run DFS not to walk this part of CFG later.
Num = SNCA.runDFS(N, Num, AlwaysDescend, 1);
- DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N)
- << "\n");
- DEBUG(dbgs() << "Last visited node: "
- << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n");
+ LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N)
+ << "\n");
+ LLVM_DEBUG(dbgs() << "Last visited node: "
+ << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n");
}
}
- DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n");
+ LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n");
// Step #2: Find all non-trivial root candidates. Those are CFG nodes that
// are reverse-unreachable were not visited by previous DFS walks (i.e. CFG
@@ -431,8 +431,8 @@ struct SemiNCAInfo {
SmallPtrSet<NodePtr, 4> ConnectToExitBlock;
for (const NodePtr I : nodes(DT.Parent)) {
if (SNCA.NodeToInfo.count(I) == 0) {
- DEBUG(dbgs() << "\t\t\tVisiting node " << BlockNamePrinter(I)
- << "\n");
+ LLVM_DEBUG(dbgs()
+ << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n");
// Find the furthest away we can get by following successors, then
// follow them in reverse. This gives us some reasonable answer about
// the post-dom tree inside any infinite loop. In particular, it
@@ -443,47 +443,49 @@ struct SemiNCAInfo {
// the lowest and highest points in the infinite loop. In theory, it
// would be nice to give the canonical backedge for the loop, but it's
// expensive and does not always lead to a minimal set of roots.
- DEBUG(dbgs() << "\t\t\tRunning forward DFS\n");
+ LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n");
const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num);
const NodePtr FurthestAway = SNCA.NumToNode[NewNum];
- DEBUG(dbgs() << "\t\t\tFound a new furthest away node "
- << "(non-trivial root): "
- << BlockNamePrinter(FurthestAway) << "\n");
+ LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node "
+ << "(non-trivial root): "
+ << BlockNamePrinter(FurthestAway) << "\n");
ConnectToExitBlock.insert(FurthestAway);
Roots.push_back(FurthestAway);
- DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: "
- << NewNum << "\n\t\t\tRemoving DFS info\n");
+ LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: "
+ << NewNum << "\n\t\t\tRemoving DFS info\n");
for (unsigned i = NewNum; i > Num; --i) {
const NodePtr N = SNCA.NumToNode[i];
- DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for "
- << BlockNamePrinter(N) << "\n");
+ LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for "
+ << BlockNamePrinter(N) << "\n");
SNCA.NodeToInfo.erase(N);
SNCA.NumToNode.pop_back();
}
const unsigned PrevNum = Num;
- DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n");
+ LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n");
Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1);
for (unsigned i = PrevNum + 1; i <= Num; ++i)
- DEBUG(dbgs() << "\t\t\t\tfound node "
- << BlockNamePrinter(SNCA.NumToNode[i]) << "\n");
+ LLVM_DEBUG(dbgs() << "\t\t\t\tfound node "
+ << BlockNamePrinter(SNCA.NumToNode[i]) << "\n");
}
}
}
- DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n");
- DEBUG(dbgs() << "Discovered CFG nodes:\n");
- DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs()
- << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n");
+ LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n");
+ LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n");
+ LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs()
+ << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n");
assert((Total + 1 == Num) && "Everything should have been visited");
// Step #3: If we found some non-trivial roots, make them non-redundant.
if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots);
- DEBUG(dbgs() << "Found roots: ");
- DEBUG(for (auto *Root : Roots) dbgs() << BlockNamePrinter(Root) << " ");
- DEBUG(dbgs() << "\n");
+ LLVM_DEBUG(dbgs() << "Found roots: ");
+ LLVM_DEBUG(for (auto *Root
+ : Roots) dbgs()
+ << BlockNamePrinter(Root) << " ");
+ LLVM_DEBUG(dbgs() << "\n");
return Roots;
}
@@ -499,7 +501,7 @@ struct SemiNCAInfo {
static void RemoveRedundantRoots(const DomTreeT &DT, BatchUpdatePtr BUI,
RootsT &Roots) {
assert(IsPostDom && "This function is for postdominators only");
- DEBUG(dbgs() << "Removing redundant roots\n");
+ LLVM_DEBUG(dbgs() << "Removing redundant roots\n");
SemiNCAInfo SNCA(BUI);
@@ -507,8 +509,8 @@ struct SemiNCAInfo {
auto &Root = Roots[i];
// Trivial roots are always non-redundant.
if (!HasForwardSuccessors(Root, BUI)) continue;
- DEBUG(dbgs() << "\tChecking if " << BlockNamePrinter(Root)
- << " remains a root\n");
+ LLVM_DEBUG(dbgs() << "\tChecking if " << BlockNamePrinter(Root)
+ << " remains a root\n");
SNCA.clear();
// Do a forward walk looking for the other roots.
const unsigned Num = SNCA.runDFS<true>(Root, 0, AlwaysDescend, 0);
@@ -520,9 +522,9 @@ struct SemiNCAInfo {
// root from the set of roots, as it is reverse-reachable from the other
// one.
if (llvm::find(Roots, N) != Roots.end()) {
- DEBUG(dbgs() << "\tForward DFS walk found another root "
- << BlockNamePrinter(N) << "\n\tRemoving root "
- << BlockNamePrinter(Root) << "\n");
+ LLVM_DEBUG(dbgs() << "\tForward DFS walk found another root "
+ << BlockNamePrinter(N) << "\n\tRemoving root "
+ << BlockNamePrinter(Root) << "\n");
std::swap(Root, Roots.back());
Roots.pop_back();
@@ -563,7 +565,8 @@ struct SemiNCAInfo {
SNCA.runSemiNCA(DT);
if (BUI) {
BUI->IsRecalculated = true;
- DEBUG(dbgs() << "DomTree recalculated, skipping future batch updates\n");
+ LLVM_DEBUG(
+ dbgs() << "DomTree recalculated, skipping future batch updates\n");
}
if (DT.Roots.empty()) return;
@@ -585,8 +588,8 @@ struct SemiNCAInfo {
// Loop over all of the discovered blocks in the function...
for (size_t i = 1, e = NumToNode.size(); i != e; ++i) {
NodePtr W = NumToNode[i];
- DEBUG(dbgs() << "\tdiscovered a new reachable node "
- << BlockNamePrinter(W) << "\n");
+ LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node "
+ << BlockNamePrinter(W) << "\n");
// Don't replace this with 'count', the insertion side effect is important
if (DT.DomTreeNodes[W]) continue; // Haven't calculated this node yet?
@@ -638,8 +641,8 @@ struct SemiNCAInfo {
assert((From || IsPostDom) &&
"From has to be a valid CFG node or a virtual root");
assert(To && "Cannot be a nullptr");
- DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> "
- << BlockNamePrinter(To) << "\n");
+ LLVM_DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> "
+ << BlockNamePrinter(To) << "\n");
TreeNodePtr FromTN = DT.getNode(From);
if (!FromTN) {
@@ -678,8 +681,8 @@ struct SemiNCAInfo {
if (RIt == DT.Roots.end())
return false; // To is not a root, nothing to update.
- DEBUG(dbgs() << "\t\tAfter the insertion, " << BlockNamePrinter(To)
- << " is no longer a root\n\t\tRebuilding the tree!!!\n");
+ LLVM_DEBUG(dbgs() << "\t\tAfter the insertion, " << BlockNamePrinter(To)
+ << " is no longer a root\n\t\tRebuilding the tree!!!\n");
CalculateFromScratch(DT, BUI);
return true;
@@ -706,8 +709,8 @@ struct SemiNCAInfo {
// can make a different (implicit) decision about which node within an
// infinite loop becomes a root.
- DEBUG(dbgs() << "Roots are different in updated trees\n"
- << "The entire tree needs to be rebuilt\n");
+ LLVM_DEBUG(dbgs() << "Roots are different in updated trees\n"
+ << "The entire tree needs to be rebuilt\n");
// It may be possible to update the tree without recalculating it, but
// we do not know yet how to do it, and it happens rarely in practise.
CalculateFromScratch(DT, BUI);
@@ -718,8 +721,8 @@ struct SemiNCAInfo {
// Handles insertion to a node already in the dominator tree.
static void InsertReachable(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr From, const TreeNodePtr To) {
- DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock())
- << " -> " << BlockNamePrinter(To->getBlock()) << "\n");
+ LLVM_DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock())
+ << " -> " << BlockNamePrinter(To->getBlock()) << "\n");
if (IsPostDom && UpdateRootsBeforeInsertion(DT, BUI, From, To)) return;
// DT.findNCD expects both pointers to be valid. When From is a virtual
// root, then its CFG block pointer is a nullptr, so we have to 'compute'
@@ -732,7 +735,7 @@ struct SemiNCAInfo {
const TreeNodePtr NCD = DT.getNode(NCDBlock);
assert(NCD);
- DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n");
+ LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n");
const TreeNodePtr ToIDom = To->getIDom();
// Nothing affected -- NCA property holds.
@@ -741,18 +744,20 @@ struct SemiNCAInfo {
// Identify and collect affected nodes.
InsertionInfo II;
- DEBUG(dbgs() << "Marking " << BlockNamePrinter(To) << " as affected\n");
+ LLVM_DEBUG(dbgs() << "Marking " << BlockNamePrinter(To)
+ << " as affected\n");
II.Affected.insert(To);
const unsigned ToLevel = To->getLevel();
- DEBUG(dbgs() << "Putting " << BlockNamePrinter(To) << " into a Bucket\n");
+ LLVM_DEBUG(dbgs() << "Putting " << BlockNamePrinter(To)
+ << " into a Bucket\n");
II.Bucket.push({ToLevel, To});
while (!II.Bucket.empty()) {
const TreeNodePtr CurrentNode = II.Bucket.top().second;
const unsigned CurrentLevel = CurrentNode->getLevel();
II.Bucket.pop();
- DEBUG(dbgs() << "\tAdding to Visited and AffectedQueue: "
- << BlockNamePrinter(CurrentNode) << "\n");
+ LLVM_DEBUG(dbgs() << "\tAdding to Visited and AffectedQueue: "
+ << BlockNamePrinter(CurrentNode) << "\n");
II.Visited.insert({CurrentNode, CurrentLevel});
II.AffectedQueue.push_back(CurrentNode);
@@ -770,8 +775,8 @@ struct SemiNCAInfo {
const TreeNodePtr TN, const unsigned RootLevel,
const TreeNodePtr NCD, InsertionInfo &II) {
const unsigned NCDLevel = NCD->getLevel();
- DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << ", RootLevel "
- << RootLevel << "\n");
+ LLVM_DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << ", RootLevel "
+ << RootLevel << "\n");
SmallVector<TreeNodePtr, 8> Stack = {TN};
assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!");
@@ -780,7 +785,7 @@ struct SemiNCAInfo {
do {
TreeNodePtr Next = Stack.pop_back_val();
- DEBUG(dbgs() << " Next: " << BlockNamePrinter(Next) << "\n");
+ LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(Next) << "\n");
for (const NodePtr Succ :
ChildrenGetter<IsPostDom>::Get(Next->getBlock(), BUI)) {
@@ -788,8 +793,8 @@ struct SemiNCAInfo {
assert(SuccTN && "Unreachable successor found at reachable insertion");
const unsigned SuccLevel = SuccTN->getLevel();
- DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) << ", level = "
- << SuccLevel << "\n");
+ LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ)
+ << ", level = " << SuccLevel << "\n");
// Do not process the same node multiple times.
if (Processed.count(Next) > 0)
@@ -798,11 +803,11 @@ struct SemiNCAInfo {
// Succ dominated by subtree From -- not affected.
// (Based on the lemma 2.5 from the second paper.)
if (SuccLevel > RootLevel) {
- DEBUG(dbgs() << "\t\tDominated by subtree From\n");
+ LLVM_DEBUG(dbgs() << "\t\tDominated by subtree From\n");
if (II.Visited.count(SuccTN) != 0) {
- DEBUG(dbgs() << "\t\t\talready visited at level "
- << II.Visited[SuccTN] << "\n\t\t\tcurrent level "
- << RootLevel << ")\n");
+ LLVM_DEBUG(dbgs() << "\t\t\talready visited at level "
+ << II.Visited[SuccTN] << "\n\t\t\tcurrent level "
+ << RootLevel << ")\n");
// A node can be necessary to visit again if we see it again at
// a lower level than before.
@@ -810,15 +815,15 @@ struct SemiNCAInfo {
continue;
}
- DEBUG(dbgs() << "\t\tMarking visited not affected "
- << BlockNamePrinter(Succ) << "\n");
+ LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected "
+ << BlockNamePrinter(Succ) << "\n");
II.Visited.insert({SuccTN, RootLevel});
II.VisitedNotAffectedQueue.push_back(SuccTN);
Stack.push_back(SuccTN);
} else if ((SuccLevel > NCDLevel + 1) &&
II.Affected.count(SuccTN) == 0) {
- DEBUG(dbgs() << "\t\tMarking affected and adding "
- << BlockNamePrinter(Succ) << " to a Bucket\n");
+ LLVM_DEBUG(dbgs() << "\t\tMarking affected and adding "
+ << BlockNamePrinter(Succ) << " to a Bucket\n");
II.Affected.insert(SuccTN);
II.Bucket.push({SuccLevel, SuccTN});
}
@@ -831,11 +836,11 @@ struct SemiNCAInfo {
// Updates immediate dominators and levels after insertion.
static void UpdateInsertion(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr NCD, InsertionInfo &II) {
- DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n");
+ LLVM_DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n");
for (const TreeNodePtr TN : II.AffectedQueue) {
- DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN)
- << ") = " << BlockNamePrinter(NCD) << "\n");
+ LLVM_DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN)
+ << ") = " << BlockNamePrinter(NCD) << "\n");
TN->setIDom(NCD);
}
@@ -844,12 +849,13 @@ struct SemiNCAInfo {
}
static void UpdateLevelsAfterInsertion(InsertionInfo &II) {
- DEBUG(dbgs() << "Updating levels for visited but not affected nodes\n");
+ LLVM_DEBUG(
+ dbgs() << "Updating levels for visited but not affected nodes\n");
for (const TreeNodePtr TN : II.VisitedNotAffectedQueue) {
- DEBUG(dbgs() << "\tlevel(" << BlockNamePrinter(TN) << ") = ("
- << BlockNamePrinter(TN->getIDom()) << ") "
- << TN->getIDom()->getLevel() << " + 1\n");
+ LLVM_DEBUG(dbgs() << "\tlevel(" << BlockNamePrinter(TN) << ") = ("
+ << BlockNamePrinter(TN->getIDom()) << ") "
+ << TN->getIDom()->getLevel() << " + 1\n");
TN->UpdateLevel();
}
}
@@ -857,23 +863,24 @@ struct SemiNCAInfo {
// Handles insertion to previously unreachable nodes.
static void InsertUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr From, const NodePtr To) {
- DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From)
- << " -> (unreachable) " << BlockNamePrinter(To) << "\n");
+ LLVM_DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From)
+ << " -> (unreachable) " << BlockNamePrinter(To) << "\n");
// Collect discovered edges to already reachable nodes.
SmallVector<std::pair<NodePtr, TreeNodePtr>, 8> DiscoveredEdgesToReachable;
// Discover and connect nodes that became reachable with the insertion.
ComputeUnreachableDominators(DT, BUI, To, From, DiscoveredEdgesToReachable);
- DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From)
- << " -> (prev unreachable) " << BlockNamePrinter(To) << "\n");
+ LLVM_DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From)
+ << " -> (prev unreachable) " << BlockNamePrinter(To)
+ << "\n");
// Used the discovered edges and inset discovered connecting (incoming)
// edges.
for (const auto &Edge : DiscoveredEdgesToReachable) {
- DEBUG(dbgs() << "\tInserting discovered connecting edge "
- << BlockNamePrinter(Edge.first) << " -> "
- << BlockNamePrinter(Edge.second) << "\n");
+ LLVM_DEBUG(dbgs() << "\tInserting discovered connecting edge "
+ << BlockNamePrinter(Edge.first) << " -> "
+ << BlockNamePrinter(Edge.second) << "\n");
InsertReachable(DT, BUI, DT.getNode(Edge.first), Edge.second);
}
}
@@ -901,14 +908,14 @@ struct SemiNCAInfo {
SNCA.runSemiNCA(DT);
SNCA.attachNewSubtree(DT, Incoming);
- DEBUG(dbgs() << "After adding unreachable nodes\n");
+ LLVM_DEBUG(dbgs() << "After adding unreachable nodes\n");
}
static void DeleteEdge(DomTreeT &DT, const BatchUpdatePtr BUI,
const NodePtr From, const NodePtr To) {
assert(From && To && "Cannot disconnect nullptrs");
- DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> "
- << BlockNamePrinter(To) << "\n");
+ LLVM_DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> "
+ << BlockNamePrinter(To) << "\n");
#ifndef NDEBUG
// Ensure that the edge was in fact deleted from the CFG before informing
@@ -928,8 +935,9 @@ struct SemiNCAInfo {
const TreeNodePtr ToTN = DT.getNode(To);
if (!ToTN) {
- DEBUG(dbgs() << "\tTo (" << BlockNamePrinter(To)
- << ") already unreachable -- there is no edge to delete\n");
+ LLVM_DEBUG(
+ dbgs() << "\tTo (" << BlockNamePrinter(To)
+ << ") already unreachable -- there is no edge to delete\n");
return;
}
@@ -941,8 +949,8 @@ struct SemiNCAInfo {
DT.DFSInfoValid = false;
const TreeNodePtr ToIDom = ToTN->getIDom();
- DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom "
- << BlockNamePrinter(ToIDom) << "\n");
+ LLVM_DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom "
+ << BlockNamePrinter(ToIDom) << "\n");
// To remains reachable after deletion.
// (Based on the caption under Figure 4. from the second paper.)
@@ -959,9 +967,9 @@ struct SemiNCAInfo {
static void DeleteReachable(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr FromTN,
const TreeNodePtr ToTN) {
- DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN) << " -> "
- << BlockNamePrinter(ToTN) << "\n");
- DEBUG(dbgs() << "\tRebuilding subtree\n");
+ LLVM_DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN)
+ << " -> " << BlockNamePrinter(ToTN) << "\n");
+ LLVM_DEBUG(dbgs() << "\tRebuilding subtree\n");
// Find the top of the subtree that needs to be rebuilt.
// (Based on the lemma 2.6 from the second paper.)
@@ -974,7 +982,7 @@ struct SemiNCAInfo {
// Top of the subtree to rebuild is the root node. Rebuild the tree from
// scratch.
if (!PrevIDomSubTree) {
- DEBUG(dbgs() << "The entire tree needs to be rebuilt\n");
+ LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n");
CalculateFromScratch(DT, BUI);
return;
}
@@ -985,11 +993,12 @@ struct SemiNCAInfo {
return DT.getNode(To)->getLevel() > Level;
};
- DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) << "\n");
+ LLVM_DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN)
+ << "\n");
SemiNCAInfo SNCA(BUI);
SNCA.runDFS(ToIDom, 0, DescendBelow, 0);
- DEBUG(dbgs() << "\tRunning Semi-NCA\n");
+ LLVM_DEBUG(dbgs() << "\tRunning Semi-NCA\n");
SNCA.runSemiNCA(DT, Level);
SNCA.reattachExistingSubtree(DT, PrevIDomSubTree);
}
@@ -998,19 +1007,20 @@ struct SemiNCAInfo {
// explained on the page 7 of the second paper.
static bool HasProperSupport(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr TN) {
- DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN) << "\n");
+ LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN)
+ << "\n");
for (const NodePtr Pred :
ChildrenGetter<!IsPostDom>::Get(TN->getBlock(), BUI)) {
- DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n");
+ LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n");
if (!DT.getNode(Pred)) continue;
const NodePtr Support =
DT.findNearestCommonDominator(TN->getBlock(), Pred);
- DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n");
+ LLVM_DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n");
if (Support != TN->getBlock()) {
- DEBUG(dbgs() << "\t" << BlockNamePrinter(TN)
- << " is reachable from support "
- << BlockNamePrinter(Support) << "\n");
+ LLVM_DEBUG(dbgs() << "\t" << BlockNamePrinter(TN)
+ << " is reachable from support "
+ << BlockNamePrinter(Support) << "\n");
return true;
}
}
@@ -1022,8 +1032,8 @@ struct SemiNCAInfo {
// (Based on the lemma 2.7 from the second paper.)
static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr ToTN) {
- DEBUG(dbgs() << "Deleting unreachable subtree " << BlockNamePrinter(ToTN)
- << "\n");
+ LLVM_DEBUG(dbgs() << "Deleting unreachable subtree "
+ << BlockNamePrinter(ToTN) << "\n");
assert(ToTN);
assert(ToTN->getBlock());
@@ -1031,8 +1041,9 @@ struct SemiNCAInfo {
// Deletion makes a region reverse-unreachable and creates a new root.
// Simulate that by inserting an edge from the virtual root to ToTN and
// adding it as a new root.
- DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n");
- DEBUG(dbgs() << "\tAdding new root " << BlockNamePrinter(ToTN) << "\n");
+ LLVM_DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n");
+ LLVM_DEBUG(dbgs() << "\tAdding new root " << BlockNamePrinter(ToTN)
+ << "\n");
DT.Roots.push_back(ToTN->getBlock());
InsertReachable(DT, BUI, DT.getNode(nullptr), ToTN);
return;
@@ -1069,15 +1080,15 @@ struct SemiNCAInfo {
const TreeNodePtr NCD = DT.getNode(NCDBlock);
assert(NCD);
- DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN)
- << " with NCD = " << BlockNamePrinter(NCD)
- << ", MinNode =" << BlockNamePrinter(MinNode) << "\n");
+ LLVM_DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN)
+ << " with NCD = " << BlockNamePrinter(NCD)
+ << ", MinNode =" << BlockNamePrinter(MinNode) << "\n");
if (NCD != TN && NCD->getLevel() < MinNode->getLevel()) MinNode = NCD;
}
// Root reached, rebuild the whole tree from scratch.
if (!MinNode->getIDom()) {
- DEBUG(dbgs() << "The entire tree needs to be rebuilt\n");
+ LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n");
CalculateFromScratch(DT, BUI);
return;
}
@@ -1087,7 +1098,7 @@ struct SemiNCAInfo {
for (unsigned i = LastDFSNum; i > 0; --i) {
const NodePtr N = SNCA.NumToNode[i];
const TreeNodePtr TN = DT.getNode(N);
- DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(TN) << "\n");
+ LLVM_DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(TN) << "\n");
EraseNode(DT, TN);
}
@@ -1095,8 +1106,8 @@ struct SemiNCAInfo {
// The affected subtree start at the To node -- there's no extra work to do.
if (MinNode == ToTN) return;
- DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = "
- << BlockNamePrinter(MinNode) << "\n");
+ LLVM_DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = "
+ << BlockNamePrinter(MinNode) << "\n");
const unsigned MinLevel = MinNode->getLevel();
const TreeNodePtr PrevIDom = MinNode->getIDom();
assert(PrevIDom);
@@ -1109,8 +1120,8 @@ struct SemiNCAInfo {
};
SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0);
- DEBUG(dbgs() << "Previous IDom(MinNode) = " << BlockNamePrinter(PrevIDom)
- << "\nRunning Semi-NCA\n");
+ LLVM_DEBUG(dbgs() << "Previous IDom(MinNode) = "
+ << BlockNamePrinter(PrevIDom) << "\nRunning Semi-NCA\n");
// Rebuild the remaining part of affected subtree.
SNCA.runSemiNCA(DT, MinLevel);
@@ -1165,15 +1176,15 @@ struct SemiNCAInfo {
// predecessors. Note that these sets will only decrease size over time, as
// the next CFG snapshots slowly approach the actual (current) CFG.
for (UpdateT &U : BUI.Updates) {
- BUI.FutureSuccessors[U.getFrom()].insert({U.getTo(), U.getKind()});
- BUI.FuturePredecessors[U.getTo()].insert({U.getFrom(), U.getKind()});
+ BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()});
+ BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()});
}
- DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n");
- DEBUG(if (NumLegalized < 32) for (const auto &U
- : reverse(BUI.Updates)) dbgs()
- << '\t' << U << "\n");
- DEBUG(dbgs() << "\n");
+ LLVM_DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n");
+ LLVM_DEBUG(if (NumLegalized < 32) for (const auto &U
+ : reverse(BUI.Updates)) dbgs()
+ << '\t' << U << "\n");
+ LLVM_DEBUG(dbgs() << "\n");
// If the DominatorTree was recalculated at some point, stop the batch
// updates. Full recalculations ignore batch updates and look at the actual
@@ -1201,7 +1212,7 @@ struct SemiNCAInfo {
// minimizes the amount of work needed done during incremental updates.
static void LegalizeUpdates(ArrayRef<UpdateT> AllUpdates,
SmallVectorImpl<UpdateT> &Result) {
- DEBUG(dbgs() << "Legalizing " << AllUpdates.size() << " updates\n");
+ LLVM_DEBUG(dbgs() << "Legalizing " << AllUpdates.size() << " updates\n");
// Count the total number of inserions of each edge.
// Each insertion adds 1 and deletion subtracts 1. The end number should be
// one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence
@@ -1241,26 +1252,31 @@ struct SemiNCAInfo {
Operations[{U.getTo(), U.getFrom()}] = int(i);
}
- std::sort(Result.begin(), Result.end(),
- [&Operations](const UpdateT &A, const UpdateT &B) {
- return Operations[{A.getFrom(), A.getTo()}] >
- Operations[{B.getFrom(), B.getTo()}];
- });
+ llvm::sort(Result.begin(), Result.end(),
+ [&Operations](const UpdateT &A, const UpdateT &B) {
+ return Operations[{A.getFrom(), A.getTo()}] >
+ Operations[{B.getFrom(), B.getTo()}];
+ });
}
static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) {
assert(!BUI.Updates.empty() && "No updates to apply!");
UpdateT CurrentUpdate = BUI.Updates.pop_back_val();
- DEBUG(dbgs() << "Applying update: " << CurrentUpdate << "\n");
+ LLVM_DEBUG(dbgs() << "Applying update: " << CurrentUpdate << "\n");
// Move to the next snapshot of the CFG by removing the reverse-applied
- // current update.
+ // current update. Since updates are performed in the same order they are
+ // legalized it's sufficient to pop the last item here.
auto &FS = BUI.FutureSuccessors[CurrentUpdate.getFrom()];
- FS.erase({CurrentUpdate.getTo(), CurrentUpdate.getKind()});
+ assert(FS.back().getPointer() == CurrentUpdate.getTo() &&
+ FS.back().getInt() == CurrentUpdate.getKind());
+ FS.pop_back();
if (FS.empty()) BUI.FutureSuccessors.erase(CurrentUpdate.getFrom());
auto &FP = BUI.FuturePredecessors[CurrentUpdate.getTo()];
- FP.erase({CurrentUpdate.getFrom(), CurrentUpdate.getKind()});
+ assert(FP.back().getPointer() == CurrentUpdate.getFrom() &&
+ FP.back().getInt() == CurrentUpdate.getKind());
+ FP.pop_back();
if (FP.empty()) BUI.FuturePredecessors.erase(CurrentUpdate.getTo());
if (CurrentUpdate.getKind() == UpdateKind::Insert)
@@ -1277,6 +1293,7 @@ struct SemiNCAInfo {
// root which is the function's entry node. A PostDominatorTree can have
// multiple roots - one for each node with no successors and for infinite
// loops.
+ // Running time: O(N).
bool verifyRoots(const DomTreeT &DT) {
if (!DT.Parent && !DT.Roots.empty()) {
errs() << "Tree has no parent but has roots!\n";
@@ -1317,6 +1334,7 @@ struct SemiNCAInfo {
}
// Checks if the tree contains all reachable nodes in the input graph.
+ // Running time: O(N).
bool verifyReachability(const DomTreeT &DT) {
clear();
doFullDFSWalk(DT, AlwaysDescend);
@@ -1352,6 +1370,7 @@ struct SemiNCAInfo {
// Check if for every parent with a level L in the tree all of its children
// have level L + 1.
+ // Running time: O(N).
static bool VerifyLevels(const DomTreeT &DT) {
for (auto &NodeToTN : DT.DomTreeNodes) {
const TreeNodePtr TN = NodeToTN.second.get();
@@ -1383,6 +1402,7 @@ struct SemiNCAInfo {
// Check if the computed DFS numbers are correct. Note that DFS info may not
// be valid, and when that is the case, we don't verify the numbers.
+ // Running time: O(N log(N)).
static bool VerifyDFSNumbers(const DomTreeT &DT) {
if (!DT.DFSInfoValid || !DT.Parent)
return true;
@@ -1426,10 +1446,10 @@ struct SemiNCAInfo {
// Make a copy and sort it such that it is possible to check if there are
// no gaps between DFS numbers of adjacent children.
SmallVector<TreeNodePtr, 8> Children(Node->begin(), Node->end());
- std::sort(Children.begin(), Children.end(),
- [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) {
- return Ch1->getDFSNumIn() < Ch2->getDFSNumIn();
- });
+ llvm::sort(Children.begin(), Children.end(),
+ [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) {
+ return Ch1->getDFSNumIn() < Ch2->getDFSNumIn();
+ });
auto PrintChildrenError = [Node, &Children, PrintNodeAndDFSNums](
const TreeNodePtr FirstCh, const TreeNodePtr SecondCh) {
@@ -1513,10 +1533,10 @@ struct SemiNCAInfo {
// linear time, but the algorithms are complex. Instead, we do it in a
// straightforward N^2 and N^3 way below, using direct path reachability.
-
// Checks if the tree has the parent property: if for all edges from V to W in
// the input graph, such that V is reachable, the parent of W in the tree is
// an ancestor of V in the tree.
+ // Running time: O(N^2).
//
// This means that if a node gets disconnected from the graph, then all of
// the nodes it dominated previously will now become unreachable.
@@ -1526,8 +1546,8 @@ struct SemiNCAInfo {
const NodePtr BB = TN->getBlock();
if (!BB || TN->getChildren().empty()) continue;
- DEBUG(dbgs() << "Verifying parent property of node "
- << BlockNamePrinter(TN) << "\n");
+ LLVM_DEBUG(dbgs() << "Verifying parent property of node "
+ << BlockNamePrinter(TN) << "\n");
clear();
doFullDFSWalk(DT, [BB](NodePtr From, NodePtr To) {
return From != BB && To != BB;
@@ -1549,6 +1569,7 @@ struct SemiNCAInfo {
// Check if the tree has sibling property: if a node V does not dominate a
// node W for all siblings V and W in the tree.
+ // Running time: O(N^3).
//
// This means that if a node gets disconnected from the graph, then all of its
// siblings will now still be reachable.
@@ -1583,6 +1604,31 @@ struct SemiNCAInfo {
return true;
}
+
+ // Check if the given tree is the same as a freshly computed one for the same
+ // Parent.
+ // Running time: O(N^2), but faster in practise (same as tree construction).
+ //
+ // Note that this does not check if that the tree construction algorithm is
+ // correct and should be only used for fast (but possibly unsound)
+ // verification.
+ static bool IsSameAsFreshTree(const DomTreeT &DT) {
+ DomTreeT FreshTree;
+ FreshTree.recalculate(*DT.Parent);
+ const bool Different = DT.compare(FreshTree);
+
+ if (Different) {
+ errs() << (DT.isPostDominator() ? "Post" : "")
+ << "DominatorTree is different than a freshly computed one!\n"
+ << "\tCurrent:\n";
+ DT.print(errs());
+ errs() << "\n\tFreshly computed tree:\n";
+ FreshTree.print(errs());
+ errs().flush();
+ }
+
+ return !Different;
+ }
};
template <class DomTreeT>
@@ -1611,11 +1657,29 @@ void ApplyUpdates(DomTreeT &DT,
}
template <class DomTreeT>
-bool Verify(const DomTreeT &DT) {
+bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) {
SemiNCAInfo<DomTreeT> SNCA(nullptr);
- return SNCA.verifyRoots(DT) && SNCA.verifyReachability(DT) &&
- SNCA.VerifyLevels(DT) && SNCA.verifyParentProperty(DT) &&
- SNCA.verifySiblingProperty(DT) && SNCA.VerifyDFSNumbers(DT);
+
+ // Simplist check is to compare against a new tree. This will also
+ // usefully print the old and new trees, if they are different.
+ if (!SNCA.IsSameAsFreshTree(DT))
+ return false;
+
+ // Common checks to verify the properties of the tree. O(N log N) at worst
+ if (!SNCA.verifyRoots(DT) || !SNCA.verifyReachability(DT) ||
+ !SNCA.VerifyLevels(DT) || !SNCA.VerifyDFSNumbers(DT))
+ return false;
+
+ // Extra checks depending on VerificationLevel. Up to O(N^3)
+ if (VL == DomTreeT::VerificationLevel::Basic ||
+ VL == DomTreeT::VerificationLevel::Full)
+ if (!SNCA.verifyParentProperty(DT))
+ return false;
+ if (VL == DomTreeT::VerificationLevel::Full)
+ if (!SNCA.verifySiblingProperty(DT))
+ return false;
+
+ return true;
}
} // namespace DomTreeBuilder
diff --git a/contrib/llvm/include/llvm/Support/GraphWriter.h b/contrib/llvm/include/llvm/Support/GraphWriter.h
index 3df5c867f7d3..c9a9f409c522 100644
--- a/contrib/llvm/include/llvm/Support/GraphWriter.h
+++ b/contrib/llvm/include/llvm/Support/GraphWriter.h
@@ -41,7 +41,7 @@ namespace DOT { // Private functions...
std::string EscapeString(const std::string &Label);
-/// \brief Get a color string for this node number. Simply round-robin selects
+/// Get a color string for this node number. Simply round-robin selects
/// from a reasonable number of colors.
StringRef getColorString(unsigned NodeNumber);
diff --git a/contrib/llvm/include/llvm/Support/Host.h b/contrib/llvm/include/llvm/Support/Host.h
index a4b0a340c568..57c79c0b9fdf 100644
--- a/contrib/llvm/include/llvm/Support/Host.h
+++ b/contrib/llvm/include/llvm/Support/Host.h
@@ -31,7 +31,7 @@
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#else
-#if !defined(BYTE_ORDER) && !defined(LLVM_ON_WIN32)
+#if !defined(BYTE_ORDER) && !defined(_WIN32)
#include <machine/endian.h>
#endif
#endif
@@ -88,9 +88,9 @@ constexpr bool IsBigEndianHost = false;
namespace detail {
/// Helper functions to extract HostCPUName from /proc/cpuinfo on linux.
- StringRef getHostCPUNameForPowerPC(const StringRef &ProcCpuinfoContent);
- StringRef getHostCPUNameForARM(const StringRef &ProcCpuinfoContent);
- StringRef getHostCPUNameForS390x(const StringRef &ProcCpuinfoContent);
+ StringRef getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent);
+ StringRef getHostCPUNameForARM(StringRef ProcCpuinfoContent);
+ StringRef getHostCPUNameForS390x(StringRef ProcCpuinfoContent);
StringRef getHostCPUNameForBPF();
}
}
diff --git a/contrib/llvm/include/llvm/Support/InitLLVM.h b/contrib/llvm/include/llvm/Support/InitLLVM.h
new file mode 100644
index 000000000000..0f629c9ac92d
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/InitLLVM.h
@@ -0,0 +1,46 @@
+//===- InitLLVM.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_SUPPORT_LLVM_H
+#define LLVM_SUPPORT_LLVM_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+// The main() functions in typical LLVM tools start with InitLLVM which does
+// the following one-time initializations:
+//
+// 1. Setting up a signal handler so that pretty stack trace is printed out
+// if a process crashes.
+//
+// 2. If running on Windows, obtain command line arguments using a
+// multibyte character-aware API and convert arguments into UTF-8
+// encoding, so that you can assume that command line arguments are
+// always encoded in UTF-8 on any platform.
+//
+// InitLLVM calls llvm_shutdown() on destruction, which cleans up
+// ManagedStatic objects.
+namespace llvm {
+class InitLLVM {
+public:
+ InitLLVM(int &Argc, const char **&Argv);
+ InitLLVM(int &Argc, char **&Argv)
+ : InitLLVM(Argc, const_cast<const char **&>(Argv)) {}
+
+ ~InitLLVM();
+
+private:
+ BumpPtrAllocator Alloc;
+ SmallVector<const char *, 0> Args;
+ PrettyStackTraceProgram StackPrinter;
+};
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/Support/JSON.h b/contrib/llvm/include/llvm/Support/JSON.h
new file mode 100644
index 000000000000..da3c5ea0b25d
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/JSON.h
@@ -0,0 +1,704 @@
+//===--- JSON.h - JSON values, parsing and serialization -------*- 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 supports working with JSON data.
+///
+/// It comprises:
+///
+/// - classes which hold dynamically-typed parsed JSON structures
+/// These are value types that can be composed, inspected, and modified.
+/// See json::Value, and the related types json::Object and json::Array.
+///
+/// - functions to parse JSON text into Values, and to serialize Values to text.
+/// See parse(), operator<<, and format_provider.
+///
+/// - a convention and helpers for mapping between json::Value and user-defined
+/// types. See fromJSON(), ObjectMapper, and the class comment on Value.
+///
+/// Typically, JSON data would be read from an external source, parsed into
+/// a Value, and then converted into some native data structure before doing
+/// real work on it. (And vice versa when writing).
+///
+/// Other serialization mechanisms you may consider:
+///
+/// - YAML is also text-based, and more human-readable than JSON. It's a more
+/// complex format and data model, and YAML parsers aren't ubiquitous.
+/// YAMLParser.h is a streaming parser suitable for parsing large documents
+/// (including JSON, as YAML is a superset). It can be awkward to use
+/// directly. YAML I/O (YAMLTraits.h) provides data mapping that is more
+/// declarative than the toJSON/fromJSON conventions here.
+///
+/// - LLVM bitstream is a space- and CPU- efficient binary format. Typically it
+/// encodes LLVM IR ("bitcode"), but it can be a container for other data.
+/// Low-level reader/writer libraries are in Bitcode/Bitstream*.h
+///
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_JSON_H
+#define LLVM_SUPPORT_JSON_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+
+namespace llvm {
+namespace json {
+
+// === String encodings ===
+//
+// JSON strings are character sequences (not byte sequences like std::string).
+// We need to know the encoding, and for simplicity only support UTF-8.
+//
+// - When parsing, invalid UTF-8 is a syntax error like any other
+//
+// - When creating Values from strings, callers must ensure they are UTF-8.
+// with asserts on, invalid UTF-8 will crash the program
+// with asserts off, we'll substitute the replacement character (U+FFFD)
+// Callers can use json::isUTF8() and json::fixUTF8() for validation.
+//
+// - When retrieving strings from Values (e.g. asString()), the result will
+// always be valid UTF-8.
+
+/// Returns true if \p S is valid UTF-8, which is required for use as JSON.
+/// If it returns false, \p Offset is set to a byte offset near the first error.
+bool isUTF8(llvm::StringRef S, size_t *ErrOffset = nullptr);
+/// Replaces invalid UTF-8 sequences in \p S with the replacement character
+/// (U+FFFD). The returned string is valid UTF-8.
+/// This is much slower than isUTF8, so test that first.
+std::string fixUTF8(llvm::StringRef S);
+
+class Array;
+class ObjectKey;
+class Value;
+template <typename T> Value toJSON(const llvm::Optional<T> &Opt);
+
+/// An Object is a JSON object, which maps strings to heterogenous JSON values.
+/// It simulates DenseMap<ObjectKey, Value>. ObjectKey is a maybe-owned string.
+class Object {
+ using Storage = DenseMap<ObjectKey, Value, llvm::DenseMapInfo<StringRef>>;
+ Storage M;
+
+public:
+ using key_type = ObjectKey;
+ using mapped_type = Value;
+ using value_type = Storage::value_type;
+ using iterator = Storage::iterator;
+ using const_iterator = Storage::const_iterator;
+
+ explicit Object() = default;
+ // KV is a trivial key-value struct for list-initialization.
+ // (using std::pair forces extra copies).
+ struct KV;
+ explicit Object(std::initializer_list<KV> Properties);
+
+ iterator begin() { return M.begin(); }
+ const_iterator begin() const { return M.begin(); }
+ iterator end() { return M.end(); }
+ const_iterator end() const { return M.end(); }
+
+ bool empty() const { return M.empty(); }
+ size_t size() const { return M.size(); }
+
+ void clear() { M.clear(); }
+ std::pair<iterator, bool> insert(KV E);
+ template <typename... Ts>
+ std::pair<iterator, bool> try_emplace(const ObjectKey &K, Ts &&... Args) {
+ return M.try_emplace(K, std::forward<Ts>(Args)...);
+ }
+ template <typename... Ts>
+ std::pair<iterator, bool> try_emplace(ObjectKey &&K, Ts &&... Args) {
+ return M.try_emplace(std::move(K), std::forward<Ts>(Args)...);
+ }
+
+ iterator find(StringRef K) { return M.find_as(K); }
+ const_iterator find(StringRef K) const { return M.find_as(K); }
+ // operator[] acts as if Value was default-constructible as null.
+ Value &operator[](const ObjectKey &K);
+ Value &operator[](ObjectKey &&K);
+ // Look up a property, returning nullptr if it doesn't exist.
+ Value *get(StringRef K);
+ const Value *get(StringRef K) const;
+ // Typed accessors return None/nullptr if
+ // - the property doesn't exist
+ // - or it has the wrong type
+ llvm::Optional<std::nullptr_t> getNull(StringRef K) const;
+ llvm::Optional<bool> getBoolean(StringRef K) const;
+ llvm::Optional<double> getNumber(StringRef K) const;
+ llvm::Optional<int64_t> getInteger(StringRef K) const;
+ llvm::Optional<llvm::StringRef> getString(StringRef K) const;
+ const json::Object *getObject(StringRef K) const;
+ json::Object *getObject(StringRef K);
+ const json::Array *getArray(StringRef K) const;
+ json::Array *getArray(StringRef K);
+};
+bool operator==(const Object &LHS, const Object &RHS);
+inline bool operator!=(const Object &LHS, const Object &RHS) {
+ return !(LHS == RHS);
+}
+
+/// An Array is a JSON array, which contains heterogeneous JSON values.
+/// It simulates std::vector<Value>.
+class Array {
+ std::vector<Value> V;
+
+public:
+ using value_type = Value;
+ using iterator = std::vector<Value>::iterator;
+ using const_iterator = std::vector<Value>::const_iterator;
+
+ explicit Array() = default;
+ explicit Array(std::initializer_list<Value> Elements);
+ template <typename Collection> explicit Array(const Collection &C) {
+ for (const auto &V : C)
+ emplace_back(V);
+ }
+
+ Value &operator[](size_t I) { return V[I]; }
+ const Value &operator[](size_t I) const { return V[I]; }
+ Value &front() { return V.front(); }
+ const Value &front() const { return V.front(); }
+ Value &back() { return V.back(); }
+ const Value &back() const { return V.back(); }
+ Value *data() { return V.data(); }
+ const Value *data() const { return V.data(); }
+
+ iterator begin() { return V.begin(); }
+ const_iterator begin() const { return V.begin(); }
+ iterator end() { return V.end(); }
+ const_iterator end() const { return V.end(); }
+
+ bool empty() const { return V.empty(); }
+ size_t size() const { return V.size(); }
+
+ void clear() { V.clear(); }
+ void push_back(const Value &E) { V.push_back(E); }
+ void push_back(Value &&E) { V.push_back(std::move(E)); }
+ template <typename... Args> void emplace_back(Args &&... A) {
+ V.emplace_back(std::forward<Args>(A)...);
+ }
+ void pop_back() { V.pop_back(); }
+ // FIXME: insert() takes const_iterator since C++11, old libstdc++ disagrees.
+ iterator insert(iterator P, const Value &E) { return V.insert(P, E); }
+ iterator insert(iterator P, Value &&E) {
+ return V.insert(P, std::move(E));
+ }
+ template <typename It> iterator insert(iterator P, It A, It Z) {
+ return V.insert(P, A, Z);
+ }
+ template <typename... Args> iterator emplace(const_iterator P, Args &&... A) {
+ return V.emplace(P, std::forward<Args>(A)...);
+ }
+
+ friend bool operator==(const Array &L, const Array &R) { return L.V == R.V; }
+};
+inline bool operator!=(const Array &L, const Array &R) { return !(L == R); }
+
+/// A Value is an JSON value of unknown type.
+/// They can be copied, but should generally be moved.
+///
+/// === Composing values ===
+///
+/// You can implicitly construct Values from:
+/// - strings: std::string, SmallString, formatv, StringRef, char*
+/// (char*, and StringRef are references, not copies!)
+/// - numbers
+/// - booleans
+/// - null: nullptr
+/// - arrays: {"foo", 42.0, false}
+/// - serializable things: types with toJSON(const T&)->Value, found by ADL
+///
+/// They can also be constructed from object/array helpers:
+/// - json::Object is a type like map<ObjectKey, Value>
+/// - json::Array is a type like vector<Value>
+/// These can be list-initialized, or used to build up collections in a loop.
+/// json::ary(Collection) converts all items in a collection to Values.
+///
+/// === Inspecting values ===
+///
+/// Each Value is one of the JSON kinds:
+/// null (nullptr_t)
+/// boolean (bool)
+/// number (double or int64)
+/// string (StringRef)
+/// array (json::Array)
+/// object (json::Object)
+///
+/// The kind can be queried directly, or implicitly via the typed accessors:
+/// if (Optional<StringRef> S = E.getAsString()
+/// assert(E.kind() == Value::String);
+///
+/// Array and Object also have typed indexing accessors for easy traversal:
+/// Expected<Value> E = parse(R"( {"options": {"font": "sans-serif"}} )");
+/// if (Object* O = E->getAsObject())
+/// if (Object* Opts = O->getObject("options"))
+/// if (Optional<StringRef> Font = Opts->getString("font"))
+/// assert(Opts->at("font").kind() == Value::String);
+///
+/// === Converting JSON values to C++ types ===
+///
+/// The convention is to have a deserializer function findable via ADL:
+/// fromJSON(const json::Value&, T&)->bool
+/// Deserializers are provided for:
+/// - bool
+/// - int and int64_t
+/// - double
+/// - std::string
+/// - vector<T>, where T is deserializable
+/// - map<string, T>, where T is deserializable
+/// - Optional<T>, where T is deserializable
+/// ObjectMapper can help writing fromJSON() functions for object types.
+///
+/// For conversion in the other direction, the serializer function is:
+/// toJSON(const T&) -> json::Value
+/// If this exists, then it also allows constructing Value from T, and can
+/// be used to serialize vector<T>, map<string, T>, and Optional<T>.
+///
+/// === Serialization ===
+///
+/// Values can be serialized to JSON:
+/// 1) raw_ostream << Value // Basic formatting.
+/// 2) raw_ostream << formatv("{0}", Value) // Basic formatting.
+/// 3) raw_ostream << formatv("{0:2}", Value) // Pretty-print with indent 2.
+///
+/// And parsed:
+/// Expected<Value> E = json::parse("[1, 2, null]");
+/// assert(E && E->kind() == Value::Array);
+class Value {
+public:
+ enum Kind {
+ Null,
+ Boolean,
+ /// Number values can store both int64s and doubles at full precision,
+ /// depending on what they were constructed/parsed from.
+ Number,
+ String,
+ Array,
+ Object,
+ };
+
+ // It would be nice to have Value() be null. But that would make {} null too.
+ Value(const Value &M) { copyFrom(M); }
+ Value(Value &&M) { moveFrom(std::move(M)); }
+ Value(std::initializer_list<Value> Elements);
+ Value(json::Array &&Elements) : Type(T_Array) {
+ create<json::Array>(std::move(Elements));
+ }
+ Value(json::Object &&Properties) : Type(T_Object) {
+ create<json::Object>(std::move(Properties));
+ }
+ // Strings: types with value semantics. Must be valid UTF-8.
+ Value(std::string V) : Type(T_String) {
+ if (LLVM_UNLIKELY(!isUTF8(V))) {
+ assert(false && "Invalid UTF-8 in value used as JSON");
+ V = fixUTF8(std::move(V));
+ }
+ create<std::string>(std::move(V));
+ }
+ Value(const llvm::SmallVectorImpl<char> &V)
+ : Value(std::string(V.begin(), V.end())){};
+ Value(const llvm::formatv_object_base &V) : Value(V.str()){};
+ // Strings: types with reference semantics. Must be valid UTF-8.
+ Value(StringRef V) : Type(T_StringRef) {
+ create<llvm::StringRef>(V);
+ if (LLVM_UNLIKELY(!isUTF8(V))) {
+ assert(false && "Invalid UTF-8 in value used as JSON");
+ *this = Value(fixUTF8(V));
+ }
+ }
+ Value(const char *V) : Value(StringRef(V)) {}
+ Value(std::nullptr_t) : Type(T_Null) {}
+ // Boolean (disallow implicit conversions).
+ // (The last template parameter is a dummy to keep templates distinct.)
+ template <
+ typename T,
+ typename = typename std::enable_if<std::is_same<T, bool>::value>::type,
+ bool = false>
+ Value(T B) : Type(T_Boolean) {
+ create<bool>(B);
+ }
+ // Integers (except boolean). Must be non-narrowing convertible to int64_t.
+ template <
+ typename T,
+ typename = typename std::enable_if<std::is_integral<T>::value>::type,
+ typename = typename std::enable_if<!std::is_same<T, bool>::value>::type>
+ Value(T I) : Type(T_Integer) {
+ create<int64_t>(int64_t{I});
+ }
+ // Floating point. Must be non-narrowing convertible to double.
+ template <typename T,
+ typename =
+ typename std::enable_if<std::is_floating_point<T>::value>::type,
+ double * = nullptr>
+ Value(T D) : Type(T_Double) {
+ create<double>(double{D});
+ }
+ // Serializable types: with a toJSON(const T&)->Value function, found by ADL.
+ template <typename T,
+ typename = typename std::enable_if<std::is_same<
+ Value, decltype(toJSON(*(const T *)nullptr))>::value>,
+ Value * = nullptr>
+ Value(const T &V) : Value(toJSON(V)) {}
+
+ Value &operator=(const Value &M) {
+ destroy();
+ copyFrom(M);
+ return *this;
+ }
+ Value &operator=(Value &&M) {
+ destroy();
+ moveFrom(std::move(M));
+ return *this;
+ }
+ ~Value() { destroy(); }
+
+ Kind kind() const {
+ switch (Type) {
+ case T_Null:
+ return Null;
+ case T_Boolean:
+ return Boolean;
+ case T_Double:
+ case T_Integer:
+ return Number;
+ case T_String:
+ case T_StringRef:
+ return String;
+ case T_Object:
+ return Object;
+ case T_Array:
+ return Array;
+ }
+ llvm_unreachable("Unknown kind");
+ }
+
+ // Typed accessors return None/nullptr if the Value is not of this type.
+ llvm::Optional<std::nullptr_t> getAsNull() const {
+ if (LLVM_LIKELY(Type == T_Null))
+ return nullptr;
+ return llvm::None;
+ }
+ llvm::Optional<bool> getAsBoolean() const {
+ if (LLVM_LIKELY(Type == T_Boolean))
+ return as<bool>();
+ return llvm::None;
+ }
+ llvm::Optional<double> getAsNumber() const {
+ if (LLVM_LIKELY(Type == T_Double))
+ return as<double>();
+ if (LLVM_LIKELY(Type == T_Integer))
+ return as<int64_t>();
+ return llvm::None;
+ }
+ // Succeeds if the Value is a Number, and exactly representable as int64_t.
+ llvm::Optional<int64_t> getAsInteger() const {
+ if (LLVM_LIKELY(Type == T_Integer))
+ return as<int64_t>();
+ if (LLVM_LIKELY(Type == T_Double)) {
+ double D = as<double>();
+ if (LLVM_LIKELY(std::modf(D, &D) == 0.0 &&
+ D >= double(std::numeric_limits<int64_t>::min()) &&
+ D <= double(std::numeric_limits<int64_t>::max())))
+ return D;
+ }
+ return llvm::None;
+ }
+ llvm::Optional<llvm::StringRef> getAsString() const {
+ if (Type == T_String)
+ return llvm::StringRef(as<std::string>());
+ if (LLVM_LIKELY(Type == T_StringRef))
+ return as<llvm::StringRef>();
+ return llvm::None;
+ }
+ const json::Object *getAsObject() const {
+ return LLVM_LIKELY(Type == T_Object) ? &as<json::Object>() : nullptr;
+ }
+ json::Object *getAsObject() {
+ return LLVM_LIKELY(Type == T_Object) ? &as<json::Object>() : nullptr;
+ }
+ const json::Array *getAsArray() const {
+ return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr;
+ }
+ json::Array *getAsArray() {
+ return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr;
+ }
+
+ /// Serializes this Value to JSON, writing it to the provided stream.
+ /// The formatting is compact (no extra whitespace) and deterministic.
+ /// For pretty-printing, use the formatv() format_provider below.
+ friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &);
+
+private:
+ void destroy();
+ void copyFrom(const Value &M);
+ // We allow moving from *const* Values, by marking all members as mutable!
+ // This hack is needed to support initializer-list syntax efficiently.
+ // (std::initializer_list<T> is a container of const T).
+ void moveFrom(const Value &&M);
+ friend class Array;
+ friend class Object;
+
+ template <typename T, typename... U> void create(U &&... V) {
+ new (reinterpret_cast<T *>(Union.buffer)) T(std::forward<U>(V)...);
+ }
+ template <typename T> T &as() const {
+ return *reinterpret_cast<T *>(Union.buffer);
+ }
+
+ template <typename Indenter>
+ void print(llvm::raw_ostream &, const Indenter &) const;
+ friend struct llvm::format_provider<llvm::json::Value>;
+
+ enum ValueType : char {
+ T_Null,
+ T_Boolean,
+ T_Double,
+ T_Integer,
+ T_StringRef,
+ T_String,
+ T_Object,
+ T_Array,
+ };
+ // All members mutable, see moveFrom().
+ mutable ValueType Type;
+ mutable llvm::AlignedCharArrayUnion<bool, double, int64_t, llvm::StringRef,
+ std::string, json::Array, json::Object>
+ Union;
+};
+
+bool operator==(const Value &, const Value &);
+inline bool operator!=(const Value &L, const Value &R) { return !(L == R); }
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &);
+
+/// ObjectKey is a used to capture keys in Object. Like Value but:
+/// - only strings are allowed
+/// - it's optimized for the string literal case (Owned == nullptr)
+/// Like Value, strings must be UTF-8. See isUTF8 documentation for details.
+class ObjectKey {
+public:
+ ObjectKey(const char *S) : ObjectKey(StringRef(S)) {}
+ ObjectKey(std::string S) : Owned(new std::string(std::move(S))) {
+ if (LLVM_UNLIKELY(!isUTF8(*Owned))) {
+ assert(false && "Invalid UTF-8 in value used as JSON");
+ *Owned = fixUTF8(std::move(*Owned));
+ }
+ Data = *Owned;
+ }
+ ObjectKey(llvm::StringRef S) : Data(S) {
+ if (LLVM_UNLIKELY(!isUTF8(Data))) {
+ assert(false && "Invalid UTF-8 in value used as JSON");
+ *this = ObjectKey(fixUTF8(S));
+ }
+ }
+ ObjectKey(const llvm::SmallVectorImpl<char> &V)
+ : ObjectKey(std::string(V.begin(), V.end())) {}
+ ObjectKey(const llvm::formatv_object_base &V) : ObjectKey(V.str()) {}
+
+ ObjectKey(const ObjectKey &C) { *this = C; }
+ ObjectKey(ObjectKey &&C) : ObjectKey(static_cast<const ObjectKey &&>(C)) {}
+ ObjectKey &operator=(const ObjectKey &C) {
+ if (C.Owned) {
+ Owned.reset(new std::string(*C.Owned));
+ Data = *Owned;
+ } else {
+ Data = C.Data;
+ }
+ return *this;
+ }
+ ObjectKey &operator=(ObjectKey &&) = default;
+
+ operator llvm::StringRef() const { return Data; }
+ std::string str() const { return Data.str(); }
+
+private:
+ // FIXME: this is unneccesarily large (3 pointers). Pointer + length + owned
+ // could be 2 pointers at most.
+ std::unique_ptr<std::string> Owned;
+ llvm::StringRef Data;
+};
+
+inline bool operator==(const ObjectKey &L, const ObjectKey &R) {
+ return llvm::StringRef(L) == llvm::StringRef(R);
+}
+inline bool operator!=(const ObjectKey &L, const ObjectKey &R) {
+ return !(L == R);
+}
+inline bool operator<(const ObjectKey &L, const ObjectKey &R) {
+ return StringRef(L) < StringRef(R);
+}
+
+struct Object::KV {
+ ObjectKey K;
+ Value V;
+};
+
+inline Object::Object(std::initializer_list<KV> Properties) {
+ for (const auto &P : Properties) {
+ auto R = try_emplace(P.K, nullptr);
+ if (R.second)
+ R.first->getSecond().moveFrom(std::move(P.V));
+ }
+}
+inline std::pair<Object::iterator, bool> Object::insert(KV E) {
+ return try_emplace(std::move(E.K), std::move(E.V));
+}
+
+// Standard deserializers are provided for primitive types.
+// See comments on Value.
+inline bool fromJSON(const Value &E, std::string &Out) {
+ if (auto S = E.getAsString()) {
+ Out = *S;
+ return true;
+ }
+ return false;
+}
+inline bool fromJSON(const Value &E, int &Out) {
+ if (auto S = E.getAsInteger()) {
+ Out = *S;
+ return true;
+ }
+ return false;
+}
+inline bool fromJSON(const Value &E, int64_t &Out) {
+ if (auto S = E.getAsInteger()) {
+ Out = *S;
+ return true;
+ }
+ return false;
+}
+inline bool fromJSON(const Value &E, double &Out) {
+ if (auto S = E.getAsNumber()) {
+ Out = *S;
+ return true;
+ }
+ return false;
+}
+inline bool fromJSON(const Value &E, bool &Out) {
+ if (auto S = E.getAsBoolean()) {
+ Out = *S;
+ return true;
+ }
+ return false;
+}
+template <typename T> bool fromJSON(const Value &E, llvm::Optional<T> &Out) {
+ if (E.getAsNull()) {
+ Out = llvm::None;
+ return true;
+ }
+ T Result;
+ if (!fromJSON(E, Result))
+ return false;
+ Out = std::move(Result);
+ return true;
+}
+template <typename T> bool fromJSON(const Value &E, std::vector<T> &Out) {
+ if (auto *A = E.getAsArray()) {
+ Out.clear();
+ Out.resize(A->size());
+ for (size_t I = 0; I < A->size(); ++I)
+ if (!fromJSON((*A)[I], Out[I]))
+ return false;
+ return true;
+ }
+ return false;
+}
+template <typename T>
+bool fromJSON(const Value &E, std::map<std::string, T> &Out) {
+ if (auto *O = E.getAsObject()) {
+ Out.clear();
+ for (const auto &KV : *O)
+ if (!fromJSON(KV.second, Out[llvm::StringRef(KV.first)]))
+ return false;
+ return true;
+ }
+ return false;
+}
+
+// Allow serialization of Optional<T> for supported T.
+template <typename T> Value toJSON(const llvm::Optional<T> &Opt) {
+ return Opt ? Value(*Opt) : Value(nullptr);
+}
+
+/// Helper for mapping JSON objects onto protocol structs.
+///
+/// Example:
+/// \code
+/// bool fromJSON(const Value &E, MyStruct &R) {
+/// ObjectMapper O(E);
+/// if (!O || !O.map("mandatory_field", R.MandatoryField))
+/// return false;
+/// O.map("optional_field", R.OptionalField);
+/// return true;
+/// }
+/// \endcode
+class ObjectMapper {
+public:
+ ObjectMapper(const Value &E) : O(E.getAsObject()) {}
+
+ /// True if the expression is an object.
+ /// Must be checked before calling map().
+ operator bool() { return O; }
+
+ /// Maps a property to a field, if it exists.
+ template <typename T> bool map(StringRef Prop, T &Out) {
+ assert(*this && "Must check this is an object before calling map()");
+ if (const Value *E = O->get(Prop))
+ return fromJSON(*E, Out);
+ return false;
+ }
+
+ /// Maps a property to a field, if it exists.
+ /// (Optional requires special handling, because missing keys are OK).
+ template <typename T> bool map(StringRef Prop, llvm::Optional<T> &Out) {
+ assert(*this && "Must check this is an object before calling map()");
+ if (const Value *E = O->get(Prop))
+ return fromJSON(*E, Out);
+ Out = llvm::None;
+ return true;
+ }
+
+private:
+ const Object *O;
+};
+
+/// Parses the provided JSON source, or returns a ParseError.
+/// The returned Value is self-contained and owns its strings (they do not refer
+/// to the original source).
+llvm::Expected<Value> parse(llvm::StringRef JSON);
+
+class ParseError : public llvm::ErrorInfo<ParseError> {
+ const char *Msg;
+ unsigned Line, Column, Offset;
+
+public:
+ static char ID;
+ ParseError(const char *Msg, unsigned Line, unsigned Column, unsigned Offset)
+ : Msg(Msg), Line(Line), Column(Column), Offset(Offset) {}
+ void log(llvm::raw_ostream &OS) const override {
+ OS << llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line, Column, Offset, Msg);
+ }
+ std::error_code convertToErrorCode() const override {
+ return llvm::inconvertibleErrorCode();
+ }
+};
+} // namespace json
+
+/// Allow printing json::Value with formatv().
+/// The default style is basic/compact formatting, like operator<<.
+/// A format string like formatv("{0:2}", Value) pretty-prints with indent 2.
+template <> struct format_provider<llvm::json::Value> {
+ static void format(const llvm::json::Value &, raw_ostream &, StringRef);
+};
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/Support/JamCRC.h b/contrib/llvm/include/llvm/Support/JamCRC.h
index 5268bbd9ba1e..846d6cea9828 100644
--- a/contrib/llvm/include/llvm/Support/JamCRC.h
+++ b/contrib/llvm/include/llvm/Support/JamCRC.h
@@ -36,7 +36,7 @@ class JamCRC {
public:
JamCRC(uint32_t Init = 0xFFFFFFFFU) : CRC(Init) {}
- // \brief Update the CRC calculation with Data.
+ // Update the CRC calculation with Data.
void update(ArrayRef<char> Data);
uint32_t getCRC() const { return CRC; }
diff --git a/contrib/llvm/include/llvm/Support/KnownBits.h b/contrib/llvm/include/llvm/Support/KnownBits.h
index 97e73b13fca3..259df9546c57 100644
--- a/contrib/llvm/include/llvm/Support/KnownBits.h
+++ b/contrib/llvm/include/llvm/Support/KnownBits.h
@@ -103,7 +103,7 @@ public:
One.setSignBit();
}
- /// Make this value negative.
+ /// Make this value non-negative.
void makeNonNegative() {
Zero.setSignBit();
}
diff --git a/contrib/llvm/include/llvm/Support/LEB128.h b/contrib/llvm/include/llvm/Support/LEB128.h
index 6af6e9f34474..9feb07229225 100644
--- a/contrib/llvm/include/llvm/Support/LEB128.h
+++ b/contrib/llvm/include/llvm/Support/LEB128.h
@@ -19,9 +19,10 @@
namespace llvm {
-/// Utility function to encode a SLEB128 value to an output stream.
-inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
- unsigned PadTo = 0) {
+/// Utility function to encode a SLEB128 value to an output stream. Returns
+/// the length in bytes of the encoded value.
+inline unsigned encodeSLEB128(int64_t Value, raw_ostream &OS,
+ unsigned PadTo = 0) {
bool More;
unsigned Count = 0;
do {
@@ -42,7 +43,9 @@ inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
for (; Count < PadTo - 1; ++Count)
OS << char(PadValue | 0x80);
OS << char(PadValue);
+ Count++;
}
+ return Count;
}
/// Utility function to encode a SLEB128 value to a buffer. Returns
@@ -73,9 +76,10 @@ inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned PadTo = 0) {
return (unsigned)(p - orig_p);
}
-/// Utility function to encode a ULEB128 value to an output stream.
-inline void encodeULEB128(uint64_t Value, raw_ostream &OS,
- unsigned PadTo = 0) {
+/// Utility function to encode a ULEB128 value to an output stream. Returns
+/// the length in bytes of the encoded value.
+inline unsigned encodeULEB128(uint64_t Value, raw_ostream &OS,
+ unsigned PadTo = 0) {
unsigned Count = 0;
do {
uint8_t Byte = Value & 0x7f;
@@ -93,6 +97,7 @@ inline void encodeULEB128(uint64_t Value, raw_ostream &OS,
OS << '\x00';
Count++;
}
+ return Count;
}
/// Utility function to encode a ULEB128 value to a buffer. Returns
diff --git a/contrib/llvm/include/llvm/Support/LineIterator.h b/contrib/llvm/include/llvm/Support/LineIterator.h
index 9d4cd3bd4c6d..892d289976cb 100644
--- a/contrib/llvm/include/llvm/Support/LineIterator.h
+++ b/contrib/llvm/include/llvm/Support/LineIterator.h
@@ -18,7 +18,7 @@ namespace llvm {
class MemoryBuffer;
-/// \brief A forward iterator which reads text lines from a buffer.
+/// A forward iterator which reads text lines from a buffer.
///
/// This class provides a forward iterator interface for reading one line at
/// a time from a buffer. When default constructed the iterator will be the
@@ -39,23 +39,23 @@ class line_iterator
StringRef CurrentLine;
public:
- /// \brief Default construct an "end" iterator.
+ /// Default construct an "end" iterator.
line_iterator() : Buffer(nullptr) {}
- /// \brief Construct a new iterator around some memory buffer.
+ /// Construct a new iterator around some memory buffer.
explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true,
char CommentMarker = '\0');
- /// \brief Return true if we've reached EOF or are an "end" iterator.
+ /// Return true if we've reached EOF or are an "end" iterator.
bool is_at_eof() const { return !Buffer; }
- /// \brief Return true if we're an "end" iterator or have reached EOF.
+ /// Return true if we're an "end" iterator or have reached EOF.
bool is_at_end() const { return is_at_eof(); }
- /// \brief Return the current line number. May return any number at EOF.
+ /// Return the current line number. May return any number at EOF.
int64_t line_number() const { return LineNumber; }
- /// \brief Advance to the next (non-empty, non-comment) line.
+ /// Advance to the next (non-empty, non-comment) line.
line_iterator &operator++() {
advance();
return *this;
@@ -66,7 +66,7 @@ public:
return tmp;
}
- /// \brief Get the current line as a \c StringRef.
+ /// Get the current line as a \c StringRef.
StringRef operator*() const { return CurrentLine; }
const StringRef *operator->() const { return &CurrentLine; }
@@ -80,7 +80,7 @@ public:
}
private:
- /// \brief Advance the iterator to the next line.
+ /// Advance the iterator to the next line.
void advance();
};
}
diff --git a/contrib/llvm/include/llvm/Support/LockFileManager.h b/contrib/llvm/include/llvm/Support/LockFileManager.h
index 1e417bdd5b25..86db0b2b1020 100644
--- a/contrib/llvm/include/llvm/Support/LockFileManager.h
+++ b/contrib/llvm/include/llvm/Support/LockFileManager.h
@@ -11,14 +11,13 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/FileSystem.h"
#include <system_error>
#include <utility> // for std::pair
namespace llvm {
class StringRef;
-/// \brief Class that manages the creation of a lock file to aid
+/// Class that manages the creation of a lock file to aid
/// implicit coordination between different processes.
///
/// The implicit coordination works by creating a ".lock" file alongside
@@ -28,33 +27,33 @@ class StringRef;
/// operation.
class LockFileManager {
public:
- /// \brief Describes the state of a lock file.
+ /// Describes the state of a lock file.
enum LockFileState {
- /// \brief The lock file has been created and is owned by this instance
+ /// The lock file has been created and is owned by this instance
/// of the object.
LFS_Owned,
- /// \brief The lock file already exists and is owned by some other
+ /// The lock file already exists and is owned by some other
/// instance.
LFS_Shared,
- /// \brief An error occurred while trying to create or find the lock
+ /// An error occurred while trying to create or find the lock
/// file.
LFS_Error
};
- /// \brief Describes the result of waiting for the owner to release the lock.
+ /// Describes the result of waiting for the owner to release the lock.
enum WaitForUnlockResult {
- /// \brief The lock was released successfully.
+ /// The lock was released successfully.
Res_Success,
- /// \brief Owner died while holding the lock.
+ /// Owner died while holding the lock.
Res_OwnerDied,
- /// \brief Reached timeout while waiting for the owner to release the lock.
+ /// Reached timeout while waiting for the owner to release the lock.
Res_Timeout
};
private:
SmallString<128> FileName;
SmallString<128> LockFileName;
- Optional<sys::fs::TempFile> UniqueLockFile;
+ SmallString<128> UniqueLockFileName;
Optional<std::pair<std::string, int> > Owner;
std::error_code ErrorCode;
@@ -73,22 +72,22 @@ public:
LockFileManager(StringRef FileName);
~LockFileManager();
- /// \brief Determine the state of the lock file.
+ /// Determine the state of the lock file.
LockFileState getState() const;
operator LockFileState() const { return getState(); }
- /// \brief For a shared lock, wait until the owner releases the lock.
+ /// 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
+ /// 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();
- /// \brief Get error message, or "" if there is no error.
+ /// Get error message, or "" if there is no error.
std::string getErrorMessage() const;
- /// \brief Set error and error message
+ /// Set error and error message
void setError(const std::error_code &EC, StringRef ErrorMsg = "") {
ErrorCode = EC;
ErrorDiagMsg = ErrorMsg.str();
diff --git a/contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h b/contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h
index 099fa4618997..a0a5a52d206e 100644
--- a/contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h
+++ b/contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h
@@ -28,7 +28,7 @@
#define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/Support/MachineValueType.h"
#include <cassert>
namespace llvm {
diff --git a/contrib/llvm/include/llvm/Support/MD5.h b/contrib/llvm/include/llvm/Support/MD5.h
index 2c0dc76485f8..bb2bdbf1bed2 100644
--- a/contrib/llvm/include/llvm/Support/MD5.h
+++ b/contrib/llvm/include/llvm/Support/MD5.h
@@ -81,20 +81,20 @@ public:
MD5();
- /// \brief Updates the hash for the byte stream provided.
+ /// Updates the hash for the byte stream provided.
void update(ArrayRef<uint8_t> Data);
- /// \brief Updates the hash for the StringRef provided.
+ /// Updates the hash for the StringRef provided.
void update(StringRef Str);
- /// \brief Finishes off the hash and puts the result in result.
+ /// Finishes off the hash and puts the result in result.
void final(MD5Result &Result);
- /// \brief Translates the bytes in \p Res to a hex string that is
+ /// Translates the bytes in \p Res to a hex string that is
/// deposited into \p Str. The result will be of length 32.
static void stringifyResult(MD5Result &Result, SmallString<32> &Str);
- /// \brief Computes the hash for a given bytes.
+ /// Computes the hash for a given bytes.
static std::array<uint8_t, 16> hash(ArrayRef<uint8_t> Data);
private:
diff --git a/contrib/llvm/include/llvm/CodeGen/MachineValueType.h b/contrib/llvm/include/llvm/Support/MachineValueType.h
index b452684757f6..552dea05029c 100644
--- a/contrib/llvm/include/llvm/CodeGen/MachineValueType.h
+++ b/contrib/llvm/include/llvm/Support/MachineValueType.h
@@ -1,4 +1,4 @@
-//===- CodeGen/MachineValueType.h - Machine-Level types ---------*- C++ -*-===//
+//===- Support/MachineValueType.h - Machine-Level types ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H
-#define LLVM_CODEGEN_MACHINEVALUETYPE_H
+#ifndef LLVM_SUPPORT_MACHINEVALUETYPE_H
+#define LLVM_SUPPORT_MACHINEVALUETYPE_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
@@ -191,8 +191,10 @@ namespace llvm {
// unspecified type. The register class
// will be determined by the opcode.
+ ExceptRef = 113, // WebAssembly's except_ref type
+
FIRST_VALUETYPE = 1, // This is always the beginning of the list.
- LAST_VALUETYPE = 113, // This always remains at the end of the list.
+ LAST_VALUETYPE = 114, // This always remains at the end of the list.
// This is the current maximum for LAST_VALUETYPE.
// MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
@@ -376,7 +378,7 @@ namespace llvm {
SimpleTy == MVT::v16i64);
}
- /// Return true if this is a 1024-bit vector type.
+ /// Return true if this is a 2048-bit vector type.
bool is2048BitVector() const {
return (SimpleTy == MVT::v256i8 || SimpleTy == MVT::v128i16 ||
SimpleTy == MVT::v64i32 || SimpleTy == MVT::v32i64);
@@ -746,6 +748,7 @@ namespace llvm {
case v64i32:
case v32i64:
case nxv32i64: return 2048;
+ case ExceptRef: return 0; // opaque type
}
}
diff --git a/contrib/llvm/include/llvm/Support/MathExtras.h b/contrib/llvm/include/llvm/Support/MathExtras.h
index a37a16784e2a..b59f21b4998e 100644
--- a/contrib/llvm/include/llvm/Support/MathExtras.h
+++ b/contrib/llvm/include/llvm/Support/MathExtras.h
@@ -23,22 +23,30 @@
#include <limits>
#include <type_traits>
-#ifdef _MSC_VER
-#include <intrin.h>
-#endif
-
#ifdef __ANDROID_NDK__
#include <android/api-level.h>
#endif
+#ifdef _MSC_VER
+// Declare these intrinsics manually rather including intrin.h. It's very
+// expensive, and MathExtras.h is popular.
+// #include <intrin.h>
+extern "C" {
+unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
+unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
+unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
+unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
+}
+#endif
+
namespace llvm {
-/// \brief The behavior an operation has on an input of 0.
+/// The behavior an operation has on an input of 0.
enum ZeroBehavior {
- /// \brief The returned value is undefined.
+ /// The returned value is undefined.
ZB_Undefined,
- /// \brief The returned value is numeric_limits<T>::max()
+ /// The returned value is numeric_limits<T>::max()
ZB_Max,
- /// \brief The returned value is numeric_limits<T>::digits
+ /// The returned value is numeric_limits<T>::digits
ZB_Width
};
@@ -101,7 +109,7 @@ template <typename T> struct TrailingZerosCounter<T, 8> {
#endif
} // namespace detail
-/// \brief Count number of 0's from the least significant bit to the most
+/// Count number of 0's from the least significant bit to the most
/// stopping at the first 1.
///
/// Only unsigned integral types are allowed.
@@ -170,7 +178,7 @@ template <typename T> struct LeadingZerosCounter<T, 8> {
#endif
} // namespace detail
-/// \brief Count number of 0's from the most significant bit to the least
+/// Count number of 0's from the most significant bit to the least
/// stopping at the first 1.
///
/// Only unsigned integral types are allowed.
@@ -185,7 +193,7 @@ std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
}
-/// \brief Get the index of the first set bit starting from the least
+/// Get the index of the first set bit starting from the least
/// significant bit.
///
/// Only unsigned integral types are allowed.
@@ -199,7 +207,7 @@ template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
return countTrailingZeros(Val, ZB_Undefined);
}
-/// \brief Create a bitmask with the N right-most bits set to 1, and all other
+/// Create a bitmask with the N right-most bits set to 1, and all other
/// bits set to 0. Only unsigned types are allowed.
template <typename T> T maskTrailingOnes(unsigned N) {
static_assert(std::is_unsigned<T>::value, "Invalid type!");
@@ -208,25 +216,25 @@ template <typename T> T maskTrailingOnes(unsigned N) {
return N == 0 ? 0 : (T(-1) >> (Bits - N));
}
-/// \brief Create a bitmask with the N left-most bits set to 1, and all other
+/// Create a bitmask with the N left-most bits set to 1, and all other
/// bits set to 0. Only unsigned types are allowed.
template <typename T> T maskLeadingOnes(unsigned N) {
return ~maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
}
-/// \brief Create a bitmask with the N right-most bits set to 0, and all other
+/// Create a bitmask with the N right-most bits set to 0, and all other
/// bits set to 1. Only unsigned types are allowed.
template <typename T> T maskTrailingZeros(unsigned N) {
return maskLeadingOnes<T>(CHAR_BIT * sizeof(T) - N);
}
-/// \brief Create a bitmask with the N left-most bits set to 0, and all other
+/// Create a bitmask with the N left-most bits set to 0, and all other
/// bits set to 1. Only unsigned types are allowed.
template <typename T> T maskLeadingZeros(unsigned N) {
return maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
}
-/// \brief Get the index of the last set bit starting from the least
+/// Get the index of the last set bit starting from the least
/// significant bit.
///
/// Only unsigned integral types are allowed.
@@ -243,7 +251,7 @@ template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
(std::numeric_limits<T>::digits - 1);
}
-/// \brief Macro compressed bit reversal table for 256 bits.
+/// Macro compressed bit reversal table for 256 bits.
///
/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
static const unsigned char BitReverseTable256[256] = {
@@ -256,7 +264,7 @@ static const unsigned char BitReverseTable256[256] = {
#undef R6
};
-/// \brief Reverse the bits in \p Val.
+/// Reverse the bits in \p Val.
template <typename T>
T reverseBits(T Val) {
unsigned char in[sizeof(Val)];
@@ -442,7 +450,7 @@ inline uint64_t ByteSwap_64(uint64_t Value) {
return sys::SwapByteOrder_64(Value);
}
-/// \brief Count the number of ones from the most significant bit to the first
+/// Count the number of ones from the most significant bit to the first
/// zero bit.
///
/// Ex. countLeadingOnes(0xFF0FFF00) == 8.
@@ -455,10 +463,10 @@ 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);
+ return countLeadingZeros<T>(~Value, ZB);
}
-/// \brief Count the number of ones from the least significant bit to the first
+/// Count the number of ones from the least significant bit to the first
/// zero bit.
///
/// Ex. countTrailingOnes(0x00FF00FF) == 8.
@@ -471,7 +479,7 @@ 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);
+ return countTrailingZeros<T>(~Value, ZB);
}
namespace detail {
@@ -505,7 +513,7 @@ template <typename T> struct PopulationCounter<T, 8> {
};
} // namespace detail
-/// \brief Count the number of set bits in a value.
+/// Count the number of set bits in a value.
/// Ex. countPopulation(0xF000F000) = 8
/// Returns 0 if the word is zero.
template <typename T>
@@ -608,7 +616,7 @@ constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) {
return (A | B) & (1 + ~(A | B));
}
-/// \brief Aligns \c Addr to \c Alignment bytes, rounding up.
+/// Aligns \c Addr to \c Alignment bytes, rounding up.
///
/// Alignment should be a power of two. This method rounds up, so
/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8.
@@ -621,7 +629,7 @@ inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1));
}
-/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment
+/// Returns the necessary adjustment for aligning \c Ptr to \c Alignment
/// bytes, rounding up.
inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
diff --git a/contrib/llvm/include/llvm/Support/MemAlloc.h b/contrib/llvm/include/llvm/Support/MemAlloc.h
new file mode 100644
index 000000000000..d06c659cfba6
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/MemAlloc.h
@@ -0,0 +1,49 @@
+//===- MemAlloc.h - Memory allocation functions -----------------*- 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 defines counterparts of C library allocation functions defined in
+/// the namespace 'std'. The new allocation functions crash on allocation
+/// failure instead of returning null pointer.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MEMALLOC_H
+#define LLVM_SUPPORT_MEMALLOC_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cstdlib>
+
+namespace llvm {
+
+LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_malloc(size_t Sz) {
+ void *Result = std::malloc(Sz);
+ if (Result == nullptr)
+ report_bad_alloc_error("Allocation failed");
+ return Result;
+}
+
+LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_calloc(size_t Count,
+ size_t Sz) {
+ void *Result = std::calloc(Count, Sz);
+ if (Result == nullptr)
+ report_bad_alloc_error("Allocation failed");
+ return Result;
+}
+
+LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
+ void *Result = std::realloc(Ptr, Sz);
+ if (Result == nullptr)
+ report_bad_alloc_error("Allocation failed");
+ return Result;
+}
+
+}
+#endif
diff --git a/contrib/llvm/include/llvm/Support/Memory.h b/contrib/llvm/include/llvm/Support/Memory.h
index 3140dc6eef42..fa026d49a61b 100644
--- a/contrib/llvm/include/llvm/Support/Memory.h
+++ b/contrib/llvm/include/llvm/Support/Memory.h
@@ -25,7 +25,7 @@ namespace sys {
/// and a size. It is used by the Memory class (a friend) as the result of
/// various memory allocation operations.
/// @see Memory
- /// @brief Memory block abstraction.
+ /// Memory block abstraction.
class MemoryBlock {
public:
MemoryBlock() : Address(nullptr), Size(0) { }
@@ -42,7 +42,7 @@ namespace sys {
/// This class provides various memory handling functions that manipulate
/// MemoryBlock instances.
/// @since 1.4
- /// @brief An abstraction for memory operations.
+ /// An abstraction for memory operations.
class Memory {
public:
enum ProtectionFlags {
@@ -74,7 +74,7 @@ namespace sys {
/// \r a non-null MemoryBlock if the function was successful,
/// otherwise a null MemoryBlock is with \p EC describing the error.
///
- /// @brief Allocate mapped memory.
+ /// Allocate mapped memory.
static MemoryBlock allocateMappedMemory(size_t NumBytes,
const MemoryBlock *const NearBlock,
unsigned Flags,
@@ -88,7 +88,7 @@ namespace sys {
/// \r error_success if the function was successful, or an error_code
/// describing the failure if an error occurred.
///
- /// @brief Release mapped memory.
+ /// Release mapped memory.
static std::error_code releaseMappedMemory(MemoryBlock &Block);
/// This method sets the protection flags for a block of memory to the
@@ -105,7 +105,7 @@ namespace sys {
/// \r error_success if the function was successful, or an error_code
/// describing the failure if an error occurred.
///
- /// @brief Set memory protection state.
+ /// Set memory protection state.
static std::error_code protectMappedMemory(const MemoryBlock &Block,
unsigned Flags);
diff --git a/contrib/llvm/include/llvm/Support/MemoryBuffer.h b/contrib/llvm/include/llvm/Support/MemoryBuffer.h
index 7b849fdb8670..535579ecff53 100644
--- a/contrib/llvm/include/llvm/Support/MemoryBuffer.h
+++ b/contrib/llvm/include/llvm/Support/MemoryBuffer.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
#include <cstddef>
#include <cstdint>
#include <memory>
@@ -49,7 +50,8 @@ protected:
void init(const char *BufStart, const char *BufEnd,
bool RequiresNullTerminator);
- static constexpr bool Writable = false;
+ static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
+ sys::fs::mapped_file_region::readonly;
public:
MemoryBuffer(const MemoryBuffer &) = delete;
@@ -117,12 +119,6 @@ public:
static std::unique_ptr<MemoryBuffer>
getMemBufferCopy(StringRef InputData, const Twine &BufferName = "");
- /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note
- /// that the caller need not initialize the memory allocated by this method.
- /// The memory is owned by the MemoryBuffer object.
- static std::unique_ptr<MemoryBuffer>
- getNewMemBuffer(size_t Size, StringRef BufferName = "");
-
/// Read all of stdin into a file buffer, and return it.
static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN();
@@ -152,17 +148,21 @@ public:
virtual BufferKind getBufferKind() const = 0;
MemoryBufferRef getMemBufferRef() const;
+
+private:
+ virtual void anchor();
};
-/// This class is an extension of MemoryBuffer, which allows writing to the
-/// underlying contents. It only supports creation methods that are guaranteed
-/// to produce a writable buffer. For example, mapping a file read-only is not
-/// supported.
+/// This class is an extension of MemoryBuffer, which allows copy-on-write
+/// access to the underlying contents. It only supports creation methods that
+/// are guaranteed to produce a writable buffer. For example, mapping a file
+/// read-only is not supported.
class WritableMemoryBuffer : public MemoryBuffer {
protected:
WritableMemoryBuffer() = default;
- static constexpr bool Writable = true;
+ static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
+ sys::fs::mapped_file_region::priv;
public:
using MemoryBuffer::getBuffer;
@@ -196,6 +196,60 @@ public:
static std::unique_ptr<WritableMemoryBuffer>
getNewUninitMemBuffer(size_t Size, const Twine &BufferName = "");
+ /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note
+ /// that the caller need not initialize the memory allocated by this method.
+ /// The memory is owned by the MemoryBuffer object.
+ static std::unique_ptr<WritableMemoryBuffer>
+ getNewMemBuffer(size_t Size, const Twine &BufferName = "");
+
+private:
+ // Hide these base class factory function so one can't write
+ // WritableMemoryBuffer::getXXX()
+ // and be surprised that he got a read-only Buffer.
+ using MemoryBuffer::getFileAsStream;
+ using MemoryBuffer::getFileOrSTDIN;
+ using MemoryBuffer::getMemBuffer;
+ using MemoryBuffer::getMemBufferCopy;
+ using MemoryBuffer::getOpenFile;
+ using MemoryBuffer::getOpenFileSlice;
+ using MemoryBuffer::getSTDIN;
+};
+
+/// This class is an extension of MemoryBuffer, which allows write access to
+/// the underlying contents and committing those changes to the original source.
+/// It only supports creation methods that are guaranteed to produce a writable
+/// buffer. For example, mapping a file read-only is not supported.
+class WriteThroughMemoryBuffer : public MemoryBuffer {
+protected:
+ WriteThroughMemoryBuffer() = default;
+
+ static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
+ sys::fs::mapped_file_region::readwrite;
+
+public:
+ using MemoryBuffer::getBuffer;
+ using MemoryBuffer::getBufferEnd;
+ using MemoryBuffer::getBufferStart;
+
+ // const_cast is well-defined here, because the underlying buffer is
+ // guaranteed to have been initialized with a mutable buffer.
+ char *getBufferStart() {
+ return const_cast<char *>(MemoryBuffer::getBufferStart());
+ }
+ char *getBufferEnd() {
+ return const_cast<char *>(MemoryBuffer::getBufferEnd());
+ }
+ MutableArrayRef<char> getBuffer() {
+ return {getBufferStart(), getBufferEnd()};
+ }
+
+ static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
+ getFile(const Twine &Filename, int64_t FileSize = -1);
+
+ /// Map a subrange of the specified file as a ReadWriteMemoryBuffer.
+ static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
+ getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
+
private:
// Hide these base class factory function so one can't write
// WritableMemoryBuffer::getXXX()
@@ -204,7 +258,6 @@ private:
using MemoryBuffer::getFileOrSTDIN;
using MemoryBuffer::getMemBuffer;
using MemoryBuffer::getMemBufferCopy;
- using MemoryBuffer::getNewMemBuffer;
using MemoryBuffer::getOpenFile;
using MemoryBuffer::getOpenFileSlice;
using MemoryBuffer::getSTDIN;
diff --git a/contrib/llvm/include/llvm/Support/MipsABIFlags.h b/contrib/llvm/include/llvm/Support/MipsABIFlags.h
index 93f6b416ba88..12c350015b21 100644
--- a/contrib/llvm/include/llvm/Support/MipsABIFlags.h
+++ b/contrib/llvm/include/llvm/Support/MipsABIFlags.h
@@ -42,7 +42,9 @@ enum AFL_ASE {
AFL_ASE_MSA = 0x00000200, // MSA ASE
AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE
AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE
- AFL_ASE_XPA = 0x00001000 // XPA ASE
+ AFL_ASE_XPA = 0x00001000, // XPA ASE
+ AFL_ASE_CRC = 0x00008000, // CRC ASE
+ AFL_ASE_GINV = 0x00020000 // GINV ASE
};
// Values for the isa_ext word of an ABI flags structure.
diff --git a/contrib/llvm/include/llvm/Support/Mutex.h b/contrib/llvm/include/llvm/Support/Mutex.h
index 0f4e61af4439..680d94b24ef5 100644
--- a/contrib/llvm/include/llvm/Support/Mutex.h
+++ b/contrib/llvm/include/llvm/Support/Mutex.h
@@ -14,6 +14,7 @@
#ifndef LLVM_SUPPORT_MUTEX_H
#define LLVM_SUPPORT_MUTEX_H
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Threading.h"
#include <cassert>
@@ -22,7 +23,7 @@ namespace llvm
{
namespace sys
{
- /// @brief Platform agnostic Mutex class.
+ /// Platform agnostic Mutex class.
class MutexImpl
{
/// @name Constructors
@@ -33,11 +34,11 @@ namespace llvm
/// to false, the lock will not be recursive which makes it cheaper but
/// also more likely to deadlock (same thread can't acquire more than
/// once).
- /// @brief Default Constructor.
+ /// Default Constructor.
explicit MutexImpl(bool recursive = true);
/// Releases and removes the lock
- /// @brief Destructor
+ /// Destructor
~MutexImpl();
/// @}
@@ -48,14 +49,14 @@ namespace llvm
/// Attempts to unconditionally acquire the lock. If the lock is held by
/// another thread, this method will wait until it can acquire the lock.
/// @returns false if any kind of error occurs, true otherwise.
- /// @brief Unconditionally acquire the lock.
+ /// Unconditionally acquire the lock.
bool acquire();
/// Attempts to release the lock. If the lock is held by the current
/// thread, the lock is released allowing other threads to acquire the
/// lock.
/// @returns false if any kind of error occurs, true otherwise.
- /// @brief Unconditionally release the lock.
+ /// Unconditionally release the lock.
bool release();
/// Attempts to acquire the lock without blocking. If the lock is not
@@ -63,7 +64,7 @@ namespace llvm
/// the lock is available, it is acquired.
/// @returns false if any kind of error occurs or the lock is not
/// available, true otherwise.
- /// @brief Try to acquire the lock.
+ /// Try to acquire the lock.
bool tryacquire();
//@}
diff --git a/contrib/llvm/include/llvm/Support/MutexGuard.h b/contrib/llvm/include/llvm/Support/MutexGuard.h
index 07b64b611960..641d64d94988 100644
--- a/contrib/llvm/include/llvm/Support/MutexGuard.h
+++ b/contrib/llvm/include/llvm/Support/MutexGuard.h
@@ -23,7 +23,7 @@ namespace llvm {
/// these on the stack at the top of some scope to be assured that C++
/// destruction of the object will always release the Mutex and thus avoid
/// a host of nasty multi-threading problems in the face of exceptions, etc.
- /// @brief Guard a section of code with a Mutex.
+ /// Guard a section of code with a Mutex.
class MutexGuard {
sys::Mutex &M;
MutexGuard(const MutexGuard &) = delete;
diff --git a/contrib/llvm/include/llvm/Support/OnDiskHashTable.h b/contrib/llvm/include/llvm/Support/OnDiskHashTable.h
index e9c28daf03b9..912e2700d1a0 100644
--- a/contrib/llvm/include/llvm/Support/OnDiskHashTable.h
+++ b/contrib/llvm/include/llvm/Support/OnDiskHashTable.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines facilities for reading and writing on-disk hash tables.
+/// Defines facilities for reading and writing on-disk hash tables.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_ONDISKHASHTABLE_H
@@ -25,7 +25,7 @@
namespace llvm {
-/// \brief Generates an on disk hash table.
+/// Generates an on disk hash table.
///
/// This needs an \c Info that handles storing values into the hash table's
/// payload and computes the hash for a given key. This should provide the
@@ -57,7 +57,7 @@ namespace llvm {
/// };
/// \endcode
template <typename Info> class OnDiskChainedHashTableGenerator {
- /// \brief A single item in the hash table.
+ /// A single item in the hash table.
class Item {
public:
typename Info::key_type Key;
@@ -75,7 +75,7 @@ template <typename Info> class OnDiskChainedHashTableGenerator {
offset_type NumEntries;
llvm::SpecificBumpPtrAllocator<Item> BA;
- /// \brief A linked list of values in a particular hash bucket.
+ /// A linked list of values in a particular hash bucket.
struct Bucket {
offset_type Off;
unsigned Length;
@@ -85,7 +85,7 @@ template <typename Info> class OnDiskChainedHashTableGenerator {
Bucket *Buckets;
private:
- /// \brief Insert an item into the appropriate hash bucket.
+ /// Insert an item into the appropriate hash bucket.
void insert(Bucket *Buckets, size_t Size, Item *E) {
Bucket &B = Buckets[E->Hash & (Size - 1)];
E->Next = B.Head;
@@ -93,9 +93,10 @@ private:
B.Head = E;
}
- /// \brief Resize the hash table, moving the old entries into the new buckets.
+ /// Resize the hash table, moving the old entries into the new buckets.
void resize(size_t NewSize) {
- Bucket *NewBuckets = (Bucket *)std::calloc(NewSize, sizeof(Bucket));
+ Bucket *NewBuckets = static_cast<Bucket *>(
+ safe_calloc(NewSize, sizeof(Bucket)));
// Populate NewBuckets with the old entries.
for (size_t I = 0; I < NumBuckets; ++I)
for (Item *E = Buckets[I].Head; E;) {
@@ -111,14 +112,14 @@ private:
}
public:
- /// \brief Insert an entry into the table.
+ /// Insert an entry into the table.
void insert(typename Info::key_type_ref Key,
typename Info::data_type_ref Data) {
Info InfoObj;
insert(Key, Data, InfoObj);
}
- /// \brief Insert an entry into the table.
+ /// Insert an entry into the table.
///
/// Uses the provided Info instead of a stack allocated one.
void insert(typename Info::key_type_ref Key,
@@ -129,7 +130,7 @@ public:
insert(Buckets, NumBuckets, new (BA.Allocate()) Item(Key, Data, InfoObj));
}
- /// \brief Determine whether an entry has been inserted.
+ /// Determine whether an entry has been inserted.
bool contains(typename Info::key_type_ref Key, Info &InfoObj) {
unsigned Hash = InfoObj.ComputeHash(Key);
for (Item *I = Buckets[Hash & (NumBuckets - 1)].Head; I; I = I->Next)
@@ -138,18 +139,18 @@ public:
return false;
}
- /// \brief Emit the table to Out, which must not be at offset 0.
+ /// Emit the table to Out, which must not be at offset 0.
offset_type Emit(raw_ostream &Out) {
Info InfoObj;
return Emit(Out, InfoObj);
}
- /// \brief Emit the table to Out, which must not be at offset 0.
+ /// Emit the table to Out, which must not be at offset 0.
///
/// Uses the provided Info instead of a stack allocated one.
offset_type Emit(raw_ostream &Out, Info &InfoObj) {
using namespace llvm::support;
- endian::Writer<little> LE(Out);
+ endian::Writer LE(Out, little);
// Now we're done adding entries, resize the bucket list if it's
// significantly too large. (This only happens if the number of
@@ -226,13 +227,13 @@ public:
NumBuckets = 64;
// Note that we do not need to run the constructors of the individual
// Bucket objects since 'calloc' returns bytes that are all 0.
- Buckets = (Bucket *)std::calloc(NumBuckets, sizeof(Bucket));
+ Buckets = static_cast<Bucket *>(safe_calloc(NumBuckets, sizeof(Bucket)));
}
~OnDiskChainedHashTableGenerator() { std::free(Buckets); }
};
-/// \brief Provides lookup on an on disk hash table.
+/// Provides lookup on an on disk hash table.
///
/// This needs an \c Info that handles reading values from the hash table's
/// payload and computes the hash for a given key. This should provide the
@@ -338,14 +339,14 @@ public:
bool operator!=(const iterator &X) const { return X.Data != Data; }
};
- /// \brief Look up the stored data for a particular key.
+ /// Look up the stored data for a particular key.
iterator find(const external_key_type &EKey, Info *InfoPtr = nullptr) {
const internal_key_type &IKey = InfoObj.GetInternalKey(EKey);
hash_value_type KeyHash = InfoObj.ComputeHash(IKey);
return find_hashed(IKey, KeyHash, InfoPtr);
}
- /// \brief Look up the stored data for a particular key with a known hash.
+ /// Look up the stored data for a particular key with a known hash.
iterator find_hashed(const internal_key_type &IKey, hash_value_type KeyHash,
Info *InfoPtr = nullptr) {
using namespace llvm::support;
@@ -403,7 +404,7 @@ public:
Info &getInfoObj() { return InfoObj; }
- /// \brief Create the hash table.
+ /// Create the hash table.
///
/// \param Buckets is the beginning of the hash table itself, which follows
/// the payload of entire structure. This is the value returned by
@@ -423,7 +424,7 @@ public:
}
};
-/// \brief Provides lookup and iteration over an on disk hash table.
+/// Provides lookup and iteration over an on disk hash table.
///
/// \copydetails llvm::OnDiskChainedHashTable
template <typename Info>
@@ -439,7 +440,7 @@ public:
typedef typename base_type::offset_type offset_type;
private:
- /// \brief Iterates over all of the keys in the table.
+ /// Iterates over all of the keys in the table.
class iterator_base {
const unsigned char *Ptr;
offset_type NumItemsInBucketLeft;
@@ -496,7 +497,7 @@ public:
: base_type(NumBuckets, NumEntries, Buckets, Base, InfoObj),
Payload(Payload) {}
- /// \brief Iterates over all of the keys in the table.
+ /// Iterates over all of the keys in the table.
class key_iterator : public iterator_base {
Info *InfoObj;
@@ -542,7 +543,7 @@ public:
return make_range(key_begin(), key_end());
}
- /// \brief Iterates over all the entries in the table, returning the data.
+ /// Iterates over all the entries in the table, returning the data.
class data_iterator : public iterator_base {
Info *InfoObj;
@@ -585,7 +586,7 @@ public:
return make_range(data_begin(), data_end());
}
- /// \brief Create the hash table.
+ /// Create the hash table.
///
/// \param Buckets is the beginning of the hash table itself, which follows
/// the payload of entire structure. This is the value returned by
diff --git a/contrib/llvm/include/llvm/Support/Options.h b/contrib/llvm/include/llvm/Support/Options.h
index 9019804d24e0..dd321c6a1984 100644
--- a/contrib/llvm/include/llvm/Support/Options.h
+++ b/contrib/llvm/include/llvm/Support/Options.h
@@ -56,7 +56,7 @@ char OptionKey<ValT, Base, Mem>::ID = 0;
} // namespace detail
-/// \brief Singleton class used to register debug options.
+/// Singleton class used to register debug options.
///
/// The OptionRegistry is responsible for managing lifetimes of the options and
/// provides interfaces for option registration and reading values from options.
@@ -66,7 +66,7 @@ class OptionRegistry {
private:
DenseMap<void *, cl::Option *> Options;
- /// \brief Adds a cl::Option to the registry.
+ /// Adds a cl::Option to the registry.
///
/// \param Key unique key for option
/// \param O option to map to \p Key
@@ -79,10 +79,10 @@ public:
~OptionRegistry();
OptionRegistry() {}
- /// \brief Returns a reference to the singleton instance.
+ /// Returns a reference to the singleton instance.
static OptionRegistry &instance();
- /// \brief Registers an option with the OptionRegistry singleton.
+ /// Registers an option with the OptionRegistry singleton.
///
/// \tparam ValT type of the option's data
/// \tparam Base class used to key the option
@@ -100,7 +100,7 @@ public:
instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option);
}
- /// \brief Returns the value of the option.
+ /// Returns the value of the option.
///
/// \tparam ValT type of the option's data
/// \tparam Base class used to key the option
diff --git a/contrib/llvm/include/llvm/Support/Parallel.h b/contrib/llvm/include/llvm/Support/Parallel.h
index 6bc0a6bbaf2b..1462265343be 100644
--- a/contrib/llvm/include/llvm/Support/Parallel.h
+++ b/contrib/llvm/include/llvm/Support/Parallel.h
@@ -56,12 +56,12 @@ public:
~Latch() { sync(); }
void inc() {
- std::unique_lock<std::mutex> lock(Mutex);
+ std::lock_guard<std::mutex> lock(Mutex);
++Count;
}
void dec() {
- std::unique_lock<std::mutex> lock(Mutex);
+ std::lock_guard<std::mutex> lock(Mutex);
if (--Count == 0)
Cond.notify_all();
}
@@ -100,7 +100,7 @@ void parallel_for_each_n(IndexTy Begin, IndexTy End, FuncTy Fn) {
#else
const ptrdiff_t MinParallelSize = 1024;
-/// \brief Inclusive median.
+/// Inclusive median.
template <class RandomAccessIterator, class Comparator>
RandomAccessIterator medianOf3(RandomAccessIterator Start,
RandomAccessIterator End,
@@ -118,7 +118,7 @@ void parallel_quick_sort(RandomAccessIterator Start, RandomAccessIterator End,
const Comparator &Comp, TaskGroup &TG, size_t Depth) {
// Do a sequential sort for small inputs.
if (std::distance(Start, End) < detail::MinParallelSize || Depth == 0) {
- std::sort(Start, End, Comp);
+ llvm::sort(Start, End, Comp);
return;
}
@@ -200,7 +200,7 @@ void sort(Policy policy, RandomAccessIterator Start, RandomAccessIterator End,
const Comparator &Comp = Comparator()) {
static_assert(is_execution_policy<Policy>::value,
"Invalid execution policy!");
- std::sort(Start, End, Comp);
+ llvm::sort(Start, End, Comp);
}
template <class Policy, class IterTy, class FuncTy>
diff --git a/contrib/llvm/include/llvm/Support/Path.h b/contrib/llvm/include/llvm/Support/Path.h
index e5979674cf1c..c4cc93721d7e 100644
--- a/contrib/llvm/include/llvm/Support/Path.h
+++ b/contrib/llvm/include/llvm/Support/Path.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/iterator.h"
#include "llvm/Support/DataTypes.h"
#include <iterator>
+#include <system_error>
namespace llvm {
namespace sys {
@@ -30,7 +31,7 @@ enum class Style { windows, posix, native };
/// @name Lexical Component Iterator
/// @{
-/// @brief Path iterator.
+/// Path iterator.
///
/// This is an input iterator that iterates over the individual components in
/// \a path. The traversal order is as follows:
@@ -66,11 +67,11 @@ public:
const_iterator &operator++(); // preincrement
bool operator==(const const_iterator &RHS) const;
- /// @brief Difference in bytes between this and RHS.
+ /// Difference in bytes between this and RHS.
ptrdiff_t operator-(const const_iterator &RHS) const;
};
-/// @brief Reverse path iterator.
+/// Reverse path iterator.
///
/// This is an input iterator that iterates over the individual components in
/// \a path in reverse order. The traversal order is exactly reversed from that
@@ -91,26 +92,26 @@ public:
reverse_iterator &operator++(); // preincrement
bool operator==(const reverse_iterator &RHS) const;
- /// @brief Difference in bytes between this and RHS.
+ /// Difference in bytes between this and RHS.
ptrdiff_t operator-(const reverse_iterator &RHS) const;
};
-/// @brief Get begin iterator over \a path.
+/// Get begin iterator over \a path.
/// @param path Input path.
/// @returns Iterator initialized with the first component of \a path.
const_iterator begin(StringRef path, Style style = Style::native);
-/// @brief Get end iterator over \a path.
+/// Get end iterator over \a path.
/// @param path Input path.
/// @returns Iterator initialized to the end of \a path.
const_iterator end(StringRef path);
-/// @brief Get reverse begin iterator over \a path.
+/// Get reverse begin iterator over \a path.
/// @param path Input path.
/// @returns Iterator initialized with the first reverse component of \a path.
reverse_iterator rbegin(StringRef path, Style style = Style::native);
-/// @brief Get reverse end iterator over \a path.
+/// Get reverse end iterator over \a path.
/// @param path Input path.
/// @returns Iterator initialized to the reverse end of \a path.
reverse_iterator rend(StringRef path);
@@ -119,7 +120,7 @@ reverse_iterator rend(StringRef path);
/// @name Lexical Modifiers
/// @{
-/// @brief Remove the last component from \a path unless it is the root dir.
+/// Remove the last component from \a path unless it is the root dir.
///
/// @code
/// directory/filename.cpp => directory/
@@ -131,7 +132,7 @@ reverse_iterator rend(StringRef path);
/// @param path A path that is modified to not have a file component.
void remove_filename(SmallVectorImpl<char> &path, Style style = Style::native);
-/// @brief Replace the file extension of \a path with \a extension.
+/// Replace the file extension of \a path with \a extension.
///
/// @code
/// ./filename.cpp => ./filename.extension
@@ -146,7 +147,7 @@ void remove_filename(SmallVectorImpl<char> &path, Style style = Style::native);
void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
Style style = Style::native);
-/// @brief Replace matching path prefix with another path.
+/// Replace matching path prefix with another path.
///
/// @code
/// /foo, /old, /new => /foo
@@ -163,7 +164,7 @@ void replace_path_prefix(SmallVectorImpl<char> &Path,
const StringRef &OldPrefix, const StringRef &NewPrefix,
Style style = Style::native);
-/// @brief Append to path.
+/// Append to path.
///
/// @code
/// /foo + bar/f => /foo/bar/f
@@ -181,7 +182,7 @@ void append(SmallVectorImpl<char> &path, const Twine &a,
void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
const Twine &b = "", const Twine &c = "", const Twine &d = "");
-/// @brief Append to path.
+/// Append to path.
///
/// @code
/// /foo + [bar,f] => /foo/bar/f
@@ -215,7 +216,7 @@ void native(const Twine &path, SmallVectorImpl<char> &result,
/// @param path A path that is transformed to native format.
void native(SmallVectorImpl<char> &path, Style style = Style::native);
-/// @brief Replaces backslashes with slashes if Windows.
+/// Replaces backslashes with slashes if Windows.
///
/// @param path processed path
/// @result The result of replacing backslashes with forward slashes if Windows.
@@ -227,7 +228,7 @@ std::string convert_to_slash(StringRef path, Style style = Style::native);
/// @name Lexical Observers
/// @{
-/// @brief Get root name.
+/// Get root name.
///
/// @code
/// //net/hello => //net
@@ -239,7 +240,7 @@ std::string convert_to_slash(StringRef path, Style style = Style::native);
/// @result The root name of \a path if it has one, otherwise "".
StringRef root_name(StringRef path, Style style = Style::native);
-/// @brief Get root directory.
+/// Get root directory.
///
/// @code
/// /goo/hello => /
@@ -252,7 +253,7 @@ StringRef root_name(StringRef path, Style style = Style::native);
/// "".
StringRef root_directory(StringRef path, Style style = Style::native);
-/// @brief Get root path.
+/// Get root path.
///
/// Equivalent to root_name + root_directory.
///
@@ -260,7 +261,7 @@ StringRef root_directory(StringRef path, Style style = Style::native);
/// @result The root path of \a path if it has one, otherwise "".
StringRef root_path(StringRef path, Style style = Style::native);
-/// @brief Get relative path.
+/// Get relative path.
///
/// @code
/// C:\hello\world => hello\world
@@ -272,7 +273,7 @@ StringRef root_path(StringRef path, Style style = Style::native);
/// @result The path starting after root_path if one exists, otherwise "".
StringRef relative_path(StringRef path, Style style = Style::native);
-/// @brief Get parent path.
+/// Get parent path.
///
/// @code
/// / => <empty>
@@ -284,7 +285,7 @@ StringRef relative_path(StringRef path, Style style = Style::native);
/// @result The parent path of \a path if one exists, otherwise "".
StringRef parent_path(StringRef path, Style style = Style::native);
-/// @brief Get filename.
+/// Get filename.
///
/// @code
/// /foo.txt => foo.txt
@@ -298,7 +299,7 @@ StringRef parent_path(StringRef path, Style style = Style::native);
/// of \a path.
StringRef filename(StringRef path, Style style = Style::native);
-/// @brief Get stem.
+/// Get stem.
///
/// If filename contains a dot but not solely one or two dots, result is the
/// substring of filename ending at (but not including) the last dot. Otherwise
@@ -316,7 +317,7 @@ StringRef filename(StringRef path, Style style = Style::native);
/// @result The stem of \a path.
StringRef stem(StringRef path, Style style = Style::native);
-/// @brief Get extension.
+/// Get extension.
///
/// If filename contains a dot but not solely one or two dots, result is the
/// substring of filename starting at (and including) the last dot, and ending
@@ -332,18 +333,18 @@ StringRef stem(StringRef path, Style style = Style::native);
/// @result The extension of \a path.
StringRef extension(StringRef path, Style style = Style::native);
-/// @brief Check whether the given char is a path separator on the host OS.
+/// Check whether the given char is a path separator on the host OS.
///
/// @param value a character
/// @result true if \a value is a path separator character on the host OS
bool is_separator(char value, Style style = Style::native);
-/// @brief Return the preferred separator for this platform.
+/// Return the preferred separator for this platform.
///
/// @result StringRef of the preferred separator, null-terminated.
StringRef get_separator(Style style = Style::native);
-/// @brief Get the typical temporary directory for the system, e.g.,
+/// Get the typical temporary directory for the system, e.g.,
/// "/var/tmp" or "C:/TEMP"
///
/// @param erasedOnReboot Whether to favor a path that is erased on reboot
@@ -354,13 +355,13 @@ StringRef get_separator(Style style = Style::native);
/// @param result Holds the resulting path name.
void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result);
-/// @brief Get the user's home directory.
+/// Get the user's home directory.
///
/// @param result Holds the resulting path name.
/// @result True if a home directory is set, false otherwise.
bool home_directory(SmallVectorImpl<char> &result);
-/// @brief Get the user's cache directory.
+/// Get the user's cache directory.
///
/// Expect the resulting path to be a directory shared with other
/// applications/services used by the user. Params \p Path1 to \p Path3 can be
@@ -376,7 +377,7 @@ bool home_directory(SmallVectorImpl<char> &result);
bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
const Twine &Path2 = "", const Twine &Path3 = "");
-/// @brief Has root name?
+/// Has root name?
///
/// root_name != ""
///
@@ -384,7 +385,7 @@ bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
/// @result True if the path has a root name, false otherwise.
bool has_root_name(const Twine &path, Style style = Style::native);
-/// @brief Has root directory?
+/// Has root directory?
///
/// root_directory != ""
///
@@ -392,7 +393,7 @@ bool has_root_name(const Twine &path, Style style = Style::native);
/// @result True if the path has a root directory, false otherwise.
bool has_root_directory(const Twine &path, Style style = Style::native);
-/// @brief Has root path?
+/// Has root path?
///
/// root_path != ""
///
@@ -400,7 +401,7 @@ bool has_root_directory(const Twine &path, Style style = Style::native);
/// @result True if the path has a root path, false otherwise.
bool has_root_path(const Twine &path, Style style = Style::native);
-/// @brief Has relative path?
+/// Has relative path?
///
/// relative_path != ""
///
@@ -408,7 +409,7 @@ bool has_root_path(const Twine &path, Style style = Style::native);
/// @result True if the path has a relative path, false otherwise.
bool has_relative_path(const Twine &path, Style style = Style::native);
-/// @brief Has parent path?
+/// Has parent path?
///
/// parent_path != ""
///
@@ -416,7 +417,7 @@ bool has_relative_path(const Twine &path, Style style = Style::native);
/// @result True if the path has a parent path, false otherwise.
bool has_parent_path(const Twine &path, Style style = Style::native);
-/// @brief Has filename?
+/// Has filename?
///
/// filename != ""
///
@@ -424,7 +425,7 @@ bool has_parent_path(const Twine &path, Style style = Style::native);
/// @result True if the path has a filename, false otherwise.
bool has_filename(const Twine &path, Style style = Style::native);
-/// @brief Has stem?
+/// Has stem?
///
/// stem != ""
///
@@ -432,7 +433,7 @@ bool has_filename(const Twine &path, Style style = Style::native);
/// @result True if the path has a stem, false otherwise.
bool has_stem(const Twine &path, Style style = Style::native);
-/// @brief Has extension?
+/// Has extension?
///
/// extension != ""
///
@@ -440,25 +441,25 @@ bool has_stem(const Twine &path, Style style = Style::native);
/// @result True if the path has a extension, false otherwise.
bool has_extension(const Twine &path, Style style = Style::native);
-/// @brief Is path absolute?
+/// Is path absolute?
///
/// @param path Input path.
/// @result True if the path is absolute, false if it is not.
bool is_absolute(const Twine &path, Style style = Style::native);
-/// @brief Is path relative?
+/// Is path relative?
///
/// @param path Input path.
/// @result True if the path is relative, false if it is not.
bool is_relative(const Twine &path, Style style = Style::native);
-/// @brief Remove redundant leading "./" pieces and consecutive separators.
+/// Remove redundant leading "./" pieces and consecutive separators.
///
/// @param path Input path.
/// @result The cleaned-up \a path.
StringRef remove_leading_dotslash(StringRef path, Style style = Style::native);
-/// @brief In-place remove any './' and optionally '../' components from a path.
+/// In-place remove any './' and optionally '../' components from a path.
///
/// @param path processed path
/// @param remove_dot_dot specify if '../' (except for leading "../") should be
@@ -467,6 +468,10 @@ StringRef remove_leading_dotslash(StringRef path, Style style = Style::native);
bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false,
Style style = Style::native);
+#if defined(_WIN32)
+std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16);
+#endif
+
} // end namespace path
} // end namespace sys
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h b/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h
index 794230d606a4..1710b57131d1 100644
--- a/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h
+++ b/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h
@@ -16,6 +16,7 @@
#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
#include "llvm/Support/DataTypes.h"
+#include <assert.h>
#include <type_traits>
namespace llvm {
@@ -111,6 +112,39 @@ template <> struct PointerLikeTypeTraits<uintptr_t> {
enum { NumLowBitsAvailable = 0 };
};
+/// Provide suitable custom traits struct for function pointers.
+///
+/// Function pointers can't be directly given these traits as functions can't
+/// have their alignment computed with `alignof` and we need different casting.
+///
+/// To rely on higher alignment for a specialized use, you can provide a
+/// customized form of this template explicitly with higher alignment, and
+/// potentially use alignment attributes on functions to satisfy that.
+template <int Alignment, typename FunctionPointerT>
+struct FunctionPointerLikeTypeTraits {
+ enum { NumLowBitsAvailable = detail::ConstantLog2<Alignment>::value };
+ static inline void *getAsVoidPointer(FunctionPointerT P) {
+ assert((reinterpret_cast<uintptr_t>(P) &
+ ~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 &&
+ "Alignment not satisfied for an actual function pointer!");
+ return reinterpret_cast<void *>(P);
+ }
+ static inline FunctionPointerT getFromVoidPointer(void *P) {
+ return reinterpret_cast<FunctionPointerT>(P);
+ }
+};
+
+/// Provide a default specialization for function pointers that assumes 4-byte
+/// alignment.
+///
+/// We assume here that functions used with this are always at least 4-byte
+/// aligned. This means that, for example, thumb functions won't work or systems
+/// with weird unaligned function pointers won't work. But all practical systems
+/// we support satisfy this requirement.
+template <typename ReturnT, typename... ParamTs>
+struct PointerLikeTypeTraits<ReturnT (*)(ParamTs...)>
+ : FunctionPointerLikeTypeTraits<4, ReturnT (*)(ParamTs...)> {};
+
} // end namespace llvm
#endif
diff --git a/contrib/llvm/include/llvm/Support/Process.h b/contrib/llvm/include/llvm/Support/Process.h
index 82b0d9f6ba28..f9f1cac86278 100644
--- a/contrib/llvm/include/llvm/Support/Process.h
+++ b/contrib/llvm/include/llvm/Support/Process.h
@@ -26,7 +26,6 @@
#define LLVM_SUPPORT_PROCESS_H
#include "llvm/ADT/Optional.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/DataTypes.h"
@@ -39,13 +38,13 @@ class StringRef;
namespace sys {
-/// \brief A collection of legacy interfaces for querying information about the
+/// A collection of legacy interfaces for querying information about the
/// current executing process.
class Process {
public:
static unsigned getPageSize();
- /// \brief Return process memory usage.
+ /// 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,
/// calloc and realloc functions and includes any "free" holes in the
@@ -67,10 +66,10 @@ public:
/// This function makes the necessary calls to the operating system to
/// prevent core files or any other kind of large memory dumps that can
/// occur when a program fails.
- /// @brief Prevent core file generation.
+ /// Prevent core file generation.
static void PreventCoreFiles();
- /// \brief true if PreventCoreFiles has been called, false otherwise.
+ /// true if PreventCoreFiles has been called, false otherwise.
static bool AreCoreFilesPrevented();
// This function returns the environment variable \arg name's value as a UTF-8
@@ -90,14 +89,6 @@ public:
static Optional<std::string> FindInEnvPath(StringRef EnvName,
StringRef FileName);
- /// This function returns a SmallVector containing the arguments passed from
- /// the operating system to the program. This function expects to be handed
- /// the vector passed in from main.
- static std::error_code
- GetArgumentVector(SmallVectorImpl<const char *> &Args,
- ArrayRef<const char *> ArgsFromMain,
- SpecificBumpPtrAllocator<char> &ArgAllocator);
-
// This functions ensures that the standard file descriptors (input, output,
// and error) are properly mapped to a file descriptor before we use any of
// them. This should only be called by standalone programs, library
diff --git a/contrib/llvm/include/llvm/Support/Program.h b/contrib/llvm/include/llvm/Support/Program.h
index 06fd35078145..1f4dbdce3323 100644
--- a/contrib/llvm/include/llvm/Support/Program.h
+++ b/contrib/llvm/include/llvm/Support/Program.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/ErrorOr.h"
#include <system_error>
@@ -27,35 +28,32 @@ namespace sys {
// a colon on Unix or a semicolon on Windows.
#if defined(LLVM_ON_UNIX)
const char EnvPathSeparator = ':';
-#elif defined (LLVM_ON_WIN32)
+#elif defined (_WIN32)
const char EnvPathSeparator = ';';
#endif
-/// @brief This struct encapsulates information about a process.
-struct ProcessInfo {
-#if defined(LLVM_ON_UNIX)
- typedef pid_t ProcessId;
-#elif defined(LLVM_ON_WIN32)
- typedef unsigned long ProcessId; // Must match the type of DWORD on Windows.
- typedef void * HANDLE; // Must match the type of HANDLE on Windows.
- /// The handle to the process (available on Windows only).
- HANDLE ProcessHandle;
+#if defined(_WIN32)
+ typedef unsigned long procid_t; // Must match the type of DWORD on Windows.
+ typedef void *process_t; // Must match the type of HANDLE on Windows.
#else
-#error "ProcessInfo is not defined for this platform!"
+ typedef pid_t procid_t;
+ typedef procid_t process_t;
#endif
- enum : ProcessId { InvalidPid = 0 };
+ /// This struct encapsulates information about a process.
+ struct ProcessInfo {
+ enum : procid_t { InvalidPid = 0 };
- /// The process identifier.
- ProcessId Pid;
+ procid_t Pid; /// The process identifier.
+ process_t Process; /// Platform-dependent process object.
- /// The return code, set after execution.
- int ReturnCode;
+ /// The return code, set after execution.
+ int ReturnCode;
- ProcessInfo();
-};
+ ProcessInfo();
+ };
- /// \brief Find the first executable file \p Name in \p Paths.
+ /// Find the first executable file \p Name in \p Paths.
///
/// This does not perform hashing as a shell would but instead stats each PATH
/// entry individually so should generally be avoided. Core LLVM library
@@ -91,12 +89,13 @@ struct ProcessInfo {
int ExecuteAndWait(
StringRef Program, ///< Path of the program to be executed. It is
///< presumed this is the result of the findProgramByName method.
- const char **Args, ///< A vector of strings that are passed to the
+ ArrayRef<StringRef> Args, ///< An array of strings that are passed to the
///< program. The first element should be the name of the program.
- ///< The list *must* be terminated by a null char* entry.
- const char **Env = nullptr, ///< An optional vector of strings to use for
- ///< the program's environment. If not provided, the current program's
- ///< environment will be used.
+ ///< The array should **not** be terminated by an empty StringRef.
+ Optional<ArrayRef<StringRef>> Env = None, ///< An optional vector of
+ ///< strings to use for the program's environment. If not provided, the
+ ///< current program's environment will be used. If specified, the
+ ///< vector should **not** be terminated by an empty StringRef.
ArrayRef<Optional<StringRef>> Redirects = {}, ///<
///< An array of optional paths. Should have a size of zero or three.
///< If the array is empty, no redirections are performed.
@@ -125,8 +124,8 @@ struct ProcessInfo {
/// \note On Microsoft Windows systems, users will need to either call
/// \see Wait until the process finished execution or win32 CloseHandle() API
/// on ProcessInfo.ProcessHandle to avoid memory leaks.
- ProcessInfo ExecuteNoWait(StringRef Program, const char **Args,
- const char **Env = nullptr,
+ ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
+ Optional<ArrayRef<StringRef>> Env,
ArrayRef<Optional<StringRef>> Redirects = {},
unsigned MemoryLimit = 0,
std::string *ErrMsg = nullptr,
@@ -135,6 +134,11 @@ struct ProcessInfo {
/// Return true if the given arguments fit within system-specific
/// argument length limits.
bool commandLineFitsWithinSystemLimits(StringRef Program,
+ ArrayRef<StringRef> Args);
+
+ /// Return true if the given arguments fit within system-specific
+ /// argument length limits.
+ bool commandLineFitsWithinSystemLimits(StringRef Program,
ArrayRef<const char *> Args);
/// File encoding options when writing contents that a non-UTF8 tool will
@@ -191,6 +195,14 @@ struct ProcessInfo {
///< string is non-empty upon return an error occurred while invoking the
///< program.
);
+
+#if defined(_WIN32)
+ /// Given a list of command line arguments, quote and escape them as necessary
+ /// to build a single flat command line appropriate for calling CreateProcess
+ /// on
+ /// Windows.
+ std::string flattenWindowsCommandLine(ArrayRef<StringRef> Args);
+#endif
}
}
diff --git a/contrib/llvm/include/llvm/Support/RWMutex.h b/contrib/llvm/include/llvm/Support/RWMutex.h
index 85f4fc09fb87..5ac3e558999b 100644
--- a/contrib/llvm/include/llvm/Support/RWMutex.h
+++ b/contrib/llvm/include/llvm/Support/RWMutex.h
@@ -21,7 +21,7 @@
namespace llvm {
namespace sys {
- /// @brief Platform agnostic RWMutex class.
+ /// Platform agnostic RWMutex class.
class RWMutexImpl
{
/// @name Constructors
@@ -29,7 +29,7 @@ namespace sys {
public:
/// Initializes the lock but doesn't acquire it.
- /// @brief Default Constructor.
+ /// Default Constructor.
explicit RWMutexImpl();
/// @}
@@ -40,7 +40,7 @@ namespace sys {
/// @}
/// Releases and removes the lock
- /// @brief Destructor
+ /// Destructor
~RWMutexImpl();
/// @}
@@ -52,24 +52,24 @@ namespace sys {
/// lock is held by a writer, this method will wait until it can acquire
/// the lock.
/// @returns false if any kind of error occurs, true otherwise.
- /// @brief Unconditionally acquire the lock in reader mode.
+ /// Unconditionally acquire the lock in reader mode.
bool reader_acquire();
/// Attempts to release the lock in reader mode.
/// @returns false if any kind of error occurs, true otherwise.
- /// @brief Unconditionally release the lock in reader mode.
+ /// Unconditionally release the lock in reader mode.
bool reader_release();
/// Attempts to unconditionally acquire the lock in reader mode. If the
/// lock is held by any readers, this method will wait until it can
/// acquire the lock.
/// @returns false if any kind of error occurs, true otherwise.
- /// @brief Unconditionally acquire the lock in writer mode.
+ /// Unconditionally acquire the lock in writer mode.
bool writer_acquire();
/// Attempts to release the lock in writer mode.
/// @returns false if any kind of error occurs, true otherwise.
- /// @brief Unconditionally release the lock in write mode.
+ /// Unconditionally release the lock in write mode.
bool writer_release();
//@}
diff --git a/contrib/llvm/include/llvm/Support/Regex.h b/contrib/llvm/include/llvm/Support/Regex.h
index f498835bcb58..d901eb1e3ffb 100644
--- a/contrib/llvm/include/llvm/Support/Regex.h
+++ b/contrib/llvm/include/llvm/Support/Regex.h
@@ -86,11 +86,11 @@ namespace llvm {
std::string sub(StringRef Repl, StringRef String,
std::string *Error = nullptr);
- /// \brief If this function returns true, ^Str$ is an extended regular
+ /// If this function returns true, ^Str$ is an extended regular
/// expression that matches Str and only Str.
static bool isLiteralERE(StringRef Str);
- /// \brief Turn String into a regex by escaping its special characters.
+ /// Turn String into a regex by escaping its special characters.
static std::string escape(StringRef String);
private:
diff --git a/contrib/llvm/include/llvm/Support/SMLoc.h b/contrib/llvm/include/llvm/Support/SMLoc.h
index 5b8be5505540..c74feff378d6 100644
--- a/contrib/llvm/include/llvm/Support/SMLoc.h
+++ b/contrib/llvm/include/llvm/Support/SMLoc.h
@@ -44,8 +44,8 @@ public:
/// Represents a range in source code.
///
/// SMRange is implemented using a half-open range, as is the convention in C++.
-/// In the string "abc", the range (1,3] represents the substring "bc", and the
-/// range (2,2] represents an empty range between the characters "b" and "c".
+/// In the string "abc", the range [1,3) represents the substring "bc", and the
+/// range [2,2) represents an empty range between the characters "b" and "c".
class SMRange {
public:
SMLoc Start, End;
@@ -54,7 +54,7 @@ public:
SMRange(NoneType) {}
SMRange(SMLoc St, SMLoc En) : Start(St), End(En) {
assert(Start.isValid() == End.isValid() &&
- "Start and end should either both be valid or both be invalid!");
+ "Start and End should either both be valid or both be invalid!");
}
bool isValid() const { return Start.isValid(); }
diff --git a/contrib/llvm/include/llvm/Support/SaveAndRestore.h b/contrib/llvm/include/llvm/Support/SaveAndRestore.h
index ef154ac9c913..8e11789907ad 100644
--- a/contrib/llvm/include/llvm/Support/SaveAndRestore.h
+++ b/contrib/llvm/include/llvm/Support/SaveAndRestore.h
@@ -32,18 +32,6 @@ private:
T OldValue;
};
-/// Similar to \c SaveAndRestore. Operates only on bools; the old value of a
-/// variable is saved, and during the dstor the old value is or'ed with the new
-/// value.
-struct SaveOr {
- SaveOr(bool &X) : X(X), OldValue(X) { X = false; }
- ~SaveOr() { X |= OldValue; }
-
-private:
- bool &X;
- const bool OldValue;
-};
-
} // namespace llvm
#endif
diff --git a/contrib/llvm/include/llvm/Support/ScaledNumber.h b/contrib/llvm/include/llvm/Support/ScaledNumber.h
index cfbdbc751617..3bd3ccedc42c 100644
--- a/contrib/llvm/include/llvm/Support/ScaledNumber.h
+++ b/contrib/llvm/include/llvm/Support/ScaledNumber.h
@@ -33,16 +33,16 @@
namespace llvm {
namespace ScaledNumbers {
-/// \brief Maximum scale; same as APFloat for easy debug printing.
+/// Maximum scale; same as APFloat for easy debug printing.
const int32_t MaxScale = 16383;
-/// \brief Maximum scale; same as APFloat for easy debug printing.
+/// Maximum scale; same as APFloat for easy debug printing.
const int32_t MinScale = -16382;
-/// \brief Get the width of a number.
+/// Get the width of a number.
template <class DigitsT> inline int getWidth() { return sizeof(DigitsT) * 8; }
-/// \brief Conditionally round up a scaled number.
+/// Conditionally round up a scaled number.
///
/// Given \c Digits and \c Scale, round up iff \c ShouldRound is \c true.
/// Always returns \c Scale unless there's an overflow, in which case it
@@ -61,19 +61,19 @@ inline std::pair<DigitsT, int16_t> getRounded(DigitsT Digits, int16_t Scale,
return std::make_pair(Digits, Scale);
}
-/// \brief Convenience helper for 32-bit rounding.
+/// Convenience helper for 32-bit rounding.
inline std::pair<uint32_t, int16_t> getRounded32(uint32_t Digits, int16_t Scale,
bool ShouldRound) {
return getRounded(Digits, Scale, ShouldRound);
}
-/// \brief Convenience helper for 64-bit rounding.
+/// Convenience helper for 64-bit rounding.
inline std::pair<uint64_t, int16_t> getRounded64(uint64_t Digits, int16_t Scale,
bool ShouldRound) {
return getRounded(Digits, Scale, ShouldRound);
}
-/// \brief Adjust a 64-bit scaled number down to the appropriate width.
+/// Adjust a 64-bit scaled number down to the appropriate width.
///
/// \pre Adding 64 to \c Scale will not overflow INT16_MAX.
template <class DigitsT>
@@ -91,24 +91,24 @@ inline std::pair<DigitsT, int16_t> getAdjusted(uint64_t Digits,
Digits & (UINT64_C(1) << (Shift - 1)));
}
-/// \brief Convenience helper for adjusting to 32 bits.
+/// Convenience helper for adjusting to 32 bits.
inline std::pair<uint32_t, int16_t> getAdjusted32(uint64_t Digits,
int16_t Scale = 0) {
return getAdjusted<uint32_t>(Digits, Scale);
}
-/// \brief Convenience helper for adjusting to 64 bits.
+/// Convenience helper for adjusting to 64 bits.
inline std::pair<uint64_t, int16_t> getAdjusted64(uint64_t Digits,
int16_t Scale = 0) {
return getAdjusted<uint64_t>(Digits, Scale);
}
-/// \brief Multiply two 64-bit integers to create a 64-bit scaled number.
+/// Multiply two 64-bit integers to create a 64-bit scaled number.
///
/// Implemented with four 64-bit integer multiplies.
std::pair<uint64_t, int16_t> multiply64(uint64_t LHS, uint64_t RHS);
-/// \brief Multiply two 32-bit integers to create a 32-bit scaled number.
+/// Multiply two 32-bit integers to create a 32-bit scaled number.
///
/// Implemented with one 64-bit integer multiply.
template <class DigitsT>
@@ -121,31 +121,31 @@ inline std::pair<DigitsT, int16_t> getProduct(DigitsT LHS, DigitsT RHS) {
return multiply64(LHS, RHS);
}
-/// \brief Convenience helper for 32-bit product.
+/// Convenience helper for 32-bit product.
inline std::pair<uint32_t, int16_t> getProduct32(uint32_t LHS, uint32_t RHS) {
return getProduct(LHS, RHS);
}
-/// \brief Convenience helper for 64-bit product.
+/// Convenience helper for 64-bit product.
inline std::pair<uint64_t, int16_t> getProduct64(uint64_t LHS, uint64_t RHS) {
return getProduct(LHS, RHS);
}
-/// \brief Divide two 64-bit integers to create a 64-bit scaled number.
+/// Divide two 64-bit integers to create a 64-bit scaled number.
///
/// Implemented with long division.
///
/// \pre \c Dividend and \c Divisor are non-zero.
std::pair<uint64_t, int16_t> divide64(uint64_t Dividend, uint64_t Divisor);
-/// \brief Divide two 32-bit integers to create a 32-bit scaled number.
+/// Divide two 32-bit integers to create a 32-bit scaled number.
///
/// Implemented with one 64-bit integer divide/remainder pair.
///
/// \pre \c Dividend and \c Divisor are non-zero.
std::pair<uint32_t, int16_t> divide32(uint32_t Dividend, uint32_t Divisor);
-/// \brief Divide two 32-bit numbers to create a 32-bit scaled number.
+/// Divide two 32-bit numbers to create a 32-bit scaled number.
///
/// Implemented with one 64-bit integer divide/remainder pair.
///
@@ -167,19 +167,19 @@ std::pair<DigitsT, int16_t> getQuotient(DigitsT Dividend, DigitsT Divisor) {
return divide32(Dividend, Divisor);
}
-/// \brief Convenience helper for 32-bit quotient.
+/// Convenience helper for 32-bit quotient.
inline std::pair<uint32_t, int16_t> getQuotient32(uint32_t Dividend,
uint32_t Divisor) {
return getQuotient(Dividend, Divisor);
}
-/// \brief Convenience helper for 64-bit quotient.
+/// Convenience helper for 64-bit quotient.
inline std::pair<uint64_t, int16_t> getQuotient64(uint64_t Dividend,
uint64_t Divisor) {
return getQuotient(Dividend, Divisor);
}
-/// \brief Implementation of getLg() and friends.
+/// Implementation of getLg() and friends.
///
/// Returns the rounded lg of \c Digits*2^Scale and an int specifying whether
/// this was rounded up (1), down (-1), or exact (0).
@@ -206,7 +206,7 @@ inline std::pair<int32_t, int> getLgImpl(DigitsT Digits, int16_t Scale) {
return std::make_pair(Floor + Round, Round ? 1 : -1);
}
-/// \brief Get the lg (rounded) of a scaled number.
+/// Get the lg (rounded) of a scaled number.
///
/// Get the lg of \c Digits*2^Scale.
///
@@ -215,7 +215,7 @@ template <class DigitsT> int32_t getLg(DigitsT Digits, int16_t Scale) {
return getLgImpl(Digits, Scale).first;
}
-/// \brief Get the lg floor of a scaled number.
+/// Get the lg floor of a scaled number.
///
/// Get the floor of the lg of \c Digits*2^Scale.
///
@@ -225,7 +225,7 @@ template <class DigitsT> int32_t getLgFloor(DigitsT Digits, int16_t Scale) {
return Lg.first - (Lg.second > 0);
}
-/// \brief Get the lg ceiling of a scaled number.
+/// Get the lg ceiling of a scaled number.
///
/// Get the ceiling of the lg of \c Digits*2^Scale.
///
@@ -235,7 +235,7 @@ template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) {
return Lg.first + (Lg.second < 0);
}
-/// \brief Implementation for comparing scaled numbers.
+/// Implementation for comparing scaled numbers.
///
/// Compare two 64-bit numbers with different scales. Given that the scale of
/// \c L is higher than that of \c R by \c ScaleDiff, compare them. Return -1,
@@ -244,7 +244,7 @@ template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) {
/// \pre 0 <= ScaleDiff < 64.
int compareImpl(uint64_t L, uint64_t R, int ScaleDiff);
-/// \brief Compare two scaled numbers.
+/// Compare two scaled numbers.
///
/// Compare two scaled numbers. Returns 0 for equal, -1 for less than, and 1
/// for greater than.
@@ -271,7 +271,7 @@ int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) {
return -compareImpl(RDigits, LDigits, LScale - RScale);
}
-/// \brief Match scales of two numbers.
+/// Match scales of two numbers.
///
/// Given two scaled numbers, match up their scales. Change the digits and
/// scales in place. Shift the digits as necessary to form equivalent numbers,
@@ -324,7 +324,7 @@ int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits,
return LScale;
}
-/// \brief Get the sum of two scaled numbers.
+/// Get the sum of two scaled numbers.
///
/// Get the sum of two scaled numbers with as much precision as possible.
///
@@ -352,19 +352,19 @@ std::pair<DigitsT, int16_t> getSum(DigitsT LDigits, int16_t LScale,
return std::make_pair(HighBit | Sum >> 1, Scale + 1);
}
-/// \brief Convenience helper for 32-bit sum.
+/// Convenience helper for 32-bit sum.
inline std::pair<uint32_t, int16_t> getSum32(uint32_t LDigits, int16_t LScale,
uint32_t RDigits, int16_t RScale) {
return getSum(LDigits, LScale, RDigits, RScale);
}
-/// \brief Convenience helper for 64-bit sum.
+/// Convenience helper for 64-bit sum.
inline std::pair<uint64_t, int16_t> getSum64(uint64_t LDigits, int16_t LScale,
uint64_t RDigits, int16_t RScale) {
return getSum(LDigits, LScale, RDigits, RScale);
}
-/// \brief Get the difference of two scaled numbers.
+/// Get the difference of two scaled numbers.
///
/// Get LHS minus RHS with as much precision as possible.
///
@@ -395,7 +395,7 @@ std::pair<DigitsT, int16_t> getDifference(DigitsT LDigits, int16_t LScale,
return std::make_pair(LDigits, LScale);
}
-/// \brief Convenience helper for 32-bit difference.
+/// Convenience helper for 32-bit difference.
inline std::pair<uint32_t, int16_t> getDifference32(uint32_t LDigits,
int16_t LScale,
uint32_t RDigits,
@@ -403,7 +403,7 @@ inline std::pair<uint32_t, int16_t> getDifference32(uint32_t LDigits,
return getDifference(LDigits, LScale, RDigits, RScale);
}
-/// \brief Convenience helper for 64-bit difference.
+/// Convenience helper for 64-bit difference.
inline std::pair<uint64_t, int16_t> getDifference64(uint64_t LDigits,
int16_t LScale,
uint64_t RDigits,
@@ -443,7 +443,7 @@ public:
}
};
-/// \brief Simple representation of a scaled number.
+/// Simple representation of a scaled number.
///
/// ScaledNumber is a number represented by digits and a scale. It uses simple
/// saturation arithmetic and every operation is well-defined for every value.
@@ -534,7 +534,7 @@ public:
int16_t getScale() const { return Scale; }
DigitsType getDigits() const { return Digits; }
- /// \brief Convert to the given integer type.
+ /// Convert to the given integer type.
///
/// Convert to \c IntT using simple saturating arithmetic, truncating if
/// necessary.
@@ -548,17 +548,17 @@ public:
return Digits == DigitsType(1) << -Scale;
}
- /// \brief The log base 2, rounded.
+ /// The log base 2, rounded.
///
/// Get the lg of the scalar. lg 0 is defined to be INT32_MIN.
int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); }
- /// \brief The log base 2, rounded towards INT32_MIN.
+ /// The log base 2, rounded towards INT32_MIN.
///
/// Get the lg floor. lg 0 is defined to be INT32_MIN.
int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); }
- /// \brief The log base 2, rounded towards INT32_MAX.
+ /// The log base 2, rounded towards INT32_MAX.
///
/// Get the lg ceiling. lg 0 is defined to be INT32_MIN.
int32_t lgCeiling() const {
@@ -574,7 +574,7 @@ public:
bool operator!() const { return isZero(); }
- /// \brief Convert to a decimal representation in a string.
+ /// Convert to a decimal representation in a string.
///
/// Convert to a string. Uses scientific notation for very large/small
/// numbers. Scientific notation is used roughly for numbers outside of the
@@ -597,7 +597,7 @@ public:
return ScaledNumberBase::toString(Digits, Scale, Width, Precision);
}
- /// \brief Print a decimal representation.
+ /// Print a decimal representation.
///
/// Print a string. See toString for documentation.
raw_ostream &print(raw_ostream &OS,
@@ -634,7 +634,7 @@ private:
void shiftLeft(int32_t Shift);
void shiftRight(int32_t Shift);
- /// \brief Adjust two floats to have matching exponents.
+ /// Adjust two floats to have matching exponents.
///
/// Adjust \c this and \c X to have matching exponents. Returns the new \c X
/// by value. Does nothing if \a isZero() for either.
@@ -647,7 +647,7 @@ private:
}
public:
- /// \brief Scale a large number accurately.
+ /// Scale a large number accurately.
///
/// Scale N (multiply it by this). Uses full precision multiplication, even
/// if Width is smaller than 64, so information is not lost.
@@ -693,7 +693,7 @@ private:
return countLeadingZeros32(Digits) + Width - 32;
}
- /// \brief Adjust a number to width, rounding up if necessary.
+ /// Adjust a number to width, rounding up if necessary.
///
/// Should only be called for \c Shift close to zero.
///
diff --git a/contrib/llvm/include/llvm/Support/ScopedPrinter.h b/contrib/llvm/include/llvm/Support/ScopedPrinter.h
index 1b6651932212..062439b4f7db 100644
--- a/contrib/llvm/include/llvm/Support/ScopedPrinter.h
+++ b/contrib/llvm/include/llvm/Support/ScopedPrinter.h
@@ -80,6 +80,8 @@ public:
void resetIndent() { IndentLevel = 0; }
+ int getIndentLevel() { return IndentLevel; }
+
void setPrefix(StringRef P) { Prefix = P; }
void printIndent() {
@@ -136,7 +138,7 @@ public:
}
}
- std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
+ llvm::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
startLine() << Label << " [ (" << hex(Value) << ")\n";
for (const auto &Flag : SetFlags) {
@@ -261,7 +263,11 @@ public:
}
void printString(StringRef Label, const std::string &Value) {
- startLine() << Label << ": " << Value << "\n";
+ printString(Label, StringRef(Value));
+ }
+
+ void printString(StringRef Label, const char* Value) {
+ printString(Label, StringRef(Value));
}
template <typename T>
diff --git a/contrib/llvm/include/llvm/Support/Signals.h b/contrib/llvm/include/llvm/Support/Signals.h
index cbd6f686a778..f25a04969904 100644
--- a/contrib/llvm/include/llvm/Support/Signals.h
+++ b/contrib/llvm/include/llvm/Support/Signals.h
@@ -29,16 +29,16 @@ namespace sys {
/// This function registers signal handlers to ensure that if a signal gets
/// delivered that the named file is removed.
- /// @brief Remove a file if a fatal signal occurs.
+ /// Remove a file if a fatal signal occurs.
bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = nullptr);
/// This function removes a file from the list of files to be removed on
/// signal delivery.
void DontRemoveFileOnSignal(StringRef Filename);
- /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the
+ /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
/// process, print a stack trace and then exit.
- /// \brief Print a stack trace if a fatal signal occurs.
+ /// Print a stack trace if a fatal signal occurs.
/// \param Argv0 the current binary name, used to find the symbolizer
/// relative to the current binary before searching $PATH; can be
/// StringRef(), in which case we will only search $PATH.
@@ -50,16 +50,18 @@ namespace sys {
/// Disable all system dialog boxes that appear when the process crashes.
void DisableSystemDialogsOnCrash();
- /// \brief Print the stack trace using the given \c raw_ostream object.
+ /// Print the stack trace using the given \c raw_ostream object.
void PrintStackTrace(raw_ostream &OS);
// Run all registered signal handlers.
void RunSignalHandlers();
- /// AddSignalHandler - Add a function to be called when an abort/kill signal
- /// is delivered to the process. The handler can have a cookie passed to it
- /// to identify what instance of the handler it is.
- void AddSignalHandler(void (*FnPtr)(void *), void *Cookie);
+ using SignalHandlerCallback = void (*)(void *);
+
+ /// Add a function to be called when an abort/kill signal is delivered to the
+ /// process. The handler can have a cookie passed to it to identify what
+ /// instance of the handler it is.
+ void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie);
/// This function registers a function to be called when the user "interrupts"
/// the program (typically by pressing ctrl-c). When the user interrupts the
@@ -69,7 +71,7 @@ namespace sys {
/// functions. An null interrupt function pointer disables the current
/// installed function. Note also that the handler may be executed on a
/// different thread on some platforms.
- /// @brief Register a function to be called when ctrl-c is pressed.
+ /// Register a function to be called when ctrl-c is pressed.
void SetInterruptFunction(void (*IF)());
} // End sys namespace
} // End llvm namespace
diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h b/contrib/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h
index 0f00ad006a7d..f43c2fb8f826 100644
--- a/contrib/llvm/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h
+++ b/contrib/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h
@@ -1,4 +1,4 @@
-//===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer -*- C++ -*-===//
+//===- SmallVectorMemoryBuffer.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,31 +21,31 @@
namespace llvm {
-/// \brief SmallVector-backed MemoryBuffer instance.
+/// 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 {
+class SmallVectorMemoryBuffer : public MemoryBuffer {
public:
-
- /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value.
+ /// Construct an SmallVectorMemoryBuffer 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>") {
+ SmallVectorMemoryBuffer(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) {
+ /// Construct a named SmallVectorMemoryBuffer from the given
+ /// SmallVector r-value and StringRef.
+ SmallVectorMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name)
+ : SV(std::move(SV)), BufferName(Name) {
init(this->SV.begin(), this->SV.end(), false);
}
@@ -56,6 +56,7 @@ public:
private:
SmallVector<char, 0> SV;
std::string BufferName;
+ void anchor() override;
};
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/Support/SourceMgr.h b/contrib/llvm/include/llvm/Support/SourceMgr.h
index c08bf858760a..63ac893239d1 100644
--- a/contrib/llvm/include/llvm/Support/SourceMgr.h
+++ b/contrib/llvm/include/llvm/Support/SourceMgr.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -57,8 +58,38 @@ private:
/// The memory buffer for the file.
std::unique_ptr<MemoryBuffer> Buffer;
+ /// Helper type for OffsetCache below: since we're storing many offsets
+ /// into relatively small files (often smaller than 2^8 or 2^16 bytes),
+ /// we select the offset vector element type dynamically based on the
+ /// size of Buffer.
+ using VariableSizeOffsets = PointerUnion4<std::vector<uint8_t> *,
+ std::vector<uint16_t> *,
+ std::vector<uint32_t> *,
+ std::vector<uint64_t> *>;
+
+ /// Vector of offsets into Buffer at which there are line-endings
+ /// (lazily populated). Once populated, the '\n' that marks the end of
+ /// line number N from [1..] is at Buffer[OffsetCache[N-1]]. Since
+ /// these offsets are in sorted (ascending) order, they can be
+ /// binary-searched for the first one after any given offset (eg. an
+ /// offset corresponding to a particular SMLoc).
+ mutable VariableSizeOffsets OffsetCache;
+
+ /// Populate \c OffsetCache and look up a given \p Ptr in it, assuming
+ /// it points somewhere into \c Buffer. The static type parameter \p T
+ /// must be an unsigned integer type from uint{8,16,32,64}_t large
+ /// enough to store offsets inside \c Buffer.
+ template<typename T>
+ unsigned getLineNumber(const char *Ptr) const;
+
/// This is the location of the parent include, or null if at the top level.
SMLoc IncludeLoc;
+
+ SrcBuffer() = default;
+ SrcBuffer(SrcBuffer &&);
+ SrcBuffer(const SrcBuffer &) = delete;
+ SrcBuffer &operator=(const SrcBuffer &) = delete;
+ ~SrcBuffer();
};
/// This is all of the buffers that we are reading from.
@@ -67,10 +98,6 @@ private:
// This is the list of directories we should search for include files in.
std::vector<std::string> IncludeDirectories;
- /// This is a cache for line number queries, its implementation is really
- /// private to SourceMgr.cpp.
- mutable void *LineNoCache = nullptr;
-
DiagHandlerTy DiagHandler = nullptr;
void *DiagContext = nullptr;
@@ -80,7 +107,7 @@ public:
SourceMgr() = default;
SourceMgr(const SourceMgr &) = delete;
SourceMgr &operator=(const SourceMgr &) = delete;
- ~SourceMgr();
+ ~SourceMgr() = default;
void setIncludeDirs(const std::vector<std::string> &Dirs) {
IncludeDirectories = Dirs;
diff --git a/contrib/llvm/include/llvm/Support/StringSaver.h b/contrib/llvm/include/llvm/Support/StringSaver.h
index e85b2895ce51..6b77d487333b 100644
--- a/contrib/llvm/include/llvm/Support/StringSaver.h
+++ b/contrib/llvm/include/llvm/Support/StringSaver.h
@@ -10,23 +10,49 @@
#ifndef LLVM_SUPPORT_STRINGSAVER_H
#define LLVM_SUPPORT_STRINGSAVER_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Allocator.h"
namespace llvm {
-/// \brief Saves strings in the inheritor's stable storage and returns a
+/// Saves strings in the provided stable storage and returns a
/// StringRef with a stable character pointer.
class StringSaver final {
BumpPtrAllocator &Alloc;
public:
StringSaver(BumpPtrAllocator &Alloc) : Alloc(Alloc) {}
+
+ // All returned strings are null-terminated: *save(S).end() == 0.
StringRef save(const char *S) { return save(StringRef(S)); }
StringRef save(StringRef S);
StringRef save(const Twine &S) { return save(StringRef(S.str())); }
StringRef save(const std::string &S) { return save(StringRef(S)); }
};
+
+/// Saves strings in the provided stable storage and returns a StringRef with a
+/// stable character pointer. Saving the same string yields the same StringRef.
+///
+/// Compared to StringSaver, it does more work but avoids saving the same string
+/// multiple times.
+///
+/// Compared to StringPool, it performs fewer allocations but doesn't support
+/// refcounting/deletion.
+class UniqueStringSaver final {
+ StringSaver Strings;
+ llvm::DenseSet<llvm::StringRef> Unique;
+
+public:
+ UniqueStringSaver(BumpPtrAllocator &Alloc) : Strings(Alloc) {}
+
+ // All returned strings are null-terminated: *save(S).end() == 0.
+ StringRef save(const char *S) { return save(StringRef(S)); }
+ StringRef save(StringRef S);
+ StringRef save(const Twine &S) { return save(StringRef(S.str())); }
+ StringRef save(const std::string &S) { return save(StringRef(S)); }
+};
+
}
#endif
diff --git a/contrib/llvm/include/llvm/Support/SystemUtils.h b/contrib/llvm/include/llvm/Support/SystemUtils.h
index 2997b1b0c9cf..bd60793d1554 100644
--- a/contrib/llvm/include/llvm/Support/SystemUtils.h
+++ b/contrib/llvm/include/llvm/Support/SystemUtils.h
@@ -21,7 +21,7 @@ namespace llvm {
/// Determine if the raw_ostream provided is connected to a terminal. If so,
/// generate a warning message to errs() advising against display of bitcode
/// and return true. Otherwise just return false.
-/// @brief Check for output written to a console
+/// Check for output written to a console
bool CheckBitcodeOutputToConsole(
raw_ostream &stream_to_check, ///< The stream to be checked
bool print_warning = true ///< Control whether warnings are printed
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.def b/contrib/llvm/include/llvm/Support/TargetOpcodes.def
index d3e8483798a7..21f5c7e709b8 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.def
+++ b/contrib/llvm/include/llvm/Support/TargetOpcodes.def
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/TargetOpcodes.def - Target Indep Opcodes ---*- C++ -*-===//
+//===-- llvm/Support/TargetOpcodes.def - Target Indep Opcodes ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -77,6 +77,9 @@ HANDLE_TARGET_OPCODE(SUBREG_TO_REG)
/// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic
HANDLE_TARGET_OPCODE(DBG_VALUE)
+/// DBG_LABEL - a mapping of the llvm.dbg.label intrinsic
+HANDLE_TARGET_OPCODE(DBG_LABEL)
+
/// REG_SEQUENCE - This variadic instruction is used to form a register that
/// represents a consecutive sequence of sub-registers. It's used as a
/// register coalescing / allocation aid and must be eliminated before code
@@ -183,10 +186,16 @@ HANDLE_TARGET_OPCODE(PATCHABLE_FUNCTION_EXIT)
/// PATCHABLE_RET which specifically only works for return instructions.
HANDLE_TARGET_OPCODE(PATCHABLE_TAIL_CALL)
-/// Wraps a logging call and its arguments with nop sleds. At runtime, this can be
-/// patched to insert instrumentation instructions.
+/// Wraps a logging call and its arguments with nop sleds. At runtime, this can
+/// be patched to insert instrumentation instructions.
HANDLE_TARGET_OPCODE(PATCHABLE_EVENT_CALL)
+/// Wraps a typed logging call and its argument with nop sleds. At runtime, this
+/// can be patched to insert instrumentation instructions.
+HANDLE_TARGET_OPCODE(PATCHABLE_TYPED_EVENT_CALL)
+
+HANDLE_TARGET_OPCODE(ICALL_BRANCH_FUNNEL)
+
/// The following generic opcodes are not supposed to appear after ISel.
/// This is something we might want to relax, but for now, this is convenient
/// to produce diagnostics.
@@ -259,9 +268,15 @@ HANDLE_TARGET_OPCODE(G_INTTOPTR)
/// COPY is the relevant instruction.
HANDLE_TARGET_OPCODE(G_BITCAST)
-/// Generic load.
+/// Generic load (including anyext load)
HANDLE_TARGET_OPCODE(G_LOAD)
+/// Generic signext load
+HANDLE_TARGET_OPCODE(G_SEXTLOAD)
+
+/// Generic zeroext load
+HANDLE_TARGET_OPCODE(G_ZEXTLOAD)
+
/// Generic store.
HANDLE_TARGET_OPCODE(G_STORE)
@@ -427,6 +442,9 @@ HANDLE_TARGET_OPCODE(G_SITOFP)
/// Generic unsigned-int to float conversion
HANDLE_TARGET_OPCODE(G_UITOFP)
+/// Generic FP absolute value.
+HANDLE_TARGET_OPCODE(G_FABS)
+
/// Generic pointer offset
HANDLE_TARGET_OPCODE(G_GEP)
@@ -449,12 +467,15 @@ HANDLE_TARGET_OPCODE(G_SHUFFLE_VECTOR)
/// Generic byte swap.
HANDLE_TARGET_OPCODE(G_BSWAP)
+/// Generic AddressSpaceCast.
+HANDLE_TARGET_OPCODE(G_ADDRSPACE_CAST)
+
// TODO: Add more generic opcodes as we move along.
/// Marker for the end of the generic opcode.
/// This is used to check if an opcode is in the range of the
/// generic opcodes.
-HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BSWAP)
+HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_ADDRSPACE_CAST)
/// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific post-isel opcode values start here.
diff --git a/contrib/llvm/include/llvm/Support/TargetParser.h b/contrib/llvm/include/llvm/Support/TargetParser.h
index 13b7befb8ce4..08ad42dda3eb 100644
--- a/contrib/llvm/include/llvm/Support/TargetParser.h
+++ b/contrib/llvm/include/llvm/Support/TargetParser.h
@@ -86,6 +86,8 @@ enum ArchExtKind : unsigned {
AEK_RAS = 1 << 12,
AEK_SVE = 1 << 13,
AEK_DOTPROD = 1 << 14,
+ AEK_SHA2 = 1 << 15,
+ AEK_AES = 1 << 16,
// Unsupported extensions.
AEK_OS = 0x8000000,
AEK_IWMMXT = 0x10000000,
@@ -137,6 +139,7 @@ unsigned parseFPU(StringRef FPU);
ArchKind parseArch(StringRef Arch);
unsigned parseArchExt(StringRef ArchExt);
ArchKind parseCPUArch(StringRef CPU);
+void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
ISAKind parseArchISA(StringRef Arch);
EndianKind parseArchEndian(StringRef Arch);
ProfileKind parseArchProfile(StringRef Arch);
@@ -170,7 +173,11 @@ enum ArchExtKind : unsigned {
AEK_SVE = 1 << 9,
AEK_DOTPROD = 1 << 10,
AEK_RCPC = 1 << 11,
- AEK_RDM = 1 << 12
+ AEK_RDM = 1 << 12,
+ AEK_SM4 = 1 << 13,
+ AEK_SHA3 = 1 << 14,
+ AEK_SHA2 = 1 << 15,
+ AEK_AES = 1 << 16,
};
StringRef getCanonicalArchName(StringRef Arch);
@@ -199,17 +206,21 @@ unsigned checkArchVersion(StringRef Arch);
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
StringRef getDefaultCPU(StringRef Arch);
+AArch64::ArchKind getCPUArchKind(StringRef CPU);
// Parser
unsigned parseFPU(StringRef FPU);
AArch64::ArchKind parseArch(StringRef Arch);
-unsigned parseArchExt(StringRef ArchExt);
+ArchExtKind parseArchExt(StringRef ArchExt);
ArchKind parseCPUArch(StringRef CPU);
+void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
ARM::ISAKind parseArchISA(StringRef Arch);
ARM::EndianKind parseArchEndian(StringRef Arch);
ARM::ProfileKind parseArchProfile(StringRef Arch);
unsigned parseArchVersion(StringRef Arch);
+bool isX18ReservedByDefault(const Triple &TT);
+
} // namespace AArch64
namespace X86 {
diff --git a/contrib/llvm/include/llvm/Support/TargetRegistry.h b/contrib/llvm/include/llvm/Support/TargetRegistry.h
index 8a429ab728ed..1bafc4e687da 100644
--- a/contrib/llvm/include/llvm/Support/TargetRegistry.h
+++ b/contrib/llvm/include/llvm/Support/TargetRegistry.h
@@ -19,7 +19,7 @@
#ifndef LLVM_SUPPORT_TARGETREGISTRY_H
#define LLVM_SUPPORT_TARGETREGISTRY_H
-#include "llvm-c/Disassembler.h"
+#include "llvm-c/DisassemblerTypes.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
@@ -46,6 +46,7 @@ class MCDisassembler;
class MCInstPrinter;
class MCInstrAnalysis;
class MCInstrInfo;
+class MCObjectWriter;
class MCRegisterInfo;
class MCRelocationInfo;
class MCStreamer;
@@ -60,27 +61,44 @@ class TargetMachine;
class TargetOptions;
MCStreamer *createNullStreamer(MCContext &Ctx);
-MCStreamer *createAsmStreamer(MCContext &Ctx,
- std::unique_ptr<formatted_raw_ostream> OS,
- bool isVerboseAsm, bool useDwarfDirectory,
- MCInstPrinter *InstPrint, MCCodeEmitter *CE,
- MCAsmBackend *TAB, bool ShowInst);
+// Takes ownership of \p TAB and \p CE.
+
+/// Create a machine code streamer which will print out assembly for the native
+/// target, suitable for compiling with a native assembler.
+///
+/// \param InstPrint - If given, the instruction printer to use. If not given
+/// the MCInst representation will be printed. This method takes ownership of
+/// InstPrint.
+///
+/// \param CE - If given, a code emitter to use to show the instruction
+/// encoding inline with the assembly. This method takes ownership of \p CE.
+///
+/// \param TAB - If given, a target asm backend to use to show the fixup
+/// information in conjunction with encoding information. This method takes
+/// ownership of \p TAB.
+///
+/// \param ShowInst - Whether to show the MCInst representation inline with
+/// the assembly.
+MCStreamer *
+createAsmStreamer(MCContext &Ctx, std::unique_ptr<formatted_raw_ostream> OS,
+ bool isVerboseAsm, bool useDwarfDirectory,
+ MCInstPrinter *InstPrint, std::unique_ptr<MCCodeEmitter> &&CE,
+ std::unique_ptr<MCAsmBackend> &&TAB, bool ShowInst);
-/// Takes ownership of \p TAB and \p CE.
MCStreamer *createELFStreamer(MCContext &Ctx,
std::unique_ptr<MCAsmBackend> &&TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll);
MCStreamer *createMachOStreamer(MCContext &Ctx,
std::unique_ptr<MCAsmBackend> &&TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll, bool DWARFMustBeAtTheEnd,
bool LabelSections = false);
MCStreamer *createWasmStreamer(MCContext &Ctx,
std::unique_ptr<MCAsmBackend> &&TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll);
@@ -143,22 +161,22 @@ public:
using ELFStreamerCtorTy =
MCStreamer *(*)(const Triple &T, MCContext &Ctx,
std::unique_ptr<MCAsmBackend> &&TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
using MachOStreamerCtorTy =
MCStreamer *(*)(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll,
bool DWARFMustBeAtTheEnd);
using COFFStreamerCtorTy =
MCStreamer *(*)(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll,
bool IncrementalLinkerCompatible);
using WasmStreamerCtorTy =
MCStreamer *(*)(const Triple &T, MCContext &Ctx,
std::unique_ptr<MCAsmBackend> &&TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
using NullTargetStreamerCtorTy = MCTargetStreamer *(*)(MCStreamer &S);
using AsmTargetStreamerCtorTy = MCTargetStreamer *(*)(
@@ -441,12 +459,12 @@ public:
/// \param T The target triple.
/// \param Ctx The target context.
/// \param TAB The target assembler backend object. Takes ownership.
- /// \param OS The stream object.
+ /// \param OW The stream object.
/// \param Emitter The target independent assembler object.Takes ownership.
/// \param RelaxAll Relax all fixups?
MCStreamer *createMCObjectStreamer(const Triple &T, MCContext &Ctx,
std::unique_ptr<MCAsmBackend> &&TAB,
- raw_pwrite_stream &OS,
+ std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&Emitter,
const MCSubtargetInfo &STI, bool RelaxAll,
bool IncrementalLinkerCompatible,
@@ -457,32 +475,35 @@ public:
llvm_unreachable("Unknown object format");
case Triple::COFF:
assert(T.isOSWindows() && "only Windows COFF is supported");
- S = COFFStreamerCtorFn(Ctx, std::move(TAB), OS, std::move(Emitter),
- RelaxAll, IncrementalLinkerCompatible);
+ S = COFFStreamerCtorFn(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll,
+ IncrementalLinkerCompatible);
break;
case Triple::MachO:
if (MachOStreamerCtorFn)
- S = MachOStreamerCtorFn(Ctx, std::move(TAB), OS, std::move(Emitter),
- RelaxAll, DWARFMustBeAtTheEnd);
+ S = MachOStreamerCtorFn(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll,
+ DWARFMustBeAtTheEnd);
else
- S = createMachOStreamer(Ctx, std::move(TAB), OS, std::move(Emitter),
- RelaxAll, DWARFMustBeAtTheEnd);
+ S = createMachOStreamer(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll,
+ DWARFMustBeAtTheEnd);
break;
case Triple::ELF:
if (ELFStreamerCtorFn)
- S = ELFStreamerCtorFn(T, Ctx, std::move(TAB), OS, std::move(Emitter),
- RelaxAll);
+ S = ELFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
else
- S = createELFStreamer(Ctx, std::move(TAB), OS, std::move(Emitter),
- RelaxAll);
+ S = createELFStreamer(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
break;
case Triple::Wasm:
if (WasmStreamerCtorFn)
- S = WasmStreamerCtorFn(T, Ctx, std::move(TAB), OS, std::move(Emitter),
- RelaxAll);
+ S = WasmStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
else
- S = createWasmStreamer(Ctx, std::move(TAB), OS, std::move(Emitter),
- RelaxAll);
+ S = createWasmStreamer(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
break;
}
if (ObjectTargetStreamerCtorFn)
@@ -493,12 +514,14 @@ public:
MCStreamer *createAsmStreamer(MCContext &Ctx,
std::unique_ptr<formatted_raw_ostream> OS,
bool IsVerboseAsm, bool UseDwarfDirectory,
- MCInstPrinter *InstPrint, MCCodeEmitter *CE,
- MCAsmBackend *TAB, bool ShowInst) const {
+ MCInstPrinter *InstPrint,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ bool ShowInst) const {
formatted_raw_ostream &OSRef = *OS;
- MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IsVerboseAsm,
- UseDwarfDirectory, InstPrint, CE,
- TAB, ShowInst);
+ MCStreamer *S = llvm::createAsmStreamer(
+ Ctx, std::move(OS), IsVerboseAsm, UseDwarfDirectory, InstPrint,
+ std::move(CE), std::move(TAB), ShowInst);
createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm);
return S;
}
diff --git a/contrib/llvm/include/llvm/Support/TaskQueue.h b/contrib/llvm/include/llvm/Support/TaskQueue.h
new file mode 100644
index 000000000000..49981adb763d
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/TaskQueue.h
@@ -0,0 +1,139 @@
+//===-- llvm/Support/TaskQueue.h - A TaskQueue implementation ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a crude C++11 based task queue.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TASK_QUEUE_H
+#define LLVM_SUPPORT_TASK_QUEUE_H
+
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/thread.h"
+
+#include <atomic>
+#include <cassert>
+#include <condition_variable>
+#include <deque>
+#include <functional>
+#include <future>
+#include <memory>
+#include <mutex>
+#include <utility>
+
+namespace llvm {
+/// TaskQueue executes serialized work on a user-defined Thread Pool. It
+/// guarantees that if task B is enqueued after task A, task B begins after
+/// task A completes and there is no overlap between the two.
+class TaskQueue {
+ // Because we don't have init capture to use move-only local variables that
+ // are captured into a lambda, we create the promise inside an explicit
+ // callable struct. We want to do as much of the wrapping in the
+ // type-specialized domain (before type erasure) and then erase this into a
+ // std::function.
+ template <typename Callable> struct Task {
+ using ResultTy = typename std::result_of<Callable()>::type;
+ explicit Task(Callable C, TaskQueue &Parent)
+ : C(std::move(C)), P(std::make_shared<std::promise<ResultTy>>()),
+ Parent(&Parent) {}
+
+ template<typename T>
+ void invokeCallbackAndSetPromise(T*) {
+ P->set_value(C());
+ }
+
+ void invokeCallbackAndSetPromise(void*) {
+ C();
+ P->set_value();
+ }
+
+ void operator()() noexcept {
+ ResultTy *Dummy = nullptr;
+ invokeCallbackAndSetPromise(Dummy);
+ Parent->completeTask();
+ }
+
+ Callable C;
+ std::shared_ptr<std::promise<ResultTy>> P;
+ TaskQueue *Parent;
+ };
+
+public:
+ /// Construct a task queue with no work.
+ TaskQueue(ThreadPool &Scheduler) : Scheduler(Scheduler) { (void)Scheduler; }
+
+ /// Blocking destructor: the queue will wait for all work to complete.
+ ~TaskQueue() {
+ Scheduler.wait();
+ assert(Tasks.empty());
+ }
+
+ /// Asynchronous submission of a task to the queue. The returned future can be
+ /// used to wait for the task (and all previous tasks that have not yet
+ /// completed) to finish.
+ template <typename Callable>
+ std::future<typename std::result_of<Callable()>::type> async(Callable &&C) {
+#if !LLVM_ENABLE_THREADS
+ static_assert(false,
+ "TaskQueue requires building with LLVM_ENABLE_THREADS!");
+#endif
+ Task<Callable> T{std::move(C), *this};
+ using ResultTy = typename std::result_of<Callable()>::type;
+ std::future<ResultTy> F = T.P->get_future();
+ {
+ std::lock_guard<std::mutex> Lock(QueueLock);
+ // If there's already a task in flight, just queue this one up. If
+ // there is not a task in flight, bypass the queue and schedule this
+ // task immediately.
+ if (IsTaskInFlight)
+ Tasks.push_back(std::move(T));
+ else {
+ Scheduler.async(std::move(T));
+ IsTaskInFlight = true;
+ }
+ }
+ return std::move(F);
+ }
+
+private:
+ void completeTask() {
+ // We just completed a task. If there are no more tasks in the queue,
+ // update IsTaskInFlight to false and stop doing work. Otherwise
+ // schedule the next task (while not holding the lock).
+ std::function<void()> Continuation;
+ {
+ std::lock_guard<std::mutex> Lock(QueueLock);
+ if (Tasks.empty()) {
+ IsTaskInFlight = false;
+ return;
+ }
+
+ Continuation = std::move(Tasks.front());
+ Tasks.pop_front();
+ }
+ Scheduler.async(std::move(Continuation));
+ }
+
+ /// The thread pool on which to run the work.
+ ThreadPool &Scheduler;
+
+ /// State which indicates whether the queue currently is currently processing
+ /// any work.
+ bool IsTaskInFlight = false;
+
+ /// Mutex for synchronizing access to the Tasks array.
+ std::mutex QueueLock;
+
+ /// Tasks waiting for execution in the queue.
+ std::deque<std::function<void()>> Tasks;
+};
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_TASK_QUEUE_H
diff --git a/contrib/llvm/include/llvm/Support/ThreadLocal.h b/contrib/llvm/include/llvm/Support/ThreadLocal.h
index 427a67e2a96d..885bd18e8356 100644
--- a/contrib/llvm/include/llvm/Support/ThreadLocal.h
+++ b/contrib/llvm/include/llvm/Support/ThreadLocal.h
@@ -24,7 +24,7 @@ namespace llvm {
// YOU SHOULD NEVER USE THIS DIRECTLY.
class ThreadLocalImpl {
typedef uint64_t ThreadLocalDataTy;
- /// \brief Platform-specific thread local data.
+ /// Platform-specific thread local data.
///
/// This is embedded in the class and we avoid malloc'ing/free'ing it,
/// to make this class more safe for use along with CrashRecoveryContext.
diff --git a/contrib/llvm/include/llvm/Support/ThreadPool.h b/contrib/llvm/include/llvm/Support/ThreadPool.h
index fb8255900510..4fdbd528b212 100644
--- a/contrib/llvm/include/llvm/Support/ThreadPool.h
+++ b/contrib/llvm/include/llvm/Support/ThreadPool.h
@@ -14,6 +14,7 @@
#ifndef LLVM_SUPPORT_THREAD_POOL_H
#define LLVM_SUPPORT_THREAD_POOL_H
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/thread.h"
#include <future>
diff --git a/contrib/llvm/include/llvm/Support/Threading.h b/contrib/llvm/include/llvm/Support/Threading.h
index 6d813bccb93f..e8021f648b0d 100644
--- a/contrib/llvm/include/llvm/Support/Threading.h
+++ b/contrib/llvm/include/llvm/Support/Threading.h
@@ -72,7 +72,7 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData,
enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 };
- /// \brief The llvm::once_flag structure
+ /// The llvm::once_flag structure
///
/// This type is modeled after std::once_flag to use with llvm::call_once.
/// This structure must be used as an opaque object. It is a struct to force
@@ -83,7 +83,7 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData,
#endif
- /// \brief Execute the function specified as a parameter once.
+ /// Execute the function specified as a parameter once.
///
/// Typical usage:
/// \code
@@ -139,17 +139,17 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData,
/// not available.
unsigned hardware_concurrency();
- /// \brief Return the current thread id, as used in various OS system calls.
+ /// Return the current thread id, as used in various OS system calls.
/// Note that not all platforms guarantee that the value returned will be
/// unique across the entire system, so portable code should not assume
/// this.
uint64_t get_threadid();
- /// \brief Get the maximum length of a thread name on this platform.
+ /// Get the maximum length of a thread name on this platform.
/// A value of 0 means there is no limit.
uint32_t get_max_thread_name_length();
- /// \brief Set the name of the current thread. Setting a thread's name can
+ /// Set the name of the current thread. Setting a thread's name can
/// be helpful for enabling useful diagnostics under a debugger or when
/// logging. The level of support for setting a thread's name varies
/// wildly across operating systems, and we only make a best effort to
@@ -157,7 +157,7 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData,
/// or failure is returned.
void set_thread_name(const Twine &Name);
- /// \brief Get the name of the current thread. The level of support for
+ /// Get the name of the current thread. The level of support for
/// getting a thread's name varies wildly across operating systems, and it
/// is not even guaranteed that if you can successfully set a thread's name
/// that you can later get it back. This function is intended for diagnostic
diff --git a/contrib/llvm/include/llvm/Support/Timer.h b/contrib/llvm/include/llvm/Support/Timer.h
index 198855ae0377..bfffbc3157b1 100644
--- a/contrib/llvm/include/llvm/Support/Timer.h
+++ b/contrib/llvm/include/llvm/Support/Timer.h
@@ -10,6 +10,7 @@
#ifndef LLVM_SUPPORT_TIMER_H
#define LLVM_SUPPORT_TIMER_H
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
@@ -194,6 +195,10 @@ class TimerGroup {
public:
explicit TimerGroup(StringRef Name, StringRef Description);
+
+ explicit TimerGroup(StringRef Name, StringRef Description,
+ const StringMap<TimeRecord> &Records);
+
~TimerGroup();
void setName(StringRef NewName, StringRef NewDescription) {
@@ -207,6 +212,8 @@ public:
/// This static method prints all timers and clears them all out.
static void printAll(raw_ostream &OS);
+ const char *printJSONValues(raw_ostream &OS, const char *delim);
+
/// Prints all timers as JSON key/value pairs, and clears them all out.
static const char *printAllJSONValues(raw_ostream &OS, const char *delim);
@@ -223,7 +230,6 @@ private:
void PrintQueuedTimers(raw_ostream &OS);
void printJSONValue(raw_ostream &OS, const PrintRecord &R,
const char *suffix, double Value);
- const char *printJSONValues(raw_ostream &OS, const char *delim);
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Support/ToolOutputFile.h b/contrib/llvm/include/llvm/Support/ToolOutputFile.h
index b41ca5a6edaa..cf3bc2fb0171 100644
--- a/contrib/llvm/include/llvm/Support/ToolOutputFile.h
+++ b/contrib/llvm/include/llvm/Support/ToolOutputFile.h
@@ -35,7 +35,7 @@ class ToolOutputFile {
/// The flag which indicates whether we should not delete the file.
bool Keep;
- explicit CleanupInstaller(StringRef ilename);
+ explicit CleanupInstaller(StringRef Filename);
~CleanupInstaller();
} Installer;
@@ -43,7 +43,7 @@ class ToolOutputFile {
raw_fd_ostream OS;
public:
- /// This constructor's arguments are passed to to raw_fd_ostream's
+ /// This constructor's arguments are passed to raw_fd_ostream's
/// constructor.
ToolOutputFile(StringRef Filename, std::error_code &EC,
sys::fs::OpenFlags Flags);
diff --git a/contrib/llvm/include/llvm/Support/TrailingObjects.h b/contrib/llvm/include/llvm/Support/TrailingObjects.h
index cb5a52b0d861..490bd94f4cd5 100644
--- a/contrib/llvm/include/llvm/Support/TrailingObjects.h
+++ b/contrib/llvm/include/llvm/Support/TrailingObjects.h
@@ -89,25 +89,25 @@ protected:
};
/// This helper template works-around MSVC 2013's lack of useful
-/// alignas() support. The argument to LLVM_ALIGNAS(), in MSVC, is
+/// alignas() support. The argument to alignas(), in MSVC, is
/// required to be a literal integer. But, you *can* use template
-/// specialization to select between a bunch of different LLVM_ALIGNAS
+/// specialization to select between a bunch of different alignas()
/// expressions...
template <int Align>
class TrailingObjectsAligner : public TrailingObjectsBase {};
template <>
-class LLVM_ALIGNAS(1) TrailingObjectsAligner<1> : public TrailingObjectsBase {};
+class alignas(1) TrailingObjectsAligner<1> : public TrailingObjectsBase {};
template <>
-class LLVM_ALIGNAS(2) TrailingObjectsAligner<2> : public TrailingObjectsBase {};
+class alignas(2) TrailingObjectsAligner<2> : public TrailingObjectsBase {};
template <>
-class LLVM_ALIGNAS(4) TrailingObjectsAligner<4> : public TrailingObjectsBase {};
+class alignas(4) TrailingObjectsAligner<4> : public TrailingObjectsBase {};
template <>
-class LLVM_ALIGNAS(8) TrailingObjectsAligner<8> : public TrailingObjectsBase {};
+class alignas(8) TrailingObjectsAligner<8> : public TrailingObjectsBase {};
template <>
-class LLVM_ALIGNAS(16) TrailingObjectsAligner<16> : public TrailingObjectsBase {
+class alignas(16) TrailingObjectsAligner<16> : public TrailingObjectsBase {
};
template <>
-class LLVM_ALIGNAS(32) TrailingObjectsAligner<32> : public TrailingObjectsBase {
+class alignas(32) TrailingObjectsAligner<32> : public TrailingObjectsBase {
};
// Just a little helper for transforming a type pack into the same
diff --git a/contrib/llvm/include/llvm/Support/Unicode.h b/contrib/llvm/include/llvm/Support/Unicode.h
index adedb1ed83a6..983acaf03635 100644
--- a/contrib/llvm/include/llvm/Support/Unicode.h
+++ b/contrib/llvm/include/llvm/Support/Unicode.h
@@ -60,6 +60,10 @@ bool isPrintable(int UCS);
/// * 1 for each of the remaining characters.
int columnWidthUTF8(StringRef Text);
+/// Fold input unicode character according the Simple unicode case folding
+/// rules.
+int foldCharSimple(int C);
+
} // namespace unicode
} // namespace sys
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h b/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h
index 4c655833b396..3cf4a6d96602 100644
--- a/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h
+++ b/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h
@@ -23,7 +23,7 @@
namespace llvm {
namespace sys {
-/// \brief Represents a closed range of Unicode code points [Lower, Upper].
+/// Represents a closed range of Unicode code points [Lower, Upper].
struct UnicodeCharRange {
uint32_t Lower;
uint32_t Upper;
@@ -36,14 +36,14 @@ inline bool operator<(UnicodeCharRange Range, uint32_t Value) {
return Range.Upper < Value;
}
-/// \brief Holds a reference to an ordered array of UnicodeCharRange and allows
+/// Holds a reference to an ordered array of UnicodeCharRange and allows
/// to quickly check if a code point is contained in the set represented by this
/// array.
class UnicodeCharSet {
public:
typedef ArrayRef<UnicodeCharRange> CharRanges;
- /// \brief Constructs a UnicodeCharSet instance from an array of
+ /// Constructs a UnicodeCharSet instance from an array of
/// UnicodeCharRanges.
///
/// Array pointed by \p Ranges should have the lifetime at least as long as
@@ -63,31 +63,31 @@ public:
}
#endif
- /// \brief Returns true if the character set contains the Unicode code point
+ /// Returns true if the character set contains the Unicode code point
/// \p C.
bool contains(uint32_t C) const {
return std::binary_search(Ranges.begin(), Ranges.end(), C);
}
private:
- /// \brief Returns true if each of the ranges is a proper closed range
+ /// Returns true if each of the ranges is a proper closed range
/// [min, max], and if the ranges themselves are ordered and non-overlapping.
bool rangesAreValid() const {
uint32_t Prev = 0;
for (CharRanges::const_iterator I = Ranges.begin(), E = Ranges.end();
I != E; ++I) {
if (I != Ranges.begin() && Prev >= I->Lower) {
- DEBUG(dbgs() << "Upper bound 0x");
- DEBUG(dbgs().write_hex(Prev));
- DEBUG(dbgs() << " should be less than succeeding lower bound 0x");
- DEBUG(dbgs().write_hex(I->Lower) << "\n");
+ LLVM_DEBUG(dbgs() << "Upper bound 0x");
+ LLVM_DEBUG(dbgs().write_hex(Prev));
+ LLVM_DEBUG(dbgs() << " should be less than succeeding lower bound 0x");
+ LLVM_DEBUG(dbgs().write_hex(I->Lower) << "\n");
return false;
}
if (I->Upper < I->Lower) {
- DEBUG(dbgs() << "Upper bound 0x");
- DEBUG(dbgs().write_hex(I->Lower));
- DEBUG(dbgs() << " should not be less than lower bound 0x");
- DEBUG(dbgs().write_hex(I->Upper) << "\n");
+ LLVM_DEBUG(dbgs() << "Upper bound 0x");
+ LLVM_DEBUG(dbgs().write_hex(I->Lower));
+ LLVM_DEBUG(dbgs() << " should not be less than lower bound 0x");
+ LLVM_DEBUG(dbgs().write_hex(I->Upper) << "\n");
return false;
}
Prev = I->Upper;
diff --git a/contrib/llvm/include/llvm/Support/UniqueLock.h b/contrib/llvm/include/llvm/Support/UniqueLock.h
index b4675f4b43ae..91dc911036d5 100644
--- a/contrib/llvm/include/llvm/Support/UniqueLock.h
+++ b/contrib/llvm/include/llvm/Support/UniqueLock.h
@@ -24,7 +24,7 @@ namespace llvm {
/// an associated mutex, which is guaranteed to be locked upon creation
/// and unlocked after destruction. unique_lock can also unlock the mutex
/// and re-lock it freely during its lifetime.
- /// @brief Guard a section of code with a mutex.
+ /// Guard a section of code with a mutex.
template<typename MutexT>
class unique_lock {
MutexT *M = nullptr;
diff --git a/contrib/llvm/include/llvm/Support/VersionTuple.h b/contrib/llvm/include/llvm/Support/VersionTuple.h
new file mode 100644
index 000000000000..e85a188e54b4
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/VersionTuple.h
@@ -0,0 +1,154 @@
+//===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Defines the llvm::VersionTuple class, which represents a version in
+/// the form major[.minor[.subminor]].
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_SUPPORT_VERSIONTUPLE_H
+#define LLVM_SUPPORT_VERSIONTUPLE_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+#include <tuple>
+
+namespace llvm {
+
+/// Represents a version number in the form major[.minor[.subminor[.build]]].
+class VersionTuple {
+ unsigned Major : 32;
+
+ unsigned Minor : 31;
+ unsigned HasMinor : 1;
+
+ unsigned Subminor : 31;
+ unsigned HasSubminor : 1;
+
+ unsigned Build : 31;
+ unsigned HasBuild : 1;
+
+public:
+ VersionTuple()
+ : Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false),
+ Build(0), HasBuild(false) {}
+
+ explicit VersionTuple(unsigned Major)
+ : Major(Major), Minor(0), HasMinor(false), Subminor(0),
+ HasSubminor(false), Build(0), HasBuild(false) {}
+
+ explicit VersionTuple(unsigned Major, unsigned Minor)
+ : Major(Major), Minor(Minor), HasMinor(true), Subminor(0),
+ HasSubminor(false), Build(0), HasBuild(false) {}
+
+ explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor)
+ : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
+ HasSubminor(true), Build(0), HasBuild(false) {}
+
+ explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
+ unsigned Build)
+ : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
+ HasSubminor(true), Build(Build), HasBuild(true) {}
+
+ /// Determine whether this version information is empty
+ /// (e.g., all version components are zero).
+ bool empty() const {
+ return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0;
+ }
+
+ /// Retrieve the major version number.
+ unsigned getMajor() const { return Major; }
+
+ /// Retrieve the minor version number, if provided.
+ Optional<unsigned> getMinor() const {
+ if (!HasMinor)
+ return None;
+ return Minor;
+ }
+
+ /// Retrieve the subminor version number, if provided.
+ Optional<unsigned> getSubminor() const {
+ if (!HasSubminor)
+ return None;
+ return Subminor;
+ }
+
+ /// Retrieve the build version number, if provided.
+ Optional<unsigned> getBuild() const {
+ if (!HasBuild)
+ return None;
+ return Build;
+ }
+
+ /// Determine if two version numbers are equivalent. If not
+ /// provided, minor and subminor version numbers are considered to be zero.
+ friend bool operator==(const VersionTuple &X, const VersionTuple &Y) {
+ return X.Major == Y.Major && X.Minor == Y.Minor &&
+ X.Subminor == Y.Subminor && X.Build == Y.Build;
+ }
+
+ /// Determine if two version numbers are not equivalent.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) {
+ return !(X == Y);
+ }
+
+ /// Determine whether one version number precedes another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
+ return std::tie(X.Major, X.Minor, X.Subminor, X.Build) <
+ std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build);
+ }
+
+ /// Determine whether one version number follows another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator>(const VersionTuple &X, const VersionTuple &Y) {
+ return Y < X;
+ }
+
+ /// Determine whether one version number precedes or is
+ /// equivalent to another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) {
+ return !(Y < X);
+ }
+
+ /// Determine whether one version number follows or is
+ /// equivalent to another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) {
+ return !(X < Y);
+ }
+
+ /// Retrieve a string representation of the version number.
+ std::string getAsString() const;
+
+ /// Try to parse the given string as a version number.
+ /// \returns \c true if the string does not match the regular expression
+ /// [0-9]+(\.[0-9]+){0,3}
+ bool tryParse(StringRef string);
+};
+
+/// Print a version number.
+raw_ostream &operator<<(raw_ostream &Out, const VersionTuple &V);
+
+} // end namespace llvm
+#endif // LLVM_SUPPORT_VERSIONTUPLE_H
diff --git a/contrib/llvm/include/llvm/Support/Win64EH.h b/contrib/llvm/include/llvm/Support/Win64EH.h
index f6c492794875..928eb906de0c 100644
--- a/contrib/llvm/include/llvm/Support/Win64EH.h
+++ b/contrib/llvm/include/llvm/Support/Win64EH.h
@@ -101,40 +101,40 @@ struct UnwindInfo {
// For more information please see MSDN at:
// http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
- /// \brief Return pointer to language specific data part of UnwindInfo.
+ /// Return pointer to language specific data part of UnwindInfo.
void *getLanguageSpecificData() {
return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]);
}
- /// \brief Return pointer to language specific data part of UnwindInfo.
+ /// Return pointer to language specific data part of UnwindInfo.
const void *getLanguageSpecificData() const {
return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes + 1) & ~1]);
}
- /// \brief Return image-relative offset of language-specific exception handler.
+ /// Return image-relative offset of language-specific exception handler.
uint32_t getLanguageSpecificHandlerOffset() const {
return *reinterpret_cast<const support::ulittle32_t *>(
getLanguageSpecificData());
}
- /// \brief Set image-relative offset of language-specific exception handler.
+ /// Set image-relative offset of language-specific exception handler.
void setLanguageSpecificHandlerOffset(uint32_t offset) {
*reinterpret_cast<support::ulittle32_t *>(getLanguageSpecificData()) =
offset;
}
- /// \brief Return pointer to exception-specific data.
+ /// Return pointer to exception-specific data.
void *getExceptionData() {
return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>(
getLanguageSpecificData())+1);
}
- /// \brief Return pointer to chained unwind info.
+ /// Return pointer to chained unwind info.
RuntimeFunction *getChainedFunctionEntry() {
return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData());
}
- /// \brief Return pointer to chained unwind info.
+ /// Return pointer to chained unwind info.
const RuntimeFunction *getChainedFunctionEntry() const {
return reinterpret_cast<const RuntimeFunction *>(getLanguageSpecificData());
}
diff --git a/contrib/llvm/include/llvm/Support/WithColor.h b/contrib/llvm/include/llvm/Support/WithColor.h
new file mode 100644
index 000000000000..85fc5fa0cf14
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/WithColor.h
@@ -0,0 +1,67 @@
+//===- WithColor.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_SUPPORT_WITHCOLOR_H
+#define LLVM_SUPPORT_WITHCOLOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace llvm {
+
+extern cl::OptionCategory ColorCategory;
+
+class raw_ostream;
+
+// Symbolic names for various syntax elements.
+enum class HighlightColor {
+ Address,
+ String,
+ Tag,
+ Attribute,
+ Enumerator,
+ Macro,
+ Error,
+ Warning,
+ Note
+};
+
+/// An RAII object that temporarily switches an output stream to a specific
+/// color.
+class WithColor {
+ raw_ostream &OS;
+ /// Determine whether colors should be displayed.
+ bool colorsEnabled(raw_ostream &OS);
+
+public:
+ /// To be used like this: WithColor(OS, HighlightColor::String) << "text";
+ WithColor(raw_ostream &OS, HighlightColor S);
+ ~WithColor();
+
+ raw_ostream &get() { return OS; }
+ operator raw_ostream &() { return OS; }
+
+ /// Convenience method for printing "error: " to stderr.
+ static raw_ostream &error();
+ /// Convenience method for printing "warning: " to stderr.
+ static raw_ostream &warning();
+ /// Convenience method for printing "note: " to stderr.
+ static raw_ostream &note();
+
+ /// Convenience method for printing "error: " to the given stream.
+ static raw_ostream &error(raw_ostream &OS, StringRef Prefix = "");
+ /// Convenience method for printing "warning: " to the given stream.
+ static raw_ostream &warning(raw_ostream &OS, StringRef Prefix = "");
+ /// Convenience method for printing "note: " to the given stream.
+ static raw_ostream &note(raw_ostream &OS, StringRef Prefix = "");
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_DEBUGINFO_WITHCOLOR_H
diff --git a/contrib/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h b/contrib/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
new file mode 100644
index 000000000000..185b357efef5
--- /dev/null
+++ b/contrib/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
@@ -0,0 +1,475 @@
+//===-- X86DisassemblerDecoderCommon.h - Disassembler decoder ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler.
+// It contains common definitions used by both the disassembler and the table
+// generator.
+// Documentation for the disassembler can be found in X86Disassembler.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLERDECODERCOMMON_H
+#define LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLERDECODERCOMMON_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+namespace X86Disassembler {
+
+#define INSTRUCTIONS_SYM x86DisassemblerInstrSpecifiers
+#define CONTEXTS_SYM x86DisassemblerContexts
+#define ONEBYTE_SYM x86DisassemblerOneByteOpcodes
+#define TWOBYTE_SYM x86DisassemblerTwoByteOpcodes
+#define THREEBYTE38_SYM x86DisassemblerThreeByte38Opcodes
+#define THREEBYTE3A_SYM x86DisassemblerThreeByte3AOpcodes
+#define XOP8_MAP_SYM x86DisassemblerXOP8Opcodes
+#define XOP9_MAP_SYM x86DisassemblerXOP9Opcodes
+#define XOPA_MAP_SYM x86DisassemblerXOPAOpcodes
+#define THREEDNOW_MAP_SYM x86Disassembler3DNowOpcodes
+
+#define INSTRUCTIONS_STR "x86DisassemblerInstrSpecifiers"
+#define CONTEXTS_STR "x86DisassemblerContexts"
+#define ONEBYTE_STR "x86DisassemblerOneByteOpcodes"
+#define TWOBYTE_STR "x86DisassemblerTwoByteOpcodes"
+#define THREEBYTE38_STR "x86DisassemblerThreeByte38Opcodes"
+#define THREEBYTE3A_STR "x86DisassemblerThreeByte3AOpcodes"
+#define XOP8_MAP_STR "x86DisassemblerXOP8Opcodes"
+#define XOP9_MAP_STR "x86DisassemblerXOP9Opcodes"
+#define XOPA_MAP_STR "x86DisassemblerXOPAOpcodes"
+#define THREEDNOW_MAP_STR "x86Disassembler3DNowOpcodes"
+
+// Attributes of an instruction that must be known before the opcode can be
+// processed correctly. Most of these indicate the presence of particular
+// prefixes, but ATTR_64BIT is simply an attribute of the decoding context.
+#define ATTRIBUTE_BITS \
+ ENUM_ENTRY(ATTR_NONE, 0x00) \
+ ENUM_ENTRY(ATTR_64BIT, (0x1 << 0)) \
+ ENUM_ENTRY(ATTR_XS, (0x1 << 1)) \
+ ENUM_ENTRY(ATTR_XD, (0x1 << 2)) \
+ ENUM_ENTRY(ATTR_REXW, (0x1 << 3)) \
+ ENUM_ENTRY(ATTR_OPSIZE, (0x1 << 4)) \
+ ENUM_ENTRY(ATTR_ADSIZE, (0x1 << 5)) \
+ ENUM_ENTRY(ATTR_VEX, (0x1 << 6)) \
+ ENUM_ENTRY(ATTR_VEXL, (0x1 << 7)) \
+ ENUM_ENTRY(ATTR_EVEX, (0x1 << 8)) \
+ ENUM_ENTRY(ATTR_EVEXL, (0x1 << 9)) \
+ ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \
+ ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \
+ ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \
+ ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13))
+
+#define ENUM_ENTRY(n, v) n = v,
+enum attributeBits {
+ ATTRIBUTE_BITS
+ ATTR_max
+};
+#undef ENUM_ENTRY
+
+// Combinations of the above attributes that are relevant to instruction
+// decode. Although other combinations are possible, they can be reduced to
+// these without affecting the ultimately decoded instruction.
+
+// Class name Rank Rationale for rank assignment
+#define INSTRUCTION_CONTEXTS \
+ ENUM_ENTRY(IC, 0, "says nothing about the instruction") \
+ ENUM_ENTRY(IC_64BIT, 1, "says the instruction applies in " \
+ "64-bit mode but no more") \
+ ENUM_ENTRY(IC_OPSIZE, 3, "requires an OPSIZE prefix, so " \
+ "operands change width") \
+ ENUM_ENTRY(IC_ADSIZE, 3, "requires an ADSIZE prefix, so " \
+ "operands change width") \
+ ENUM_ENTRY(IC_OPSIZE_ADSIZE, 4, "requires ADSIZE and OPSIZE prefixes") \
+ ENUM_ENTRY(IC_XD, 2, "may say something about the opcode " \
+ "but not the operands") \
+ ENUM_ENTRY(IC_XS, 2, "may say something about the opcode " \
+ "but not the operands") \
+ ENUM_ENTRY(IC_XD_OPSIZE, 3, "requires an OPSIZE prefix, so " \
+ "operands change width") \
+ ENUM_ENTRY(IC_XS_OPSIZE, 3, "requires an OPSIZE prefix, so " \
+ "operands change width") \
+ ENUM_ENTRY(IC_XD_ADSIZE, 3, "requires an ADSIZE prefix, so " \
+ "operands change width") \
+ ENUM_ENTRY(IC_XS_ADSIZE, 3, "requires an ADSIZE prefix, so " \
+ "operands change width") \
+ ENUM_ENTRY(IC_64BIT_REXW, 5, "requires a REX.W prefix, so operands "\
+ "change width; overrides IC_OPSIZE") \
+ ENUM_ENTRY(IC_64BIT_REXW_ADSIZE, 6, "requires a REX.W prefix and 0x67 " \
+ "prefix") \
+ ENUM_ENTRY(IC_64BIT_OPSIZE, 3, "Just as meaningful as IC_OPSIZE") \
+ ENUM_ENTRY(IC_64BIT_ADSIZE, 3, "Just as meaningful as IC_ADSIZE") \
+ ENUM_ENTRY(IC_64BIT_OPSIZE_ADSIZE, 4, "Just as meaningful as IC_OPSIZE/" \
+ "IC_ADSIZE") \
+ ENUM_ENTRY(IC_64BIT_XD, 6, "XD instructions are SSE; REX.W is " \
+ "secondary") \
+ ENUM_ENTRY(IC_64BIT_XS, 6, "Just as meaningful as IC_64BIT_XD") \
+ ENUM_ENTRY(IC_64BIT_XD_OPSIZE, 3, "Just as meaningful as IC_XD_OPSIZE") \
+ ENUM_ENTRY(IC_64BIT_XS_OPSIZE, 3, "Just as meaningful as IC_XS_OPSIZE") \
+ ENUM_ENTRY(IC_64BIT_XD_ADSIZE, 3, "Just as meaningful as IC_XD_ADSIZE") \
+ ENUM_ENTRY(IC_64BIT_XS_ADSIZE, 3, "Just as meaningful as IC_XS_ADSIZE") \
+ ENUM_ENTRY(IC_64BIT_REXW_XS, 7, "OPSIZE could mean a different " \
+ "opcode") \
+ ENUM_ENTRY(IC_64BIT_REXW_XD, 7, "Just as meaningful as " \
+ "IC_64BIT_REXW_XS") \
+ ENUM_ENTRY(IC_64BIT_REXW_OPSIZE, 8, "The Dynamic Duo! Prefer over all " \
+ "else because this changes most " \
+ "operands' meaning") \
+ ENUM_ENTRY(IC_VEX, 1, "requires a VEX prefix") \
+ ENUM_ENTRY(IC_VEX_XS, 2, "requires VEX and the XS prefix") \
+ ENUM_ENTRY(IC_VEX_XD, 2, "requires VEX and the XD prefix") \
+ ENUM_ENTRY(IC_VEX_OPSIZE, 2, "requires VEX and the OpSize prefix") \
+ ENUM_ENTRY(IC_VEX_W, 3, "requires VEX and the W prefix") \
+ ENUM_ENTRY(IC_VEX_W_XS, 4, "requires VEX, W, and XS prefix") \
+ ENUM_ENTRY(IC_VEX_W_XD, 4, "requires VEX, W, and XD prefix") \
+ ENUM_ENTRY(IC_VEX_W_OPSIZE, 4, "requires VEX, W, and OpSize") \
+ ENUM_ENTRY(IC_VEX_L, 3, "requires VEX and the L prefix") \
+ ENUM_ENTRY(IC_VEX_L_XS, 4, "requires VEX and the L and XS prefix")\
+ ENUM_ENTRY(IC_VEX_L_XD, 4, "requires VEX and the L and XD prefix")\
+ ENUM_ENTRY(IC_VEX_L_OPSIZE, 4, "requires VEX, L, and OpSize") \
+ ENUM_ENTRY(IC_VEX_L_W, 4, "requires VEX, L and W") \
+ ENUM_ENTRY(IC_VEX_L_W_XS, 5, "requires VEX, L, W and XS prefix") \
+ ENUM_ENTRY(IC_VEX_L_W_XD, 5, "requires VEX, L, W and XD prefix") \
+ ENUM_ENTRY(IC_VEX_L_W_OPSIZE, 5, "requires VEX, L, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX, 1, "requires an EVEX prefix") \
+ ENUM_ENTRY(IC_EVEX_XS, 2, "requires EVEX and the XS prefix") \
+ ENUM_ENTRY(IC_EVEX_XD, 2, "requires EVEX and the XD prefix") \
+ ENUM_ENTRY(IC_EVEX_OPSIZE, 2, "requires EVEX and the OpSize prefix") \
+ ENUM_ENTRY(IC_EVEX_W, 3, "requires EVEX and the W prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XS, 4, "requires EVEX, W, and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XD, 4, "requires EVEX, W, and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_W_OPSIZE, 4, "requires EVEX, W, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L, 3, "requires EVEX and the L prefix") \
+ ENUM_ENTRY(IC_EVEX_L_XS, 4, "requires EVEX and the L and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L_XD, 4, "requires EVEX and the L and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L_OPSIZE, 4, "requires EVEX, L, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_W, 3, "requires EVEX, L and W") \
+ ENUM_ENTRY(IC_EVEX_L_W_XS, 4, "requires EVEX, L, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_XD, 4, "requires EVEX, L, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_OPSIZE, 4, "requires EVEX, L, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2, 3, "requires EVEX and the L2 prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_XS, 4, "requires EVEX and the L2 and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_XD, 4, "requires EVEX and the L2 and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_OPSIZE, 4, "requires EVEX, L2, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_W, 3, "requires EVEX, L2 and W") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XS, 4, "requires EVEX, L2, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XD, 4, "requires EVEX, L2, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE, 4, "requires EVEX, L2, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_K, 1, "requires an EVEX_K prefix") \
+ ENUM_ENTRY(IC_EVEX_XS_K, 2, "requires EVEX_K and the XS prefix") \
+ ENUM_ENTRY(IC_EVEX_XD_K, 2, "requires EVEX_K and the XD prefix") \
+ ENUM_ENTRY(IC_EVEX_OPSIZE_K, 2, "requires EVEX_K and the OpSize prefix") \
+ ENUM_ENTRY(IC_EVEX_W_K, 3, "requires EVEX_K and the W prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XS_K, 4, "requires EVEX_K, W, and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XD_K, 4, "requires EVEX_K, W, and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_W_OPSIZE_K, 4, "requires EVEX_K, W, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_K, 3, "requires EVEX_K and the L prefix") \
+ ENUM_ENTRY(IC_EVEX_L_XS_K, 4, "requires EVEX_K and the L and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L_XD_K, 4, "requires EVEX_K and the L and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L_OPSIZE_K, 4, "requires EVEX_K, L, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_W_K, 3, "requires EVEX_K, L and W") \
+ ENUM_ENTRY(IC_EVEX_L_W_XS_K, 4, "requires EVEX_K, L, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_XD_K, 4, "requires EVEX_K, L, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_K, 4, "requires EVEX_K, L, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_K, 3, "requires EVEX_K and the L2 prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_XS_K, 4, "requires EVEX_K and the L2 and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_XD_K, 4, "requires EVEX_K and the L2 and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_OPSIZE_K, 4, "requires EVEX_K, L2, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_W_K, 3, "requires EVEX_K, L2 and W") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XS_K, 4, "requires EVEX_K, L2, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XD_K, 4, "requires EVEX_K, L2, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K, 4, "requires EVEX_K, L2, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_B, 1, "requires an EVEX_B prefix") \
+ ENUM_ENTRY(IC_EVEX_XS_B, 2, "requires EVEX_B and the XS prefix") \
+ ENUM_ENTRY(IC_EVEX_XD_B, 2, "requires EVEX_B and the XD prefix") \
+ ENUM_ENTRY(IC_EVEX_OPSIZE_B, 2, "requires EVEX_B and the OpSize prefix") \
+ ENUM_ENTRY(IC_EVEX_W_B, 3, "requires EVEX_B and the W prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XS_B, 4, "requires EVEX_B, W, and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XD_B, 4, "requires EVEX_B, W, and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_W_OPSIZE_B, 4, "requires EVEX_B, W, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_B, 3, "requires EVEX_B and the L prefix") \
+ ENUM_ENTRY(IC_EVEX_L_XS_B, 4, "requires EVEX_B and the L and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L_XD_B, 4, "requires EVEX_B and the L and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L_OPSIZE_B, 4, "requires EVEX_B, L, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_W_B, 3, "requires EVEX_B, L and W") \
+ ENUM_ENTRY(IC_EVEX_L_W_XS_B, 4, "requires EVEX_B, L, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_XD_B, 4, "requires EVEX_B, L, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_B, 4, "requires EVEX_B, L, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_B, 3, "requires EVEX_B and the L2 prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_XS_B, 4, "requires EVEX_B and the L2 and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_XD_B, 4, "requires EVEX_B and the L2 and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_OPSIZE_B, 4, "requires EVEX_B, L2, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_W_B, 3, "requires EVEX_B, L2 and W") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XS_B, 4, "requires EVEX_B, L2, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XD_B, 4, "requires EVEX_B, L2, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_B, 4, "requires EVEX_B, L2, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_K_B, 1, "requires EVEX_B and EVEX_K prefix") \
+ ENUM_ENTRY(IC_EVEX_XS_K_B, 2, "requires EVEX_B, EVEX_K and the XS prefix") \
+ ENUM_ENTRY(IC_EVEX_XD_K_B, 2, "requires EVEX_B, EVEX_K and the XD prefix") \
+ ENUM_ENTRY(IC_EVEX_OPSIZE_K_B, 2, "requires EVEX_B, EVEX_K and the OpSize prefix") \
+ ENUM_ENTRY(IC_EVEX_W_K_B, 3, "requires EVEX_B, EVEX_K and the W prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, W, and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, W, and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_W_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, W, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_K_B, 3, "requires EVEX_B, EVEX_K and the L prefix") \
+ ENUM_ENTRY(IC_EVEX_L_XS_K_B, 4, "requires EVEX_B, EVEX_K and the L and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L_XD_K_B, 4, "requires EVEX_B, EVEX_K and the L and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, L, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_W_K_B, 3, "requires EVEX_B, EVEX_K, L and W") \
+ ENUM_ENTRY(IC_EVEX_L_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, L, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, L, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_K_B,4, "requires EVEX_B, EVEX_K, L, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_K_B, 3, "requires EVEX_B, EVEX_K and the L2 prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_XS_K_B, 4, "requires EVEX_B, EVEX_K and the L2 and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_XD_K_B, 4, "requires EVEX_B, EVEX_K and the L2 and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, L2, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_W_K_B, 3, "requires EVEX_B, EVEX_K, L2 and W") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, L2, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, L2, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K_B,4, "requires EVEX_B, EVEX_K, L2, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_KZ_B, 1, "requires EVEX_B and EVEX_KZ prefix") \
+ ENUM_ENTRY(IC_EVEX_XS_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the XS prefix") \
+ ENUM_ENTRY(IC_EVEX_XD_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the XD prefix") \
+ ENUM_ENTRY(IC_EVEX_OPSIZE_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the OpSize prefix") \
+ ENUM_ENTRY(IC_EVEX_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the W prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the L prefix") \
+ ENUM_ENTRY(IC_EVEX_L_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ, L and W") \
+ ENUM_ENTRY(IC_EVEX_L_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the L2 prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L2 and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L2 and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ, L2 and W") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_KZ, 1, "requires an EVEX_KZ prefix") \
+ ENUM_ENTRY(IC_EVEX_XS_KZ, 2, "requires EVEX_KZ and the XS prefix") \
+ ENUM_ENTRY(IC_EVEX_XD_KZ, 2, "requires EVEX_KZ and the XD prefix") \
+ ENUM_ENTRY(IC_EVEX_OPSIZE_KZ, 2, "requires EVEX_KZ and the OpSize prefix") \
+ ENUM_ENTRY(IC_EVEX_W_KZ, 3, "requires EVEX_KZ and the W prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XS_KZ, 4, "requires EVEX_KZ, W, and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_W_XD_KZ, 4, "requires EVEX_KZ, W, and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_W_OPSIZE_KZ, 4, "requires EVEX_KZ, W, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_KZ, 3, "requires EVEX_KZ and the L prefix") \
+ ENUM_ENTRY(IC_EVEX_L_XS_KZ, 4, "requires EVEX_KZ and the L and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L_XD_KZ, 4, "requires EVEX_KZ and the L and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L_OPSIZE_KZ, 4, "requires EVEX_KZ, L, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L_W_KZ, 3, "requires EVEX_KZ, L and W") \
+ ENUM_ENTRY(IC_EVEX_L_W_XS_KZ, 4, "requires EVEX_KZ, L, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_XD_KZ, 4, "requires EVEX_KZ, L, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L, W and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_KZ, 3, "requires EVEX_KZ and the L2 prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_XS_KZ, 4, "requires EVEX_KZ and the L2 and XS prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_XD_KZ, 4, "requires EVEX_KZ and the L2 and XD prefix")\
+ ENUM_ENTRY(IC_EVEX_L2_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, and OpSize") \
+ ENUM_ENTRY(IC_EVEX_L2_W_KZ, 3, "requires EVEX_KZ, L2 and W") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ, 4, "requires EVEX_KZ, L2, W and XS prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ, 4, "requires EVEX_KZ, L2, W and XD prefix") \
+ ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize")
+
+#define ENUM_ENTRY(n, r, d) n,
+enum InstructionContext {
+ INSTRUCTION_CONTEXTS
+ IC_max
+};
+#undef ENUM_ENTRY
+
+// Opcode types, which determine which decode table to use, both in the Intel
+// manual and also for the decoder.
+enum OpcodeType {
+ ONEBYTE = 0,
+ TWOBYTE = 1,
+ THREEBYTE_38 = 2,
+ THREEBYTE_3A = 3,
+ XOP8_MAP = 4,
+ XOP9_MAP = 5,
+ XOPA_MAP = 6,
+ THREEDNOW_MAP = 7
+};
+
+// The following structs are used for the hierarchical decode table. After
+// determining the instruction's class (i.e., which IC_* constant applies to
+// it), the decoder reads the opcode. Some instructions require specific
+// values of the ModR/M byte, so the ModR/M byte indexes into the final table.
+//
+// If a ModR/M byte is not required, "required" is left unset, and the values
+// for each instructionID are identical.
+typedef uint16_t InstrUID;
+
+// ModRMDecisionType - describes the type of ModR/M decision, allowing the
+// consumer to determine the number of entries in it.
+//
+// MODRM_ONEENTRY - No matter what the value of the ModR/M byte is, the decoded
+// instruction is the same.
+// MODRM_SPLITRM - If the ModR/M byte is between 0x00 and 0xbf, the opcode
+// corresponds to one instruction; otherwise, it corresponds to
+// a different instruction.
+// MODRM_SPLITMISC- If the ModR/M byte is between 0x00 and 0xbf, ModR/M byte
+// divided by 8 is used to select instruction; otherwise, each
+// value of the ModR/M byte could correspond to a different
+// instruction.
+// MODRM_SPLITREG - ModR/M byte divided by 8 is used to select instruction. This
+// corresponds to instructions that use reg field as opcode
+// MODRM_FULL - Potentially, each value of the ModR/M byte could correspond
+// to a different instruction.
+#define MODRMTYPES \
+ ENUM_ENTRY(MODRM_ONEENTRY) \
+ ENUM_ENTRY(MODRM_SPLITRM) \
+ ENUM_ENTRY(MODRM_SPLITMISC) \
+ ENUM_ENTRY(MODRM_SPLITREG) \
+ ENUM_ENTRY(MODRM_FULL)
+
+#define ENUM_ENTRY(n) n,
+enum ModRMDecisionType {
+ MODRMTYPES
+ MODRM_max
+};
+#undef ENUM_ENTRY
+
+#define CASE_ENCODING_RM \
+ case ENCODING_RM: \
+ case ENCODING_RM_CD2: \
+ case ENCODING_RM_CD4: \
+ case ENCODING_RM_CD8: \
+ case ENCODING_RM_CD16: \
+ case ENCODING_RM_CD32: \
+ case ENCODING_RM_CD64
+
+#define CASE_ENCODING_VSIB \
+ case ENCODING_VSIB: \
+ case ENCODING_VSIB_CD2: \
+ case ENCODING_VSIB_CD4: \
+ case ENCODING_VSIB_CD8: \
+ case ENCODING_VSIB_CD16: \
+ case ENCODING_VSIB_CD32: \
+ case ENCODING_VSIB_CD64
+
+// Physical encodings of instruction operands.
+#define ENCODINGS \
+ ENUM_ENTRY(ENCODING_NONE, "") \
+ ENUM_ENTRY(ENCODING_REG, "Register operand in ModR/M byte.") \
+ ENUM_ENTRY(ENCODING_RM, "R/M operand in ModR/M byte.") \
+ ENUM_ENTRY(ENCODING_RM_CD2, "R/M operand with CDisp scaling of 2") \
+ ENUM_ENTRY(ENCODING_RM_CD4, "R/M operand with CDisp scaling of 4") \
+ ENUM_ENTRY(ENCODING_RM_CD8, "R/M operand with CDisp scaling of 8") \
+ ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16") \
+ ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32") \
+ ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64") \
+ ENUM_ENTRY(ENCODING_VSIB, "VSIB operand in ModR/M byte.") \
+ ENUM_ENTRY(ENCODING_VSIB_CD2, "VSIB operand with CDisp scaling of 2") \
+ ENUM_ENTRY(ENCODING_VSIB_CD4, "VSIB operand with CDisp scaling of 4") \
+ ENUM_ENTRY(ENCODING_VSIB_CD8, "VSIB operand with CDisp scaling of 8") \
+ ENUM_ENTRY(ENCODING_VSIB_CD16,"VSIB operand with CDisp scaling of 16") \
+ ENUM_ENTRY(ENCODING_VSIB_CD32,"VSIB operand with CDisp scaling of 32") \
+ ENUM_ENTRY(ENCODING_VSIB_CD64,"VSIB operand with CDisp scaling of 64") \
+ ENUM_ENTRY(ENCODING_VVVV, "Register operand in VEX.vvvv byte.") \
+ ENUM_ENTRY(ENCODING_WRITEMASK, "Register operand in EVEX.aaa byte.") \
+ ENUM_ENTRY(ENCODING_IB, "1-byte immediate") \
+ ENUM_ENTRY(ENCODING_IW, "2-byte") \
+ ENUM_ENTRY(ENCODING_ID, "4-byte") \
+ ENUM_ENTRY(ENCODING_IO, "8-byte") \
+ ENUM_ENTRY(ENCODING_RB, "(AL..DIL, R8L..R15L) Register code added to " \
+ "the opcode byte") \
+ ENUM_ENTRY(ENCODING_RW, "(AX..DI, R8W..R15W)") \
+ ENUM_ENTRY(ENCODING_RD, "(EAX..EDI, R8D..R15D)") \
+ ENUM_ENTRY(ENCODING_RO, "(RAX..RDI, R8..R15)") \
+ ENUM_ENTRY(ENCODING_FP, "Position on floating-point stack in ModR/M " \
+ "byte.") \
+ \
+ ENUM_ENTRY(ENCODING_Iv, "Immediate of operand size") \
+ ENUM_ENTRY(ENCODING_Ia, "Immediate of address size") \
+ ENUM_ENTRY(ENCODING_IRC, "Immediate for static rounding control") \
+ ENUM_ENTRY(ENCODING_Rv, "Register code of operand size added to the " \
+ "opcode byte") \
+ ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \
+ "in type") \
+ ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix") \
+ ENUM_ENTRY(ENCODING_DI, "Destination index; encoded in prefixes")
+
+#define ENUM_ENTRY(n, d) n,
+enum OperandEncoding {
+ ENCODINGS
+ ENCODING_max
+};
+#undef ENUM_ENTRY
+
+// Semantic interpretations of instruction operands.
+#define TYPES \
+ ENUM_ENTRY(TYPE_NONE, "") \
+ ENUM_ENTRY(TYPE_REL, "immediate address") \
+ ENUM_ENTRY(TYPE_R8, "1-byte register operand") \
+ ENUM_ENTRY(TYPE_R16, "2-byte") \
+ ENUM_ENTRY(TYPE_R32, "4-byte") \
+ ENUM_ENTRY(TYPE_R64, "8-byte") \
+ ENUM_ENTRY(TYPE_IMM, "immediate operand") \
+ ENUM_ENTRY(TYPE_IMM3, "1-byte immediate operand between 0 and 7") \
+ ENUM_ENTRY(TYPE_IMM5, "1-byte immediate operand between 0 and 31") \
+ ENUM_ENTRY(TYPE_AVX512ICC, "1-byte immediate operand for AVX512 icmp") \
+ ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \
+ ENUM_ENTRY(TYPE_M, "Memory operand") \
+ ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \
+ ENUM_ENTRY(TYPE_MVSIBY, "Memory operand using YMM index") \
+ ENUM_ENTRY(TYPE_MVSIBZ, "Memory operand using ZMM index") \
+ ENUM_ENTRY(TYPE_SRCIDX, "memory at source index") \
+ ENUM_ENTRY(TYPE_DSTIDX, "memory at destination index") \
+ ENUM_ENTRY(TYPE_MOFFS, "memory offset (relative to segment base)") \
+ ENUM_ENTRY(TYPE_ST, "Position on the floating-point stack") \
+ ENUM_ENTRY(TYPE_MM64, "8-byte MMX register") \
+ ENUM_ENTRY(TYPE_XMM, "16-byte") \
+ ENUM_ENTRY(TYPE_YMM, "32-byte") \
+ ENUM_ENTRY(TYPE_ZMM, "64-byte") \
+ ENUM_ENTRY(TYPE_VK, "mask register") \
+ ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \
+ ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \
+ ENUM_ENTRY(TYPE_CONTROLREG, "Control register operand") \
+ ENUM_ENTRY(TYPE_BNDR, "MPX bounds register") \
+ \
+ ENUM_ENTRY(TYPE_Rv, "Register operand of operand size") \
+ ENUM_ENTRY(TYPE_RELv, "Immediate address of operand size") \
+ ENUM_ENTRY(TYPE_DUP0, "Duplicate of operand 0") \
+ ENUM_ENTRY(TYPE_DUP1, "operand 1") \
+ ENUM_ENTRY(TYPE_DUP2, "operand 2") \
+ ENUM_ENTRY(TYPE_DUP3, "operand 3") \
+ ENUM_ENTRY(TYPE_DUP4, "operand 4") \
+
+#define ENUM_ENTRY(n, d) n,
+enum OperandType {
+ TYPES
+ TYPE_max
+};
+#undef ENUM_ENTRY
+
+/// The specification for how to extract and interpret one operand.
+struct OperandSpecifier {
+ uint8_t encoding;
+ uint8_t type;
+};
+
+static const unsigned X86_MAX_OPERANDS = 6;
+
+/// Decoding mode for the Intel disassembler. 16-bit, 32-bit, and 64-bit mode
+/// are supported, and represent real mode, IA-32e, and IA-32e in 64-bit mode,
+/// respectively.
+enum DisassemblerMode {
+ MODE_16BIT,
+ MODE_32BIT,
+ MODE_64BIT
+};
+
+} // namespace X86Disassembler
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/Support/X86TargetParser.def b/contrib/llvm/include/llvm/Support/X86TargetParser.def
index 5c8c576b1027..e4af0657a350 100644
--- a/contrib/llvm/include/llvm/Support/X86TargetParser.def
+++ b/contrib/llvm/include/llvm/Support/X86TargetParser.def
@@ -65,6 +65,8 @@ X86_CPU_TYPE ("athlon-xp", AMD_ATHLON_XP)
X86_CPU_TYPE ("k8", AMD_K8)
X86_CPU_TYPE ("k8-sse3", AMD_K8SSE3)
X86_CPU_TYPE ("goldmont", INTEL_GOLDMONT)
+X86_CPU_TYPE ("goldmont-plus", INTEL_GOLDMONT_PLUS)
+X86_CPU_TYPE ("tremont", INTEL_TREMONT)
#undef X86_CPU_TYPE_COMPAT_WITH_ALIAS
#undef X86_CPU_TYPE_COMPAT
#undef X86_CPU_TYPE
diff --git a/contrib/llvm/include/llvm/Support/YAMLParser.h b/contrib/llvm/include/llvm/Support/YAMLParser.h
index c907a99ddb59..5b031a9a4270 100644
--- a/contrib/llvm/include/llvm/Support/YAMLParser.h
+++ b/contrib/llvm/include/llvm/Support/YAMLParser.h
@@ -64,23 +64,26 @@ class Node;
class Scanner;
struct Token;
-/// \brief Dump all the tokens in this stream to OS.
+/// Dump all the tokens in this stream to OS.
/// \returns true if there was an error, false otherwise.
bool dumpTokens(StringRef Input, raw_ostream &);
-/// \brief Scans all tokens in input without outputting anything. This is used
+/// Scans all tokens in input without outputting anything. This is used
/// for benchmarking the tokenizer.
/// \returns true if there was an error, false otherwise.
bool scanTokens(StringRef Input);
-/// \brief Escape \a Input for a double quoted scalar.
-std::string escape(StringRef Input);
+/// Escape \a Input for a double quoted scalar; if \p EscapePrintable
+/// is true, all UTF8 sequences will be escaped, if \p EscapePrintable is
+/// false, those UTF8 sequences encoding printable unicode scalars will not be
+/// escaped, but emitted verbatim.
+std::string escape(StringRef Input, bool EscapePrintable = true);
-/// \brief This class represents a YAML stream potentially containing multiple
+/// This class represents a YAML stream potentially containing multiple
/// documents.
class Stream {
public:
- /// \brief This keeps a reference to the string referenced by \p Input.
+ /// This keeps a reference to the string referenced by \p Input.
Stream(StringRef Input, SourceMgr &, bool ShowColors = true,
std::error_code *EC = nullptr);
@@ -107,7 +110,7 @@ private:
std::unique_ptr<Document> CurrentDoc;
};
-/// \brief Abstract base class for all Nodes.
+/// Abstract base class for all Nodes.
class Node {
virtual void anchor();
@@ -125,6 +128,11 @@ public:
Node(unsigned int Type, std::unique_ptr<Document> &, StringRef Anchor,
StringRef Tag);
+ // It's not safe to copy YAML nodes; the document is streamed and the position
+ // is part of the state.
+ Node(const Node &) = delete;
+ void operator=(const Node &) = delete;
+
void *operator new(size_t Size, BumpPtrAllocator &Alloc,
size_t Alignment = 16) noexcept {
return Alloc.Allocate(Size, Alignment);
@@ -137,15 +145,15 @@ public:
void operator delete(void *) noexcept = delete;
- /// \brief Get the value of the anchor attached to this node. If it does not
+ /// Get the value of the anchor attached to this node. If it does not
/// have one, getAnchor().size() will be 0.
StringRef getAnchor() const { return Anchor; }
- /// \brief Get the tag as it was written in the document. This does not
+ /// Get the tag as it was written in the document. This does not
/// perform tag resolution.
StringRef getRawTag() const { return Tag; }
- /// \brief Get the verbatium tag for a given Node. This performs tag resoluton
+ /// Get the verbatium tag for a given Node. This performs tag resoluton
/// and substitution.
std::string getVerbatimTag() const;
@@ -173,11 +181,11 @@ protected:
private:
unsigned int TypeID;
StringRef Anchor;
- /// \brief The tag as typed in the document.
+ /// The tag as typed in the document.
StringRef Tag;
};
-/// \brief A null value.
+/// A null value.
///
/// Example:
/// !!null null
@@ -191,7 +199,7 @@ public:
static bool classof(const Node *N) { return N->getType() == NK_Null; }
};
-/// \brief A scalar node is an opaque datum that can be presented as a
+/// A scalar node is an opaque datum that can be presented as a
/// series of zero or more Unicode scalar values.
///
/// Example:
@@ -213,7 +221,7 @@ public:
// utf8).
StringRef getRawValue() const { return Value; }
- /// \brief Gets the value of this node as a StringRef.
+ /// Gets the value of this node as a StringRef.
///
/// \param Storage is used to store the content of the returned StringRef iff
/// it requires any modification from how it appeared in the source.
@@ -232,7 +240,7 @@ private:
SmallVectorImpl<char> &Storage) const;
};
-/// \brief A block scalar node is an opaque datum that can be presented as a
+/// A block scalar node is an opaque datum that can be presented as a
/// series of zero or more Unicode scalar values.
///
/// Example:
@@ -251,7 +259,7 @@ public:
SourceRange = SMRange(Start, End);
}
- /// \brief Gets the value of this node as a StringRef.
+ /// Gets the value of this node as a StringRef.
StringRef getValue() const { return Value; }
static bool classof(const Node *N) {
@@ -262,7 +270,7 @@ private:
StringRef Value;
};
-/// \brief A key and value pair. While not technically a Node under the YAML
+/// A key and value pair. While not technically a Node under the YAML
/// representation graph, it is easier to treat them this way.
///
/// TODO: Consider making this not a child of Node.
@@ -276,14 +284,14 @@ public:
KeyValueNode(std::unique_ptr<Document> &D)
: Node(NK_KeyValue, D, StringRef(), StringRef()) {}
- /// \brief Parse and return the key.
+ /// Parse and return the key.
///
/// This may be called multiple times.
///
/// \returns The key, or nullptr if failed() == true.
Node *getKey();
- /// \brief Parse and return the value.
+ /// Parse and return the value.
///
/// This may be called multiple times.
///
@@ -307,7 +315,7 @@ private:
Node *Value = nullptr;
};
-/// \brief This is an iterator abstraction over YAML collections shared by both
+/// This is an iterator abstraction over YAML collections shared by both
/// sequences and maps.
///
/// BaseT must have a ValueT* member named CurrentEntry and a member function
@@ -387,7 +395,7 @@ template <class CollectionType> void skip(CollectionType &C) {
i->skip();
}
-/// \brief Represents a YAML map created from either a block map for a flow map.
+/// Represents a YAML map created from either a block map for a flow map.
///
/// This parses the YAML stream as increment() is called.
///
@@ -434,7 +442,7 @@ private:
void increment();
};
-/// \brief Represents a YAML sequence created from either a block sequence for a
+/// Represents a YAML sequence created from either a block sequence for a
/// flow sequence.
///
/// This parses the YAML stream as increment() is called.
@@ -490,7 +498,7 @@ private:
Node *CurrentEntry = nullptr;
};
-/// \brief Represents an alias to a Node with an anchor.
+/// Represents an alias to a Node with an anchor.
///
/// Example:
/// *AnchorName
@@ -510,20 +518,20 @@ private:
StringRef Name;
};
-/// \brief A YAML Stream is a sequence of Documents. A document contains a root
+/// A YAML Stream is a sequence of Documents. A document contains a root
/// node.
class Document {
public:
Document(Stream &ParentStream);
- /// \brief Root for parsing a node. Returns a single node.
+ /// Root for parsing a node. Returns a single node.
Node *parseBlockNode();
- /// \brief Finish parsing the current document and return true if there are
+ /// Finish parsing the current document and return true if there are
/// more. Return false otherwise.
bool skip();
- /// \brief Parse and return the root level node.
+ /// Parse and return the root level node.
Node *getRoot() {
if (Root)
return Root;
@@ -536,18 +544,18 @@ private:
friend class Node;
friend class document_iterator;
- /// \brief Stream to read tokens from.
+ /// Stream to read tokens from.
Stream &stream;
- /// \brief Used to allocate nodes to. All are destroyed without calling their
+ /// Used to allocate nodes to. All are destroyed without calling their
/// destructor when the document is destroyed.
BumpPtrAllocator NodeAllocator;
- /// \brief The root node. Used to support skipping a partially parsed
+ /// The root node. Used to support skipping a partially parsed
/// document.
Node *Root;
- /// \brief Maps tag prefixes to their expansion.
+ /// Maps tag prefixes to their expansion.
std::map<StringRef, StringRef> TagMap;
Token &peekNext();
@@ -555,20 +563,20 @@ private:
void setError(const Twine &Message, Token &Location) const;
bool failed() const;
- /// \brief Parse %BLAH directives and return true if any were encountered.
+ /// Parse %BLAH directives and return true if any were encountered.
bool parseDirectives();
- /// \brief Parse %YAML
+ /// Parse %YAML
void parseYAMLDirective();
- /// \brief Parse %TAG
+ /// Parse %TAG
void parseTAGDirective();
- /// \brief Consume the next token and error if it is not \a TK.
+ /// Consume the next token and error if it is not \a TK.
bool expectToken(int TK);
};
-/// \brief Iterator abstraction for Documents over a Stream.
+/// Iterator abstraction for Documents over a Stream.
class document_iterator {
public:
document_iterator() = default;
diff --git a/contrib/llvm/include/llvm/Support/YAMLTraits.h b/contrib/llvm/include/llvm/Support/YAMLTraits.h
index 674c78a11695..4b8c4e958288 100644
--- a/contrib/llvm/include/llvm/Support/YAMLTraits.h
+++ b/contrib/llvm/include/llvm/Support/YAMLTraits.h
@@ -511,8 +511,6 @@ inline QuotingType needsQuotes(StringRef S) {
return QuotingType::Single;
if (isspace(S.front()) || isspace(S.back()))
return QuotingType::Single;
- if (S.front() == ',')
- return QuotingType::Single;
if (isNull(S))
return QuotingType::Single;
if (isBool(S))
@@ -520,6 +518,13 @@ inline QuotingType needsQuotes(StringRef S) {
if (isNumeric(S))
return QuotingType::Single;
+ // 7.3.3 Plain Style
+ // Plain scalars must not begin with most indicators, as this would cause
+ // ambiguity with other YAML constructs.
+ static constexpr char Indicators[] = R"(-?:\,[]{}#&*!|>'"%@`)";
+ if (S.find_first_of(Indicators) == 0)
+ return QuotingType::Single;
+
QuotingType MaxQuotingNeeded = QuotingType::None;
for (unsigned char C : S) {
// Alphanum is safe.
@@ -535,11 +540,14 @@ inline QuotingType needsQuotes(StringRef S) {
case '.':
case ',':
case ' ':
- // TAB (0x9), LF (0xA), CR (0xD) and NEL (0x85) are allowed.
+ // TAB (0x9) is allowed in unquoted strings.
case 0x9:
+ continue;
+ // LF(0xA) and CR(0xD) may delimit values and so require at least single
+ // quotes.
case 0xA:
case 0xD:
- case 0x85:
+ MaxQuotingNeeded = QuotingType::Single;
continue;
// DEL (0x7F) are excluded from the allowed character range.
case 0x7F:
@@ -1306,7 +1314,7 @@ public:
Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
~Output() override;
- /// \brief Set whether or not to output optional values which are equal
+ /// Set whether or not to output optional values which are equal
/// to the default value. By default, when outputting if you attempt
/// to write a value that is equal to the default, the value gets ignored.
/// Sometimes, it is useful to be able to see these in the resulting YAML
diff --git a/contrib/llvm/include/llvm/Support/raw_ostream.h b/contrib/llvm/include/llvm/Support/raw_ostream.h
index d11f5a837796..b9ea9b5817f2 100644
--- a/contrib/llvm/include/llvm/Support/raw_ostream.h
+++ b/contrib/llvm/include/llvm/Support/raw_ostream.h
@@ -33,7 +33,9 @@ class FormattedBytes;
namespace sys {
namespace fs {
+enum FileAccess : unsigned;
enum OpenFlags : unsigned;
+enum CreationDisposition : unsigned;
} // end namespace fs
} // end namespace sys
@@ -218,7 +220,7 @@ public:
raw_ostream &write_uuid(const uuid_t UUID);
/// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't
- /// satisfy std::isprint into an escape sequence.
+ /// satisfy llvm::isPrint into an escape sequence.
raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false);
raw_ostream &write(unsigned char C);
@@ -242,6 +244,9 @@ public:
/// indent - Insert 'NumSpaces' spaces.
raw_ostream &indent(unsigned NumSpaces);
+ /// write_zeros - Insert 'NumZeros' nulls.
+ raw_ostream &write_zeros(unsigned NumZeros);
+
/// Changes the foreground color of text that will be output from this point
/// forward.
/// @param Color ANSI color to use, the special SAVEDCOLOR can be used to
@@ -293,9 +298,6 @@ private:
/// \invariant { Size > 0 }
virtual void write_impl(const char *Ptr, size_t Size) = 0;
- // An out of line virtual method to provide a home for the class vtable.
- virtual void handle();
-
/// Return the current position within the stream, not counting the bytes
/// currently in the buffer.
virtual uint64_t current_pos() const = 0;
@@ -329,6 +331,8 @@ private:
/// Copy data into the buffer. Size must not be greater than the number of
/// unused bytes in the buffer.
void copy_to_buffer(const char *Ptr, size_t Size);
+
+ virtual void anchor();
};
/// An abstract base class for streams implementations that also support a
@@ -336,6 +340,7 @@ private:
/// but needs to patch in a header that needs to know the output size.
class raw_pwrite_stream : public raw_ostream {
virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0;
+ void anchor() override;
public:
explicit raw_pwrite_stream(bool Unbuffered = false)
@@ -383,6 +388,8 @@ class raw_fd_ostream : public raw_pwrite_stream {
/// Set the flag indicating that an output error has been encountered.
void error_detected(std::error_code EC) { this->EC = EC; }
+ void anchor() override;
+
public:
/// Open the specified file for writing. If an error occurs, information
/// about the error is put into EC, and the stream should be immediately
@@ -392,7 +399,15 @@ public:
/// As a special case, if Filename is "-", then the stream will use
/// STDOUT_FILENO instead of opening a file. This will not close the stdout
/// descriptor.
+ raw_fd_ostream(StringRef Filename, std::error_code &EC);
+ raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::CreationDisposition Disp);
+ raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::FileAccess Access);
+ raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::OpenFlags Flags);
raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access,
sys::fs::OpenFlags Flags);
/// FD is the file descriptor that this writes to. If ShouldClose is true,
diff --git a/contrib/llvm/include/llvm/Support/type_traits.h b/contrib/llvm/include/llvm/Support/type_traits.h
index cc0878358800..55d84f138f07 100644
--- a/contrib/llvm/include/llvm/Support/type_traits.h
+++ b/contrib/llvm/include/llvm/Support/type_traits.h
@@ -54,7 +54,7 @@ struct isPodLike<std::pair<T, U>> {
static const bool value = isPodLike<T>::value && isPodLike<U>::value;
};
-/// \brief Metafunction that determines whether the given type is either an
+/// Metafunction that determines whether the given type is either an
/// integral type or an enumeration type, including enum classes.
///
/// Note that this accepts potentially more integral types than is_integral
@@ -73,7 +73,7 @@ public:
std::is_convertible<UnderlyingT, unsigned long long>::value);
};
-/// \brief If T is a pointer, just return it. If it is not, return T&.
+/// If T is a pointer, just return it. If it is not, return T&.
template<typename T, typename Enable = void>
struct add_lvalue_reference_if_not_pointer { using type = T &; };
@@ -83,7 +83,7 @@ struct add_lvalue_reference_if_not_pointer<
using type = T;
};
-/// \brief If T is a pointer to X, return a pointer to const X. If it is not,
+/// If T is a pointer to X, return a pointer to const X. If it is not,
/// return const T.
template<typename T, typename Enable = void>
struct add_const_past_pointer { using type = const T; };
@@ -104,12 +104,51 @@ struct const_pointer_or_const_ref<
using type = typename add_const_past_pointer<T>::type;
};
+namespace detail {
+/// Internal utility to detect trivial copy construction.
+template<typename T> union copy_construction_triviality_helper {
+ T t;
+ copy_construction_triviality_helper() = default;
+ copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default;
+ ~copy_construction_triviality_helper() = default;
+};
+/// Internal utility to detect trivial move construction.
+template<typename T> union move_construction_triviality_helper {
+ T t;
+ move_construction_triviality_helper() = default;
+ move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
+ ~move_construction_triviality_helper() = default;
+};
+} // end namespace detail
+
+/// An implementation of `std::is_trivially_copy_constructible` since we have
+/// users with STLs that don't yet include it.
+template <typename T>
+struct is_trivially_copy_constructible
+ : std::is_copy_constructible<
+ ::llvm::detail::copy_construction_triviality_helper<T>> {};
+template <typename T>
+struct is_trivially_copy_constructible<T &> : std::true_type {};
+template <typename T>
+struct is_trivially_copy_constructible<T &&> : std::false_type {};
+
+/// An implementation of `std::is_trivially_move_constructible` since we have
+/// users with STLs that don't yet include it.
+template <typename T>
+struct is_trivially_move_constructible
+ : std::is_move_constructible<
+ ::llvm::detail::move_construction_triviality_helper<T>> {};
+template <typename T>
+struct is_trivially_move_constructible<T &> : std::true_type {};
+template <typename T>
+struct is_trivially_move_constructible<T &&> : std::true_type {};
+
} // end namespace llvm
// If the compiler supports detecting whether a class is final, define
// an LLVM_IS_FINAL macro. If it cannot be defined properly, this
// macro will be left undefined.
-#if __cplusplus >= 201402L
+#if __cplusplus >= 201402L || defined(_MSC_VER)
#define LLVM_IS_FINAL(Ty) std::is_final<Ty>()
#elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0)
#define LLVM_IS_FINAL(Ty) __is_final(Ty)
diff --git a/contrib/llvm/include/llvm/TableGen/Record.h b/contrib/llvm/include/llvm/TableGen/Record.h
index 55b4dfe2fa2f..e022bc82b4e4 100644
--- a/contrib/llvm/include/llvm/TableGen/Record.h
+++ b/contrib/llvm/include/llvm/TableGen/Record.h
@@ -16,6 +16,8 @@
#define LLVM_TABLEGEN_RECORD_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
@@ -42,7 +44,9 @@ struct MultiClass;
class Record;
class RecordKeeper;
class RecordVal;
+class Resolver;
class StringInit;
+class TypedInit;
//===----------------------------------------------------------------------===//
// Type Classes
@@ -50,7 +54,7 @@ class StringInit;
class RecTy {
public:
- /// \brief Subclass discriminator (for dyn_cast<> et al.)
+ /// Subclass discriminator (for dyn_cast<> et al.)
enum RecTyKind {
BitRecTyKind,
BitsRecTyKind,
@@ -80,6 +84,10 @@ public:
/// type.
virtual bool typeIsConvertibleTo(const RecTy *RHS) const;
+ /// Return true if 'this' type is equal to or a subtype of RHS. For example,
+ /// a bit set is not an int, but they are convertible.
+ virtual bool typeIsA(const RecTy *RHS) const;
+
/// Returns the type representing list<this>.
ListRecTy *getListTy();
};
@@ -125,6 +133,8 @@ public:
std::string getAsString() const override;
bool typeIsConvertibleTo(const RecTy *RHS) const override;
+
+ bool typeIsA(const RecTy *RHS) const override;
};
/// 'code' - Represent a code fragment
@@ -141,6 +151,8 @@ public:
static CodeRecTy *get() { return &Shared; }
std::string getAsString() const override { return "code"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
/// 'int' - Represent an integer value of no particular size
@@ -169,13 +181,14 @@ class StringRecTy : public RecTy {
public:
static bool classof(const RecTy *RT) {
- return RT->getRecTyKind() == StringRecTyKind ||
- RT->getRecTyKind() == CodeRecTyKind;
+ return RT->getRecTyKind() == StringRecTyKind;
}
static StringRecTy *get() { return &Shared; }
std::string getAsString() const override;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
/// 'list<Ty>' - Represent a list of values, all of which must be of
@@ -198,6 +211,8 @@ public:
std::string getAsString() const override;
bool typeIsConvertibleTo(const RecTy *RHS) const override;
+
+ bool typeIsA(const RecTy *RHS) const override;
};
/// 'dag' - Represent a dag fragment
@@ -216,27 +231,50 @@ public:
std::string getAsString() const override;
};
-/// '[classname]' - Represent an instance of a class, such as:
-/// (R32 X = EAX).
-class RecordRecTy : public RecTy {
+/// '[classname]' - Type of record values that have zero or more superclasses.
+///
+/// The list of superclasses is non-redundant, i.e. only contains classes that
+/// are not the superclass of some other listed class.
+class RecordRecTy final : public RecTy, public FoldingSetNode,
+ public TrailingObjects<RecordRecTy, Record *> {
friend class Record;
- Record *Rec;
+ unsigned NumClasses;
- explicit RecordRecTy(Record *R) : RecTy(RecordRecTyKind), Rec(R) {}
+ explicit RecordRecTy(unsigned Num)
+ : RecTy(RecordRecTyKind), NumClasses(Num) {}
public:
+ RecordRecTy(const RecordRecTy &) = delete;
+ RecordRecTy &operator=(const RecordRecTy &) = delete;
+
+ // Do not use sized deallocation due to trailing objects.
+ void operator delete(void *p) { ::operator delete(p); }
+
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == RecordRecTyKind;
}
- static RecordRecTy *get(Record *R);
+ /// Get the record type with the given non-redundant list of superclasses.
+ static RecordRecTy *get(ArrayRef<Record *> Classes);
+
+ void Profile(FoldingSetNodeID &ID) const;
+
+ ArrayRef<Record *> getClasses() const {
+ return makeArrayRef(getTrailingObjects<Record *>(), NumClasses);
+ }
+
+ using const_record_iterator = Record * const *;
- Record *getRecord() const { return Rec; }
+ const_record_iterator classes_begin() const { return getClasses().begin(); }
+ const_record_iterator classes_end() const { return getClasses().end(); }
std::string getAsString() const override;
+ bool isSubClassOf(Record *Class) const;
bool typeIsConvertibleTo(const RecTy *RHS) const override;
+
+ bool typeIsA(const RecTy *RHS) const override;
};
/// Find a common type that T1 and T2 convert to.
@@ -249,7 +287,7 @@ RecTy *resolveTypes(RecTy *T1, RecTy *T2);
class Init {
protected:
- /// \brief Discriminator enum (for isa<>, dyn_cast<>, et al.)
+ /// Discriminator enum (for isa<>, dyn_cast<>, et al.)
///
/// This enum is laid out by a preorder traversal of the inheritance
/// hierarchy, and does not contain an entry for abstract classes, as per
@@ -263,8 +301,9 @@ protected:
/// and IK_LastXXXInit be their own values, but that would degrade
/// readability for really no benefit.
enum InitKind : uint8_t {
- IK_BitInit,
+ IK_First, // unused; silence a spurious warning
IK_FirstTypedInit,
+ IK_BitInit,
IK_BitsInit,
IK_CodeInit,
IK_DagInit,
@@ -277,12 +316,15 @@ protected:
IK_TernOpInit,
IK_UnOpInit,
IK_LastOpInit,
+ IK_FoldOpInit,
+ IK_IsAOpInit,
IK_StringInit,
IK_VarInit,
IK_VarListElementInit,
+ IK_VarBitInit,
+ IK_VarDefInit,
IK_LastTypedInit,
- IK_UnsetInit,
- IK_VarBitInit
+ IK_UnsetInit
};
private:
@@ -309,6 +351,10 @@ public:
/// not be completely specified yet.
virtual bool isComplete() const { return true; }
+ /// Is this a concrete and fully resolved value without any references or
+ /// stuck operations? Unset values are concrete.
+ virtual bool isConcrete() const { return false; }
+
/// Print out this value.
void print(raw_ostream &OS) const { OS << getAsString(); }
@@ -324,8 +370,14 @@ public:
/// invokes print on stderr.
void dump() const;
- /// This virtual function converts to the appropriate
- /// Init based on the passed in type.
+ /// If this initializer is convertible to Ty, return an initializer whose
+ /// type is-a Ty, generating a !cast operation if required. Otherwise, return
+ /// nullptr.
+ virtual Init *getCastTo(RecTy *Ty) const = 0;
+
+ /// Convert to an initializer whose type is-a Ty, or return nullptr if this
+ /// is not possible (this can happen if the initializer's type is convertible
+ /// to Ty, but there are unresolved references).
virtual Init *convertInitializerTo(RecTy *Ty) const = 0;
/// This method is used to implement the bitrange
@@ -351,33 +403,17 @@ public:
return nullptr;
}
- /// This method complements getFieldType to return the
- /// initializer for the specified field. If getFieldType returns non-null
- /// this method should return non-null, otherwise it returns null.
- virtual Init *getFieldInit(Record &R, const RecordVal *RV,
- StringInit *FieldName) const {
- return nullptr;
- }
-
/// This method is used by classes that refer to other
/// variables which may not be defined at the time the expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
- virtual Init *resolveReferences(Record &R, const RecordVal *RV) const {
+ virtual Init *resolveReferences(Resolver &R) const {
return const_cast<Init *>(this);
}
/// This method is used to return the initializer for the specified
/// bit.
virtual Init *getBit(unsigned Bit) const = 0;
-
- /// This method is used to retrieve the initializer for bit
- /// reference. For non-VarBitInit, it simply returns itself.
- virtual Init *getBitVar() const { return const_cast<Init*>(this); }
-
- /// This method is used to retrieve the bit number of a bit
- /// reference. For non-VarBitInit, it simply returns 0.
- virtual unsigned getBitNum() const { return 0; }
};
inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
@@ -404,6 +440,7 @@ public:
RecTy *getType() const { return Ty; }
+ Init *getCastTo(RecTy *Ty) const override;
Init *convertInitializerTo(RecTy *Ty) const override;
Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const override;
@@ -414,12 +451,6 @@ public:
/// they are of record type.
///
RecTy *getFieldType(StringInit *FieldName) const override;
-
- /// This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const = 0;
};
/// '?' - Represents an uninitialized value
@@ -436,6 +467,7 @@ public:
static UnsetInit *get();
+ Init *getCastTo(RecTy *Ty) const override;
Init *convertInitializerTo(RecTy *Ty) const override;
Init *getBit(unsigned Bit) const override {
@@ -443,14 +475,15 @@ public:
}
bool isComplete() const override { return false; }
+ bool isConcrete() const override { return true; }
std::string getAsString() const override { return "?"; }
};
/// 'true'/'false' - Represent a concrete initializer for a bit.
-class BitInit : public Init {
+class BitInit final : public TypedInit {
bool Value;
- explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {}
+ explicit BitInit(bool V) : TypedInit(IK_BitInit, BitRecTy::get()), Value(V) {}
public:
BitInit(const BitInit &) = delete;
@@ -471,6 +504,7 @@ public:
return const_cast<BitInit*>(this);
}
+ bool isConcrete() const override { return true; }
std::string getAsString() const override { return Value ? "1" : "0"; }
};
@@ -515,17 +549,10 @@ public:
return true;
}
+ bool isConcrete() const override;
std::string getAsString() const override;
- /// This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override {
- llvm_unreachable("Illegal element reference off bits<n>");
- }
-
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override {
assert(Bit < NumBits && "Bit index out of range!");
@@ -555,16 +582,9 @@ public:
Init *convertInitializerTo(RecTy *Ty) const override;
Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const override;
+ bool isConcrete() const override { return true; }
std::string getAsString() const override;
- /// This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override {
- llvm_unreachable("Illegal element reference off int");
- }
-
Init *getBit(unsigned Bit) const override {
return BitInit::get((Value & (1ULL << Bit)) != 0);
}
@@ -591,18 +611,11 @@ public:
Init *convertInitializerTo(RecTy *Ty) const override;
+ bool isConcrete() const override { return true; }
std::string getAsString() const override { return "\"" + Value.str() + "\""; }
std::string getAsUnquotedString() const override { return Value; }
- /// resolveListElementReference - This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override {
- llvm_unreachable("Illegal element reference off string");
- }
-
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off string");
}
@@ -629,20 +642,13 @@ public:
Init *convertInitializerTo(RecTy *Ty) const override;
+ bool isConcrete() const override { return true; }
std::string getAsString() const override {
return "[{" + Value.str() + "}]";
}
std::string getAsUnquotedString() const override { return Value; }
- /// This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override {
- llvm_unreachable("Illegal element reference off string");
- }
-
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off string");
}
@@ -679,6 +685,9 @@ public:
assert(i < NumValues && "List element index out of range!");
return getTrailingObjects<Init *>()[i];
}
+ RecTy *getElementType() const {
+ return cast<ListRecTy>(getType())->getElementType();
+ }
Record *getElementAsRecord(unsigned i) const;
@@ -691,8 +700,9 @@ public:
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
///
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
+ bool isConcrete() const override;
std::string getAsString() const override;
ArrayRef<Init*> getValues() const {
@@ -705,12 +715,6 @@ public:
size_t size () const { return NumValues; }
bool empty() const { return NumValues == 0; }
- /// This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override;
-
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off list");
}
@@ -738,13 +742,6 @@ public:
virtual unsigned getNumOperands() const = 0;
virtual Init *getOperand(unsigned i) const = 0;
- // Fold - If possible, fold this to a simpler init. Return this if not
- // possible to fold.
- virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0;
-
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override;
-
Init *getBit(unsigned Bit) const override;
};
@@ -752,7 +749,7 @@ public:
///
class UnOpInit : public OpInit, public FoldingSetNode {
public:
- enum UnaryOp : uint8_t { CAST, HEAD, TAIL, EMPTY };
+ enum UnaryOp : uint8_t { CAST, HEAD, TAIL, SIZE, EMPTY };
private:
Init *LHS;
@@ -791,9 +788,9 @@ public:
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;
+ Init *Fold(Record *CurRec, bool IsFinal = false) const;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
};
@@ -802,7 +799,7 @@ public:
class BinOpInit : public OpInit, public FoldingSetNode {
public:
enum BinaryOp : uint8_t { ADD, AND, OR, SHL, SRA, SRL, LISTCONCAT,
- STRCONCAT, CONCAT, EQ };
+ STRCONCAT, CONCAT, EQ, NE, LE, LT, GE, GT };
private:
Init *LHS, *RHS;
@@ -820,6 +817,7 @@ public:
static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs,
RecTy *Type);
+ static Init *getStrConcat(Init *lhs, Init *rhs);
void Profile(FoldingSetNodeID &ID) const;
@@ -845,9 +843,9 @@ public:
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;
+ Init *Fold(Record *CurRec) const;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
};
@@ -855,7 +853,7 @@ public:
/// !op (X, Y, Z) - Combine two inits.
class TernOpInit : public OpInit, public FoldingSetNode {
public:
- enum TernaryOp : uint8_t { SUBST, FOREACH, IF };
+ enum TernaryOp : uint8_t { SUBST, FOREACH, IF, DAG };
private:
Init *LHS, *MHS, *RHS;
@@ -903,11 +901,83 @@ public:
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;
+ Init *Fold(Record *CurRec) const;
+
+ bool isComplete() const override {
+ return LHS->isComplete() && MHS->isComplete() && RHS->isComplete();
+ }
+
+ Init *resolveReferences(Resolver &R) const override;
+
+ std::string getAsString() const override;
+};
+
+/// !foldl (a, b, expr, start, lst) - Fold over a list.
+class FoldOpInit : public TypedInit, public FoldingSetNode {
+private:
+ Init *Start;
+ Init *List;
+ Init *A;
+ Init *B;
+ Init *Expr;
+
+ FoldOpInit(Init *Start, Init *List, Init *A, Init *B, Init *Expr, RecTy *Type)
+ : TypedInit(IK_FoldOpInit, Type), Start(Start), List(List), A(A), B(B),
+ Expr(Expr) {}
+
+public:
+ FoldOpInit(const FoldOpInit &) = delete;
+ FoldOpInit &operator=(const FoldOpInit &) = delete;
+
+ static bool classof(const Init *I) { return I->getKind() == IK_FoldOpInit; }
+
+ static FoldOpInit *get(Init *Start, Init *List, Init *A, Init *B, Init *Expr,
+ RecTy *Type);
+
+ void Profile(FoldingSetNodeID &ID) const;
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ Init *Fold(Record *CurRec) const;
+
+ bool isComplete() const override { return false; }
+
+ Init *resolveReferences(Resolver &R) const override;
+
+ Init *getBit(unsigned Bit) const override;
+
+ std::string getAsString() const override;
+};
+
+/// !isa<type>(expr) - Dynamically determine the type of an expression.
+class IsAOpInit : public TypedInit, public FoldingSetNode {
+private:
+ RecTy *CheckType;
+ Init *Expr;
+
+ IsAOpInit(RecTy *CheckType, Init *Expr)
+ : TypedInit(IK_IsAOpInit, IntRecTy::get()), CheckType(CheckType),
+ Expr(Expr) {}
+
+public:
+ IsAOpInit(const IsAOpInit &) = delete;
+ IsAOpInit &operator=(const IsAOpInit &) = delete;
+
+ static bool classof(const Init *I) { return I->getKind() == IK_IsAOpInit; }
+
+ static IsAOpInit *get(RecTy *CheckType, Init *Expr);
+
+ void Profile(FoldingSetNodeID &ID) const;
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ Init *Fold() const;
bool isComplete() const override { return false; }
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
+
+ Init *getBit(unsigned Bit) const override;
std::string getAsString() const override;
};
@@ -937,19 +1007,12 @@ public:
return getNameInit()->getAsUnquotedString();
}
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override;
-
- RecTy *getFieldType(StringInit *FieldName) const override;
- Init *getFieldInit(Record &R, const RecordVal *RV,
- StringInit *FieldName) const override;
-
/// This method is used by classes that refer to other
/// variables which may not be defined at the time they expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
///
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override;
@@ -957,11 +1020,12 @@ public:
};
/// Opcode{0} - Represent access to one bit of a variable or field.
-class VarBitInit : public Init {
+class VarBitInit final : public TypedInit {
TypedInit *TI;
unsigned Bit;
- VarBitInit(TypedInit *T, unsigned B) : Init(IK_VarBitInit), TI(T), Bit(B) {
+ VarBitInit(TypedInit *T, unsigned B)
+ : TypedInit(IK_VarBitInit, BitRecTy::get()), TI(T), Bit(B) {
assert(T->getType() &&
(isa<IntRecTy>(T->getType()) ||
(isa<BitsRecTy>(T->getType()) &&
@@ -979,13 +1043,11 @@ public:
static VarBitInit *get(TypedInit *T, unsigned B);
- Init *convertInitializerTo(RecTy *Ty) const override;
-
- Init *getBitVar() const override { return TI; }
- unsigned getBitNum() const override { return Bit; }
+ Init *getBitVar() const { return TI; }
+ unsigned getBitNum() const { return Bit; }
std::string getAsString() const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned B) const override {
assert(B < 1 && "Bit index out of range!");
@@ -1020,14 +1082,8 @@ public:
TypedInit *getVariable() const { return TI; }
unsigned getElementNum() const { return Element; }
- /// This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override;
-
std::string getAsString() const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override;
};
@@ -1038,7 +1094,7 @@ class DefInit : public TypedInit {
Record *Def;
- DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {}
+ explicit DefInit(Record *D);
public:
DefInit(const DefInit &) = delete;
@@ -1057,21 +1113,64 @@ public:
//virtual Init *convertInitializerBitRange(ArrayRef<unsigned> Bits);
RecTy *getFieldType(StringInit *FieldName) const override;
- Init *getFieldInit(Record &R, const RecordVal *RV,
- StringInit *FieldName) const override;
+ bool isConcrete() const override { return true; }
std::string getAsString() const override;
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off def");
}
+};
- /// This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override {
- llvm_unreachable("Illegal element reference off def");
+/// classname<targs...> - Represent an uninstantiated anonymous class
+/// instantiation.
+class VarDefInit final : public TypedInit, public FoldingSetNode,
+ public TrailingObjects<VarDefInit, Init *> {
+ Record *Class;
+ DefInit *Def = nullptr; // after instantiation
+ unsigned NumArgs;
+
+ explicit VarDefInit(Record *Class, unsigned N)
+ : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Class(Class), NumArgs(N) {}
+
+ DefInit *instantiate();
+
+public:
+ VarDefInit(const VarDefInit &) = delete;
+ VarDefInit &operator=(const VarDefInit &) = delete;
+
+ // Do not use sized deallocation due to trailing objects.
+ void operator delete(void *p) { ::operator delete(p); }
+
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_VarDefInit;
+ }
+ static VarDefInit *get(Record *Class, ArrayRef<Init *> Args);
+
+ void Profile(FoldingSetNodeID &ID) const;
+
+ Init *resolveReferences(Resolver &R) const override;
+ Init *Fold() const;
+
+ std::string getAsString() const override;
+
+ Init *getArg(unsigned i) const {
+ assert(i < NumArgs && "Argument index out of range!");
+ return getTrailingObjects<Init *>()[i];
+ }
+
+ using const_iterator = Init *const *;
+
+ const_iterator args_begin() const { return getTrailingObjects<Init *>(); }
+ const_iterator args_end () const { return args_begin() + NumArgs; }
+
+ size_t args_size () const { return NumArgs; }
+ bool args_empty() const { return NumArgs == 0; }
+
+ ArrayRef<Init *> args() const { return makeArrayRef(args_begin(), NumArgs); }
+
+ Init *getBit(unsigned Bit) const override {
+ llvm_unreachable("Illegal bit reference off anonymous def");
}
};
@@ -1095,12 +1194,13 @@ public:
static FieldInit *get(Init *R, StringInit *FN);
- Init *getBit(unsigned Bit) const override;
+ Init *getRecord() const { return Rec; }
+ StringInit *getFieldName() const { return FieldName; }
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override;
+ Init *getBit(unsigned Bit) const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
+ Init *Fold(Record *CurRec) const;
std::string getAsString() const override {
return Rec->getAsString() + "." + FieldName->getValue().str();
@@ -1140,8 +1240,6 @@ public:
void Profile(FoldingSetNodeID &ID) const;
- Init *convertInitializerTo(RecTy *Ty) const override;
-
Init *getOperator() const { return Val; }
StringInit *getName() const { return ValName; }
@@ -1175,8 +1273,9 @@ public:
return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames);
}
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
+ bool isConcrete() const override;
std::string getAsString() const override;
using const_arg_iterator = SmallVectorImpl<Init*>::const_iterator;
@@ -1197,11 +1296,6 @@ public:
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off dag");
}
-
- Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) const override {
- llvm_unreachable("Illegal element reference off dag");
- }
};
//===----------------------------------------------------------------------===//
@@ -1229,14 +1323,7 @@ public:
RecTy *getType() const { return TyAndPrefix.getPointer(); }
Init *getValue() const { return Value; }
- bool setValue(Init *V) {
- if (V) {
- Value = V->convertInitializerTo(getType());
- return Value == nullptr;
- }
- Value = nullptr;
- return false;
- }
+ bool setValue(Init *V);
void dump() const;
void print(raw_ostream &OS, bool PrintSem = true) const;
@@ -1256,6 +1343,9 @@ class Record {
SmallVector<SMLoc, 4> Locs;
SmallVector<Init *, 0> TemplateArgs;
SmallVector<RecordVal, 0> Values;
+
+ // All superclasses in the inheritance forest in reverse preorder (yes, it
+ // must be a forest; diamond-shaped inheritance is not allowed).
SmallVector<std::pair<Record *, SMRange>, 0> SuperClasses;
// Tracks Record instances. Not owned by Record.
@@ -1267,49 +1357,37 @@ class Record {
unsigned ID;
bool IsAnonymous;
+ bool IsClass;
- // Class-instance values can be used by other defs. For example, Struct<i>
- // is used here as a template argument to another class:
- //
- // multiclass MultiClass<int i> {
- // def Def : Class<Struct<i>>;
- //
- // These need to get fully resolved before instantiating any other
- // definitions that use them (e.g. Def). However, inside a multiclass they
- // can't be immediately resolved so we mark them ResolveFirst to fully
- // resolve them later as soon as the multiclass is instantiated.
- bool ResolveFirst = false;
-
- void init();
void checkName();
public:
// Constructs a record.
explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
- bool Anonymous = false) :
- Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records),
- ID(LastID++), IsAnonymous(Anonymous) {
- init();
+ bool Anonymous = false, bool Class = false)
+ : Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records),
+ ID(LastID++), IsAnonymous(Anonymous), IsClass(Class) {
+ checkName();
}
explicit Record(StringRef N, ArrayRef<SMLoc> locs, RecordKeeper &records,
- bool Anonymous = false)
- : Record(StringInit::get(N), locs, records, Anonymous) {}
+ bool Class = false)
+ : Record(StringInit::get(N), locs, records, false, Class) {}
// When copy-constructing a Record, we must still guarantee a globally unique
// ID number. Don't copy TheInit either since it's owned by the original
// record. All other fields can be copied normally.
- Record(const Record &O) :
- Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
- Values(O.Values), SuperClasses(O.SuperClasses),
- TrackedRecords(O.TrackedRecords), ID(LastID++),
- IsAnonymous(O.IsAnonymous), ResolveFirst(O.ResolveFirst) { }
+ Record(const Record &O)
+ : Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
+ Values(O.Values), SuperClasses(O.SuperClasses),
+ TrackedRecords(O.TrackedRecords), ID(LastID++),
+ IsAnonymous(O.IsAnonymous), IsClass(O.IsClass) { }
static unsigned getNewUID() { return LastID++; }
unsigned getID() const { return ID; }
- StringRef getName() const;
+ StringRef getName() const { return cast<StringInit>(Name)->getValue(); }
Init *getNameInit() const {
return Name;
@@ -1322,10 +1400,16 @@ public:
void setName(Init *Name); // Also updates RecordKeeper.
ArrayRef<SMLoc> getLoc() const { return Locs; }
+ void appendLoc(SMLoc Loc) { Locs.push_back(Loc); }
+
+ // Make the type that this record should have based on its superclasses.
+ RecordRecTy *getType();
/// get the corresponding DefInit.
DefInit *getDefInit();
+ bool isClass() const { return IsClass; }
+
ArrayRef<Init *> getTemplateArgs() const {
return TemplateArgs;
}
@@ -1336,6 +1420,9 @@ public:
return SuperClasses;
}
+ /// Append the direct super classes of this record to Classes.
+ void getDirectSuperClasses(SmallVectorImpl<Record *> &Classes) const;
+
bool isTemplateArg(Init *Name) const {
for (Init *TA : TemplateArgs)
if (TA == Name) return true;
@@ -1368,13 +1455,6 @@ public:
void addValue(const RecordVal &RV) {
assert(getValue(RV.getNameInit()) == nullptr && "Value already added!");
Values.push_back(RV);
- if (Values.size() > 1)
- // Keep NAME at the end of the list. It makes record dumps a
- // bit prettier and allows TableGen tests to be written more
- // naturally. Tests can use CHECK-NEXT to look for Record
- // fields they expect to see after a def. They can't do that if
- // NAME is the first Record field.
- std::swap(Values[Values.size() - 2], Values[Values.size() - 1]);
}
void removeValue(Init *Name) {
@@ -1410,13 +1490,24 @@ public:
}
void addSuperClass(Record *R, SMRange Range) {
+ assert(!TheInit && "changing type of record after it has been referenced");
assert(!isSubClassOf(R) && "Already subclassing record!");
SuperClasses.push_back(std::make_pair(R, Range));
}
/// If there are any field references that refer to fields
/// that have been filled in, we can propagate the values now.
- void resolveReferences() { resolveReferencesTo(nullptr); }
+ ///
+ /// This is a final resolve: any error messages, e.g. due to undefined
+ /// !cast references, are generated now.
+ void resolveReferences();
+
+ /// Apply the resolver to the name of the record as well as to the
+ /// initializers of all fields of the record except SkipVal.
+ ///
+ /// The resolver should not resolve any of the fields itself, to avoid
+ /// recursion / infinite loops.
+ void resolveReferences(Resolver &R, const RecordVal *SkipVal = nullptr);
/// If anything in this record refers to RV, replace the
/// reference to RV with the RHS of RV. If RV is null, we resolve all
@@ -1431,14 +1522,6 @@ public:
return IsAnonymous;
}
- bool isResolveFirst() const {
- return ResolveFirst;
- }
-
- void setResolveFirst(bool b) {
- ResolveFirst = b;
- }
-
void print(raw_ostream &OS) const;
void dump() const;
@@ -1513,20 +1596,13 @@ public:
raw_ostream &operator<<(raw_ostream &OS, const Record &R);
-struct MultiClass {
- Record Rec; // Placeholder for template args and Name.
- using RecordVector = std::vector<std::unique_ptr<Record>>;
- RecordVector DefPrototypes;
-
- void dump() const;
-
- MultiClass(StringRef Name, SMLoc Loc, RecordKeeper &Records) :
- Rec(Name, Loc, Records) {}
-};
-
class RecordKeeper {
+ friend class RecordRecTy;
using RecordMap = std::map<std::string, std::unique_ptr<Record>>;
RecordMap Classes, Defs;
+ FoldingSet<RecordRecTy> RecordTypePool;
+ std::map<std::string, Init *> ExtraGlobals;
+ unsigned AnonCounter = 0;
public:
const RecordMap &getClasses() const { return Classes; }
@@ -1542,6 +1618,13 @@ public:
return I == Defs.end() ? nullptr : I->second.get();
}
+ Init *getGlobal(StringRef Name) const {
+ if (Record *R = getDef(Name))
+ return R->getDefInit();
+ auto It = ExtraGlobals.find(Name);
+ return It == ExtraGlobals.end() ? nullptr : It->second;
+ }
+
void addClass(std::unique_ptr<Record> R) {
bool Ins = Classes.insert(std::make_pair(R->getName(),
std::move(R))).second;
@@ -1556,6 +1639,15 @@ public:
assert(Ins && "Record already exists");
}
+ void addExtraGlobal(StringRef Name, Init *I) {
+ bool Ins = ExtraGlobals.insert(std::make_pair(Name, I)).second;
+ (void)Ins;
+ assert(!getDef(Name));
+ assert(Ins && "Global already exists");
+ }
+
+ Init *getNewAnonymousName();
+
//===--------------------------------------------------------------------===//
// High-level helper methods, useful for tablegen backends...
@@ -1673,10 +1765,142 @@ struct LessRecordRegister {
raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
-/// Return an Init with a qualifier prefix referring
-/// to CurRec's name.
-Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
- Init *Name, StringRef Scoper);
+//===----------------------------------------------------------------------===//
+// Resolvers
+//===----------------------------------------------------------------------===//
+
+/// Interface for looking up the initializer for a variable name, used by
+/// Init::resolveReferences.
+class Resolver {
+ Record *CurRec;
+ bool IsFinal = false;
+
+public:
+ explicit Resolver(Record *CurRec) : CurRec(CurRec) {}
+ virtual ~Resolver() {}
+
+ Record *getCurrentRecord() const { return CurRec; }
+
+ /// Return the initializer for the given variable name (should normally be a
+ /// StringInit), or nullptr if the name could not be resolved.
+ virtual Init *resolve(Init *VarName) = 0;
+
+ // Whether bits in a BitsInit should stay unresolved if resolving them would
+ // result in a ? (UnsetInit). This behavior is used to represent instruction
+ // encodings by keeping references to unset variables within a record.
+ virtual bool keepUnsetBits() const { return false; }
+
+ // Whether this is the final resolve step before adding a record to the
+ // RecordKeeper. Error reporting during resolve and related constant folding
+ // should only happen when this is true.
+ bool isFinal() const { return IsFinal; }
+
+ void setFinal(bool Final) { IsFinal = Final; }
+};
+
+/// Resolve arbitrary mappings.
+class MapResolver final : public Resolver {
+ struct MappedValue {
+ Init *V;
+ bool Resolved;
+
+ MappedValue() : V(nullptr), Resolved(false) {}
+ MappedValue(Init *V, bool Resolved) : V(V), Resolved(Resolved) {}
+ };
+
+ DenseMap<Init *, MappedValue> Map;
+
+public:
+ explicit MapResolver(Record *CurRec = nullptr) : Resolver(CurRec) {}
+
+ void set(Init *Key, Init *Value) { Map[Key] = {Value, false}; }
+
+ Init *resolve(Init *VarName) override;
+};
+
+/// Resolve all variables from a record except for unset variables.
+class RecordResolver final : public Resolver {
+ DenseMap<Init *, Init *> Cache;
+ SmallVector<Init *, 4> Stack;
+
+public:
+ explicit RecordResolver(Record &R) : Resolver(&R) {}
+
+ Init *resolve(Init *VarName) override;
+
+ bool keepUnsetBits() const override { return true; }
+};
+
+/// Resolve all references to a specific RecordVal.
+//
+// TODO: This is used for resolving references to template arguments, in a
+// rather inefficient way. Change those uses to resolve all template
+// arguments simultaneously and get rid of this class.
+class RecordValResolver final : public Resolver {
+ const RecordVal *RV;
+
+public:
+ explicit RecordValResolver(Record &R, const RecordVal *RV)
+ : Resolver(&R), RV(RV) {}
+
+ Init *resolve(Init *VarName) override {
+ if (VarName == RV->getNameInit())
+ return RV->getValue();
+ return nullptr;
+ }
+};
+
+/// Delegate resolving to a sub-resolver, but shadow some variable names.
+class ShadowResolver final : public Resolver {
+ Resolver &R;
+ DenseSet<Init *> Shadowed;
+
+public:
+ explicit ShadowResolver(Resolver &R)
+ : Resolver(R.getCurrentRecord()), R(R) {
+ setFinal(R.isFinal());
+ }
+
+ void addShadow(Init *Key) { Shadowed.insert(Key); }
+
+ Init *resolve(Init *VarName) override {
+ if (Shadowed.count(VarName))
+ return nullptr;
+ return R.resolve(VarName);
+ }
+};
+
+/// (Optionally) delegate resolving to a sub-resolver, and keep track whether
+/// there were unresolved references.
+class TrackUnresolvedResolver final : public Resolver {
+ Resolver *R;
+ bool FoundUnresolved = false;
+
+public:
+ explicit TrackUnresolvedResolver(Resolver *R = nullptr)
+ : Resolver(R ? R->getCurrentRecord() : nullptr), R(R) {}
+
+ bool foundUnresolved() const { return FoundUnresolved; }
+
+ Init *resolve(Init *VarName) override;
+};
+
+/// Do not resolve anything, but keep track of whether a given variable was
+/// referenced.
+class HasReferenceResolver final : public Resolver {
+ Init *VarNameToTrack;
+ bool Found = false;
+
+public:
+ explicit HasReferenceResolver(Init *VarNameToTrack)
+ : Resolver(nullptr), VarNameToTrack(VarNameToTrack) {}
+
+ bool found() const { return Found; }
+
+ Init *resolve(Init *VarName) override;
+};
+
+void EmitJSON(RecordKeeper &RK, raw_ostream &OS);
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/TableGen/SearchableTable.td b/contrib/llvm/include/llvm/TableGen/SearchableTable.td
index 12aaf6000c31..1089d363eb6f 100644
--- a/contrib/llvm/include/llvm/TableGen/SearchableTable.td
+++ b/contrib/llvm/include/llvm/TableGen/SearchableTable.td
@@ -8,32 +8,127 @@
//===----------------------------------------------------------------------===//
//
// This file defines the key top-level classes needed to produce a reasonably
-// generic table that can be binary-searched via int and string entries.
+// generic table that can be binary-searched. Three types of objects can be
+// defined using the classes in this file:
//
-// Each table must instantiate "Mappingkind", listing the fields that should be
-// included and fields that shoould be searchable. Only two kinds of fields are
-// searchable at the moment: "strings" (which are compared case-insensitively),
-// and "bits".
+// 1. (Generic) Enums. By instantiating the GenericEnum class once, an enum with
+// the name of the def is generated. It is guarded by the preprocessor define
+// GET_name_DECL, where name is the name of the def.
//
-// For each "MappingKind" the generated header will create GET_MAPPINGKIND_DECL
-// and GET_MAPPINGKIND_IMPL guards.
+// 2. (Generic) Tables and search indices. By instantiating the GenericTable
+// class once, a table with the name of the instantiating def is generated and
+// guarded by the GET_name_IMPL preprocessor guard.
//
-// Inside the DECL guard will be a set of function declarations:
-// "lookup{InstanceClass}By{SearchableField}", returning "const {InstanceClass}
-// *" and accepting either a StringRef or a uintN_t. Additionally, if
-// EnumNameField is still defined, there will be an "enum {InstanceClass}Values"
-// allowing C++ code to reference either the primary data table's entries (if
-// EnumValueField is not defined) or some other field (e.g. encoding) if it is.
-//
-// Inside the IMPL guard will be a primary data table "{InstanceClass}sList" and
-// as many searchable indexes as requested
-// ("{InstanceClass}sBy{SearchableField}"). Additionally implementations of the
-// lookup function will be provided.
+// Both a primary key and additional secondary keys / search indices can also
+// be defined, which result in the generation of lookup functions. Their
+// declarations and definitions are all guarded by GET_name_DECL and
+// GET_name_IMPL, respectively, where name is the name of the underlying table.
//
// See AArch64SystemOperands.td and its generated header for example uses.
//
//===----------------------------------------------------------------------===//
+// Define a record derived from this class to generate a generic enum.
+//
+// The name of the record is used as the type name of the C++ enum.
+class GenericEnum {
+ // Name of a TableGen class. The enum will have one entry for each record
+ // that derives from that class.
+ string FilterClass;
+
+ // (Optional) Name of a field that is present in all collected records and
+ // contains the name of enum entries.
+ //
+ // If NameField is not set, the record names will be used instead.
+ string NameField;
+
+ // (Optional) Name of a field that is present in all collected records and
+ // contains the numerical value of enum entries.
+ //
+ // If ValueField is not set, enum values will be assigned automatically,
+ // starting at 0, according to a lexicographical sort of the entry names.
+ string ValueField;
+}
+
+// Define a record derived from this class to generate a generic table. This
+// table can have a searchable primary key, and it can also be referenced by
+// external search indices.
+//
+// The name of the record is used as the name of the global primary array of
+// entries of the table in C++.
+class GenericTable {
+ // Name of a class. The table will have one entry for each record that
+ // derives from that class.
+ string FilterClass;
+
+ // Name of the C++ struct/class type that holds table entries. The
+ // declaration of this type is not generated automatically.
+ string CppTypeName = FilterClass;
+
+ // List of the names of fields of collected records that contain the data for
+ // table entries, in the order that is used for initialization in C++.
+ //
+ // For each field of the table named XXX, TableGen will look for a value
+ // called TypeOf_XXX and use that as a more detailed description of the
+ // type of the field if present. This is required for fields whose type
+ // cannot be deduced automatically, such as enum fields. For example:
+ //
+ // def MyEnum : GenericEnum {
+ // let FilterClass = "MyEnum";
+ // ...
+ // }
+ //
+ // class MyTableEntry {
+ // MyEnum V;
+ // ...
+ // }
+ //
+ // def MyTable : GenericTable {
+ // let FilterClass = "MyTableEntry";
+ // let Fields = ["V", ...];
+ // GenericEnum TypeOf_V = MyEnum;
+ // }
+ //
+ // Fields of type bit, bits<N>, string, Intrinsic, and Instruction (or
+ // derived classes of those) are supported natively.
+ //
+ // Additionally, fields of type `code` can appear, where the value is used
+ // verbatim as an initializer. However, these fields cannot be used as
+ // search keys.
+ list<string> Fields;
+
+ // (Optional) List of fields that make up the primary key.
+ list<string> PrimaryKey;
+
+ // (Optional) Name of the primary key search function.
+ string PrimaryKeyName;
+
+ // See SearchIndex.EarlyOut
+ bit PrimaryKeyEarlyOut = 0;
+}
+
+// Define a record derived from this class to generate an additional search
+// index for a generic table that has been defined earlier.
+//
+// The name of the record will be used as the name of the C++ lookup function.
+class SearchIndex {
+ // Table that this search index refers to.
+ GenericTable Table;
+
+ // List of fields that make up the key.
+ list<string> Key;
+
+ // If true, the lookup function will check the first field of the key against
+ // the minimum and maximum values in the index before entering the binary
+ // search. This is convenient for tables that add extended data for a subset
+ // of a larger enum-based space, e.g. extended data about a subset of
+ // instructions.
+ //
+ // Can only be used when the first field is an integral (non-string) type.
+ bit EarlyOut = 0;
+}
+
+// Legacy table type with integrated enum.
class SearchableTable {
list<string> SearchableFields;
string EnumNameField = "Name";
diff --git a/contrib/llvm/include/llvm/Support/CodeGenCWrappers.h b/contrib/llvm/include/llvm/Target/CodeGenCWrappers.h
index 47971e80cefb..e9a990569d36 100644
--- a/contrib/llvm/include/llvm/Support/CodeGenCWrappers.h
+++ b/contrib/llvm/include/llvm/Target/CodeGenCWrappers.h
@@ -1,4 +1,4 @@
-//===- llvm/Support/CodeGenCWrappers.h - CodeGen C Wrappers -----*- C++ -*-===//
+//===- llvm/Target/CodeGenCWrappers.h - CodeGen C Wrappers ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_CODEGENCWRAPPERS_H
-#define LLVM_SUPPORT_CODEGENCWRAPPERS_H
+#ifndef LLVM_TARGET_CODEGENCWRAPPERS_H
+#define LLVM_TARGET_CODEGENCWRAPPERS_H
#include "llvm-c/TargetMachine.h"
#include "llvm/ADT/Optional.h"
@@ -56,7 +56,6 @@ inline LLVMCodeModel wrap(CodeModel::Model Model) {
}
llvm_unreachable("Bad CodeModel!");
}
-
-} // end llvm namespace
+} // namespace llvm
#endif
diff --git a/contrib/llvm/include/llvm/Target/GenericOpcodes.td b/contrib/llvm/include/llvm/Target/GenericOpcodes.td
index 28c90bf22767..d72746a0838a 100644
--- a/contrib/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/contrib/llvm/include/llvm/Target/GenericOpcodes.td
@@ -126,6 +126,11 @@ def G_BSWAP : GenericInstruction {
let hasSideEffects = 0;
}
+def G_ADDRSPACE_CAST : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type1:$src);
+ let hasSideEffects = 0;
+}
//------------------------------------------------------------------------------
// Binary ops.
//------------------------------------------------------------------------------
@@ -378,6 +383,12 @@ def G_UITOFP : GenericInstruction {
let hasSideEffects = 0;
}
+def G_FABS : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type0:$src);
+ let hasSideEffects = 0;
+}
+
//------------------------------------------------------------------------------
// Floating Point Binary ops.
//------------------------------------------------------------------------------
@@ -476,6 +487,22 @@ def G_LOAD : GenericInstruction {
let mayLoad = 1;
}
+// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
+def G_SEXTLOAD : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins ptype1:$addr);
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+}
+
+// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
+def G_ZEXTLOAD : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins ptype1:$addr);
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+}
+
// Generic store. Expects a MachineMemOperand in addition to explicit operands.
def G_STORE : GenericInstruction {
let OutOperandList = (outs);
diff --git a/contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index 575f228cd773..d487759a4852 100644
--- a/contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -28,6 +28,13 @@ class GINodeEquiv<Instruction i, SDNode node> {
// (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel
// stores this information in the MachineMemoryOperand.
bit CheckMMOIsNonAtomic = 0;
+
+ // SelectionDAG has one node for all loads and uses predicates to
+ // differentiate them. GlobalISel on the other hand uses separate opcodes.
+ // When this is true, the resulting opcode is G_LOAD/G_SEXTLOAD/G_ZEXTLOAD
+ // depending on the predicates on the node.
+ Instruction IfSignExtend = ?;
+ Instruction IfZeroExtend = ?;
}
// These are defined in the same order as the G_* instructions.
@@ -80,11 +87,15 @@ def : GINodeEquiv<G_BSWAP, bswap>;
// Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some
// complications that tablegen must take care of. For example, Predicates such
// as isSignExtLoad require that this is not a perfect 1:1 mapping since a
-// sign-extending load is (G_SEXT (G_LOAD x)) in GlobalISel. Additionally,
+// sign-extending load is (G_SEXTLOAD x) in GlobalISel. Additionally,
// G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had
// separate nodes for them. This GINodeEquiv maps the non-atomic loads to
// G_LOAD with a non-atomic MachineMemOperand.
-def : GINodeEquiv<G_LOAD, ld> { let CheckMMOIsNonAtomic = 1; }
+def : GINodeEquiv<G_LOAD, ld> {
+ let CheckMMOIsNonAtomic = 1;
+ let IfSignExtend = G_SEXTLOAD;
+ let IfZeroExtend = G_ZEXTLOAD;
+}
// Broadly speaking G_STORE is equivalent to ISD::STORE but there are some
// complications that tablegen must take care of. For example, predicates such
// as isTruncStore require that this is not a perfect 1:1 mapping since a
@@ -112,3 +123,9 @@ def : GINodeEquiv<G_ATOMICRMW_UMAX, atomic_load_umax>;
class GIComplexPatternEquiv<ComplexPattern seldag> {
ComplexPattern SelDAGEquivalent = seldag;
}
+
+// Specifies the GlobalISel equivalents for SelectionDAG's SDNodeXForm.
+// Should be used on defs that subclass GICustomOperandRenderer<>.
+class GISDNodeXFormEquiv<SDNodeXForm seldag> {
+ SDNodeXForm SelDAGEquivalent = seldag;
+}
diff --git a/contrib/llvm/include/llvm/Target/GlobalISel/Target.td b/contrib/llvm/include/llvm/Target/GlobalISel/Target.td
index fd2ebca86d60..6740f404a9d3 100644
--- a/contrib/llvm/include/llvm/Target/GlobalISel/Target.td
+++ b/contrib/llvm/include/llvm/Target/GlobalISel/Target.td
@@ -46,3 +46,16 @@ class GIComplexOperandMatcher<LLT type, string matcherfn> {
// overwritten.
string MatcherFn = matcherfn;
}
+
+// Defines a custom renderer. This is analogous to SDNodeXForm from
+// SelectionDAG. Unlike SDNodeXForm, this matches a MachineInstr and
+// renders directly to the result instruction without an intermediate node.
+//
+// Definitions that inherit from this may also inherit from GISDNodeXFormEquiv
+// to enable the import of SelectionDAG patterns involving those SDNodeXForms.
+class GICustomOperandRenderer<string rendererfn> {
+ // The function renders the operand(s) of the matched instruction to
+ // the specified instruction. It should be of the form:
+ // void render(MachineInstrBuilder &MIB, const MachineInstr &MI)
+ string RendererFn = rendererfn;
+}
diff --git a/contrib/llvm/include/llvm/Target/Target.td b/contrib/llvm/include/llvm/Target/Target.td
index 82a3be5e63d4..b746505d2a45 100644
--- a/contrib/llvm/include/llvm/Target/Target.td
+++ b/contrib/llvm/include/llvm/Target/Target.td
@@ -175,6 +175,8 @@ class Register<string n, list<string> altNames = []> {
// HWEncoding - The target specific hardware encoding for this register.
bits<16> HWEncoding = 0;
+
+ bit isArtificial = 0;
}
// RegisterWithSubRegs - This can be used to define instances of Register which
@@ -382,6 +384,11 @@ class DwarfRegAlias<Register reg> {
}
//===----------------------------------------------------------------------===//
+// Pull in the common support for MCPredicate (portable scheduling predicates).
+//
+include "llvm/Target/TargetInstrPredicate.td"
+
+//===----------------------------------------------------------------------===//
// Pull in the common support for scheduling
//
include "llvm/Target/TargetSchedule.td"
@@ -435,11 +442,13 @@ class Instruction {
bit isIndirectBranch = 0; // Is this instruction an indirect branch?
bit isCompare = 0; // Is this instruction a comparison instruction?
bit isMoveImm = 0; // Is this instruction a move immediate instruction?
+ bit isMoveReg = 0; // Is this instruction a move register instruction?
bit isBitcast = 0; // Is this instruction a bitcast instruction?
bit isSelect = 0; // Is this instruction a select instruction?
bit isBarrier = 0; // Can control flow fall through this instruction?
bit isCall = 0; // Is this instruction a call instruction?
bit isAdd = 0; // Is this instruction an add instruction?
+ bit isTrap = 0; // Is this instruction a trap instruction?
bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand?
bit mayLoad = ?; // Is it possible for this inst to read memory?
bit mayStore = ?; // Is it possible for this inst to write memory?
@@ -566,6 +575,12 @@ class Instruction {
/// can be queried via the getNamedOperandIdx() function which is generated
/// by TableGen.
bit UseNamedOperandTable = 0;
+
+ /// Should FastISel ignore this instruction. For certain ISAs, they have
+ /// instructions which map to the same ISD Opcode, value type operands and
+ /// instruction selection predicates. FastISel cannot handle such cases, but
+ /// SelectionDAG can.
+ bit FastISelShouldIgnore = 0;
}
/// PseudoInstExpansion - Expansion information for a pseudo-instruction.
@@ -995,6 +1010,12 @@ def DBG_VALUE : StandardPseudoInstruction {
let AsmString = "DBG_VALUE";
let hasSideEffects = 0;
}
+def DBG_LABEL : StandardPseudoInstruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins unknown:$label);
+ let AsmString = "DBG_LABEL";
+ let hasSideEffects = 0;
+}
def REG_SEQUENCE : StandardPseudoInstruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$supersrc, variable_ops);
@@ -1097,7 +1118,7 @@ def PATCHABLE_FUNCTION_ENTER : StandardPseudoInstruction {
let hasSideEffects = 0;
}
def PATCHABLE_RET : StandardPseudoInstruction {
- let OutOperandList = (outs unknown:$dst);
+ let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "# XRay Function Patchable RET.";
let usesCustomInserter = 1;
@@ -1114,7 +1135,7 @@ def PATCHABLE_FUNCTION_EXIT : StandardPseudoInstruction {
let isReturn = 0; // Original return instruction will follow
}
def PATCHABLE_TAIL_CALL : StandardPseudoInstruction {
- let OutOperandList = (outs unknown:$dst);
+ let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "# XRay Tail Call Exit.";
let usesCustomInserter = 1;
@@ -1131,6 +1152,16 @@ def PATCHABLE_EVENT_CALL : StandardPseudoInstruction {
let mayStore = 1;
let hasSideEffects = 1;
}
+def PATCHABLE_TYPED_EVENT_CALL : StandardPseudoInstruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins i16imm:$type, ptr_rc:$event, i32imm:$size);
+ let AsmString = "# XRay Typed Event Log.";
+ let usesCustomInserter = 1;
+ let isCall = 1;
+ let mayLoad = 1;
+ let mayStore = 1;
+ let hasSideEffects = 1;
+}
def FENTRY_CALL : StandardPseudoInstruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins variable_ops);
@@ -1140,6 +1171,12 @@ def FENTRY_CALL : StandardPseudoInstruction {
let mayStore = 1;
let hasSideEffects = 1;
}
+def ICALL_BRANCH_FUNNEL : StandardPseudoInstruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins variable_ops);
+ let AsmString = "";
+ let hasSideEffects = 1;
+}
// Generic opcodes used in GlobalISel.
include "llvm/Target/GenericOpcodes.td"
@@ -1290,7 +1327,7 @@ class MnemonicAlias<string From, string To, string VariantName = ""> {
/// InstAlias - This defines an alternate assembly syntax that is allowed to
/// match an instruction that has a different (more canonical) assembly
/// representation.
-class InstAlias<string Asm, dag Result, int Emit = 1> {
+class InstAlias<string Asm, dag Result, int Emit = 1, string VariantName = ""> {
string AsmString = Asm; // The .s format to match the instruction with.
dag ResultInst = Result; // The MCInst to generate.
@@ -1314,7 +1351,7 @@ class InstAlias<string Asm, dag Result, int Emit = 1> {
// Assembler variant name to use for this alias. If not specified then
// assembler variants will be determined based on AsmString
- string AsmVariantName = "";
+ string AsmVariantName = VariantName;
}
//===----------------------------------------------------------------------===//
@@ -1362,6 +1399,12 @@ class Target {
// AssemblyWriters - The AsmWriter instances available for this target.
list<AsmWriter> AssemblyWriters = [DefaultAsmWriter];
+
+ // AllowRegisterRenaming - Controls whether this target allows
+ // post-register-allocation renaming of registers. This is done by
+ // setting hasExtraDefRegAllocReq and hasExtraSrcRegAllocReq to 1
+ // for all opcodes if this flag is set to 0.
+ int AllowRegisterRenaming = 0;
}
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/include/llvm/Target/TargetInstrPredicate.td b/contrib/llvm/include/llvm/Target/TargetInstrPredicate.td
new file mode 100644
index 000000000000..d38279b0d65e
--- /dev/null
+++ b/contrib/llvm/include/llvm/Target/TargetInstrPredicate.td
@@ -0,0 +1,197 @@
+//===- TargetInstrPredicate.td - ---------------------------*- 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 MCInstPredicate classes and its subclasses.
+//
+// MCInstPredicate is used to describe constraints on the opcode/operand(s) of
+// an instruction. Each MCInstPredicate class has a well-known semantic, and it
+// is used by a PredicateExpander to generate code for MachineInstr and/or
+// MCInst.
+//
+// MCInstPredicate definitions can be used to construct MCSchedPredicate
+// definitions. An MCSchedPredicate can be used in place of a SchedPredicate
+// when defining SchedReadVariant and SchedWriteVariant used by a processor
+// scheduling model.
+//
+// Here is an example of MCInstPredicate definition:
+//
+// def MCInstPredicateExample : CheckAll<[
+// CheckOpcode<[BLR]>,
+// CheckIsRegOperand<0>,
+// CheckNot<CheckRegOperand<0, LR>>]>;
+//
+// Predicate `MCInstPredicateExample` checks that the machine instruction in
+// input is a BLR, and that operand at index 0 is register `LR`.
+//
+// That predicate could be used to rewrite the following definition (from
+// AArch64SchedExynosM3.td):
+//
+// def M3BranchLinkFastPred : SchedPredicate<[{
+// MI->getOpcode() == AArch64::BLR &&
+// MI->getOperand(0).isReg() &&
+// MI->getOperand(0).getReg() != AArch64::LR}]>;
+//
+// MCInstPredicate definitions are used to construct MCSchedPredicate (see the
+// definition of class MCSchedPredicate in llvm/Target/TargetSchedule.td). An
+// MCSchedPredicate can be used by a `SchedVar` to associate a predicate with a
+// list of SchedReadWrites. Note that `SchedVar` are used to create SchedVariant
+// definitions.
+//
+// Each MCInstPredicate class has a well known semantic. For example,
+// `CheckOpcode` is only used to check the instruction opcode value.
+//
+// MCInstPredicate classes allow the definition of predicates in a declarative
+// way. These predicates don't require a custom block of C++, and can be used
+// to define conditions on instructions without being bound to a particular
+// representation (i.e. MachineInstr vs MCInst).
+//
+// It also means that tablegen backends must know how to parse and expand them
+// into code that works on MCInst (or MachineInst).
+//
+// Instances of class PredicateExpander (see utils/Tablegen/PredicateExpander.h)
+// know how to expand a predicate. For each MCInstPredicate class, there must be
+// an "expand" method available in the PredicateExpander interface.
+//
+// For example, a `CheckOpcode` predicate is expanded using method
+// `PredicateExpander::expandCheckOpcode()`.
+//
+// New MCInstPredicate classes must be added to this file. For each new class
+// XYZ, an "expandXYZ" method must be added to the PredicateExpander.
+//
+//===----------------------------------------------------------------------===//
+
+// Forward declarations.
+class Instruction;
+
+// A generic machine instruction predicate.
+class MCInstPredicate;
+
+class MCTrue : MCInstPredicate; // A predicate that always evaluates to True.
+class MCFalse : MCInstPredicate; // A predicate that always evaluates to False.
+def TruePred : MCTrue;
+def FalsePred : MCFalse;
+
+// A predicate used to negate the outcome of another predicate.
+// It allows to easily express "set difference" operations. For example, it
+// makes it easy to describe a check that tests if an opcode is not part of a
+// set of opcodes.
+class CheckNot<MCInstPredicate P> : MCInstPredicate {
+ MCInstPredicate Pred = P;
+}
+
+// This class is used as a building block to define predicates on instruction
+// operands. It is used to reference a specific machine operand.
+class MCOperandPredicate<int Index> : MCInstPredicate {
+ int OpIndex = Index;
+}
+
+// Return true if machine operand at position `Index` is a register operand.
+class CheckIsRegOperand<int Index> : MCOperandPredicate<Index>;
+
+// Return true if machine operand at position `Index` is an immediate operand.
+class CheckIsImmOperand<int Index> : MCOperandPredicate<Index>;
+
+// Check if machine operands at index `First` and index `Second` both reference
+// the same register.
+class CheckSameRegOperand<int First, int Second> : MCInstPredicate {
+ int FirstIndex = First;
+ int SecondIndex = Second;
+}
+
+// Check that the machine register operand at position `Index` references
+// register R. This predicate assumes that we already checked that the machine
+// operand at position `Index` is a register operand.
+class CheckRegOperand<int Index, Register R> : MCOperandPredicate<Index> {
+ Register Reg = R;
+}
+
+// Check if register operand at index `Index` is the invalid register.
+class CheckInvalidRegOperand<int Index> : MCOperandPredicate<Index>;
+
+// Check that the operand at position `Index` is immediate `Imm`.
+class CheckImmOperand<int Index, int Imm> : MCOperandPredicate<Index> {
+ int ImmVal = Imm;
+}
+
+// Similar to CheckImmOperand, however the immediate is not a literal number.
+// This is useful when we want to compare the value of an operand against an
+// enum value, and we know the actual integer value of that enum.
+class CheckImmOperand_s<int Index, string Value> : MCOperandPredicate<Index> {
+ string ImmVal = Value;
+}
+
+// Check that the operand at position `Index` is immediate value zero.
+class CheckZeroOperand<int Index> : CheckImmOperand<Index, 0>;
+
+// Check that the instruction has exactly `Num` operands.
+class CheckNumOperands<int Num> : MCInstPredicate {
+ int NumOps = Num;
+}
+
+// Check that the instruction opcode is one of the opcodes in set `Opcodes`.
+// This is a simple set membership query. The easier way to check if an opcode
+// is not a member of the set is by using a `CheckNot<CheckOpcode<[...]>>`
+// sequence.
+class CheckOpcode<list<Instruction> Opcodes> : MCInstPredicate {
+ list<Instruction> ValidOpcodes = Opcodes;
+}
+
+// Check that the instruction opcode is a pseudo opcode member of the set
+// `Opcodes`. This check is always expanded to "false" if we are generating
+// code for MCInst.
+class CheckPseudo<list<Instruction> Opcodes> : CheckOpcode<Opcodes>;
+
+// A non-portable predicate. Only to use as a last resort when a block of code
+// cannot possibly be converted in a declarative way using other MCInstPredicate
+// classes. This check is always expanded to "false" when generating code for
+// MCInst.
+class CheckNonPortable<string Code> : MCInstPredicate {
+ string CodeBlock = Code;
+}
+
+// A sequence of predicates. It is used as the base class for CheckAll, and
+// CheckAny. It allows to describe compositions of predicates.
+class CheckPredicateSequence<list<MCInstPredicate> Preds> : MCInstPredicate {
+ list<MCInstPredicate> Predicates = Preds;
+}
+
+// Check that all of the predicates in `Preds` evaluate to true.
+class CheckAll<list<MCInstPredicate> Sequence>
+ : CheckPredicateSequence<Sequence>;
+
+// Check that at least one of the predicates in `Preds` evaluates to true.
+class CheckAny<list<MCInstPredicate> Sequence>
+ : CheckPredicateSequence<Sequence>;
+
+// Check that a call to method `Name` in class "XXXGenInstrInfo" (where XXX is
+// the `Target` name) returns true.
+//
+// TIIPredicate definitions are used to model calls to the target-specific
+// InstrInfo. A TIIPredicate is treated specially by the InstrInfoEmitter
+// tablegen backend, which will use it to automatically generate a definition in
+// the target specific `GenInstrInfo` class.
+class TIIPredicate<string Target, string Name, MCInstPredicate P> : MCInstPredicate {
+ string TargetName = Target;
+ string FunctionName = Name;
+ MCInstPredicate Pred = P;
+}
+
+// A function predicate that takes as input a machine instruction, and returns
+// a boolean value.
+//
+// This predicate is expanded into a function call by the PredicateExpander.
+// In particular, the PredicateExpander would either expand this predicate into
+// a call to `MCInstFn`, or into a call to`MachineInstrFn` depending on whether
+// it is lowering predicates for MCInst or MachineInstr.
+//
+// In this context, `MCInstFn` and `MachineInstrFn` are both function names.
+class CheckFunctionPredicate<string MCInstFn, string MachineInstrFn> : MCInstPredicate {
+ string MCInstFnName = MCInstFn;
+ string MachineInstrFnName = MachineInstrFn;
+}
diff --git a/contrib/llvm/include/llvm/Target/TargetItinerary.td b/contrib/llvm/include/llvm/Target/TargetItinerary.td
index 3b1998dfb1ff..182054d8444e 100644
--- a/contrib/llvm/include/llvm/Target/TargetItinerary.td
+++ b/contrib/llvm/include/llvm/Target/TargetItinerary.td
@@ -44,9 +44,9 @@ def Reserved : ReservationKind<1>;
// the execution of an instruction. Cycles represents the number of
// discrete time slots needed to complete the stage. Units represent
// the choice of functional units that can be used to complete the
-// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many
-// cycles should elapse from the start of this stage to the start of
-// the next stage in the itinerary. For example:
+// stage. Eg. IntUnit1, IntUnit2. TimeInc indicates how many cycles
+// should elapse from the start of this stage to the start of the next
+// stage in the itinerary. For example:
//
// A stage is specified in one of two ways:
//
diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFile.h b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index fe77c2954129..dbdfd4139a0f 100644
--- a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFile.h
+++ b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/TargetLoweringObjectFile.h - Object Info ---*- C++ -*-===//
+//===-- llvm/Target/TargetLoweringObjectFile.h - Object Info ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -71,8 +71,7 @@ public:
const MCSymbol *Sym) const;
/// Emit the module-level metadata that the platform cares about.
- virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M,
- const TargetMachine &TM) const {}
+ virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {}
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
@@ -149,7 +148,7 @@ public:
return StaticDtorSection;
}
- /// \brief Create a symbol reference to describe the given TLS variable when
+ /// Create a symbol reference to describe the given TLS variable when
/// emitting the address in debug info.
virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const;
@@ -159,19 +158,19 @@ public:
return nullptr;
}
- /// \brief Target supports replacing a data "PC"-relative access to a symbol
+ /// 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 Target GOT "PC"-relative relocation supports encoding an additional
+ /// Target GOT "PC"-relative relocation supports encoding an additional
/// binary expression with an offset?
bool supportGOTPCRelWithOffset() const {
return SupportGOTPCRelWithOffset;
}
- /// \brief Get the target specific PC relative GOT entry relocation
+ /// Get the target specific PC relative GOT entry relocation
virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
const MCValue &MV,
int64_t Offset,
@@ -183,6 +182,9 @@ public:
virtual void emitLinkerFlagsForGlobal(raw_ostream &OS,
const GlobalValue *GV) const {}
+ virtual void emitLinkerFlagsForUsed(raw_ostream &OS,
+ const GlobalValue *GV) const {}
+
protected:
virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO,
SectionKind Kind,
diff --git a/contrib/llvm/include/llvm/Target/TargetMachine.h b/contrib/llvm/include/llvm/Target/TargetMachine.h
index 97442f9a7849..1ca68c8df63a 100644
--- a/contrib/llvm/include/llvm/Target/TargetMachine.h
+++ b/contrib/llvm/include/llvm/Target/TargetMachine.h
@@ -138,9 +138,23 @@ public:
/// Get the pointer size for this target.
///
/// This is the only time the DataLayout in the TargetMachine is used.
- unsigned getPointerSize() const { return DL.getPointerSize(); }
+ unsigned getPointerSize(unsigned AS) const {
+ return DL.getPointerSize(AS);
+ }
+
+ unsigned getPointerSizeInBits(unsigned AS) const {
+ return DL.getPointerSizeInBits(AS);
+ }
+
+ unsigned getProgramPointerSize() const {
+ return DL.getPointerSize(DL.getProgramAddressSpace());
+ }
- /// \brief Reset the target options based on the function's attributes.
+ unsigned getAllocaPointerSize() const {
+ return DL.getPointerSize(DL.getAllocaAddrSpace());
+ }
+
+ /// Reset the target options based on the function's attributes.
// FIXME: Remove TargetOptions that affect per-function code generation
// from TargetMachine.
void resetTargetOptions(const Function &F) const;
@@ -172,18 +186,28 @@ public:
bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const;
+ /// Returns true if this target uses emulated TLS.
+ bool useEmulatedTLS() const;
+
/// Returns the TLS model which should be used for the given global variable.
TLSModel::Model getTLSModel(const GlobalValue *GV) const;
/// Returns the optimization level: None, Less, Default, or Aggressive.
CodeGenOpt::Level getOptLevel() const;
- /// \brief Overrides the optimization level.
+ /// Overrides the optimization level.
void setOptLevel(CodeGenOpt::Level Level);
void setFastISel(bool Enable) { Options.EnableFastISel = Enable; }
bool getO0WantsFastISel() { return O0WantsFastISel; }
void setO0WantsFastISel(bool Enable) { O0WantsFastISel = Enable; }
+ void setGlobalISel(bool Enable) { Options.EnableGlobalISel = Enable; }
+ void setMachineOutliner(bool Enable) {
+ Options.EnableMachineOutliner = Enable;
+ }
+ void setSupportsDefaultOutlining(bool Enable) {
+ Options.SupportsDefaultOutlining = Enable;
+ }
bool shouldPrintMachineCode() const { return Options.PrintMachineCode; }
@@ -201,14 +225,14 @@ public:
return Options.FunctionSections;
}
- /// \brief Get a \c TargetIRAnalysis appropriate for the target.
+ /// 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.
TargetIRAnalysis getTargetIRAnalysis();
- /// \brief Return a TargetTransformInfo for a given function.
+ /// Return a TargetTransformInfo for a given function.
///
/// The returned TargetTransformInfo is specialized to the subtarget
/// corresponding to \p F.
@@ -234,7 +258,7 @@ public:
/// \p MMI is an optional parameter that, if set to non-nullptr,
/// will be used to set the MachineModuloInfo for this PM.
virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &,
- CodeGenFileType,
+ raw_pwrite_stream *, CodeGenFileType,
bool /*DisableVerify*/ = true,
MachineModuleInfo *MMI = nullptr) {
return true;
@@ -281,14 +305,14 @@ public:
class LLVMTargetMachine : public TargetMachine {
protected: // Can only create subclasses.
LLVMTargetMachine(const Target &T, StringRef DataLayoutString,
- const Triple &TargetTriple, StringRef CPU, StringRef FS,
+ const Triple &TT, StringRef CPU, StringRef FS,
const TargetOptions &Options, Reloc::Model RM,
CodeModel::Model CM, CodeGenOpt::Level OL);
void initAsmInfo();
public:
- /// \brief Get a TargetTransformInfo implementation for the target.
+ /// Get a TargetTransformInfo implementation for the target.
///
/// The TTI returned uses the common code generator to answer queries about
/// the IR.
@@ -303,7 +327,8 @@ public:
/// \p MMI is an optional parameter that, if set to non-nullptr,
/// will be used to set the MachineModuloInfofor this PM.
bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
- CodeGenFileType FileType, bool DisableVerify = true,
+ raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
+ bool DisableVerify = true,
MachineModuleInfo *MMI = nullptr) override;
/// Add passes to the specified pass manager to get machine code emitted with
@@ -311,7 +336,7 @@ public:
/// fills the MCContext Ctx pointer which can be used to build custom
/// MCStreamer.
bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
- raw_pwrite_stream &OS,
+ raw_pwrite_stream &Out,
bool DisableVerify = true) override;
/// Returns true if the target is expected to pass all machine verifier
@@ -320,10 +345,11 @@ public:
/// EXPENSIVE_CHECKS is enabled.
virtual bool isMachineVerifierClean() const { return true; }
- /// \brief Adds an AsmPrinter pass to the pipeline that prints assembly or
+ /// Adds an AsmPrinter pass to the pipeline that prints assembly or
/// machine code from the MI representation.
bool addAsmPrinter(PassManagerBase &PM, raw_pwrite_stream &Out,
- CodeGenFileType FileTYpe, MCContext &Context);
+ raw_pwrite_stream *DwoOut, CodeGenFileType FileTYpe,
+ MCContext &Context);
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Target/TargetOptions.h b/contrib/llvm/include/llvm/Target/TargetOptions.h
index 70fac7833f32..07ed773de55e 100644
--- a/contrib/llvm/include/llvm/Target/TargetOptions.h
+++ b/contrib/llvm/include/llvm/Target/TargetOptions.h
@@ -104,11 +104,14 @@ namespace llvm {
NoSignedZerosFPMath(false),
HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
- EnableFastISel(false), UseInitArray(false),
+ EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false),
DisableIntegratedAS(false), RelaxELFRelocations(false),
FunctionSections(false), DataSections(false),
- UniqueSectionNames(true), TrapUnreachable(false), EmulatedTLS(false),
- EnableIPRA(false), EmitStackSizeSection(false) {}
+ UniqueSectionNames(true), TrapUnreachable(false),
+ NoTrapAfterNoreturn(false), EmulatedTLS(false),
+ ExplicitEmulatedTLS(false), EnableIPRA(false),
+ EmitStackSizeSection(false), EnableMachineOutliner(false),
+ SupportsDefaultOutlining(false), EmitAddrsig(false) {}
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs
/// option is specified on the command line, and should enable debugging
@@ -186,6 +189,9 @@ namespace llvm {
/// compile time.
unsigned EnableFastISel : 1;
+ /// EnableGlobalISel - This flag enables global instruction selection.
+ unsigned EnableGlobalISel : 1;
+
/// UseInitArray - Use .init_array instead of .ctors for static
/// constructors.
unsigned UseInitArray : 1;
@@ -209,16 +215,32 @@ namespace llvm {
/// Emit target-specific trap instruction for 'unreachable' IR instructions.
unsigned TrapUnreachable : 1;
+ /// Do not emit a trap instruction for 'unreachable' IR instructions behind
+ /// noreturn calls, even if TrapUnreachable is true.
+ unsigned NoTrapAfterNoreturn : 1;
+
/// EmulatedTLS - This flag enables emulated TLS model, using emutls
/// function in the runtime library..
unsigned EmulatedTLS : 1;
+ /// Whether -emulated-tls or -no-emulated-tls is set.
+ unsigned ExplicitEmulatedTLS : 1;
+
/// This flag enables InterProcedural Register Allocation (IPRA).
unsigned EnableIPRA : 1;
/// Emit section containing metadata on function stack sizes.
unsigned EmitStackSizeSection : 1;
+ /// Enables the MachineOutliner pass.
+ unsigned EnableMachineOutliner : 1;
+
+ /// Set if the target supports default outlining behaviour.
+ unsigned SupportsDefaultOutlining : 1;
+
+ /// Emit address-significance table.
+ unsigned EmitAddrsig : 1;
+
/// FloatABIType - This setting is set by -float-abi=xxx option is specfied
/// on the command line. This setting may either be Default, Soft, or Hard.
/// Default selects the target's default behavior. Soft selects the ABI for
diff --git a/contrib/llvm/include/llvm/Target/TargetSchedule.td b/contrib/llvm/include/llvm/Target/TargetSchedule.td
index 7b00c9420e35..6fd2d5b78e54 100644
--- a/contrib/llvm/include/llvm/Target/TargetSchedule.td
+++ b/contrib/llvm/include/llvm/Target/TargetSchedule.td
@@ -99,6 +99,12 @@ class SchedMachineModel {
// resulting from changes to the instruction definitions.
bit CompleteModel = 1;
+ // Indicates that we should do full overlap checking for multiple InstrRWs
+ // definining the same instructions within the same SchedMachineModel.
+ // FIXME: Remove when all in tree targets are clean with the full check
+ // enabled.
+ bit FullInstRWOverlapCheck = 1;
+
// A processor may only implement part of published ISA, due to either new ISA
// extensions, (e.g. Pentium 4 doesn't have AVX) or implementation
// (ARM/MIPS/PowerPC/SPARC soft float cores).
@@ -175,9 +181,9 @@ class ProcResourceKind;
// BufferSize=1.
//
// SchedModel ties these units to a processor for any stand-alone defs
-// of this class. Instances of subclass ProcResource will be automatically
-// attached to a processor, so SchedModel is not needed.
-class ProcResourceUnits<ProcResourceKind kind, int num> {
+// of this class.
+class ProcResourceUnits<ProcResourceKind kind, int num,
+ list<string> pfmCounters> {
ProcResourceKind Kind = kind;
int NumUnits = num;
ProcResourceKind Super = ?;
@@ -192,8 +198,8 @@ def EponymousProcResourceKind : ProcResourceKind;
// Subtargets typically define processor resource kind and number of
// units in one place.
-class ProcResource<int num> : ProcResourceKind,
- ProcResourceUnits<EponymousProcResourceKind, num>;
+class ProcResource<int num, list<string> pfmCounters = []> : ProcResourceKind,
+ ProcResourceUnits<EponymousProcResourceKind, num, pfmCounters>;
class ProcResGroup<list<ProcResource> resources> : ProcResourceKind {
list<ProcResource> Resources = resources;
@@ -275,10 +281,9 @@ class ProcWriteResources<list<ProcResourceKind> resources> {
// ProcResources indicates the set of resources consumed by the write.
// Optionally, ResourceCycles indicates the number of cycles the
// resource is consumed. Each ResourceCycles item is paired with the
-// ProcResource item at the same position in its list. Since
-// ResourceCycles are rarely specialized, the list may be
-// incomplete. By default, resources are consumed for a single cycle,
-// regardless of latency, which models a fully pipelined processing
+// ProcResource item at the same position in its list. ResourceCycles
+// can be `[]`: in that case, all resources are consumed for a single
+// cycle, regardless of latency, which models a fully pipelined processing
// unit. A value of 0 for ResourceCycles means that the resource must
// be available but is not consumed, which is only relevant for
// unbuffered resources.
@@ -349,13 +354,23 @@ class PredicateProlog<code c> {
code Code = c;
}
+// Base class for scheduling predicates.
+class SchedPredicateBase;
+
+// A scheduling predicate whose logic is defined by a MCInstPredicate.
+// This can directly be used by SchedWriteVariant definitions.
+class MCSchedPredicate<MCInstPredicate P> : SchedPredicateBase {
+ MCInstPredicate Pred = P;
+ SchedMachineModel SchedModel = ?;
+}
+
// Define a predicate to determine which SchedVariant applies to a
// particular MachineInstr. The code snippet is used as an
// if-statement's expression. Available variables are MI, SchedModel,
// and anything defined in a PredicateProlog.
//
// SchedModel silences warnings but is ignored.
-class SchedPredicate<code pred> {
+class SchedPredicate<code pred> : SchedPredicateBase {
SchedMachineModel SchedModel = ?;
code Predicate = pred;
}
@@ -370,8 +385,8 @@ def NoSchedPred : SchedPredicate<[{true}]>;
// operands. In this case, latency is not additive. If the current Variant
// is already part of a Sequence, then that entire chain leading up to
// the Variant is distributed over the variadic operands.
-class SchedVar<SchedPredicate pred, list<SchedReadWrite> selected> {
- SchedPredicate Predicate = pred;
+class SchedVar<SchedPredicateBase pred, list<SchedReadWrite> selected> {
+ SchedPredicateBase Predicate = pred;
list<SchedReadWrite> Selected = selected;
}
@@ -437,3 +452,102 @@ class SchedAlias<SchedReadWrite match, SchedReadWrite alias> {
SchedReadWrite AliasRW = alias;
SchedMachineModel SchedModel = ?;
}
+
+// Allow the definition of processor register files for register renaming
+// purposes.
+//
+// Each processor register file declares:
+// - The set of registers that can be renamed.
+// - The number of physical registers which can be used for register renaming
+// purpose.
+// - The cost of a register rename.
+//
+// The cost of a rename is the number of physical registers allocated by the
+// register alias table to map the new definition. By default, register can be
+// renamed at the cost of a single physical register. Note that register costs
+// are defined at register class granularity (see field `Costs`).
+//
+// The set of registers that are subject to register renaming is declared using
+// a list of register classes (see field `RegClasses`). An empty list of
+// register classes means: all the logical registers defined by the target can
+// be fully renamed.
+//
+// A register R can be renamed if its register class appears in the `RegClasses`
+// set. When R is written, a new alias is allocated at the cost of one or more
+// physical registers; as a result, false dependencies on R are removed.
+//
+// A sub-register V of register R is implicitly part of the same register file.
+// However, V is only renamed if its register class is part of `RegClasses`.
+// Otherwise, the processor keeps it (as well as any other different part
+// of R) together with R, and a write of V always causes a compulsory read of R.
+//
+// This is what happens for example on AMD processors (at least from Bulldozer
+// onwards), where AL and AH are not treated as independent from AX, and AX is
+// not treated as independent from EAX. A write to AL has an implicity false
+// dependency on the last write to EAX (or a portion of EAX). As a consequence,
+// a write to AL cannot go in parallel with a write to AH.
+//
+// There is no false dependency if the partial register write belongs to a
+// register class that is in `RegClasses`.
+// There is also no penalty for writes that "clear the content a super-register"
+// (see MC/MCInstrAnalysis.h - method MCInstrAnalysis::clearsSuperRegisters()).
+// On x86-64, 32-bit GPR writes implicitly zero the upper half of the underlying
+// physical register, effectively removing any false dependencies with the
+// previous register definition.
+//
+// TODO: This implementation assumes that there is no limit in the number of
+// renames per cycle, which might not be true for all hardware or register
+// classes. Also, there is no limit to how many times the same logical register
+// can be renamed during the same cycle.
+//
+// TODO: we don't currently model merge penalties for the case where a write to
+// a part of a register is followed by a read from a larger part of the same
+// register. On some Intel chips, different parts of a GPR can be stored in
+// different physical registers. However, there is a cost to pay for when the
+// partial write is combined with the previous super-register definition. We
+// should add support for these cases, and correctly model merge problems with
+// partial register accesses.
+class RegisterFile<int numPhysRegs, list<RegisterClass> Classes = [],
+ list<int> Costs = []> {
+ list<RegisterClass> RegClasses = Classes;
+ list<int> RegCosts = Costs;
+ int NumPhysRegs = numPhysRegs;
+ SchedMachineModel SchedModel = ?;
+}
+
+// Describe the retire control unit.
+// A retire control unit specifies the size of the reorder buffer, as well as
+// the maximum number of opcodes that can be retired every cycle.
+// A value less-than-or-equal-to zero for field 'ReorderBufferSize' means: "the
+// size is unknown". The idea is that external tools can fall-back to using
+// field MicroOpBufferSize in SchedModel if the reorder buffer size is unknown.
+// A zero or negative value for field 'MaxRetirePerCycle' means "no
+// restrictions on the number of instructions retired per cycle".
+// Models can optionally specify up to one instance of RetireControlUnit per
+// scheduling model.
+class RetireControlUnit<int bufferSize, int retirePerCycle> {
+ int ReorderBufferSize = bufferSize;
+ int MaxRetirePerCycle = retirePerCycle;
+ SchedMachineModel SchedModel = ?;
+}
+
+// Allow the definition of hardware counters.
+class PfmCounter {
+ SchedMachineModel SchedModel = ?;
+}
+
+// Each processor can define how to measure cycles by defining a
+// PfmCycleCounter.
+class PfmCycleCounter<string counter> : PfmCounter {
+ string Counter = counter;
+}
+
+// Each ProcResourceUnits can define how to measure issued uops by defining
+// a PfmIssueCounter.
+class PfmIssueCounter<ProcResourceUnits resource, list<string> counters>
+ : PfmCounter{
+ // The resource units on which uops are issued.
+ ProcResourceUnits Resource = resource;
+ // The list of counters that measure issue events.
+ list<string> Counters = counters;
+}
diff --git a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td
index f6162377b8b7..4ba4d821225d 100644
--- a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -485,6 +485,8 @@ def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , SDTAtomic2,
[SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>;
def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , SDTAtomic2,
[SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>;
+def atomic_load_clr : SDNode<"ISD::ATOMIC_LOAD_CLR" , SDTAtomic2,
+ [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>;
def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , SDTAtomic2,
[SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>;
def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , SDTAtomic2,
@@ -613,14 +615,18 @@ class CodePatPred<code predicate> : PatPred {
// compact and readable.
//
-/// PatFrag - Represents a pattern fragment. This can match something on the
-/// DAG, from a single node to multiple nested other fragments.
+/// PatFrags - Represents a set of pattern fragments. Each single fragment
+/// can match something on the DAG, from a single node to multiple nested other
+/// fragments. The whole set of fragments matches if any of the single
+/// fragemnts match. This allows e.g. matching and "add with overflow" and
+/// a regular "add" with the same fragment set.
///
-class PatFrag<dag ops, dag frag, code pred = [{}],
- SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator {
+class PatFrags<dag ops, list<dag> frags, code pred = [{}],
+ SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator {
dag Operands = ops;
- dag Fragment = frag;
+ list<dag> Fragments = frags;
code PredicateCode = pred;
+ code GISelPredicateCode = [{}];
code ImmediateCode = [{}];
SDNodeXForm OperandTransform = xform;
@@ -679,6 +685,11 @@ class PatFrag<dag ops, dag frag, code pred = [{}],
ValueType ScalarMemoryVT = ?;
}
+// PatFrag - A version of PatFrags matching only a single fragment.
+class PatFrag<dag ops, dag frag, code pred = [{}],
+ SDNodeXForm xform = NOOP_SDNodeXForm>
+ : PatFrags<ops, [frag], pred, xform>;
+
// OutPatFrag is a pattern fragment that is used as part of an output pattern
// (not an input pattern). These do not have predicates or transforms, but are
// used to avoid repeated subexpressions in output patterns.
@@ -1130,27 +1141,27 @@ def setne : PatFrag<(ops node:$lhs, node:$rhs),
multiclass binary_atomic_op_ord<SDNode atomic_op> {
def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingMonotonic = 1;
}
def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingAcquire = 1;
}
def #NAME#_release : PatFrag<(ops node:$ptr, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingRelease = 1;
}
def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingAcquireRelease = 1;
}
def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingSequentiallyConsistent = 1;
}
@@ -1158,27 +1169,27 @@ multiclass binary_atomic_op_ord<SDNode atomic_op> {
multiclass ternary_atomic_op_ord<SDNode atomic_op> {
def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingMonotonic = 1;
}
def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingAcquire = 1;
}
def #NAME#_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingRelease = 1;
}
def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingAcquireRelease = 1;
}
def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
- (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
+ (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
let IsAtomic = 1;
let IsAtomicOrderingSequentiallyConsistent = 1;
}
@@ -1244,6 +1255,7 @@ defm atomic_load_add : binary_atomic_op<atomic_load_add>;
defm atomic_swap : binary_atomic_op<atomic_swap>;
defm atomic_load_sub : binary_atomic_op<atomic_load_sub>;
defm atomic_load_and : binary_atomic_op<atomic_load_and>;
+defm atomic_load_clr : binary_atomic_op<atomic_load_clr>;
defm atomic_load_or : binary_atomic_op<atomic_load_or>;
defm atomic_load_xor : binary_atomic_op<atomic_load_xor>;
defm atomic_load_nand : binary_atomic_op<atomic_load_nand>;
diff --git a/contrib/llvm/include/llvm/Testing/Support/Error.h b/contrib/llvm/include/llvm/Testing/Support/Error.h
index 50889b9c66f5..0e5b5403ce87 100644
--- a/contrib/llvm/include/llvm/Testing/Support/Error.h
+++ b/contrib/llvm/include/llvm/Testing/Support/Error.h
@@ -38,7 +38,7 @@ public:
bool MatchAndExplain(const ExpectedHolder<T> &Holder,
testing::MatchResultListener *listener) const override {
- if (!Holder.Success)
+ if (!Holder.Success())
return false;
bool result = Matcher.MatchAndExplain(*Holder.Exp, listener);
@@ -82,6 +82,53 @@ private:
M Matcher;
};
+template <typename InfoT>
+class ErrorMatchesMono : public testing::MatcherInterface<const ErrorHolder &> {
+public:
+ explicit ErrorMatchesMono(Optional<testing::Matcher<InfoT &>> Matcher)
+ : Matcher(std::move(Matcher)) {}
+
+ bool MatchAndExplain(const ErrorHolder &Holder,
+ testing::MatchResultListener *listener) const override {
+ if (Holder.Success())
+ return false;
+
+ if (Holder.Infos.size() > 1) {
+ *listener << "multiple errors";
+ return false;
+ }
+
+ auto &Info = *Holder.Infos[0];
+ if (!Info.isA<InfoT>()) {
+ *listener << "Error was not of given type";
+ return false;
+ }
+
+ if (!Matcher)
+ return true;
+
+ return Matcher->MatchAndExplain(static_cast<InfoT &>(Info), listener);
+ }
+
+ void DescribeTo(std::ostream *OS) const override {
+ *OS << "failed with Error of given type";
+ if (Matcher) {
+ *OS << " and the error ";
+ Matcher->DescribeTo(OS);
+ }
+ }
+
+ void DescribeNegationTo(std::ostream *OS) const override {
+ *OS << "succeeded or did not fail with the error of given type";
+ if (Matcher) {
+ *OS << " or the error ";
+ Matcher->DescribeNegationTo(OS);
+ }
+ }
+
+private:
+ Optional<testing::Matcher<InfoT &>> Matcher;
+};
} // namespace detail
#define EXPECT_THAT_ERROR(Err, Matcher) \
@@ -94,8 +141,19 @@ private:
#define ASSERT_THAT_EXPECTED(Err, Matcher) \
ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher)
-MATCHER(Succeeded, "") { return arg.Success; }
-MATCHER(Failed, "") { return !arg.Success; }
+MATCHER(Succeeded, "") { return arg.Success(); }
+MATCHER(Failed, "") { return !arg.Success(); }
+
+template <typename InfoT>
+testing::Matcher<const detail::ErrorHolder &> Failed() {
+ return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(None));
+}
+
+template <typename InfoT, typename M>
+testing::Matcher<const detail::ErrorHolder &> Failed(M Matcher) {
+ return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(
+ testing::SafeMatcherCast<InfoT &>(Matcher)));
+}
template <typename M>
detail::ValueMatchesPoly<M> HasValue(M Matcher) {
diff --git a/contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h b/contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h
index d7f0c7142b2c..96264ac81dc4 100644
--- a/contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h
+++ b/contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h
@@ -17,8 +17,9 @@
namespace llvm {
namespace detail {
struct ErrorHolder {
- bool Success;
- std::string Message;
+ std::vector<std::shared_ptr<ErrorInfoBase>> Infos;
+
+ bool Success() const { return Infos.empty(); }
};
template <typename T> struct ExpectedHolder : public ErrorHolder {
@@ -29,15 +30,22 @@ template <typename T> struct ExpectedHolder : public ErrorHolder {
};
inline void PrintTo(const ErrorHolder &Err, std::ostream *Out) {
- *Out << (Err.Success ? "succeeded" : "failed");
- if (!Err.Success) {
- *Out << " (" << StringRef(Err.Message).trim().str() << ")";
+ raw_os_ostream OS(*Out);
+ OS << (Err.Success() ? "succeeded" : "failed");
+ if (!Err.Success()) {
+ const char *Delim = " (";
+ for (const auto &Info : Err.Infos) {
+ OS << Delim;
+ Delim = "; ";
+ Info->log(OS);
+ }
+ OS << ")";
}
}
template <typename T>
void PrintTo(const ExpectedHolder<T> &Item, std::ostream *Out) {
- if (Item.Success) {
+ if (Item.Success()) {
*Out << "succeeded with value " << ::testing::PrintToString(*Item.Exp);
} else {
PrintTo(static_cast<const ErrorHolder &>(Item), Out);
diff --git a/contrib/llvm/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h b/contrib/llvm/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h
new file mode 100644
index 000000000000..f970acdc741f
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h
@@ -0,0 +1,41 @@
+//===- AggressiveInstCombine.h - AggressiveInstCombine 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 aggressive instcombine pass.
+/// This pass is suitable for use in the new pass manager. For a pass that works
+/// with the legacy pass manager, please use
+/// \c createAggressiveInstCombinerPass().
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_AGGRESSIVE_INSTCOMBINE_INSTCOMBINE_H
+#define LLVM_TRANSFORMS_AGGRESSIVE_INSTCOMBINE_INSTCOMBINE_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class AggressiveInstCombinePass
+ : public PassInfoMixin<AggressiveInstCombinePass> {
+
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+//===----------------------------------------------------------------------===//
+//
+// AggressiveInstCombiner - Combine expression patterns to form expressions with
+// fewer, simple instructions. This pass does not modify the CFG.
+//
+FunctionPass *createAggressiveInstCombinerPass();
+}
+
+#endif
diff --git a/contrib/llvm/include/llvm/Transforms/IPO.h b/contrib/llvm/include/llvm/Transforms/IPO.h
index ce20a726b783..ebc76bf82118 100644
--- a/contrib/llvm/include/llvm/Transforms/IPO.h
+++ b/contrib/llvm/include/llvm/Transforms/IPO.h
@@ -15,6 +15,7 @@
#ifndef LLVM_TRANSFORMS_IPO_H
#define LLVM_TRANSFORMS_IPO_H
+#include "llvm/ADT/SmallVector.h"
#include <functional>
#include <vector>
@@ -44,10 +45,6 @@ ModulePass *createStripSymbolsPass(bool OnlyDebugInfo = false);
//
ModulePass *createStripNonDebugSymbolsPass();
-/// This function returns a new pass that downgrades the debug info in the
-/// module to line tables only.
-ModulePass *createStripNonLineTableDebugInfoPass();
-
//===----------------------------------------------------------------------===//
//
// This pass removes llvm.dbg.declare intrinsics.
@@ -179,10 +176,13 @@ Pass *createLoopExtractorPass();
///
Pass *createSingleLoopExtractorPass();
-/// createBlockExtractorPass - This pass extracts all blocks (except those
-/// specified in the argument list) from the functions in the module.
+/// createBlockExtractorPass - This pass extracts all the specified blocks
+/// from the functions in the module.
///
ModulePass *createBlockExtractorPass();
+ModulePass *
+createBlockExtractorPass(const SmallVectorImpl<BasicBlock *> &BlocksToExtract,
+ bool EraseFunctions);
/// createStripDeadPrototypesPass - This pass removes any function declarations
/// (prototypes) that are not used.
@@ -207,11 +207,6 @@ ModulePass *createMergeFunctionsPass();
ModulePass *createPartialInliningPass();
//===----------------------------------------------------------------------===//
-// createMetaRenamerPass - Rename everything with metasyntatic names.
-//
-ModulePass *createMetaRenamerPass();
-
-//===----------------------------------------------------------------------===//
/// createBarrierNoopPass - This pass is purely a module pass barrier in a pass
/// manager.
ModulePass *createBarrierNoopPass();
@@ -227,7 +222,7 @@ enum class PassSummaryAction {
Export, ///< Export information to summary.
};
-/// \brief This pass lowers type metadata and the llvm.type.test intrinsic to
+/// This pass lowers type metadata and the llvm.type.test intrinsic to
/// bitsets.
///
/// The behavior depends on the summary arguments:
@@ -240,10 +235,10 @@ enum class PassSummaryAction {
ModulePass *createLowerTypeTestsPass(ModuleSummaryIndex *ExportSummary,
const ModuleSummaryIndex *ImportSummary);
-/// \brief This pass export CFI checks for use by external modules.
+/// This pass export CFI checks for use by external modules.
ModulePass *createCrossDSOCFIPass();
-/// \brief This pass implements whole-program devirtualization using type
+/// This pass implements whole-program devirtualization using type
/// metadata.
///
/// The behavior depends on the summary arguments:
diff --git a/contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h b/contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h
index 15c80357e4a8..b52c0fdbd2c9 100644
--- a/contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h
+++ b/contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h
@@ -27,7 +27,13 @@ namespace llvm {
/// be the simplest possible pass to remove always_inline function definitions'
/// uses by inlining them. The \c GlobalDCE pass can be used to remove these
/// functions once all users are gone.
-struct AlwaysInlinerPass : PassInfoMixin<AlwaysInlinerPass> {
+class AlwaysInlinerPass : public PassInfoMixin<AlwaysInlinerPass> {
+ bool InsertLifetime;
+
+public:
+ AlwaysInlinerPass(bool InsertLifetime = true)
+ : InsertLifetime(InsertLifetime) {}
+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
};
diff --git a/contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h b/contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h
index 82ffc69a166e..49ca6cc73393 100644
--- a/contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h
+++ b/contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h
@@ -22,7 +22,11 @@ namespace llvm {
/// transform it and all of its callers to replace indirect arguments with
/// direct (by-value) arguments.
class ArgumentPromotionPass : public PassInfoMixin<ArgumentPromotionPass> {
+ unsigned MaxElements;
+
public:
+ ArgumentPromotionPass(unsigned MaxElements = 3u) : MaxElements(MaxElements) {}
+
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
LazyCallGraph &CG, CGSCCUpdateResult &UR);
};
diff --git a/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h b/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h
index 39e5b5c8ae6f..120a34e15933 100644
--- a/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h
+++ b/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h
@@ -33,11 +33,17 @@ class Module;
/// based on the provided summary informations.
class FunctionImporter {
public:
- /// Set of functions to import from a source module. Each entry is a map
- /// containing all the functions to import for a source module.
- /// The keys is the GUID identifying a function to import, and the value
- /// is the threshold applied when deciding to import it.
- using FunctionsToImportTy = std::map<GlobalValue::GUID, unsigned>;
+ /// Set of functions to import from a source module. Each entry is a set
+ /// containing all the GUIDs of all functions to import for a source module.
+ using FunctionsToImportTy = std::unordered_set<GlobalValue::GUID>;
+
+ /// Map of callee GUID considered for import into a given module to a pair
+ /// consisting of the largest threshold applied when deciding whether to
+ /// import it and, if we decided to import, a pointer to the summary instance
+ /// imported. If we decided not to import, the summary will be nullptr.
+ using ImportThresholdsTy =
+ DenseMap<GlobalValue::GUID,
+ std::pair<unsigned, const GlobalValueSummary *>>;
/// The map contains an entry for every module to import from, the key being
/// the module identifier to pass to the ModuleLoader. The value is the set of
@@ -107,12 +113,24 @@ void ComputeCrossModuleImportForModuleFromIndex(
StringRef ModulePath, const ModuleSummaryIndex &Index,
FunctionImporter::ImportMapTy &ImportList);
+/// PrevailingType enum used as a return type of callback passed
+/// to computeDeadSymbols. Yes and No values used when status explicitly
+/// set by symbols resolution, otherwise status is Unknown.
+enum class PrevailingType { Yes, No, Unknown };
+
/// Compute all the symbols that are "dead": i.e these that can't be reached
/// in the graph from any of the given symbols listed in
-/// \p GUIDPreservedSymbols.
+/// \p GUIDPreservedSymbols. Non-prevailing symbols are symbols without a
+/// prevailing copy anywhere in IR and are normally dead, \p isPrevailing
+/// predicate returns status of symbol.
void computeDeadSymbols(
ModuleSummaryIndex &Index,
- const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols);
+ const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
+ function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing);
+
+/// Converts value \p GV to declaration, or replaces with a declaration if
+/// it is an alias. Returns true if converted, false if replaced.
+bool convertToDeclaration(GlobalValue &GV);
/// Compute the set of summaries needed for a ThinLTO backend compilation of
/// \p ModulePath.
@@ -131,9 +149,9 @@ void gatherImportedSummariesForModule(
std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex);
/// Emit into \p OutputFilename the files module \p ModulePath will import from.
-std::error_code
-EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename,
- const FunctionImporter::ImportMapTy &ModuleImports);
+std::error_code EmitImportsFiles(
+ StringRef ModulePath, StringRef OutputFilename,
+ const std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex);
/// Resolve WeakForLinker values in \p TheModule based on the information
/// recorded in the summaries during global summary-based analysis.
diff --git a/contrib/llvm/include/llvm/Transforms/IPO/Inliner.h b/contrib/llvm/include/llvm/Transforms/IPO/Inliner.h
index eda8cf462b50..610e4500e4b1 100644
--- a/contrib/llvm/include/llvm/Transforms/IPO/Inliner.h
+++ b/contrib/llvm/include/llvm/Transforms/IPO/Inliner.h
@@ -96,12 +96,17 @@ class InlinerPass : public PassInfoMixin<InlinerPass> {
public:
InlinerPass(InlineParams Params = getInlineParams())
: Params(std::move(Params)) {}
+ ~InlinerPass();
+ InlinerPass(InlinerPass &&Arg)
+ : Params(std::move(Arg.Params)),
+ ImportedFunctionsStats(std::move(Arg.ImportedFunctionsStats)) {}
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
LazyCallGraph &CG, CGSCCUpdateResult &UR);
private:
InlineParams Params;
+ std::unique_ptr<ImportedFunctionsInliningStatistics> ImportedFunctionsStats;
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h b/contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h
index 3bcfe65df550..bc448386b63d 100644
--- a/contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h
+++ b/contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h
@@ -26,6 +26,7 @@
namespace llvm {
class Module;
+class ModuleSummaryIndex;
class raw_ostream;
namespace lowertypetests {
@@ -197,6 +198,11 @@ struct ByteArrayBuilder {
class LowerTypeTestsPass : public PassInfoMixin<LowerTypeTestsPass> {
public:
+ ModuleSummaryIndex *ExportSummary;
+ const ModuleSummaryIndex *ImportSummary;
+ LowerTypeTestsPass(ModuleSummaryIndex *ExportSummary,
+ const ModuleSummaryIndex *ImportSummary)
+ : ExportSummary(ExportSummary), ImportSummary(ImportSummary) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
diff --git a/contrib/llvm/include/llvm/Transforms/SampleProfile.h b/contrib/llvm/include/llvm/Transforms/IPO/SampleProfile.h
index f5a8590e14a1..cd5a0563898e 100644
--- a/contrib/llvm/include/llvm/Transforms/SampleProfile.h
+++ b/contrib/llvm/include/llvm/Transforms/IPO/SampleProfile.h
@@ -1,4 +1,4 @@
-//===- Transforms/SampleProfile.h - SamplePGO pass --------------*- C++ -*-===//
+//===- SampleProfile.h - SamplePGO pass ---------- --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TRANSFORMS_SAMPLEPROFILE_H
-#define LLVM_TRANSFORMS_SAMPLEPROFILE_H
+#ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILE_H
+#define LLVM_TRANSFORMS_IPO_SAMPLEPROFILE_H
#include "llvm/IR/PassManager.h"
#include <string>
diff --git a/contrib/llvm/include/llvm/Transforms/IPO/SyntheticCountsPropagation.h b/contrib/llvm/include/llvm/Transforms/IPO/SyntheticCountsPropagation.h
new file mode 100644
index 000000000000..0b3ba86bc9e4
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/IPO/SyntheticCountsPropagation.h
@@ -0,0 +1,19 @@
+#ifndef LLVM_TRANSFORMS_IPO_SYNTHETIC_COUNTS_PROPAGATION_H
+#define LLVM_TRANSFORMS_IPO_SYNTHETIC_COUNTS_PROPAGATION_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/ScaledNumber.h"
+
+namespace llvm {
+class Function;
+class Module;
+
+class SyntheticCountsPropagation
+ : public PassInfoMixin<SyntheticCountsPropagation> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+};
+} // namespace llvm
+#endif
diff --git a/contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h b/contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h
index 1aa4c6f4f559..bf2c79b0751e 100644
--- a/contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h
+++ b/contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h
@@ -28,6 +28,7 @@ template <typename T> class ArrayRef;
template <typename T> class MutableArrayRef;
class Function;
class GlobalVariable;
+class ModuleSummaryIndex;
namespace wholeprogramdevirt {
@@ -218,6 +219,13 @@ void setAfterReturnValues(MutableArrayRef<VirtualCallTarget> Targets,
} // end namespace wholeprogramdevirt
struct WholeProgramDevirtPass : public PassInfoMixin<WholeProgramDevirtPass> {
+ ModuleSummaryIndex *ExportSummary;
+ const ModuleSummaryIndex *ImportSummary;
+ WholeProgramDevirtPass(ModuleSummaryIndex *ExportSummary,
+ const ModuleSummaryIndex *ImportSummary)
+ : ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
+ assert(!(ExportSummary && ImportSummary));
+ }
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
};
diff --git a/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h b/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
index 6bd22dc46255..ab25fe08553a 100644
--- a/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
+++ b/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
@@ -10,8 +10,7 @@
///
/// 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.
+/// legacy pass manager, use \c createInstructionCombiningPass().
///
//===----------------------------------------------------------------------===//
@@ -37,7 +36,7 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief The legacy pass manager's instcombine pass.
+/// The legacy pass manager's instcombine pass.
///
/// This is a basic whole-function wrapper around the instcombine utility. It
/// will try to combine all instructions in the function.
@@ -56,6 +55,20 @@ public:
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
};
+
+//===----------------------------------------------------------------------===//
+//
+// InstructionCombining - Combine instructions to form fewer, simple
+// instructions. This pass does not modify the CFG, and has a tendency to make
+// instructions dead, so a subsequent DCE pass is useful.
+//
+// This pass combines things like:
+// %Y = add int 1, %X
+// %Z = add int 1, %Y
+// into:
+// %Z = add int 2, %X
+//
+FunctionPass *createInstructionCombiningPass(bool ExpensiveCombines = true);
}
#endif
diff --git a/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h b/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
index 271e891bb45e..f860b4b86555 100644
--- a/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
+++ b/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
@@ -40,7 +40,7 @@ public:
/// in it.
void Add(Instruction *I) {
if (WorklistMap.insert(std::make_pair(I, Worklist.size())).second) {
- DEBUG(dbgs() << "IC: ADD: " << *I << '\n');
+ LLVM_DEBUG(dbgs() << "IC: ADD: " << *I << '\n');
Worklist.push_back(I);
}
}
@@ -57,7 +57,8 @@ public:
assert(Worklist.empty() && "Worklist must be empty to add initial group");
Worklist.reserve(List.size()+16);
WorklistMap.reserve(List.size());
- DEBUG(dbgs() << "IC: ADDING: " << List.size() << " instrs to worklist\n");
+ LLVM_DEBUG(dbgs() << "IC: ADDING: " << List.size()
+ << " instrs to worklist\n");
unsigned Idx = 0;
for (Instruction *I : reverse(List)) {
WorklistMap.insert(std::make_pair(I, Idx++));
diff --git a/contrib/llvm/include/llvm/Transforms/Instrumentation.h b/contrib/llvm/include/llvm/Transforms/Instrumentation.h
index b1e13f17aef1..4a346c8d7450 100644
--- a/contrib/llvm/include/llvm/Transforms/Instrumentation.h
+++ b/contrib/llvm/include/llvm/Transforms/Instrumentation.h
@@ -133,7 +133,8 @@ ModulePass *createAddressSanitizerModulePass(bool CompileKernel = false,
FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0,
bool Recover = false);
-FunctionPass *createHWAddressSanitizerPass(bool Recover = false);
+FunctionPass *createHWAddressSanitizerPass(bool CompileKernel = false,
+ bool Recover = false);
// Insert ThreadSanitizer (race detection) instrumentation
FunctionPass *createThreadSanitizerPass();
@@ -186,7 +187,7 @@ struct SanitizerCoverageOptions {
ModulePass *createSanitizerCoverageModulePass(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions());
-/// \brief Calculate what to divide by to scale counts.
+/// Calculate what to divide by to scale counts.
///
/// Given the maximum count, calculate a divisor that will scale all the
/// weights to strictly less than std::numeric_limits<uint32_t>::max().
@@ -196,7 +197,7 @@ static inline uint64_t calculateCountScale(uint64_t MaxCount) {
: MaxCount / std::numeric_limits<uint32_t>::max() + 1;
}
-/// \brief Scale an individual branch count.
+/// Scale an individual branch count.
///
/// Scale a 64-bit weight down to 32-bits using \c Scale.
///
diff --git a/contrib/llvm/include/llvm/Transforms/Instrumentation/CGProfile.h b/contrib/llvm/include/llvm/Transforms/Instrumentation/CGProfile.h
new file mode 100644
index 000000000000..c06c1a28715e
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/Instrumentation/CGProfile.h
@@ -0,0 +1,31 @@
+//===- Transforms/Instrumentation/CGProfile.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 the interface for LLVM's Call Graph Profile pass.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_CGPROFILE_H
+#define LLVM_TRANSFORMS_CGPROFILE_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class CGProfilePass : public PassInfoMixin<CGProfilePass> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+
+private:
+ void addModuleFlags(
+ Module &M,
+ MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const;
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_CGPROFILE_H
diff --git a/contrib/llvm/include/llvm/Transforms/GCOVProfiler.h b/contrib/llvm/include/llvm/Transforms/Instrumentation/GCOVProfiler.h
index 66bd75c88e24..dd55fbe29eed 100644
--- a/contrib/llvm/include/llvm/Transforms/GCOVProfiler.h
+++ b/contrib/llvm/include/llvm/Transforms/Instrumentation/GCOVProfiler.h
@@ -1,4 +1,4 @@
-//===- Transforms/GCOVProfiler.h - GCOVProfiler pass ----------*- C++ -*-===//
+//===- Transforms/Instrumentation/GCOVProfiler.h ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/include/llvm/Transforms/InstrProfiling.h b/contrib/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h
index 0fe6ad5eeac7..13fb3db4ae6f 100644
--- a/contrib/llvm/include/llvm/Transforms/InstrProfiling.h
+++ b/contrib/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h
@@ -1,4 +1,4 @@
-//===- Transforms/InstrProfiling.h - Instrumentation passes -----*- C++ -*-===//
+//===- Transforms/Instrumentation/InstrProfiling.h --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -109,7 +109,8 @@ private:
void emitRegistration();
/// Emit the necessary plumbing to pull in the runtime initialization.
- void emitRuntimeHook();
+ /// Returns true if a change was made.
+ bool emitRuntimeHook();
/// Add uses of our data variables and runtime hook.
void emitUses();
diff --git a/contrib/llvm/include/llvm/Transforms/PGOInstrumentation.h b/contrib/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h
index c2cc76c422da..c0b37c470b74 100644
--- a/contrib/llvm/include/llvm/Transforms/PGOInstrumentation.h
+++ b/contrib/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h
@@ -1,4 +1,4 @@
-//===- Transforms/PGOInstrumentation.h - PGO gen/use passes -----*- C++ -*-===//
+//===- Transforms/Instrumentation/PGOInstrumentation.h ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar.h b/contrib/llvm/include/llvm/Transforms/Scalar.h
index 49186bc5cd66..9491e1bbac93 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar.h
@@ -80,7 +80,6 @@ FunctionPass *createDeadStoreEliminationPass();
// values.
FunctionPass *createCallSiteSplittingPass();
-
//===----------------------------------------------------------------------===//
//
// AggressiveDCE - This pass uses the SSA based Aggressive DCE algorithm. This
@@ -89,7 +88,6 @@ FunctionPass *createCallSiteSplittingPass();
//
FunctionPass *createAggressiveDCEPass();
-
//===----------------------------------------------------------------------===//
//
// GuardWidening - An optimization over the @llvm.experimental.guard intrinsic
@@ -101,6 +99,16 @@ FunctionPass *createGuardWideningPass();
//===----------------------------------------------------------------------===//
//
+// LoopGuardWidening - Analogous to the GuardWidening pass, but restricted to a
+// single loop at a time for use within a LoopPassManager. Desired effect is
+// to widen guards into preheader or a single guard within loop if that's not
+// possible.
+//
+Pass *createLoopGuardWideningPass();
+
+
+//===----------------------------------------------------------------------===//
+//
// BitTrackingDCE - This pass uses a bit-tracking DCE algorithm in order to
// remove computations of dead bits.
//
@@ -128,20 +136,6 @@ Pass *createIndVarSimplifyPass();
//===----------------------------------------------------------------------===//
//
-// InstructionCombining - Combine instructions to form fewer, simple
-// instructions. This pass does not modify the CFG, and has a tendency to make
-// instructions dead, so a subsequent DCE pass is useful.
-//
-// This pass combines things like:
-// %Y = add int 1, %X
-// %Z = add int 1, %Y
-// into:
-// %Z = add int 2, %X
-//
-FunctionPass *createInstructionCombiningPass(bool ExpensiveCombines = true);
-
-//===----------------------------------------------------------------------===//
-//
// LICM - This pass is a loop invariant code motion and memory promotion pass.
//
Pass *createLICMPass();
@@ -198,6 +192,12 @@ Pass *createSimpleLoopUnrollPass(int OptLevel = 2);
//===----------------------------------------------------------------------===//
//
+// LoopUnrollAndJam - This pass is a simple loop unroll and jam pass.
+//
+Pass *createLoopUnrollAndJamPass(int OptLevel = 2);
+
+//===----------------------------------------------------------------------===//
+//
// LoopReroll - This pass is a simple loop rerolling pass.
//
Pass *createLoopRerollPass();
@@ -222,20 +222,6 @@ Pass *createLoopVersioningLICMPass();
//===----------------------------------------------------------------------===//
//
-// PromoteMemoryToRegister - This pass is used to promote memory references to
-// be register references. A simple example of the transformation performed by
-// this pass is:
-//
-// FROM CODE TO CODE
-// %X = alloca i32, i32 1 ret i32 42
-// store i32 42, i32 *%X
-// %Y = load i32* %X
-// ret i32 %Y
-//
-FunctionPass *createPromoteMemoryToRegisterPass();
-
-//===----------------------------------------------------------------------===//
-//
// DemoteRegisterToMemoryPass - This pass is used to demote registers to memory
// references. In basically undoes the PromoteMemoryToRegister pass to make cfg
// hacking easier.
@@ -288,31 +274,6 @@ Pass *createStructurizeCFGPass(bool SkipUniformRegions = false);
//===----------------------------------------------------------------------===//
//
-// BreakCriticalEdges - Break all of the critical edges in the CFG by inserting
-// a dummy basic block. This pass may be "required" by passes that cannot deal
-// with critical edges. For this usage, a pass must call:
-//
-// AU.addRequiredID(BreakCriticalEdgesID);
-//
-// This pass obviously invalidates the CFG, but can update forward dominator
-// (set, immediate dominators, tree, and frontier) information.
-//
-FunctionPass *createBreakCriticalEdgesPass();
-extern char &BreakCriticalEdgesID;
-
-//===----------------------------------------------------------------------===//
-//
-// LoopSimplify - Insert Pre-header blocks into the CFG for every function in
-// the module. This pass updates dominator information, loop information, and
-// does not add critical edges to the CFG.
-//
-// AU.addRequiredID(LoopSimplifyID);
-//
-Pass *createLoopSimplifyPass();
-extern char &LoopSimplifyID;
-
-//===----------------------------------------------------------------------===//
-//
// TailCallElimination - This pass eliminates call instructions to the current
// function which occur immediately before return instructions.
//
@@ -320,30 +281,6 @@ FunctionPass *createTailCallEliminationPass();
//===----------------------------------------------------------------------===//
//
-// LowerSwitch - This pass converts SwitchInst instructions into a sequence of
-// chained binary branch instructions.
-//
-FunctionPass *createLowerSwitchPass();
-extern char &LowerSwitchID;
-
-//===----------------------------------------------------------------------===//
-//
-// LowerInvoke - This pass removes invoke instructions, converting them to call
-// instructions.
-//
-FunctionPass *createLowerInvokePass();
-extern char &LowerInvokePassID;
-
-//===----------------------------------------------------------------------===//
-//
-// LCSSA - This pass inserts phi nodes at loop boundaries to simplify other loop
-// optimizations.
-//
-Pass *createLCSSAPass();
-extern char &LCSSAID;
-
-//===----------------------------------------------------------------------===//
-//
// EarlyCSE - This pass performs a simple and fast CSE pass over the dominator
// tree.
//
@@ -405,13 +342,6 @@ FunctionPass *createConstantHoistingPass();
//===----------------------------------------------------------------------===//
//
-// InstructionNamer - Give any unnamed non-void instructions "tmp" names.
-//
-FunctionPass *createInstructionNamerPass();
-extern char &InstructionNamerID;
-
-//===----------------------------------------------------------------------===//
-//
// Sink - Code Sinking
//
FunctionPass *createSinkingPass();
@@ -451,13 +381,6 @@ extern char &InferAddressSpacesID;
//===----------------------------------------------------------------------===//
//
-// InstructionSimplifier - Remove redundant instructions.
-//
-FunctionPass *createInstructionSimplifierPass();
-extern char &InstructionSimplifierID;
-
-//===----------------------------------------------------------------------===//
-//
// LowerExpectIntrinsics - Removes llvm.expect intrinsics and creates
// "block_weights" metadata.
FunctionPass *createLowerExpectIntrinsicPass();
@@ -477,16 +400,9 @@ FunctionPass *createScalarizerPass();
//===----------------------------------------------------------------------===//
//
-// AddDiscriminators - Add DWARF path discriminators to the IR.
-FunctionPass *createAddDiscriminatorsPass();
-
-//===----------------------------------------------------------------------===//
-//
// SeparateConstOffsetFromGEP - Split GEPs for better CSE
//
-FunctionPass *
-createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr,
- bool LowerGEP = false);
+FunctionPass *createSeparateConstOffsetFromGEPPass(bool LowerGEP = false);
//===----------------------------------------------------------------------===//
//
@@ -525,13 +441,6 @@ ModulePass *createRewriteStatepointsForGCLegacyPass();
//===----------------------------------------------------------------------===//
//
-// StripGCRelocates - Remove GC relocates that have been inserted by
-// RewriteStatepointsForGC. The resulting IR is incorrect, but this is useful
-// for manual inspection.
-FunctionPass *createStripGCRelocatesPass();
-
-//===----------------------------------------------------------------------===//
-//
// Float2Int - Demote floats to ints where possible.
//
FunctionPass *createFloat2IntPass();
@@ -556,13 +465,6 @@ FunctionPass *createLoopLoadEliminationPass();
//===----------------------------------------------------------------------===//
//
-// LoopSimplifyCFG - This pass performs basic CFG simplification on loops,
-// primarily to help other loop passes.
-//
-Pass *createLoopSimplifyCFGPass();
-
-//===----------------------------------------------------------------------===//
-//
// LoopVersioning - Perform loop multi-versioning.
//
FunctionPass *createLoopVersioningPass();
@@ -585,13 +487,10 @@ FunctionPass *createLibCallsShrinkWrapPass();
//===----------------------------------------------------------------------===//
//
-// EntryExitInstrumenter pass - Instrument function entry/exit with calls to
-// mcount(), @__cyg_profile_func_{enter,exit} and the like. There are two
-// variants, intended to run pre- and post-inlining, respectively.
+// LoopSimplifyCFG - This pass performs basic CFG simplification on loops,
+// primarily to help other loop passes.
//
-FunctionPass *createEntryExitInstrumenterPass();
-FunctionPass *createPostInlineEntryExitInstrumenterPass();
-
+Pass *createLoopSimplifyCFGPass();
} // End llvm namespace
#endif
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h b/contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h
index f75dc4dc331d..61975036e9ff 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h
@@ -33,12 +33,6 @@ struct AlignmentFromAssumptionsPass
bool runImpl(Function &F, AssumptionCache &AC, ScalarEvolution *SE_,
DominatorTree *DT_);
- // For memory transfers, we need a common alignment for both the source and
- // destination. If we have a new alignment for only one operand of a transfer
- // instruction, save it in these maps. If we reach the other operand through
- // another assumption later, then we may change the alignment at that point.
- DenseMap<MemTransferInst *, unsigned> NewDestAlignments, NewSrcAlignments;
-
ScalarEvolution *SE = nullptr;
DominatorTree *DT = nullptr;
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h b/contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h
index 5ab951a49f2c..b2ca2a1c09ae 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h
@@ -21,7 +21,7 @@
namespace llvm {
struct CallSiteSplittingPass : PassInfoMixin<CallSiteSplittingPass> {
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
} // end namespace llvm
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h b/contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h
index d3322dc1c414..84589bf4db99 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h
@@ -60,7 +60,7 @@ class TargetTransformInfo;
/// clients.
namespace consthoist {
-/// \brief Keeps track of the user of a constant and the operand index where the
+/// Keeps track of the user of a constant and the operand index where the
/// constant is used.
struct ConstantUser {
Instruction *Inst;
@@ -71,7 +71,7 @@ struct ConstantUser {
using ConstantUseListType = SmallVector<ConstantUser, 8>;
-/// \brief Keeps track of a constant candidate and its uses.
+/// Keeps track of a constant candidate and its uses.
struct ConstantCandidate {
ConstantUseListType Uses;
ConstantInt *ConstInt;
@@ -79,14 +79,14 @@ struct ConstantCandidate {
ConstantCandidate(ConstantInt *ConstInt) : ConstInt(ConstInt) {}
- /// \brief Add the user to the use list and update the cost.
+ /// Add the user to the use list and update the cost.
void addUser(Instruction *Inst, unsigned Idx, unsigned Cost) {
CumulativeCost += Cost;
Uses.push_back(ConstantUser(Inst, Idx));
}
};
-/// \brief This represents a constant that has been rebased with respect to a
+/// This represents a constant that has been rebased with respect to a
/// base constant. The difference to the base constant is recorded in Offset.
struct RebasedConstantInfo {
ConstantUseListType Uses;
@@ -98,7 +98,7 @@ struct RebasedConstantInfo {
using RebasedConstantListType = SmallVector<RebasedConstantInfo, 4>;
-/// \brief A base constant and all its rebased constants.
+/// A base constant and all its rebased constants.
struct ConstantInfo {
ConstantInt *BaseConstant;
RebasedConstantListType RebasedConstants;
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h b/contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h
index dca3b2dbf04f..faf03a4ec489 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h
@@ -21,7 +21,7 @@ namespace llvm {
class Function;
-/// \brief A simple and fast domtree-based CSE pass.
+/// 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
@@ -31,7 +31,7 @@ class Function;
struct EarlyCSEPass : PassInfoMixin<EarlyCSEPass> {
EarlyCSEPass(bool UseMemorySSA = false) : UseMemorySSA(UseMemorySSA) {}
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
bool UseMemorySSA;
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/GVN.h b/contrib/llvm/include/llvm/Transforms/Scalar/GVN.h
index 440d3f67c35a..b9de07ec9279 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/GVN.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/GVN.h
@@ -69,7 +69,7 @@ class GVN : public PassInfoMixin<GVN> {
public:
struct Expression;
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
/// This removes the specified instruction from
@@ -291,17 +291,17 @@ private:
/// loads are eliminated by the pass.
FunctionPass *createGVNPass(bool NoLoads = false);
-/// \brief A simple and fast domtree-based GVN pass to hoist common expressions
+/// A simple and fast domtree-based GVN pass to hoist common expressions
/// from sibling branches.
struct GVNHoistPass : PassInfoMixin<GVNHoistPass> {
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Uses an "inverted" value numbering to decide the similarity of
+/// Uses an "inverted" value numbering to decide the similarity of
/// expressions and sinks similar expressions into successors.
struct GVNSinkPass : PassInfoMixin<GVNSinkPass> {
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h b/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h
index 99dae15a3ac0..8b346969b1e9 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h
@@ -159,7 +159,7 @@ public:
return ET > ET_BasicStart && ET < ET_BasicEnd;
}
- /// \brief Swap two operands. Used during GVN to put commutative operands in
+ /// Swap two operands. Used during GVN to put commutative operands in
/// order.
void swapOperands(unsigned First, unsigned Second) {
std::swap(Operands[First], Operands[Second]);
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h b/contrib/llvm/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h
new file mode 100644
index 000000000000..311c549b8326
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h
@@ -0,0 +1,31 @@
+//===- InductiveRangeCheckElimination.h - IRCE ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the interface for the Inductive Range Check Elimination
+// loop pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H
+#define LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H
+
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Scalar/LoopPassManager.h"
+
+namespace llvm {
+
+class IRCEPass : public PassInfoMixin<IRCEPass> {
+public:
+ PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
+ LoopStandardAnalysisResults &AR, LPMUpdater &U);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/InstSimplifyPass.h b/contrib/llvm/include/llvm/Transforms/Scalar/InstSimplifyPass.h
new file mode 100644
index 000000000000..da79a13eb7cf
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/InstSimplifyPass.h
@@ -0,0 +1,46 @@
+//===- InstSimplifyPass.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Defines passes for running instruction simplification across chunks of IR.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_INSTSIMPLIFYPASS_H
+#define LLVM_TRANSFORMS_UTILS_INSTSIMPLIFYPASS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class FunctionPass;
+
+/// Run instruction simplification across each instruction in the function.
+///
+/// Instruction simplification has useful constraints in some contexts:
+/// - It will never introduce *new* instructions.
+/// - There is no need to iterate to a fixed point.
+///
+/// Many passes use instruction simplification as a library facility, but it may
+/// also be useful (in tests and other contexts) to have access to this very
+/// restricted transform at a pass granularity. However, for a much more
+/// powerful and comprehensive peephole optimization engine, see the
+/// `instcombine` pass instead.
+class InstSimplifyPass : public PassInfoMixin<InstSimplifyPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+/// Create a legacy pass that does instruction simplification on each
+/// instruction in a function.
+FunctionPass *createInstSimplifyLegacyPass();
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_INSTSIMPLIFYPASS_H
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h b/contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h
index a9466713b8e6..b3493a292498 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h
@@ -34,6 +34,7 @@ class BinaryOperator;
class BranchInst;
class CmpInst;
class Constant;
+class DeferredDominance;
class Function;
class Instruction;
class IntrinsicInst;
@@ -77,6 +78,7 @@ class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> {
TargetLibraryInfo *TLI;
LazyValueInfo *LVI;
AliasAnalysis *AA;
+ DeferredDominance *DDT;
std::unique_ptr<BlockFrequencyInfo> BFI;
std::unique_ptr<BranchProbabilityInfo> BPI;
bool HasProfileData = false;
@@ -107,8 +109,8 @@ public:
// Glue for old PM.
bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_,
- AliasAnalysis *AA_, bool HasProfileData_,
- std::unique_ptr<BlockFrequencyInfo> BFI_,
+ AliasAnalysis *AA_, DeferredDominance *DDT_,
+ bool HasProfileData_, std::unique_ptr<BlockFrequencyInfo> BFI_,
std::unique_ptr<BranchProbabilityInfo> BPI_);
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h b/contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h
index 5eddd5fdc7e7..e1b33799578b 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h
@@ -15,7 +15,7 @@
namespace llvm {
-/// \brief Printer pass for the \c LoopAccessInfo results.
+/// Printer pass for the \c LoopAccessInfo results.
class LoopAccessInfoPrinterPass
: public PassInfoMixin<LoopAccessInfoPrinterPass> {
raw_ostream &OS;
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h b/contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h
index 12c7a030ff8b..e1ad67ac6fff 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h
@@ -24,7 +24,7 @@ class LoopDataPrefetchPass : public PassInfoMixin<LoopDataPrefetchPass> {
public:
LoopDataPrefetchPass() = default;
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
index 56a45ed34178..5f61c39b5530 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
@@ -71,7 +71,7 @@ PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
extern template class PassManager<Loop, LoopAnalysisManager,
LoopStandardAnalysisResults &, LPMUpdater &>;
-/// \brief The Loop pass manager.
+/// The Loop pass manager.
///
/// See the documentation for the PassManager template for details. It runs
/// a sequence of Loop passes over each Loop that the manager is run over. This
@@ -253,7 +253,7 @@ private:
: Worklist(Worklist), LAM(LAM) {}
};
-/// \brief Adaptor that maps from a function to its loops.
+/// Adaptor that maps from a function to its loops.
///
/// Designed to allow composition of a LoopPass(Manager) and a
/// FunctionPassManager. Note that if this pass is constructed with a \c
@@ -270,7 +270,7 @@ public:
LoopCanonicalizationFPM.addPass(LCSSAPass());
}
- /// \brief Runs the loop passes across every loop in the function.
+ /// Runs the loop passes across every loop in the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
// Before we even compute any loop analyses, first run a miniature function
// pass pipeline to put loops into their canonical form. Note that we can
@@ -381,7 +381,7 @@ private:
FunctionPassManager LoopCanonicalizationFPM;
};
-/// \brief A function to deduce a loop pass type and wrap it in the templated
+/// A function to deduce a loop pass type and wrap it in the templated
/// adaptor.
template <typename LoopPassT>
FunctionToLoopPassAdaptor<LoopPassT>
@@ -389,7 +389,7 @@ createFunctionToLoopPassAdaptor(LoopPassT Pass, bool DebugLogging = false) {
return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass), DebugLogging);
}
-/// \brief Pass for printing a loop's contents as textual IR.
+/// Pass for printing a loop's contents as textual IR.
class PrintLoopPass : public PassInfoMixin<PrintLoopPass> {
raw_ostream &OS;
std::string Banner;
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h b/contrib/llvm/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h
new file mode 100644
index 000000000000..fc69aa361059
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h
@@ -0,0 +1,35 @@
+//===- LoopUnrollAndJamPass.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_TRANSFORMS_SCALAR_LOOPUNROLLANDJAMPASS_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPUNROLLANDJAMPASS_H
+
+#include "llvm/Analysis/LoopAnalysisManager.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class Loop;
+struct LoopStandardAnalysisResults;
+class LPMUpdater;
+
+/// A simple loop rotation transformation.
+class LoopUnrollAndJamPass : public PassInfoMixin<LoopUnrollAndJamPass> {
+ const int OptLevel;
+
+public:
+ explicit LoopUnrollAndJamPass(int OptLevel = 2) : OptLevel(OptLevel) {}
+ PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
+ LoopStandardAnalysisResults &AR, LPMUpdater &U);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPUNROLLANDJAMPASS_H
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h b/contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
index ab9dec0311b2..b6ee6523697c 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
@@ -22,7 +22,7 @@
namespace llvm {
struct LowerExpectIntrinsicPass : PassInfoMixin<LowerExpectIntrinsicPass> {
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
///
/// This will lower all of the expect intrinsic calls in this function into
/// branch weight metadata. That metadata will subsequently feed the analysis
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h b/contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h
index 3cad7bb070d0..48df09cdec9e 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
//! \file
-//! \brief This pass performs merges of loads and stores on both sides of a
+//! This pass performs merges of loads and stores on both sides of a
// diamond (hammock). It hoists the loads and sinks the stores.
//
// The algorithm iteratively hoists two loads to the same address out of a
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h b/contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h
index 05db25502dc3..3f7541863a19 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h
@@ -23,7 +23,7 @@ class Function;
class NewGVNPass : public PassInfoMixin<NewGVNPass> {
public:
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h b/contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h
index 9997dfa5b6f3..ba7586dffd9d 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h
@@ -29,6 +29,7 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
+#include <deque>
namespace llvm {
@@ -54,7 +55,7 @@ inline bool operator<(const ValueEntry &LHS, const ValueEntry &RHS) {
return LHS.Rank > RHS.Rank; // Sort so that highest rank goes to start.
}
-/// \brief Utility class representing a base and exponent pair which form one
+/// Utility class representing a base and exponent pair which form one
/// factor of some product.
struct Factor {
Value *Base;
@@ -69,9 +70,14 @@ class XorOpnd;
/// Reassociate commutative expressions.
class ReassociatePass : public PassInfoMixin<ReassociatePass> {
+public:
+ using OrderedSet =
+ SetVector<AssertingVH<Instruction>, std::deque<AssertingVH<Instruction>>>;
+
+protected:
DenseMap<BasicBlock *, unsigned> RankMap;
DenseMap<AssertingVH<Value>, unsigned> ValueRankMap;
- SetVector<AssertingVH<Instruction>> RedoInsts;
+ OrderedSet RedoInsts;
// Arbitrary, but prevents quadratic behavior.
static const unsigned GlobalReassociateLimit = 10;
@@ -108,8 +114,7 @@ private:
SmallVectorImpl<reassociate::ValueEntry> &Ops);
Value *RemoveFactorFromExpression(Value *V, Value *Factor);
void EraseInst(Instruction *I);
- void RecursivelyEraseDeadInsts(Instruction *I,
- SetVector<AssertingVH<Instruction>> &Insts);
+ void RecursivelyEraseDeadInsts(Instruction *I, OrderedSet &Insts);
void OptimizeInst(Instruction *I);
Instruction *canonicalizeNegConstExpr(Instruction *I);
void BuildPairMap(ReversePostOrderTraversal<Function *> &RPOT);
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h b/contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h
index b93287fff907..2a294c95a17b 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h
@@ -21,6 +21,10 @@
#ifndef LLVM_TRANSFORMS_SCALAR_SCCP_H
#define LLVM_TRANSFORMS_SCALAR_SCCP_H
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
@@ -33,6 +37,7 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
+bool runIPSCCP(Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI);
} // end namespace llvm
#endif // LLVM_TRANSFORMS_SCALAR_SCCP_H
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SROA.h b/contrib/llvm/include/llvm/Transforms/Scalar/SROA.h
index 4a321e75c68b..b36c6f492be1 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/SROA.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/SROA.h
@@ -45,7 +45,7 @@ class SROALegacyPass;
} // end namespace sroa
-/// \brief An optimization pass providing Scalar Replacement of Aggregates.
+/// An optimization pass providing Scalar Replacement of Aggregates.
///
/// This pass takes allocations which can be completely analyzed (that is, they
/// don't escape) and tries to turn them into scalar SSA values. There are
@@ -68,7 +68,7 @@ class SROA : public PassInfoMixin<SROA> {
DominatorTree *DT = nullptr;
AssumptionCache *AC = nullptr;
- /// \brief Worklist of alloca instructions to simplify.
+ /// Worklist of alloca instructions to simplify.
///
/// Each alloca in the function is added to this. Each new alloca formed gets
/// added to it as well to recursively simplify unless that alloca can be
@@ -77,12 +77,12 @@ class SROA : public PassInfoMixin<SROA> {
/// already present to ensure it is re-visited.
SetVector<AllocaInst *, SmallVector<AllocaInst *, 16>> Worklist;
- /// \brief A collection of instructions to delete.
+ /// A collection of instructions to delete.
/// We try to batch deletions to simplify code and make things a bit more
/// efficient.
SetVector<Instruction *, SmallVector<Instruction *, 8>> DeadInsts;
- /// \brief Post-promotion worklist.
+ /// Post-promotion worklist.
///
/// Sometimes we discover an alloca which has a high probability of becoming
/// viable for SROA after a round of promotion takes place. In those cases,
@@ -92,17 +92,17 @@ class SROA : public PassInfoMixin<SROA> {
/// the event they are deleted.
SetVector<AllocaInst *, SmallVector<AllocaInst *, 16>> PostPromotionWorklist;
- /// \brief A collection of alloca instructions we can directly promote.
+ /// A collection of alloca instructions we can directly promote.
std::vector<AllocaInst *> PromotableAllocas;
- /// \brief A worklist of PHIs to speculate prior to promoting allocas.
+ /// A worklist of PHIs to speculate prior to promoting allocas.
///
/// All of these PHIs have been checked for the safety of speculation and by
/// being speculated will allow promoting allocas currently in the promotable
/// queue.
SetVector<PHINode *, SmallVector<PHINode *, 2>> SpeculatablePHIs;
- /// \brief A worklist of select instructions to speculate prior to promoting
+ /// A worklist of select instructions to speculate prior to promoting
/// allocas.
///
/// All of these select instructions have been checked for the safety of
@@ -113,7 +113,7 @@ class SROA : public PassInfoMixin<SROA> {
public:
SROA() = default;
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
private:
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h b/contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h
index 63bfe6373d04..eed50ec96161 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h
@@ -17,9 +17,9 @@
namespace llvm {
-/// This pass transforms loops that contain branches on loop-invariant
-/// conditions to have multiple loops. For example, it turns the left into the
-/// right code:
+/// This pass transforms loops that contain branches or switches on loop-
+/// invariant conditions to have multiple loops. For example, it turns the left
+/// into the right code:
///
/// for (...) if (lic)
/// A for (...)
@@ -35,6 +35,31 @@ namespace llvm {
/// This pass expects LICM to be run before it to hoist invariant conditions out
/// of the loop, to make the unswitching opportunity obvious.
///
+/// There is a taxonomy of unswitching that we use to classify different forms
+/// of this transformaiton:
+///
+/// - Trival unswitching: this is when the condition can be unswitched without
+/// cloning any code from inside the loop. A non-trivial unswitch requires
+/// code duplication.
+///
+/// - Full unswitching: this is when the branch or switch is completely moved
+/// from inside the loop to outside the loop. Partial unswitching removes the
+/// branch from the clone of the loop but must leave a (somewhat simplified)
+/// branch in the original loop. While theoretically partial unswitching can
+/// be done for switches, the requirements are extreme - we need the loop
+/// invariant input to the switch to be sufficient to collapse to a single
+/// successor in each clone.
+///
+/// This pass always does trivial, full unswitching for both branches and
+/// switches. For branches, it also always does trivial, partial unswitching.
+///
+/// If enabled (via the constructor's `NonTrivial` parameter), this pass will
+/// additionally do non-trivial, full unswitching for branches and switches, and
+/// will do non-trivial, partial unswitching for branches.
+///
+/// Because partial unswitching of switches is extremely unlikely to be possible
+/// in practice and significantly complicates the implementation, this pass does
+/// not currently implement that in any mode.
class SimpleLoopUnswitchPass : public PassInfoMixin<SimpleLoopUnswitchPass> {
bool NonTrivial;
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h b/contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h
index 1afb9c7f954f..ce0a35fc06bd 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h
@@ -15,9 +15,9 @@
#ifndef LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H
#define LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
-#include "llvm/Transforms/Utils/Local.h"
namespace llvm {
@@ -46,7 +46,7 @@ public:
/// Construct a pass with optional optimizations.
SimplifyCFGPass(const SimplifyCFGOptions &PassOptions);
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h b/contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h
index f39e03d22d65..4a0bfd754723 100644
--- a/contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h
+++ b/contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h
@@ -102,7 +102,7 @@ namespace llvm {
/// here are relatively simple ones around execution and codesize cost, without
/// any need to consider simplifications or other transformations.
struct SpeculateAroundPHIsPass : PassInfoMixin<SpeculateAroundPHIsPass> {
- /// \brief Run the pass over the function.
+ /// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
diff --git a/contrib/llvm/include/llvm/Transforms/Utils.h b/contrib/llvm/include/llvm/Transforms/Utils.h
new file mode 100644
index 000000000000..0d997ce17b83
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/Utils.h
@@ -0,0 +1,118 @@
+//===- llvm/Transforms/Utils.h - Utility Transformations --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file defines prototypes for accessor functions that expose passes
+// in the Utils transformations library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_H
+#define LLVM_TRANSFORMS_UTILS_H
+
+namespace llvm {
+
+class ModulePass;
+class FunctionPass;
+class Pass;
+
+//===----------------------------------------------------------------------===//
+// createMetaRenamerPass - Rename everything with metasyntatic names.
+//
+ModulePass *createMetaRenamerPass();
+
+//===----------------------------------------------------------------------===//
+//
+// LowerInvoke - This pass removes invoke instructions, converting them to call
+// instructions.
+//
+FunctionPass *createLowerInvokePass();
+extern char &LowerInvokePassID;
+
+//===----------------------------------------------------------------------===//
+//
+// InstructionNamer - Give any unnamed non-void instructions "tmp" names.
+//
+FunctionPass *createInstructionNamerPass();
+extern char &InstructionNamerID;
+
+//===----------------------------------------------------------------------===//
+//
+// LowerSwitch - This pass converts SwitchInst instructions into a sequence of
+// chained binary branch instructions.
+//
+FunctionPass *createLowerSwitchPass();
+extern char &LowerSwitchID;
+
+//===----------------------------------------------------------------------===//
+//
+// EntryExitInstrumenter pass - Instrument function entry/exit with calls to
+// mcount(), @__cyg_profile_func_{enter,exit} and the like. There are two
+// variants, intended to run pre- and post-inlining, respectively.
+//
+FunctionPass *createEntryExitInstrumenterPass();
+FunctionPass *createPostInlineEntryExitInstrumenterPass();
+
+//===----------------------------------------------------------------------===//
+//
+// BreakCriticalEdges - Break all of the critical edges in the CFG by inserting
+// a dummy basic block. This pass may be "required" by passes that cannot deal
+// with critical edges. For this usage, a pass must call:
+//
+// AU.addRequiredID(BreakCriticalEdgesID);
+//
+// This pass obviously invalidates the CFG, but can update forward dominator
+// (set, immediate dominators, tree, and frontier) information.
+//
+FunctionPass *createBreakCriticalEdgesPass();
+extern char &BreakCriticalEdgesID;
+
+//===----------------------------------------------------------------------===//
+//
+// LCSSA - This pass inserts phi nodes at loop boundaries to simplify other loop
+// optimizations.
+//
+Pass *createLCSSAPass();
+extern char &LCSSAID;
+
+//===----------------------------------------------------------------------===//
+//
+// AddDiscriminators - Add DWARF path discriminators to the IR.
+FunctionPass *createAddDiscriminatorsPass();
+
+//===----------------------------------------------------------------------===//
+//
+// PromoteMemoryToRegister - This pass is used to promote memory references to
+// be register references. A simple example of the transformation performed by
+// this pass is:
+//
+// FROM CODE TO CODE
+// %X = alloca i32, i32 1 ret i32 42
+// store i32 42, i32 *%X
+// %Y = load i32* %X
+// ret i32 %Y
+//
+FunctionPass *createPromoteMemoryToRegisterPass();
+
+//===----------------------------------------------------------------------===//
+//
+// LoopSimplify - Insert Pre-header blocks into the CFG for every function in
+// the module. This pass updates dominator information, loop information, and
+// does not add critical edges to the CFG.
+//
+// AU.addRequiredID(LoopSimplifyID);
+//
+Pass *createLoopSimplifyPass();
+extern char &LoopSimplifyID;
+
+/// This function returns a new pass that downgrades the debug info in the
+/// module to line tables only.
+ModulePass *createStripNonLineTableDebugInfoPass();
+}
+
+#endif
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 74f75509f550..3dfc73b64842 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -27,6 +27,7 @@ namespace llvm {
class BlockFrequencyInfo;
class BranchProbabilityInfo;
+class DeferredDominance;
class DominatorTree;
class Function;
class Instruction;
@@ -38,7 +39,7 @@ class TargetLibraryInfo;
class Value;
/// Delete the specified block, which must have no predecessors.
-void DeleteDeadBlock(BasicBlock *BB);
+void DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT = nullptr);
/// We know that BB has one predecessor. If there are any single-entry PHI nodes
/// in it, fold them away. This handles the case when all entries to the PHI
@@ -57,7 +58,8 @@ bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr);
/// value indicates success or failure.
bool MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT = nullptr,
LoopInfo *LI = nullptr,
- MemoryDependenceResults *MemDep = nullptr);
+ MemoryDependenceResults *MemDep = nullptr,
+ DeferredDominance *DDT = nullptr);
/// Replace all uses of an instruction (specified by BI) with a value, then
/// remove and delete the original instruction.
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
index a067a685b837..bdcdf6f361f2 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -15,6 +15,7 @@
#ifndef LLVM_TRANSFORMS_UTILS_BUILDLIBCALLS_H
#define LLVM_TRANSFORMS_UTILS_BUILDLIBCALLS_H
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"
namespace llvm {
@@ -29,6 +30,12 @@ namespace llvm {
/// Returns true if any attributes were set and false otherwise.
bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI);
+ /// Check whether the overloaded unary floating point function
+ /// corresponding to \a Ty is available.
+ bool hasUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty,
+ LibFunc DoubleFn, LibFunc FloatFn,
+ LibFunc LongDoubleFn);
+
/// Return V if it is an i8*, otherwise cast it to i8*.
Value *castToCStr(Value *V, IRBuilder<> &B);
@@ -104,15 +111,54 @@ namespace llvm {
Value *emitFPutC(Value *Char, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);
- /// Emit a call to the puts function. Str is required to be a pointer and
+ /// Emit a call to the fputc_unlocked function. This assumes that Char is an
+ /// i32, and File is a pointer to FILE.
+ Value *emitFPutCUnlocked(Value *Char, Value *File, IRBuilder<> &B,
+ const TargetLibraryInfo *TLI);
+
+ /// Emit a call to the fputs function. Str is required to be a pointer and
/// File is a pointer to FILE.
Value *emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);
+ /// Emit a call to the fputs_unlocked function. Str is required to be a
+ /// pointer and File is a pointer to FILE.
+ Value *emitFPutSUnlocked(Value *Str, Value *File, IRBuilder<> &B,
+ const TargetLibraryInfo *TLI);
+
/// Emit a call to the fwrite function. This assumes that Ptr is a pointer,
/// Size is an 'intptr_t', and File is a pointer to FILE.
Value *emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
const DataLayout &DL, const TargetLibraryInfo *TLI);
+
+ /// Emit a call to the malloc function.
+ Value *emitMalloc(Value *Num, IRBuilder<> &B, const DataLayout &DL,
+ const TargetLibraryInfo *TLI);
+
+ /// Emit a call to the calloc function.
+ Value *emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs,
+ IRBuilder<> &B, const TargetLibraryInfo &TLI);
+
+ /// Emit a call to the fwrite_unlocked function. This assumes that Ptr is a
+ /// pointer, Size is an 'intptr_t', N is nmemb and File is a pointer to FILE.
+ Value *emitFWriteUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
+ IRBuilder<> &B, const DataLayout &DL,
+ const TargetLibraryInfo *TLI);
+
+ /// Emit a call to the fgetc_unlocked function. File is a pointer to FILE.
+ Value *emitFGetCUnlocked(Value *File, IRBuilder<> &B,
+ const TargetLibraryInfo *TLI);
+
+ /// Emit a call to the fgets_unlocked function. Str is required to be a
+ /// pointer, Size is an i32 and File is a pointer to FILE.
+ Value *emitFGetSUnlocked(Value *Str, Value *Size, Value *File, IRBuilder<> &B,
+ const TargetLibraryInfo *TLI);
+
+ /// Emit a call to the fread_unlocked function. This assumes that Ptr is a
+ /// pointer, Size is an 'intptr_t', N is nmemb and File is a pointer to FILE.
+ Value *emitFReadUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
+ IRBuilder<> &B, const DataLayout &DL,
+ const TargetLibraryInfo *TLI);
}
#endif
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h
index 178bae76cef6..7531fb2d69b3 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h
@@ -49,15 +49,15 @@ class ReturnInst;
/// Return an exact copy of the specified module
///
-std::unique_ptr<Module> CloneModule(const Module *M);
-std::unique_ptr<Module> CloneModule(const Module *M, ValueToValueMapTy &VMap);
+std::unique_ptr<Module> CloneModule(const Module &M);
+std::unique_ptr<Module> CloneModule(const Module &M, ValueToValueMapTy &VMap);
/// Return a copy of the specified module. The ShouldCloneDefinition function
/// controls whether a specific GlobalValue's definition is cloned. If the
/// function returns false, the module copy will contain an external reference
/// in place of the global definition.
std::unique_ptr<Module>
-CloneModule(const Module *M, ValueToValueMapTy &VMap,
+CloneModule(const Module &M, ValueToValueMapTy &VMap,
function_ref<bool(const GlobalValue *)> ShouldCloneDefinition);
/// ClonedCodeInfo - This struct can be used to capture information about code
@@ -240,7 +240,7 @@ bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
AAResults *CalleeAAR = nullptr, bool InsertLifetime = true,
Function *ForwardVarArgsTo = nullptr);
-/// \brief Clones a loop \p OrigLoop. Returns the loop and the blocks in \p
+/// Clones a loop \p OrigLoop. Returns the loop and the blocks in \p
/// Blocks.
///
/// Updates LoopInfo and DominatorTree assuming the loop is dominated by block
@@ -252,7 +252,7 @@ Loop *cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB,
DominatorTree *DT,
SmallVectorImpl<BasicBlock *> &Blocks);
-/// \brief Remaps instructions in \p Blocks using the mapping in \p VMap.
+/// Remaps instructions in \p Blocks using the mapping in \p VMap.
void remapInstructionsInBlocks(const SmallVectorImpl<BasicBlock *> &Blocks,
ValueToValueMapTy &VMap);
@@ -265,7 +265,8 @@ void remapInstructionsInBlocks(const SmallVectorImpl<BasicBlock *> &Blocks,
BasicBlock *
DuplicateInstructionsInSplitBetween(BasicBlock *BB, BasicBlock *PredBB,
Instruction *StopAt,
- ValueToValueMapTy &ValueMapping);
+ ValueToValueMapTy &ValueMapping,
+ DominatorTree *DT = nullptr);
} // end namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_CLONING_H
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h b/contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h
index 63d34511102d..fab8334d4c66 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h
@@ -34,7 +34,7 @@ class Module;
class Type;
class Value;
- /// \brief Utility class for extracting code into a new function.
+ /// Utility class for extracting code into a new function.
///
/// This utility provides a simple interface for extracting some sequence of
/// code into its own function, replacing it with a call to that function. It
@@ -65,20 +65,22 @@ class Value;
Type *RetTy;
public:
- /// \brief Create a code extractor for a sequence of blocks.
+ /// Create a code extractor for a sequence of blocks.
///
/// Given a sequence of basic blocks where the first block in the sequence
/// dominates the rest, prepare a code extractor object for pulling this
/// sequence out into its new function. When a DominatorTree is also given,
/// extra checking and transformations are enabled. If AllowVarArgs is true,
/// vararg functions can be extracted. This is safe, if all vararg handling
- /// code is extracted, including vastart.
+ /// code is extracted, including vastart. If AllowAlloca is true, then
+ /// extraction of blocks containing alloca instructions would be possible,
+ /// however code extractor won't validate whether extraction is legal.
CodeExtractor(ArrayRef<BasicBlock *> BBs, DominatorTree *DT = nullptr,
bool AggregateArgs = false, BlockFrequencyInfo *BFI = nullptr,
BranchProbabilityInfo *BPI = nullptr,
- bool AllowVarArgs = false);
+ bool AllowVarArgs = false, bool AllowAlloca = false);
- /// \brief Create a code extractor for a loop body.
+ /// Create a code extractor for a loop body.
///
/// Behaves just like the generic code sequence constructor, but uses the
/// block sequence of the loop.
@@ -86,27 +88,19 @@ class Value;
BlockFrequencyInfo *BFI = nullptr,
BranchProbabilityInfo *BPI = nullptr);
- /// \brief Check to see if a block is valid for extraction.
- ///
- /// Blocks containing EHPads, allocas and invokes are not valid. If
- /// AllowVarArgs is true, blocks with vastart can be extracted. This is
- /// safe, if all vararg handling code is extracted, including vastart.
- static bool isBlockValidForExtraction(const BasicBlock &BB,
- bool AllowVarArgs);
-
- /// \brief Perform the extraction, returning the new function.
+ /// Perform the extraction, returning the new function.
///
/// Returns zero when called on a CodeExtractor instance where isEligible
/// returns false.
Function *extractCodeRegion();
- /// \brief Test whether this code extractor is eligible.
+ /// Test whether this code extractor is eligible.
///
/// Based on the blocks used when constructing the code extractor,
/// determine whether it is eligible for extraction.
bool isEligible() const { return !Blocks.empty(); }
- /// \brief Compute the set of input values and output values for the code.
+ /// Compute the set of input values and output values for the code.
///
/// These can be used either when performing the extraction or to evaluate
/// the expected size of a call to the extracted function. Note that this
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h b/contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h
index 0e987b93177a..9908ae6fd393 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
@@ -73,6 +74,18 @@ public:
ValueStack.back()[V] = C;
}
+ /// Given call site return callee and list of its formal arguments
+ Function *getCalleeWithFormalArgs(CallSite &CS,
+ SmallVector<Constant *, 8> &Formals);
+
+ /// Given call site and callee returns list of callee formal argument
+ /// values converting them when necessary
+ bool getFormalParams(CallSite &CS, Function *F,
+ SmallVector<Constant *, 8> &Formals);
+
+ /// Casts call result to a type of bitcast call expression
+ Constant *castCallResultIfNeeded(Value *CallExpr, Constant *RV);
+
const DenseMap<Constant*, Constant*> &getMutatedMemory() const {
return MutatedMemory;
}
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h b/contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h
index b7a3d130aa11..b55a9893bcf7 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h
@@ -22,7 +22,7 @@
namespace llvm {
class Module;
class Function;
-/// \brief Calculate and dump ThinLTO specific inliner stats.
+/// Calculate and dump ThinLTO specific inliner stats.
/// The main statistics are:
/// (1) Number of inlined imported functions,
/// (2) Number of imported functions inlined into importing module (indirect),
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h b/contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h
index 0ec3321b9cf8..5d9927eb51b2 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h
@@ -29,7 +29,7 @@ namespace llvm {
/// e.g. when more information about the operands are known. Implements both
/// 32bit and 64bit scalar division.
///
- /// @brief Replace Rem with generated code.
+ /// Replace Rem with generated code.
bool expandRemainder(BinaryOperator *Rem);
/// Generate code to divide two integers, replacing Div with the generated
@@ -38,7 +38,7 @@ namespace llvm {
/// when more information about the operands are known. Implements both
/// 32bit and 64bit scalar division.
///
- /// @brief Replace Div with generated code.
+ /// Replace Div with generated code.
bool expandDivision(BinaryOperator* Div);
/// Generate code to calculate the remainder of two integers, replacing Rem
@@ -46,26 +46,26 @@ namespace llvm {
/// makes it useful for targets with little or no support for less than
/// 32 bit arithmetic.
///
- /// @brief Replace Rem with generated code.
+ /// Replace Rem with generated code.
bool expandRemainderUpTo32Bits(BinaryOperator *Rem);
/// Generate code to calculate the remainder of two integers, replacing Rem
/// with the generated code. Uses ExpandReminder with a 64bit Rem.
///
- /// @brief Replace Rem with generated code.
+ /// Replace Rem with generated code.
bool expandRemainderUpTo64Bits(BinaryOperator *Rem);
/// Generate code to divide two integers, replacing Div with the generated
/// code. Uses ExpandDivision with a 32bit Div which makes it useful for
/// targets with little or no support for less than 32 bit arithmetic.
///
- /// @brief Replace Rem with generated code.
+ /// Replace Rem with generated code.
bool expandDivisionUpTo32Bits(BinaryOperator *Div);
/// Generate code to divide two integers, replacing Div with the generated
/// code. Uses ExpandDivision with a 64bit Div.
///
- /// @brief Replace Rem with generated code.
+ /// Replace Rem with generated code.
bool expandDivisionUpTo64Bits(BinaryOperator *Div);
} // End llvm namespace
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Local.h b/contrib/llvm/include/llvm/Transforms/Utils/Local.h
index 01db88bc15c2..b8df32565723 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/Local.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/Local.h
@@ -16,10 +16,12 @@
#define LLVM_TRANSFORMS_UTILS_LOCAL_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/Utils/Local.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
@@ -117,7 +119,8 @@ struct SimplifyCFGOptions {
/// conditions and indirectbr addresses this might make dead if
/// DeleteDeadConditions is true.
bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false,
- const TargetLibraryInfo *TLI = nullptr);
+ const TargetLibraryInfo *TLI = nullptr,
+ DeferredDominance *DDT = nullptr);
//===----------------------------------------------------------------------===//
// Local dead code elimination.
@@ -140,6 +143,18 @@ bool wouldInstructionBeTriviallyDead(Instruction *I,
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V,
const TargetLibraryInfo *TLI = nullptr);
+/// Delete all of the instructions in `DeadInsts`, and all other instructions
+/// that deleting these in turn causes to be trivially dead.
+///
+/// The initial instructions in the provided vector must all have empty use
+/// lists and satisfy `isInstructionTriviallyDead`.
+///
+/// `DeadInsts` will be used as scratch storage for this routine and will be
+/// empty afterward.
+void RecursivelyDeleteTriviallyDeadInstructions(
+ SmallVectorImpl<Instruction *> &DeadInsts,
+ const TargetLibraryInfo *TLI = nullptr);
+
/// If the specified value is an effectively dead PHI node, due to being a
/// def-use chain of single-use nodes that either forms a cycle or is terminated
/// by a trivially dead instruction, delete it. If that makes any of its
@@ -171,18 +186,21 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB,
///
/// .. and delete the predecessor corresponding to the '1', this will attempt to
/// recursively fold the 'and' to 0.
-void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred);
+void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
+ DeferredDominance *DDT = nullptr);
/// BB is a block with one predecessor and its predecessor is known to have one
/// successor (BB!). Eliminate the edge between them, moving the instructions in
/// the predecessor into BB. This deletes the predecessor block.
-void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr);
+void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr,
+ DeferredDominance *DDT = nullptr);
/// BB is known to contain an unconditional branch, and contains no instructions
/// other than PHI nodes, potential debug intrinsics and the branch. If
/// possible, eliminate BB by rewriting all the predecessors to branch to the
/// successor block and return true. If we can't transform, return false.
-bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB);
+bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
+ DeferredDominance *DDT = nullptr);
/// Check for and eliminate duplicate PHI nodes in this block. This doesn't try
/// to be clever about PHI nodes which differ only in the order of the incoming
@@ -246,72 +264,6 @@ inline unsigned getKnownAlignment(Value *V, const DataLayout &DL,
return getOrEnforceKnownAlignment(V, 0, DL, CxtI, AC, DT);
}
-/// Given a getelementptr instruction/constantexpr, emit the code necessary to
-/// compute the offset from the base pointer (without adding in the base
-/// pointer). Return the result as a signed integer of intptr size.
-/// When NoAssumptions is true, no assumptions about index computation not
-/// overflowing is made.
-template <typename IRBuilderTy>
-Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP,
- bool NoAssumptions = false) {
- GEPOperator *GEPOp = cast<GEPOperator>(GEP);
- Type *IntPtrTy = DL.getIntPtrType(GEP->getType());
- Value *Result = Constant::getNullValue(IntPtrTy);
-
- // If the GEP is inbounds, we know that none of the addressing operations will
- // overflow in an unsigned sense.
- bool isInBounds = GEPOp->isInBounds() && !NoAssumptions;
-
- // Build a mask for high order bits.
- unsigned IntPtrWidth = IntPtrTy->getScalarType()->getIntegerBitWidth();
- uint64_t PtrSizeMask =
- std::numeric_limits<uint64_t>::max() >> (64 - IntPtrWidth);
-
- gep_type_iterator GTI = gep_type_begin(GEP);
- for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e;
- ++i, ++GTI) {
- Value *Op = *i;
- uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask;
- if (Constant *OpC = dyn_cast<Constant>(Op)) {
- if (OpC->isZeroValue())
- continue;
-
- // Handle a struct index, which adds its field offset to the pointer.
- if (StructType *STy = GTI.getStructTypeOrNull()) {
- if (OpC->getType()->isVectorTy())
- OpC = OpC->getSplatValue();
-
- uint64_t OpValue = cast<ConstantInt>(OpC)->getZExtValue();
- Size = DL.getStructLayout(STy)->getElementOffset(OpValue);
-
- if (Size)
- Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size),
- GEP->getName()+".offs");
- continue;
- }
-
- Constant *Scale = ConstantInt::get(IntPtrTy, Size);
- Constant *OC = ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/);
- Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/);
- // Emit an add instruction.
- Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs");
- continue;
- }
- // Convert to correct type.
- if (Op->getType() != IntPtrTy)
- Op = Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c");
- if (Size != 1) {
- // We'll let instcombine(mul) convert this to a shl if possible.
- Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size),
- GEP->getName()+".idx", isInBounds /*NUW*/);
- }
-
- // Emit an add instruction.
- Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs");
- }
- return Result;
-}
-
///===---------------------------------------------------------------------===//
/// Dbg Intrinsic utilities
///
@@ -335,6 +287,10 @@ void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
/// llvm.dbg.value intrinsics.
bool LowerDbgDeclare(Function &F);
+/// Propagate dbg.value intrinsics through the newly inserted PHIs.
+void insertDebugValuesForPHIs(BasicBlock *BB,
+ SmallVectorImpl<PHINode *> &InsertedPHIs);
+
/// Finds all intrinsics declaring local variables as living in the memory that
/// 'V' points to. This may include a mix of dbg.declare and
/// dbg.addr intrinsics.
@@ -343,6 +299,9 @@ TinyPtrVector<DbgInfoIntrinsic *> FindDbgAddrUses(Value *V);
/// Finds the llvm.dbg.value intrinsics describing a value.
void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V);
+/// Finds the debug info intrinsics describing a value.
+void findDbgUsers(SmallVectorImpl<DbgInfoIntrinsic *> &DbgInsts, Value *V);
+
/// Replaces llvm.dbg.declare instruction when the address it
/// describes is replaced with a new value. If Deref is true, an
/// additional DW_OP_deref is prepended to the expression. If Offset
@@ -357,7 +316,7 @@ bool replaceDbgDeclare(Value *Address, Value *NewAddress,
/// DW_OP_deref is prepended to the expression. If Offset is non-zero,
/// a constant displacement is added to the expression (between the
/// optional Deref operations). Offset can be negative. The new
-/// llvm.dbg.declare is inserted immediately before AI.
+/// llvm.dbg.declare is inserted immediately after AI.
bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
DIBuilder &Builder, bool DerefBefore,
int Offset, bool DerefAfter);
@@ -370,10 +329,27 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
void replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
DIBuilder &Builder, int Offset = 0);
-/// Assuming the instruction \p I is going to be deleted, attempt to salvage any
-/// dbg.value intrinsics referring to \p I by rewriting its effect into a
-/// DIExpression.
-void salvageDebugInfo(Instruction &I);
+/// Assuming the instruction \p I is going to be deleted, attempt to salvage
+/// debug users of \p I by writing the effect of \p I in a DIExpression.
+/// Returns true if any debug users were updated.
+bool salvageDebugInfo(Instruction &I);
+
+/// Point debug users of \p From to \p To or salvage them. Use this function
+/// only when replacing all uses of \p From with \p To, with a guarantee that
+/// \p From is going to be deleted.
+///
+/// Follow these rules to prevent use-before-def of \p To:
+/// . If \p To is a linked Instruction, set \p DomPoint to \p To.
+/// . If \p To is an unlinked Instruction, set \p DomPoint to the Instruction
+/// \p To will be inserted after.
+/// . If \p To is not an Instruction (e.g a Constant), the choice of
+/// \p DomPoint is arbitrary. Pick \p From for simplicity.
+///
+/// If a debug user cannot be preserved without reordering variable updates or
+/// introducing a use-before-def, it is either salvaged (\ref salvageDebugInfo)
+/// or deleted. Returns true if any debug users were updated.
+bool replaceAllDbgUsesWith(Instruction &From, Value &To, Instruction &DomPoint,
+ DominatorTree &DT);
/// Remove all instructions from a basic block other than it's terminator
/// and any present EH pad instructions.
@@ -382,7 +358,8 @@ unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB);
/// Insert an unreachable instruction before the specified
/// instruction, making it and the rest of the code in the block dead.
unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap,
- bool PreserveLCSSA = false);
+ bool PreserveLCSSA = false,
+ DeferredDominance *DDT = nullptr);
/// Convert the CallInst to InvokeInst with the specified unwind edge basic
/// block. This also splits the basic block where CI is located, because
@@ -397,12 +374,13 @@ BasicBlock *changeToInvokeAndSplitBasicBlock(CallInst *CI,
///
/// \param BB Block whose terminator will be replaced. Its terminator must
/// have an unwind successor.
-void removeUnwindEdge(BasicBlock *BB);
+void removeUnwindEdge(BasicBlock *BB, DeferredDominance *DDT = nullptr);
/// Remove all blocks that can not be reached from the function's entry.
///
/// Returns true if any basic block was removed.
-bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr);
+bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr,
+ DeferredDominance *DDT = nullptr);
/// Combine the metadata of two instructions so that K can replace J
///
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/LoopRotationUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/LoopRotationUtils.h
new file mode 100644
index 000000000000..231e5bbb6dee
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/Utils/LoopRotationUtils.h
@@ -0,0 +1,40 @@
+//===- LoopRotationUtils.h - Utilities to perform loop rotation -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides utilities to convert a loop into a loop with bottom test.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_LOOPROTATIONUTILS_H
+#define LLVM_TRANSFORMS_UTILS_LOOPROTATIONUTILS_H
+
+namespace llvm {
+
+class AssumptionCache;
+class DominatorTree;
+class Loop;
+class LoopInfo;
+class ScalarEvolution;
+struct SimplifyQuery;
+class TargetTransformInfo;
+
+/// Convert a loop into a loop with bottom test. It may
+/// perform loop latch simplication as well if the flag RotationOnly
+/// is false. The flag Threshold represents the size threshold of the loop
+/// header. If the loop header's size exceeds the threshold, the loop rotation
+/// will give up. The flag IsUtilMode controls the heuristic used in the
+/// LoopRotation. If it is true, the profitability heuristic will be ignored.
+bool LoopRotation(Loop *L, LoopInfo *LI, const TargetTransformInfo *TTI,
+ AssumptionCache *AC, DominatorTree *DT, ScalarEvolution *SE,
+ const SimplifyQuery &SQ, bool RotationOnly,
+ unsigned Threshold, bool IsUtilMode);
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h b/contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h
index f3828bc16e2f..166da2738ffd 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h
@@ -52,7 +52,7 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Simplify each loop in a loop nest recursively.
+/// Simplify each loop in a loop nest recursively.
///
/// This takes a potentially un-simplified loop L (and its children) and turns
/// it into a simplified loop nest with preheaders and single backedges. It will
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index fb53647112f9..eb4c99102a63 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -23,6 +23,7 @@
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/DemandedBits.h"
#include "llvm/Analysis/EHPersonalities.h"
+#include "llvm/Analysis/MustExecute.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
@@ -47,17 +48,6 @@ class SCEV;
class TargetLibraryInfo;
class TargetTransformInfo;
-/// \brief Captures loop safety information.
-/// It keep information for loop & its header may throw exception.
-struct LoopSafetyInfo {
- bool MayThrow = false; // The current loop contains an instruction which
- // may throw.
- bool HeaderMayThrow = false; // Same as previous, but specific to loop header
- // Used to update funclet bundle operands.
- DenseMap<BasicBlock *, ColorVector> BlockColors;
-
- LoopSafetyInfo() = default;
-};
/// The RecurrenceDescriptor is used to identify recurrences variables in a
/// loop. Reduction is a special case of recurrence that has uses of the
@@ -299,16 +289,16 @@ public:
/// induction, the induction descriptor \p D will contain the data describing
/// this induction. If by some other means the caller has a better SCEV
/// expression for \p Phi than the one returned by the ScalarEvolution
- /// analysis, it can be passed through \p Expr. If the def-use chain
+ /// analysis, it can be passed through \p Expr. If the def-use chain
/// associated with the phi includes casts (that we know we can ignore
/// under proper runtime checks), they are passed through \p CastsToIgnore.
- static bool
+ static bool
isInductionPHI(PHINode *Phi, const Loop* L, ScalarEvolution *SE,
InductionDescriptor &D, const SCEV *Expr = nullptr,
SmallVectorImpl<Instruction *> *CastsToIgnore = nullptr);
/// Returns true if \p Phi is a floating point induction in the loop \p L.
- /// If \p Phi is an induction, the induction descriptor \p D will contain
+ /// If \p Phi is an induction, the induction descriptor \p D will contain
/// the data describing this induction.
static bool isFPInductionPHI(PHINode *Phi, const Loop* L,
ScalarEvolution *SE, InductionDescriptor &D);
@@ -344,11 +334,11 @@ public:
Instruction::BinaryOpsEnd;
}
- /// Returns a reference to the type cast instructions in the induction
+ /// Returns a reference to the type cast instructions in the induction
/// update chain, that are redundant when guarded with a runtime
/// SCEV overflow check.
- const SmallVectorImpl<Instruction *> &getCastInsts() const {
- return RedundantCasts;
+ const SmallVectorImpl<Instruction *> &getCastInsts() const {
+ return RedundantCasts;
}
private:
@@ -395,7 +385,7 @@ bool formDedicatedExitBlocks(Loop *L, DominatorTree *DT, LoopInfo *LI,
bool formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
DominatorTree &DT, LoopInfo &LI);
-/// \brief Put loop into LCSSA form.
+/// Put loop into LCSSA form.
///
/// Looks at all instructions in the loop which have uses outside of the
/// current loop. For each, an LCSSA PHI node is inserted and the uses outside
@@ -408,7 +398,7 @@ bool formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
/// Returns true if any modifications are made to the loop.
bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE);
-/// \brief Put a loop nest into LCSSA form.
+/// Put a loop nest into LCSSA form.
///
/// This recursively forms LCSSA for a loop nest.
///
@@ -420,7 +410,7 @@ bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE);
bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI,
ScalarEvolution *SE);
-/// \brief Walk the specified region of the CFG (defined by all blocks
+/// 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
@@ -433,7 +423,7 @@ bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
AliasSetTracker *, LoopSafetyInfo *,
OptimizationRemarkEmitter *ORE);
-/// \brief Walk the specified region of the CFG (defined by all blocks
+/// 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.
@@ -459,7 +449,7 @@ bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
void deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
LoopInfo *LI);
-/// \brief Try to promote memory values to scalars by sinking stores out of
+/// 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 a set of must-alias values, Loop exit blocks
@@ -480,22 +470,10 @@ bool promoteLoopAccessesToScalars(const SmallSetVector<Value *, 8> &,
SmallVector<DomTreeNode *, 16> collectChildrenInLoop(DomTreeNode *N,
const Loop *CurLoop);
-/// \brief Computes safety information for a loop
-/// checks loop body & header for the possibility of may throw
-/// exception, it takes LoopSafetyInfo and loop as argument.
-/// Updates safety information in LoopSafetyInfo argument.
-void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *);
-
-/// Returns true if the instruction in a loop is guaranteed to execute at least
-/// once.
-bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT,
- const Loop *CurLoop,
- const LoopSafetyInfo *SafetyInfo);
-
-/// \brief Returns the instructions that use values defined in the loop.
+/// Returns the instructions that use values defined in the loop.
SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L);
-/// \brief Find string metadata for loop
+/// Find string metadata for loop
///
/// If it has a value (e.g. {"llvm.distribute", 1} return the value as an
/// operand or null otherwise. If the string metadata is not found return
@@ -503,11 +481,11 @@ SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L);
Optional<const MDOperand *> findStringMetadataForLoop(Loop *TheLoop,
StringRef Name);
-/// \brief Set input string into loop metadata by keeping other values intact.
+/// Set input string into loop metadata by keeping other values intact.
void addStringMetadataToLoop(Loop *TheLoop, const char *MDString,
unsigned V = 0);
-/// \brief Get a loop's estimated trip count based on branch weight metadata.
+/// Get a loop's estimated trip count based on branch weight metadata.
/// Returns 0 when the count is estimated to be 0, or None when a meaningful
/// estimate can not be made.
Optional<unsigned> getLoopEstimatedTripCount(Loop *L);
@@ -531,11 +509,18 @@ bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
LoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE = nullptr);
+/// Generates an ordered vector reduction using extracts to reduce the value.
+Value *
+getOrderedReduction(IRBuilder<> &Builder, Value *Acc, Value *Src, unsigned Op,
+ RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind =
+ RecurrenceDescriptor::MRK_Invalid,
+ ArrayRef<Value *> RedOps = None);
+
/// Generates a vector reduction using shufflevectors to reduce the value.
Value *getShuffleReduction(IRBuilder<> &Builder, Value *Src, unsigned Op,
RecurrenceDescriptor::MinMaxRecurrenceKind
MinMaxKind = RecurrenceDescriptor::MRK_Invalid,
- ArrayRef<Value *> RedOps = ArrayRef<Value *>());
+ ArrayRef<Value *> RedOps = None);
/// Create a target reduction of the given vector. The reduction operation
/// is described by the \p Opcode parameter. min/max reductions require
@@ -547,7 +532,7 @@ createSimpleTargetReduction(IRBuilder<> &B, const TargetTransformInfo *TTI,
unsigned Opcode, Value *Src,
TargetTransformInfo::ReductionFlags Flags =
TargetTransformInfo::ReductionFlags(),
- ArrayRef<Value *> RedOps = ArrayRef<Value *>());
+ ArrayRef<Value *> RedOps = None);
/// Create a generic target reduction using a recurrence descriptor \p Desc
/// The target is queried to determine if intrinsics or shuffle sequences are
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h b/contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h
index fa5d7845d080..fcd734b37a1f 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h
@@ -28,14 +28,14 @@ class LoopAccessInfo;
class LoopInfo;
class ScalarEvolution;
-/// \brief This class emits a version of the loop where run-time checks ensure
+/// This class emits a version of the loop where run-time checks ensure
/// that may-alias pointers can't overlap.
///
/// It currently only supports single-exit loops and assumes that the loop
/// already has a preheader.
class LoopVersioning {
public:
- /// \brief Expects LoopAccessInfo, Loop, LoopInfo, DominatorTree as input.
+ /// Expects LoopAccessInfo, Loop, LoopInfo, DominatorTree as input.
/// It uses runtime check provided by the user. If \p UseLAIChecks is true,
/// we will retain the default checks made by LAI. Otherwise, construct an
/// object having no checks and we expect the user to add them.
@@ -43,7 +43,7 @@ public:
DominatorTree *DT, ScalarEvolution *SE,
bool UseLAIChecks = true);
- /// \brief Performs the CFG manipulation part of versioning the loop including
+ /// Performs the CFG manipulation part of versioning the loop including
/// the DominatorTree and LoopInfo updates.
///
/// The loop that was used to construct the class will be the "versioned" loop
@@ -58,38 +58,38 @@ public:
/// transform L
void versionLoop() { versionLoop(findDefsUsedOutsideOfLoop(VersionedLoop)); }
- /// \brief Same but if the client has already precomputed the set of values
+ /// Same but if the client has already precomputed the set of values
/// used outside the loop, this API will allows passing that.
void versionLoop(const SmallVectorImpl<Instruction *> &DefsUsedOutside);
- /// \brief Returns the versioned loop. Control flows here if pointers in the
+ /// Returns the versioned loop. Control flows here if pointers in the
/// loop don't alias (i.e. all memchecks passed). (This loop is actually the
/// same as the original loop that we got constructed with.)
Loop *getVersionedLoop() { return VersionedLoop; }
- /// \brief Returns the fall-back loop. Control flows here if pointers in the
+ /// Returns the fall-back loop. Control flows here if pointers in the
/// loop may alias (i.e. one of the memchecks failed).
Loop *getNonVersionedLoop() { return NonVersionedLoop; }
- /// \brief Sets the runtime alias checks for versioning the loop.
+ /// Sets the runtime alias checks for versioning the loop.
void setAliasChecks(
SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks);
- /// \brief Sets the runtime SCEV checks for versioning the loop.
+ /// Sets the runtime SCEV checks for versioning the loop.
void setSCEVChecks(SCEVUnionPredicate Check);
- /// \brief Annotate memory instructions in the versioned loop with no-alias
+ /// Annotate memory instructions in the versioned loop with no-alias
/// metadata based on the memchecks issued.
///
/// This is just wrapper that calls prepareNoAliasMetadata and
/// annotateInstWithNoAlias on the instructions of the versioned loop.
void annotateLoopWithNoAlias();
- /// \brief Set up the aliasing scopes based on the memchecks. This needs to
+ /// Set up the aliasing scopes based on the memchecks. This needs to
/// be called before the first call to annotateInstWithNoAlias.
void prepareNoAliasMetadata();
- /// \brief Add the noalias annotations to \p VersionedInst.
+ /// Add the noalias annotations to \p VersionedInst.
///
/// \p OrigInst is the instruction corresponding to \p VersionedInst in the
/// original loop. Initialize the aliasing scopes with
@@ -98,50 +98,50 @@ public:
const Instruction *OrigInst);
private:
- /// \brief Adds the necessary PHI nodes for the versioned loops based on the
+ /// Adds the necessary PHI nodes for the versioned loops based on the
/// loop-defined values used outside of the loop.
///
/// This needs to be called after versionLoop if there are defs in the loop
/// that are used outside the loop.
void addPHINodes(const SmallVectorImpl<Instruction *> &DefsUsedOutside);
- /// \brief Add the noalias annotations to \p I. Initialize the aliasing
+ /// Add the noalias annotations to \p I. Initialize the aliasing
/// scopes with prepareNoAliasMetadata once before this can be called.
void annotateInstWithNoAlias(Instruction *I) {
annotateInstWithNoAlias(I, I);
}
- /// \brief The original loop. This becomes the "versioned" one. I.e.,
+ /// The original loop. This becomes the "versioned" one. I.e.,
/// control flows here if pointers in the loop don't alias.
Loop *VersionedLoop;
- /// \brief The fall-back loop. I.e. control flows here if pointers in the
+ /// The fall-back loop. I.e. control flows here if pointers in the
/// loop may alias (memchecks failed).
Loop *NonVersionedLoop;
- /// \brief This maps the instructions from VersionedLoop to their counterpart
+ /// This maps the instructions from VersionedLoop to their counterpart
/// in NonVersionedLoop.
ValueToValueMapTy VMap;
- /// \brief The set of alias checks that we are versioning for.
+ /// The set of alias checks that we are versioning for.
SmallVector<RuntimePointerChecking::PointerCheck, 4> AliasChecks;
- /// \brief The set of SCEV checks that we are versioning for.
+ /// The set of SCEV checks that we are versioning for.
SCEVUnionPredicate Preds;
- /// \brief Maps a pointer to the pointer checking group that the pointer
+ /// Maps a pointer to the pointer checking group that the pointer
/// belongs to.
DenseMap<const Value *, const RuntimePointerChecking::CheckingPtrGroup *>
PtrToGroup;
- /// \brief The alias scope corresponding to a pointer checking group.
+ /// The alias scope corresponding to a pointer checking group.
DenseMap<const RuntimePointerChecking::CheckingPtrGroup *, MDNode *>
GroupToScope;
- /// \brief The list of alias scopes that a pointer checking group can't alias.
+ /// The list of alias scopes that a pointer checking group can't alias.
DenseMap<const RuntimePointerChecking::CheckingPtrGroup *, MDNode *>
GroupToNonAliasingScopeList;
- /// \brief Analyses used.
+ /// Analyses used.
const LoopAccessInfo &LAI;
LoopInfo *LI;
DominatorTree *DT;
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
index 4b9bc8293810..14615c25d093 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -49,7 +49,7 @@ Function *checkSanitizerInterfaceFunction(Constant *FuncOrBitcast);
Function *declareSanitizerInitFunction(Module &M, StringRef InitName,
ArrayRef<Type *> InitArgTypes);
-/// \brief Creates sanitizer constructor function, and calls sanitizer's init
+/// Creates sanitizer constructor function, and calls sanitizer's init
/// function from it.
/// \return Returns pair of pointers to constructor, and init functions
/// respectively.
@@ -62,10 +62,10 @@ std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions(
/// the list of public globals in the module.
bool nameUnamedGlobals(Module &M);
-/// \brief Adds global values to the llvm.used list.
+/// Adds global values to the llvm.used list.
void appendToUsed(Module &M, ArrayRef<GlobalValue *> Values);
-/// \brief Adds global values to the llvm.compiler.used list.
+/// Adds global values to the llvm.compiler.used list.
void appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values);
/// Filter out potentially dead comdat functions where other entries keep the
@@ -84,7 +84,7 @@ void appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values);
void filterDeadComdatFunctions(
Module &M, SmallVectorImpl<Function *> &DeadComdatFunctions);
-/// \brief Produce a unique identifier for this module by taking the MD5 sum of
+/// Produce a unique identifier for this module by taking the MD5 sum of
/// the names of the module's strong external symbols that are not comdat
/// members.
///
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h b/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h
index 165d4bdaa6d4..7f57fde638b8 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h
@@ -35,6 +35,11 @@ class OrderedInstructions {
/// The dominator tree of the parent function.
DominatorTree *DT;
+ /// Return true if the first instruction comes before the second in the
+ /// same basic block. It will create an ordered basic block, if it does
+ /// not yet exist in OBBMap.
+ bool localDominates(const Instruction *, const Instruction *) const;
+
public:
/// Constructor.
OrderedInstructions(DominatorTree *DT) : DT(DT) {}
@@ -42,6 +47,12 @@ public:
/// Return true if first instruction dominates the second.
bool dominates(const Instruction *, const Instruction *) const;
+ /// Return true if the first instruction comes before the second in the
+ /// dominator tree DFS traversal if they are in different basic blocks,
+ /// or if the first instruction comes before the second in the same basic
+ /// block.
+ bool dfsBefore(const Instruction *, const Instruction *) const;
+
/// Invalidate the OrderedBasicBlock cache when its basic block changes.
/// i.e. If an instruction is deleted or added to the basic block, the user
/// should call this function to invalidate the OrderedBasicBlock cache for
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h b/contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
index 8150f1528397..b53eda7e5a42 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file implements the PredicateInfo analysis, which creates an Extended
+/// This file implements the PredicateInfo analysis, which creates an Extended
/// SSA form for operations used in branch comparisons and llvm.assume
/// comparisons.
///
@@ -31,7 +31,7 @@
/// %cmp = icmp eq i32, %x, 50
/// br i1 %cmp, label %true, label %false
/// true:
-/// %x.0 = call @llvm.ssa_copy.i32(i32 %x)
+/// %x.0 = call \@llvm.ssa_copy.i32(i32 %x)
/// ret i32 %x.0
/// false:
/// ret i32 1
@@ -54,6 +54,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
@@ -69,6 +70,7 @@
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/Support/Casting.h"
@@ -193,7 +195,7 @@ namespace PredicateInfoClasses {
struct ValueDFS;
}
-/// \brief Encapsulates PredicateInfo, including all data associated with memory
+/// Encapsulates PredicateInfo, including all data associated with memory
/// accesses.
class PredicateInfo {
private:
@@ -261,6 +263,8 @@ private:
// The set of edges along which we can only handle phi uses, due to critical
// edges.
DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeUsesOnly;
+ // The set of ssa_copy declarations we created with our custom mangling.
+ SmallSet<AssertingVH<Function>, 20> CreatedDeclarations;
};
// This pass does eager building and then printing of PredicateInfo. It is used
@@ -275,7 +279,7 @@ public:
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
-/// \brief Printer pass for \c PredicateInfo.
+/// Printer pass for \c PredicateInfo.
class PredicateInfoPrinterPass
: public PassInfoMixin<PredicateInfoPrinterPass> {
raw_ostream &OS;
@@ -285,7 +289,7 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Verifier pass for \c PredicateInfo.
+/// Verifier pass for \c PredicateInfo.
struct PredicateInfoVerifierPass : PassInfoMixin<PredicateInfoVerifierPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h b/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h
index bb8a61a474f2..5ddfbe2bf058 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h
@@ -23,7 +23,7 @@ class DominatorTree;
class AliasSetTracker;
class AssumptionCache;
-/// \brief Return true if this alloca is legal for promotion.
+/// Return true if this alloca is legal for promotion.
///
/// This is true if there are only loads, stores, and lifetime markers
/// (transitively) using this alloca. This also enforces that there is only
@@ -31,7 +31,7 @@ class AssumptionCache;
/// markers.
bool isAllocaPromotable(const AllocaInst *AI);
-/// \brief Promote the specified list of alloca instructions into scalar
+/// Promote the specified list of alloca instructions into scalar
/// registers, inserting PHI nodes as appropriate.
///
/// This function makes use of DominanceFrontier information. This function
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h
index 6cd9f1539b0b..4a7911662990 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h
@@ -30,7 +30,7 @@ class Type;
class Use;
class Value;
-/// \brief Helper class for SSA formation on a set of values defined in
+/// Helper class for SSA formation on a set of values defined in
/// multiple blocks.
///
/// This is used when code duplication or another unstructured
@@ -62,25 +62,25 @@ public:
SSAUpdater &operator=(const SSAUpdater &) = delete;
~SSAUpdater();
- /// \brief Reset this object to get ready for a new set of SSA updates with
+ /// Reset this object to get ready for a new set of SSA updates with
/// type 'Ty'.
///
/// PHI nodes get a name based on 'Name'.
void Initialize(Type *Ty, StringRef Name);
- /// \brief Indicate that a rewritten value is available in the specified block
+ /// Indicate that a rewritten value is available in the specified block
/// with the specified value.
void AddAvailableValue(BasicBlock *BB, Value *V);
- /// \brief Return true if the SSAUpdater already has a value for the specified
+ /// Return true if the SSAUpdater already has a value for the specified
/// block.
bool HasValueForBlock(BasicBlock *BB) const;
- /// \brief Construct SSA form, materializing a value that is live at the end
+ /// Construct SSA form, materializing a value that is live at the end
/// of the specified block.
Value *GetValueAtEndOfBlock(BasicBlock *BB);
- /// \brief Construct SSA form, materializing a value that is live in the
+ /// Construct SSA form, materializing a value that is live in the
/// middle of the specified block.
///
/// \c GetValueInMiddleOfBlock is the same as \c GetValueAtEndOfBlock except
@@ -102,7 +102,7 @@ public:
/// merge the appropriate values, and this value isn't live out of the block.
Value *GetValueInMiddleOfBlock(BasicBlock *BB);
- /// \brief Rewrite a use of the symbolic value.
+ /// Rewrite a use of the symbolic value.
///
/// This handles PHI nodes, which use their value in the corresponding
/// predecessor. Note that this will not work if the use is supposed to be
@@ -111,7 +111,7 @@ public:
/// be below it.
void RewriteUse(Use &U);
- /// \brief Rewrite a use like \c RewriteUse but handling in-block definitions.
+ /// Rewrite a use like \c RewriteUse but handling in-block definitions.
///
/// This version of the method can rewrite uses in the same block as
/// a definition, because it assumes that all uses of a value are below any
@@ -122,7 +122,7 @@ private:
Value *GetValueAtEndOfBlockInternal(BasicBlock *BB);
};
-/// \brief Helper class for promoting a collection of loads and stores into SSA
+/// Helper class for promoting a collection of loads and stores into SSA
/// Form using the SSAUpdater.
///
/// This handles complexities that SSAUpdater doesn't, such as multiple loads
@@ -139,32 +139,32 @@ public:
SSAUpdater &S, StringRef Name = StringRef());
virtual ~LoadAndStorePromoter() = default;
- /// \brief This does the promotion.
+ /// This does the promotion.
///
/// Insts is a list of loads and stores to promote, and Name is the basename
/// for the PHIs to insert. After this is complete, the loads and stores are
/// removed from the code.
void run(const SmallVectorImpl<Instruction *> &Insts) const;
- /// \brief Return true if the specified instruction is in the Inst list.
+ /// Return true if the specified instruction is in the Inst list.
///
/// The Insts list is the one passed into the constructor. Clients should
/// implement this with a more efficient version if possible.
virtual bool isInstInList(Instruction *I,
const SmallVectorImpl<Instruction *> &Insts) const;
- /// \brief This hook is invoked after all the stores are found and inserted as
+ /// This hook is invoked after all the stores are found and inserted as
/// available values.
virtual void doExtraRewritesBeforeFinalDeletion() const {}
- /// \brief Clients can choose to implement this to get notified right before
+ /// Clients can choose to implement this to get notified right before
/// a load is RAUW'd another value.
virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {}
- /// \brief Called before each instruction is deleted.
+ /// Called before each instruction is deleted.
virtual void instructionDeleted(Instruction *I) const {}
- /// \brief Called to update debug info associated with the instruction.
+ /// Called to update debug info associated with the instruction.
virtual void updateDebugInfo(Instruction *I) const {}
};
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h
new file mode 100644
index 000000000000..53a608f01804
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h
@@ -0,0 +1,92 @@
+//===- SSAUpdaterBulk.h - Unstructured SSA Update Tool ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SSAUpdaterBulk class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATERBULK_H
+#define LLVM_TRANSFORMS_UTILS_SSAUPDATERBULK_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/PredIteratorCache.h"
+
+namespace llvm {
+
+class BasicBlock;
+class PHINode;
+template <typename T> class SmallVectorImpl;
+class Type;
+class Use;
+class Value;
+class DominatorTree;
+
+/// Helper class for SSA formation on a set of values defined in multiple
+/// blocks.
+///
+/// This is used when code duplication or another unstructured transformation
+/// wants to rewrite a set of uses of one value with uses of a set of values.
+/// The update is done only when RewriteAllUses is called, all other methods are
+/// used for book-keeping. That helps to share some common computations between
+/// updates of different uses (which is not the case when traditional SSAUpdater
+/// is used).
+class SSAUpdaterBulk {
+ struct RewriteInfo {
+ DenseMap<BasicBlock *, Value *> Defines;
+ SmallVector<Use *, 4> Uses;
+ StringRef Name;
+ Type *Ty;
+ RewriteInfo(){};
+ RewriteInfo(StringRef &N, Type *T) : Name(N), Ty(T){};
+ };
+ SmallVector<RewriteInfo, 4> Rewrites;
+
+ PredIteratorCache PredCache;
+
+ Value *computeValueAt(BasicBlock *BB, RewriteInfo &R, DominatorTree *DT);
+
+public:
+ explicit SSAUpdaterBulk(){};
+ SSAUpdaterBulk(const SSAUpdaterBulk &) = delete;
+ SSAUpdaterBulk &operator=(const SSAUpdaterBulk &) = delete;
+ ~SSAUpdaterBulk(){};
+
+ /// Add a new variable to the SSA rewriter. This needs to be called before
+ /// AddAvailableValue or AddUse calls. The return value is the variable ID,
+ /// which needs to be passed to AddAvailableValue and AddUse.
+ unsigned AddVariable(StringRef Name, Type *Ty);
+
+ /// Indicate that a rewritten value is available in the specified block with
+ /// the specified value.
+ void AddAvailableValue(unsigned Var, BasicBlock *BB, Value *V);
+
+ /// Record a use of the symbolic value. This use will be updated with a
+ /// rewritten value when RewriteAllUses is called.
+ void AddUse(unsigned Var, Use *U);
+
+ /// Return true if the SSAUpdater already has a value for the specified
+ /// variable in the specified block.
+ bool HasValueForBlock(unsigned Var, BasicBlock *BB);
+
+ /// Perform all the necessary updates, including new PHI-nodes insertion and
+ /// the requested uses update.
+ ///
+ /// The function requires dominator tree DT, which is used for computing
+ /// locations for new phi-nodes insertions. If a nonnull pointer to a vector
+ /// InsertedPHIs is passed, all the new phi-nodes will be added to this
+ /// vector.
+ void RewriteAllUses(DominatorTree *DT,
+ SmallVectorImpl<PHINode *> *InsertedPHIs = nullptr);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_SSAUPDATERBULK_H
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h
index b1611d49a456..b7649ba88334 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h
@@ -379,7 +379,7 @@ public:
Traits::AddPHIOperand(PHI, PredInfo->AvailableVal, Pred);
}
- DEBUG(dbgs() << " Inserted PHI: " << *PHI << "\n");
+ LLVM_DEBUG(dbgs() << " Inserted PHI: " << *PHI << "\n");
// If the client wants to know about all new instructions, tell it.
if (InsertedPHIs) InsertedPHIs->push_back(PHI);
@@ -389,12 +389,8 @@ public:
/// FindExistingPHI - Look through the PHI nodes in a block to see if any of
/// them match what is needed.
void FindExistingPHI(BlkT *BB, BlockListTy *BlockList) {
- for (typename BlkT::iterator BBI = BB->begin(), BBE = BB->end();
- BBI != BBE; ++BBI) {
- PhiT *SomePHI = Traits::InstrIsPHI(&*BBI);
- if (!SomePHI)
- break;
- if (CheckIfPHIMatches(SomePHI)) {
+ for (auto &SomePHI : BB->phis()) {
+ if (CheckIfPHIMatches(&SomePHI)) {
RecordMatchingPHIs(BlockList);
break;
}
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyInstructions.h b/contrib/llvm/include/llvm/Transforms/Utils/SimplifyInstructions.h
deleted file mode 100644
index 3f838611626f..000000000000
--- a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyInstructions.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- SimplifyInstructions.h - Remove redundant instructions ---*- 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 utility pass used for testing the InstructionSimplify analysis.
-// The analysis is applied to every instruction, and if it simplifies then the
-// instruction is replaced by the simplification. If you are looking for a pass
-// that performs serious instruction folding, use the instcombine pass instead.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H
-#define LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H
-
-#include "llvm/IR/PassManager.h"
-
-namespace llvm {
-
-/// This pass removes redundant instructions.
-class InstSimplifierPass : public PassInfoMixin<InstSimplifierPass> {
-public:
- PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
-};
-} // end namespace llvm
-
-#endif // LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 73a62f59203b..d007f909c6a4 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -30,7 +30,7 @@ class BasicBlock;
class Function;
class OptimizationRemarkEmitter;
-/// \brief This class implements simplifications for calls to fortified library
+/// 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
@@ -45,7 +45,7 @@ public:
FortifiedLibCallSimplifier(const TargetLibraryInfo *TLI,
bool OnlyLowerUnknownSize = false);
- /// \brief Take the given call instruction and return a more
+ /// 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.
@@ -60,7 +60,7 @@ private:
Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
- /// \brief Checks whether the call \p CI to a fortified libcall is foldable
+ /// 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);
@@ -78,13 +78,13 @@ private:
bool UnsafeFPShrink;
function_ref<void(Instruction *, Value *)> Replacer;
- /// \brief Internal wrapper for RAUW that is the default implementation.
+ /// 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);
- /// \brief Replace an instruction's uses with a value using our replacer.
+ /// Replace an instruction's uses with a value using our replacer.
void replaceAllUsesWith(Instruction *I, Value *With);
public:
@@ -124,6 +124,7 @@ private:
Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeRealloc(CallInst *CI, IRBuilder<> &B);
Value *optimizeWcslen(CallInst *CI, IRBuilder<> &B);
// Wrapper for all String/Memory Library Call Optimizations
Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B);
@@ -150,15 +151,22 @@ private:
Value *optimizeIsDigit(CallInst *CI, IRBuilder<> &B);
Value *optimizeIsAscii(CallInst *CI, IRBuilder<> &B);
Value *optimizeToAscii(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeAtoi(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrtol(CallInst *CI, IRBuilder<> &B);
// Formatting and IO Library Call Optimizations
Value *optimizeErrorReporting(CallInst *CI, IRBuilder<> &B,
int StreamArg = -1);
Value *optimizePrintF(CallInst *CI, IRBuilder<> &B);
Value *optimizeSPrintF(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeSnPrintF(CallInst *CI, IRBuilder<> &B);
Value *optimizeFPrintF(CallInst *CI, IRBuilder<> &B);
Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeFRead(CallInst *CI, IRBuilder<> &B);
Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeFGets(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeFPutc(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeFGetc(CallInst *CI, IRBuilder<> &B);
Value *optimizePuts(CallInst *CI, IRBuilder<> &B);
// Helper methods
@@ -169,6 +177,7 @@ private:
SmallVectorImpl<CallInst *> &SinCosCalls);
Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B);
Value *optimizeSPrintFString(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeSnPrintFString(CallInst *CI, IRBuilder<> &B);
Value *optimizeFPrintFString(CallInst *CI, IRBuilder<> &B);
/// hasFloatVersion - Checks if there is a float version of the specified
diff --git a/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h b/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h
index 12aa3bc6e770..a6b84af068a5 100644
--- a/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h
+++ b/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h
@@ -19,11 +19,13 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/Transforms/Utils/ValueMapper.h"
namespace llvm {
class AssumptionCache;
class BasicBlock;
+class DependenceInfo;
class DominatorTree;
class Loop;
class LoopInfo;
@@ -71,13 +73,54 @@ bool UnrollRuntimeLoopRemainder(Loop *L, unsigned Count,
void computePeelCount(Loop *L, unsigned LoopSize,
TargetTransformInfo::UnrollingPreferences &UP,
- unsigned &TripCount);
+ unsigned &TripCount, ScalarEvolution &SE);
+
+bool canPeel(Loop *L);
bool peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI, ScalarEvolution *SE,
DominatorTree *DT, AssumptionCache *AC, bool PreserveLCSSA);
+LoopUnrollResult UnrollAndJamLoop(Loop *L, unsigned Count, unsigned TripCount,
+ unsigned TripMultiple, bool UnrollRemainder,
+ LoopInfo *LI, ScalarEvolution *SE,
+ DominatorTree *DT, AssumptionCache *AC,
+ OptimizationRemarkEmitter *ORE);
+
+bool isSafeToUnrollAndJam(Loop *L, ScalarEvolution &SE, DominatorTree &DT,
+ DependenceInfo &DI);
+
+bool computeUnrollCount(Loop *L, const TargetTransformInfo &TTI,
+ DominatorTree &DT, LoopInfo *LI, ScalarEvolution &SE,
+ const SmallPtrSetImpl<const Value *> &EphValues,
+ OptimizationRemarkEmitter *ORE, unsigned &TripCount,
+ unsigned MaxTripCount, unsigned &TripMultiple,
+ unsigned LoopSize,
+ TargetTransformInfo::UnrollingPreferences &UP,
+ bool &UseUpperBound);
+
+BasicBlock *foldBlockIntoPredecessor(BasicBlock *BB, LoopInfo *LI,
+ ScalarEvolution *SE, DominatorTree *DT);
+
+void remapInstruction(Instruction *I, ValueToValueMapTy &VMap);
+
+void simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI,
+ ScalarEvolution *SE, DominatorTree *DT,
+ AssumptionCache *AC);
+
MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name);
+TargetTransformInfo::UnrollingPreferences gatherUnrollingPreferences(
+ Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, int OptLevel,
+ Optional<unsigned> UserThreshold, Optional<unsigned> UserCount,
+ Optional<bool> UserAllowPartial, Optional<bool> UserRuntime,
+ Optional<bool> UserUpperBound, Optional<bool> UserAllowPeeling);
+
+unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls,
+ bool &NotDuplicatable, bool &Convergent,
+ const TargetTransformInfo &TTI,
+ const SmallPtrSetImpl<const Value *> &EphValues,
+ unsigned BEInsns);
+
} // end namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H
diff --git a/contrib/llvm/include/llvm/Transforms/Vectorize.h b/contrib/llvm/include/llvm/Transforms/Vectorize.h
index 19845e471e48..950af7ffe05f 100644
--- a/contrib/llvm/include/llvm/Transforms/Vectorize.h
+++ b/contrib/llvm/include/llvm/Transforms/Vectorize.h
@@ -21,88 +21,88 @@ class BasicBlockPass;
class Pass;
//===----------------------------------------------------------------------===//
-/// @brief Vectorize configuration.
+/// Vectorize configuration.
struct VectorizeConfig {
//===--------------------------------------------------------------------===//
// Target architecture related parameters
- /// @brief The size of the native vector registers.
+ /// The size of the native vector registers.
unsigned VectorBits;
- /// @brief Vectorize boolean values.
+ /// Vectorize boolean values.
bool VectorizeBools;
- /// @brief Vectorize integer values.
+ /// Vectorize integer values.
bool VectorizeInts;
- /// @brief Vectorize floating-point values.
+ /// Vectorize floating-point values.
bool VectorizeFloats;
- /// @brief Vectorize pointer values.
+ /// Vectorize pointer values.
bool VectorizePointers;
- /// @brief Vectorize casting (conversion) operations.
+ /// Vectorize casting (conversion) operations.
bool VectorizeCasts;
- /// @brief Vectorize floating-point math intrinsics.
+ /// Vectorize floating-point math intrinsics.
bool VectorizeMath;
- /// @brief Vectorize bit intrinsics.
+ /// Vectorize bit intrinsics.
bool VectorizeBitManipulations;
- /// @brief Vectorize the fused-multiply-add intrinsic.
+ /// Vectorize the fused-multiply-add intrinsic.
bool VectorizeFMA;
- /// @brief Vectorize select instructions.
+ /// Vectorize select instructions.
bool VectorizeSelect;
- /// @brief Vectorize comparison instructions.
+ /// Vectorize comparison instructions.
bool VectorizeCmp;
- /// @brief Vectorize getelementptr instructions.
+ /// Vectorize getelementptr instructions.
bool VectorizeGEP;
- /// @brief Vectorize loads and stores.
+ /// Vectorize loads and stores.
bool VectorizeMemOps;
- /// @brief Only generate aligned loads and stores.
+ /// Only generate aligned loads and stores.
bool AlignedOnly;
//===--------------------------------------------------------------------===//
// Misc parameters
- /// @brief The required chain depth for vectorization.
+ /// The required chain depth for vectorization.
unsigned ReqChainDepth;
- /// @brief The maximum search distance for instruction pairs.
+ /// The maximum search distance for instruction pairs.
unsigned SearchLimit;
- /// @brief The maximum number of candidate pairs with which to use a full
+ /// The maximum number of candidate pairs with which to use a full
/// cycle check.
unsigned MaxCandPairsForCycleCheck;
- /// @brief Replicating one element to a pair breaks the chain.
+ /// Replicating one element to a pair breaks the chain.
bool SplatBreaksChain;
- /// @brief The maximum number of pairable instructions per group.
+ /// The maximum number of pairable instructions per group.
unsigned MaxInsts;
- /// @brief The maximum number of candidate instruction pairs per group.
+ /// The maximum number of candidate instruction pairs per group.
unsigned MaxPairs;
- /// @brief The maximum number of pairing iterations.
+ /// The maximum number of pairing iterations.
unsigned MaxIter;
- /// @brief Don't try to form odd-length vectors.
+ /// Don't try to form odd-length vectors.
bool Pow2LenOnly;
- /// @brief Don't boost the chain-depth contribution of loads and stores.
+ /// Don't boost the chain-depth contribution of loads and stores.
bool NoMemOpBoost;
- /// @brief Use a fast instruction dependency analysis.
+ /// Use a fast instruction dependency analysis.
bool FastDep;
- /// @brief Initialize the VectorizeConfig from command line options.
+ /// Initialize the VectorizeConfig from command line options.
VectorizeConfig();
};
@@ -120,7 +120,7 @@ Pass *createLoopVectorizePass(bool NoUnrolling = false,
Pass *createSLPVectorizerPass();
//===----------------------------------------------------------------------===//
-/// @brief Vectorize the BasicBlock.
+/// Vectorize the BasicBlock.
///
/// @param BB The BasicBlock to be vectorized
/// @param P The current running pass, should require AliasAnalysis and
diff --git a/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
new file mode 100644
index 000000000000..224879cdba52
--- /dev/null
+++ b/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -0,0 +1,482 @@
+//===- llvm/Transforms/Vectorize/LoopVectorizationLegality.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 defines the LoopVectorizationLegality class. Original code
+/// in Loop Vectorizer has been moved out to its own file for modularity
+/// and reusability.
+///
+/// Currently, it works for innermost loop vectorization. Extending this to
+/// outer loop vectorization is a TODO item.
+///
+/// Also provides:
+/// 1) LoopVectorizeHints class which keeps a number of loop annotations
+/// locally for easy look up. It has the ability to write them back as
+/// loop metadata, upon request.
+/// 2) LoopVectorizationRequirements class for lazy bail out for the purpose
+/// of reporting useful failure to vectorize message.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONLEGALITY_H
+#define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONLEGALITY_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/Analysis/LoopAccessAnalysis.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/Transforms/Utils/LoopUtils.h"
+
+namespace llvm {
+
+/// Create an analysis remark that explains why vectorization failed
+///
+/// \p PassName is the name of the pass (e.g. can be AlwaysPrint). \p
+/// RemarkName is the identifier for the remark. If \p I is passed it is an
+/// instruction that prevents vectorization. Otherwise \p TheLoop is used for
+/// the location of the remark. \return the remark object that can be
+/// streamed to.
+OptimizationRemarkAnalysis createLVMissedAnalysis(const char *PassName,
+ StringRef RemarkName,
+ Loop *TheLoop,
+ Instruction *I = nullptr);
+
+/// Utility class for getting and setting loop vectorizer hints in the form
+/// of loop metadata.
+/// This class keeps a number of loop annotations locally (as member variables)
+/// and can, upon request, write them back as metadata on the loop. It will
+/// initially scan the loop for existing metadata, and will update the local
+/// values based on information in the loop.
+/// We cannot write all values to metadata, as the mere presence of some info,
+/// for example 'force', means a decision has been made. So, we need to be
+/// careful NOT to add them if the user hasn't specifically asked so.
+class LoopVectorizeHints {
+ enum HintKind { HK_WIDTH, HK_UNROLL, HK_FORCE, HK_ISVECTORIZED };
+
+ /// Hint - associates name and validation with the hint value.
+ struct Hint {
+ const char *Name;
+ unsigned Value; // This may have to change for non-numeric values.
+ HintKind Kind;
+
+ Hint(const char *Name, unsigned Value, HintKind Kind)
+ : Name(Name), Value(Value), Kind(Kind) {}
+
+ bool validate(unsigned Val);
+ };
+
+ /// Vectorization width.
+ Hint Width;
+
+ /// Vectorization interleave factor.
+ Hint Interleave;
+
+ /// Vectorization forced
+ Hint Force;
+
+ /// Already Vectorized
+ Hint IsVectorized;
+
+ /// Return the loop metadata prefix.
+ static StringRef Prefix() { return "llvm.loop."; }
+
+ /// True if there is any unsafe math in the loop.
+ bool PotentiallyUnsafe = false;
+
+public:
+ enum ForceKind {
+ FK_Undefined = -1, ///< Not selected.
+ FK_Disabled = 0, ///< Forcing disabled.
+ FK_Enabled = 1, ///< Forcing enabled.
+ };
+
+ LoopVectorizeHints(const Loop *L, bool DisableInterleaving,
+ OptimizationRemarkEmitter &ORE);
+
+ /// Mark the loop L as already vectorized by setting the width to 1.
+ void setAlreadyVectorized() {
+ IsVectorized.Value = 1;
+ Hint Hints[] = {IsVectorized};
+ writeHintsToMetadata(Hints);
+ }
+
+ bool allowVectorization(Function *F, Loop *L, bool AlwaysVectorize) const;
+
+ /// Dumps all the hint information.
+ void emitRemarkWithHints() const;
+
+ unsigned getWidth() const { return Width.Value; }
+ unsigned getInterleave() const { return Interleave.Value; }
+ unsigned getIsVectorized() const { return IsVectorized.Value; }
+ enum ForceKind getForce() const { return (ForceKind)Force.Value; }
+
+ /// If hints are provided that force vectorization, use the AlwaysPrint
+ /// pass name to force the frontend to print the diagnostic.
+ const char *vectorizeAnalysisPassName() const;
+
+ bool allowReordering() const {
+ // When enabling loop hints are provided we allow the vectorizer to change
+ // the order of operations that is given by the scalar loop. This is not
+ // enabled by default because can be unsafe or inefficient. For example,
+ // reordering floating-point operations will change the way round-off
+ // error accumulates in the loop.
+ return getForce() == LoopVectorizeHints::FK_Enabled || getWidth() > 1;
+ }
+
+ bool isPotentiallyUnsafe() const {
+ // Avoid FP vectorization if the target is unsure about proper support.
+ // This may be related to the SIMD unit in the target not handling
+ // IEEE 754 FP ops properly, or bad single-to-double promotions.
+ // Otherwise, a sequence of vectorized loops, even without reduction,
+ // could lead to different end results on the destination vectors.
+ return getForce() != LoopVectorizeHints::FK_Enabled && PotentiallyUnsafe;
+ }
+
+ void setPotentiallyUnsafe() { PotentiallyUnsafe = true; }
+
+private:
+ /// Find hints specified in the loop metadata and update local values.
+ void getHintsFromMetadata();
+
+ /// Checks string hint with one operand and set value if valid.
+ void setHint(StringRef Name, Metadata *Arg);
+
+ /// Create a new hint from name / value pair.
+ MDNode *createHintMetadata(StringRef Name, unsigned V) const;
+
+ /// Matches metadata with hint name.
+ bool matchesHintMetadataName(MDNode *Node, ArrayRef<Hint> HintTypes);
+
+ /// Sets current hints into loop metadata, keeping other values intact.
+ void writeHintsToMetadata(ArrayRef<Hint> HintTypes);
+
+ /// The loop these hints belong to.
+ const Loop *TheLoop;
+
+ /// Interface to emit optimization remarks.
+ OptimizationRemarkEmitter &ORE;
+};
+
+/// This holds vectorization requirements that must be verified late in
+/// the process. The requirements are set by legalize and costmodel. Once
+/// vectorization has been determined to be possible and profitable the
+/// requirements can be verified by looking for metadata or compiler options.
+/// For example, some loops require FP commutativity which is only allowed if
+/// vectorization is explicitly specified or if the fast-math compiler option
+/// has been provided.
+/// Late evaluation of these requirements allows helpful diagnostics to be
+/// composed that tells the user what need to be done to vectorize the loop. For
+/// example, by specifying #pragma clang loop vectorize or -ffast-math. Late
+/// evaluation should be used only when diagnostics can generated that can be
+/// followed by a non-expert user.
+class LoopVectorizationRequirements {
+public:
+ LoopVectorizationRequirements(OptimizationRemarkEmitter &ORE) : ORE(ORE) {}
+
+ void addUnsafeAlgebraInst(Instruction *I) {
+ // First unsafe algebra instruction.
+ if (!UnsafeAlgebraInst)
+ UnsafeAlgebraInst = I;
+ }
+
+ void addRuntimePointerChecks(unsigned Num) { NumRuntimePointerChecks = Num; }
+
+ bool doesNotMeet(Function *F, Loop *L, const LoopVectorizeHints &Hints);
+
+private:
+ unsigned NumRuntimePointerChecks = 0;
+ Instruction *UnsafeAlgebraInst = nullptr;
+
+ /// Interface to emit optimization remarks.
+ OptimizationRemarkEmitter &ORE;
+};
+
+/// LoopVectorizationLegality checks if it is legal to vectorize a loop, and
+/// to what vectorization factor.
+/// This class does not look at the profitability of vectorization, only the
+/// legality. This class has two main kinds of checks:
+/// * Memory checks - The code in canVectorizeMemory checks if vectorization
+/// will change the order of memory accesses in a way that will change the
+/// correctness of the program.
+/// * Scalars checks - The code in canVectorizeInstrs and canVectorizeMemory
+/// checks for a number of different conditions, such as the availability of a
+/// single induction variable, that all types are supported and vectorize-able,
+/// etc. This code reflects the capabilities of InnerLoopVectorizer.
+/// This class is also used by InnerLoopVectorizer for identifying
+/// induction variable and the different reduction variables.
+class LoopVectorizationLegality {
+public:
+ LoopVectorizationLegality(
+ Loop *L, PredicatedScalarEvolution &PSE, DominatorTree *DT,
+ TargetLibraryInfo *TLI, AliasAnalysis *AA, Function *F,
+ std::function<const LoopAccessInfo &(Loop &)> *GetLAA, LoopInfo *LI,
+ OptimizationRemarkEmitter *ORE, LoopVectorizationRequirements *R,
+ LoopVectorizeHints *H, DemandedBits *DB, AssumptionCache *AC)
+ : TheLoop(L), LI(LI), PSE(PSE), TLI(TLI), DT(DT), GetLAA(GetLAA),
+ ORE(ORE), Requirements(R), Hints(H), DB(DB), AC(AC) {}
+
+ /// ReductionList contains the reduction descriptors for all
+ /// of the reductions that were found in the loop.
+ using ReductionList = DenseMap<PHINode *, RecurrenceDescriptor>;
+
+ /// InductionList saves induction variables and maps them to the
+ /// induction descriptor.
+ using InductionList = MapVector<PHINode *, InductionDescriptor>;
+
+ /// RecurrenceSet contains the phi nodes that are recurrences other than
+ /// inductions and reductions.
+ using RecurrenceSet = SmallPtrSet<const PHINode *, 8>;
+
+ /// Returns true if it is legal to vectorize this loop.
+ /// This does not mean that it is profitable to vectorize this
+ /// loop, only that it is legal to do so.
+ /// Temporarily taking UseVPlanNativePath parameter. If true, take
+ /// the new code path being implemented for outer loop vectorization
+ /// (should be functional for inner loop vectorization) based on VPlan.
+ /// If false, good old LV code.
+ bool canVectorize(bool UseVPlanNativePath);
+
+ /// Returns the primary induction variable.
+ PHINode *getPrimaryInduction() { return PrimaryInduction; }
+
+ /// Returns the reduction variables found in the loop.
+ ReductionList *getReductionVars() { return &Reductions; }
+
+ /// Returns the induction variables found in the loop.
+ InductionList *getInductionVars() { return &Inductions; }
+
+ /// Return the first-order recurrences found in the loop.
+ RecurrenceSet *getFirstOrderRecurrences() { return &FirstOrderRecurrences; }
+
+ /// Return the set of instructions to sink to handle first-order recurrences.
+ DenseMap<Instruction *, Instruction *> &getSinkAfter() { return SinkAfter; }
+
+ /// Returns the widest induction type.
+ Type *getWidestInductionType() { return WidestIndTy; }
+
+ /// Returns True if V is a Phi node of an induction variable in this loop.
+ bool isInductionPhi(const Value *V);
+
+ /// Returns True if V is a cast that is part of an induction def-use chain,
+ /// and had been proven to be redundant under a runtime guard (in other
+ /// words, the cast has the same SCEV expression as the induction phi).
+ bool isCastedInductionVariable(const Value *V);
+
+ /// Returns True if V can be considered as an induction variable in this
+ /// loop. V can be the induction phi, or some redundant cast in the def-use
+ /// chain of the inducion phi.
+ bool isInductionVariable(const Value *V);
+
+ /// Returns True if PN is a reduction variable in this loop.
+ bool isReductionVariable(PHINode *PN) { return Reductions.count(PN); }
+
+ /// Returns True if Phi is a first-order recurrence in this loop.
+ bool isFirstOrderRecurrence(const PHINode *Phi);
+
+ /// Return true if the block BB needs to be predicated in order for the loop
+ /// to be vectorized.
+ bool blockNeedsPredication(BasicBlock *BB);
+
+ /// Check if this pointer is consecutive when vectorizing. This happens
+ /// when the last index of the GEP is the induction variable, or that the
+ /// pointer itself is an induction variable.
+ /// This check allows us to vectorize A[idx] into a wide load/store.
+ /// Returns:
+ /// 0 - Stride is unknown or non-consecutive.
+ /// 1 - Address is consecutive.
+ /// -1 - Address is consecutive, and decreasing.
+ /// NOTE: This method must only be used before modifying the original scalar
+ /// loop. Do not use after invoking 'createVectorizedLoopSkeleton' (PR34965).
+ int isConsecutivePtr(Value *Ptr);
+
+ /// Returns true if the value V is uniform within the loop.
+ bool isUniform(Value *V);
+
+ /// Returns the information that we collected about runtime memory check.
+ const RuntimePointerChecking *getRuntimePointerChecking() const {
+ return LAI->getRuntimePointerChecking();
+ }
+
+ const LoopAccessInfo *getLAI() const { return LAI; }
+
+ unsigned getMaxSafeDepDistBytes() { return LAI->getMaxSafeDepDistBytes(); }
+
+ uint64_t getMaxSafeRegisterWidth() const {
+ return LAI->getDepChecker().getMaxSafeRegisterWidth();
+ }
+
+ bool hasStride(Value *V) { return LAI->hasStride(V); }
+
+ /// Returns true if vector representation of the instruction \p I
+ /// requires mask.
+ bool isMaskRequired(const Instruction *I) { return (MaskedOp.count(I) != 0); }
+
+ unsigned getNumStores() const { return LAI->getNumStores(); }
+ unsigned getNumLoads() const { return LAI->getNumLoads(); }
+
+ // Returns true if the NoNaN attribute is set on the function.
+ bool hasFunNoNaNAttr() const { return HasFunNoNaNAttr; }
+
+private:
+ /// Return true if the pre-header, exiting and latch blocks of \p Lp and all
+ /// its nested loops are considered legal for vectorization. These legal
+ /// checks are common for inner and outer loop vectorization.
+ /// Temporarily taking UseVPlanNativePath parameter. If true, take
+ /// the new code path being implemented for outer loop vectorization
+ /// (should be functional for inner loop vectorization) based on VPlan.
+ /// If false, good old LV code.
+ bool canVectorizeLoopNestCFG(Loop *Lp, bool UseVPlanNativePath);
+
+ /// Return true if the pre-header, exiting and latch blocks of \p Lp
+ /// (non-recursive) are considered legal for vectorization.
+ /// Temporarily taking UseVPlanNativePath parameter. If true, take
+ /// the new code path being implemented for outer loop vectorization
+ /// (should be functional for inner loop vectorization) based on VPlan.
+ /// If false, good old LV code.
+ bool canVectorizeLoopCFG(Loop *Lp, bool UseVPlanNativePath);
+
+ /// Check if a single basic block loop is vectorizable.
+ /// At this point we know that this is a loop with a constant trip count
+ /// and we only need to check individual instructions.
+ bool canVectorizeInstrs();
+
+ /// When we vectorize loops we may change the order in which
+ /// we read and write from memory. This method checks if it is
+ /// legal to vectorize the code, considering only memory constrains.
+ /// Returns true if the loop is vectorizable
+ bool canVectorizeMemory();
+
+ /// Return true if we can vectorize this loop using the IF-conversion
+ /// transformation.
+ bool canVectorizeWithIfConvert();
+
+ /// Return true if we can vectorize this outer loop. The method performs
+ /// specific checks for outer loop vectorization.
+ bool canVectorizeOuterLoop();
+
+ /// Return true if all of the instructions in the block can be speculatively
+ /// executed. \p SafePtrs is a list of addresses that are known to be legal
+ /// and we know that we can read from them without segfault.
+ bool blockCanBePredicated(BasicBlock *BB, SmallPtrSetImpl<Value *> &SafePtrs);
+
+ /// Updates the vectorization state by adding \p Phi to the inductions list.
+ /// This can set \p Phi as the main induction of the loop if \p Phi is a
+ /// better choice for the main induction than the existing one.
+ void addInductionPhi(PHINode *Phi, const InductionDescriptor &ID,
+ SmallPtrSetImpl<Value *> &AllowedExit);
+
+ /// Create an analysis remark that explains why vectorization failed
+ ///
+ /// \p RemarkName is the identifier for the remark. If \p I is passed it is
+ /// an instruction that prevents vectorization. Otherwise the loop is used
+ /// for the location of the remark. \return the remark object that can be
+ /// streamed to.
+ OptimizationRemarkAnalysis
+ createMissedAnalysis(StringRef RemarkName, Instruction *I = nullptr) const {
+ return createLVMissedAnalysis(Hints->vectorizeAnalysisPassName(),
+ RemarkName, TheLoop, I);
+ }
+
+ /// If an access has a symbolic strides, this maps the pointer value to
+ /// the stride symbol.
+ const ValueToValueMap *getSymbolicStrides() {
+ // FIXME: Currently, the set of symbolic strides is sometimes queried before
+ // it's collected. This happens from canVectorizeWithIfConvert, when the
+ // pointer is checked to reference consecutive elements suitable for a
+ // masked access.
+ return LAI ? &LAI->getSymbolicStrides() : nullptr;
+ }
+
+ /// The loop that we evaluate.
+ Loop *TheLoop;
+
+ /// Loop Info analysis.
+ LoopInfo *LI;
+
+ /// A wrapper around ScalarEvolution used to add runtime SCEV checks.
+ /// Applies dynamic knowledge to simplify SCEV expressions in the context
+ /// of existing SCEV assumptions. The analysis will also add a minimal set
+ /// of new predicates if this is required to enable vectorization and
+ /// unrolling.
+ PredicatedScalarEvolution &PSE;
+
+ /// Target Library Info.
+ TargetLibraryInfo *TLI;
+
+ /// Dominator Tree.
+ DominatorTree *DT;
+
+ // LoopAccess analysis.
+ std::function<const LoopAccessInfo &(Loop &)> *GetLAA;
+
+ // And the loop-accesses info corresponding to this loop. This pointer is
+ // null until canVectorizeMemory sets it up.
+ const LoopAccessInfo *LAI = nullptr;
+
+ /// Interface to emit optimization remarks.
+ OptimizationRemarkEmitter *ORE;
+
+ // --- vectorization state --- //
+
+ /// Holds the primary induction variable. This is the counter of the
+ /// loop.
+ PHINode *PrimaryInduction = nullptr;
+
+ /// Holds the reduction variables.
+ ReductionList Reductions;
+
+ /// Holds all of the induction variables that we found in the loop.
+ /// Notice that inductions don't need to start at zero and that induction
+ /// variables can be pointers.
+ InductionList Inductions;
+
+ /// Holds all the casts that participate in the update chain of the induction
+ /// variables, and that have been proven to be redundant (possibly under a
+ /// runtime guard). These casts can be ignored when creating the vectorized
+ /// loop body.
+ SmallPtrSet<Instruction *, 4> InductionCastsToIgnore;
+
+ /// Holds the phi nodes that are first-order recurrences.
+ RecurrenceSet FirstOrderRecurrences;
+
+ /// Holds instructions that need to sink past other instructions to handle
+ /// first-order recurrences.
+ DenseMap<Instruction *, Instruction *> SinkAfter;
+
+ /// Holds the widest induction type encountered.
+ Type *WidestIndTy = nullptr;
+
+ /// Allowed outside users. This holds the induction and reduction
+ /// vars which can be accessed from outside the loop.
+ SmallPtrSet<Value *, 4> AllowedExit;
+
+ /// Can we assume the absence of NaNs.
+ bool HasFunNoNaNAttr = false;
+
+ /// Vectorization requirements that will go through late-evaluation.
+ LoopVectorizationRequirements *Requirements;
+
+ /// Used to emit an analysis of any legality issues.
+ LoopVectorizeHints *Hints;
+
+ /// The demanded bits analsyis is used to compute the minimum type size in
+ /// which a reduction can be computed.
+ DemandedBits *DB;
+
+ /// The assumption cache analysis is used to compute the minimum type size in
+ /// which a reduction can be computed.
+ AssumptionCache *AC;
+
+ /// While vectorizing these instructions we have to generate a
+ /// call to the appropriate masked intrinsic
+ SmallPtrSet<const Instruction *, 8> MaskedOp;
+};
+
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONLEGALITY_H
diff --git a/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h b/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h
index 32b56d372ea1..d79d84691803 100644
--- a/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h
+++ b/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h
@@ -26,6 +26,14 @@
// of vectorization. It decides on the optimal vector width, which
// can be one, if vectorization is not profitable.
//
+// There is a development effort going on to migrate loop vectorizer to the
+// VPlan infrastructure and to introduce outer loop vectorization support (see
+// docs/Proposal/VectorizationPlan.rst and
+// http://lists.llvm.org/pipermail/llvm-dev/2017-December/119523.html). For this
+// purpose, we temporarily introduced the VPlan-native vectorization path: an
+// alternative vectorization path that is natively implemented on top of the
+// VPlan infrastructure. See EnableVPlanNativePath for enabling.
+//
//===----------------------------------------------------------------------===//
//
// The reduction-variable vectorization is based on the paper:
diff --git a/contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h b/contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h
index 781a628a0974..3152e8192fc5 100644
--- a/contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h
+++ b/contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h
@@ -82,7 +82,7 @@ public:
OptimizationRemarkEmitter *ORE_);
private:
- /// \brief Collect store and getelementptr instructions and organize them
+ /// Collect store and getelementptr instructions and organize them
/// according to the underlying object of their pointer operands. We sort the
/// instructions by their underlying objects to reduce the cost of
/// consecutive access queries.
@@ -91,21 +91,23 @@ private:
/// every time we run into a memory barrier.
void collectSeedInstructions(BasicBlock *BB);
- /// \brief Try to vectorize a chain that starts at two arithmetic instrs.
+ /// Try to vectorize a chain that starts at two arithmetic instrs.
bool tryToVectorizePair(Value *A, Value *B, slpvectorizer::BoUpSLP &R);
- /// \brief Try to vectorize a list of operands.
+ /// Try to vectorize a list of operands.
+ /// \param UserCost Cost of the user operations of \p VL if they may affect
+ /// the cost of the vectorization.
/// \returns true if a value was vectorized.
bool tryToVectorizeList(ArrayRef<Value *> VL, slpvectorizer::BoUpSLP &R,
- bool AllowReorder = false);
+ int UserCost = 0, bool AllowReorder = false);
- /// \brief Try to vectorize a chain that may start at the operands of \p I.
+ /// Try to vectorize a chain that may start at the operands of \p I.
bool tryToVectorize(Instruction *I, slpvectorizer::BoUpSLP &R);
- /// \brief Vectorize the store instructions collected in Stores.
+ /// Vectorize the store instructions collected in Stores.
bool vectorizeStoreChains(slpvectorizer::BoUpSLP &R);
- /// \brief Vectorize the index computations of the getelementptr instructions
+ /// Vectorize the index computations of the getelementptr instructions
/// collected in GEPs.
bool vectorizeGEPIndices(BasicBlock *BB, slpvectorizer::BoUpSLP &R);
@@ -131,7 +133,7 @@ private:
bool vectorizeSimpleInstructions(SmallVectorImpl<WeakVH> &Instructions,
BasicBlock *BB, slpvectorizer::BoUpSLP &R);
- /// \brief Scan the basic block and look for patterns that are likely to start
+ /// Scan the basic block and look for patterns that are likely to start
/// a vectorization chain.
bool vectorizeChainsInBlock(BasicBlock *BB, slpvectorizer::BoUpSLP &R);
diff --git a/contrib/llvm/include/llvm/XRay/XRayRecord.h b/contrib/llvm/include/llvm/XRay/XRayRecord.h
index 5c5e9f436f4a..76873447f170 100644
--- a/contrib/llvm/include/llvm/XRay/XRayRecord.h
+++ b/contrib/llvm/include/llvm/XRay/XRayRecord.h
@@ -75,6 +75,9 @@ struct XRayRecord {
/// The thread ID for the currently running thread.
uint32_t TId;
+ /// The process ID for the currently running process.
+ uint32_t PId;
+
/// The function call arguments.
std::vector<uint64_t> CallArgs;
};
diff --git a/contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h b/contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h
index b436aefb1e8f..0de9ea0968e6 100644
--- a/contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h
+++ b/contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h
@@ -37,6 +37,7 @@ struct YAMLXRayRecord {
std::string Function;
uint64_t TSC;
uint32_t TId;
+ uint32_t PId;
std::vector<uint64_t> CallArgs;
};
@@ -79,6 +80,7 @@ template <> struct MappingTraits<xray::YAMLXRayRecord> {
IO.mapOptional("args", Record.CallArgs);
IO.mapRequired("cpu", Record.CPU);
IO.mapRequired("thread", Record.TId);
+ IO.mapOptional("process", Record.PId, 0U);
IO.mapRequired("kind", Record.Type);
IO.mapRequired("tsc", Record.TSC);
}
diff --git a/contrib/llvm/include/llvm/module.modulemap b/contrib/llvm/include/llvm/module.modulemap
index d8b07c4f54da..649cdf3b0a89 100644
--- a/contrib/llvm/include/llvm/module.modulemap
+++ b/contrib/llvm/include/llvm/module.modulemap
@@ -20,15 +20,12 @@ module LLVM_Backend {
// Exclude these; they're intended to be included into only a single
// translation unit (or none) and aren't part of this module.
- exclude header "CodeGen/CommandFlags.h"
exclude header "CodeGen/LinkAllAsmWriterComponents.h"
exclude header "CodeGen/LinkAllCodegenComponents.h"
// These are intended for (repeated) textual inclusion.
- textual header "CodeGen/CommandFlags.def"
+ textual header "CodeGen/CommandFlags.inc"
textual header "CodeGen/DIEValue.def"
- textual header "CodeGen/RuntimeLibcalls.def"
- textual header "CodeGen/TargetOpcodes.def"
}
module Target {
@@ -43,6 +40,7 @@ module LLVM_BinaryFormat {
requires cplusplus
umbrella "BinaryFormat" module * { export * }
textual header "BinaryFormat/Dwarf.def"
+ textual header "BinaryFormat/DynamicTags.def"
textual header "BinaryFormat/MachO.def"
textual header "BinaryFormat/ELFRelocs/AArch64.def"
textual header "BinaryFormat/ELFRelocs/AMDGPU.def"
@@ -60,7 +58,6 @@ module LLVM_BinaryFormat {
textual header "BinaryFormat/ELFRelocs/Sparc.def"
textual header "BinaryFormat/ELFRelocs/SystemZ.def"
textual header "BinaryFormat/ELFRelocs/x86_64.def"
- textual header "BinaryFormat/ELFRelocs/WebAssembly.def"
textual header "BinaryFormat/WasmRelocs.def"
}
@@ -90,16 +87,21 @@ module LLVM_DebugInfo_PDB {
// 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/DIAEnumInjectedSources.h"
exclude header "DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumSectionContribs.h"
exclude header "DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
exclude header "DebugInfo/PDB/DIA/DIAEnumSymbols.h"
exclude header "DebugInfo/PDB/DIA/DIAEnumTables.h"
+ exclude header "DebugInfo/PDB/DIA/DIAInjectedSource.h"
exclude header "DebugInfo/PDB/DIA/DIALineNumber.h"
exclude header "DebugInfo/PDB/DIA/DIARawSymbol.h"
+ exclude header "DebugInfo/PDB/DIA/DIASectionContrib.h"
exclude header "DebugInfo/PDB/DIA/DIASession.h"
exclude header "DebugInfo/PDB/DIA/DIASourceFile.h"
exclude header "DebugInfo/PDB/DIA/DIASupport.h"
exclude header "DebugInfo/PDB/DIA/DIATable.h"
+ exclude header "DebugInfo/PDB/DIA/DIAUtils.h"
}
module LLVM_DebugInfo_PDB_DIA {
@@ -192,6 +194,8 @@ module LLVM_intrinsic_gen {
module IR_CFG { header "IR/CFG.h" export * }
module IR_ConstantRange { header "IR/ConstantRange.h" export * }
module IR_Dominators { header "IR/Dominators.h" export * }
+ module Analysis_PostDominators { header "Analysis/PostDominators.h" export * }
+ module IR_DomTreeUpdater { header "IR/DomTreeUpdater.h" export * }
module IR_IRBuilder { header "IR/IRBuilder.h" export * }
module IR_PassManager { header "IR/PassManager.h" export * }
module IR_PredIteratorCache { header "IR/PredIteratorCache.h" export * }
@@ -217,6 +221,7 @@ module LLVM_IR {
textual header "IR/Instruction.def"
textual header "IR/Metadata.def"
textual header "IR/Value.def"
+ textual header "IR/RuntimeLibcalls.def"
}
module LLVM_IRReader { requires cplusplus umbrella "IRReader" module * { export * } }
@@ -229,7 +234,7 @@ module LLVM_MC {
umbrella "MC"
module * { export * }
- textual header "MC/MCTargetOptionsCommandFlags.def"
+ textual header "MC/MCTargetOptionsCommandFlags.inc"
}
// Used by llvm-tblgen
@@ -297,6 +302,7 @@ module LLVM_Utils {
// These are intended for textual inclusion.
textual header "Support/ARMTargetParser.def"
textual header "Support/AArch64TargetParser.def"
+ textual header "Support/TargetOpcodes.def"
textual header "Support/X86TargetParser.def"
}
@@ -305,12 +311,6 @@ module LLVM_Utils {
header "Support/ConvertUTF.h"
export *
}
-
- module LLVM_CodeGen_MachineValueType {
- requires cplusplus
- header "CodeGen/MachineValueType.h"
- export *
- }
}
// This is used for a $src == $build compilation. Otherwise we use