aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-01-18 16:17:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-01-18 16:17:27 +0000
commit67c32a98315f785a9ec9d531c1f571a0196c7463 (patch)
tree4abb9cbeecc7901726dd0b4a37369596c852e9ef /include
parent9f61947910e6ab40de38e6b4034751ef1513200f (diff)
downloadsrc-67c32a98315f785a9ec9d531c1f571a0196c7463.tar.gz
src-67c32a98315f785a9ec9d531c1f571a0196c7463.zip
Notes
Diffstat (limited to 'include')
-rw-r--r--include/llvm-c/BitReader.h4
-rw-r--r--include/llvm-c/BitWriter.h7
-rw-r--r--include/llvm-c/Core.h126
-rw-r--r--include/llvm-c/Disassembler.h20
-rw-r--r--include/llvm-c/ExecutionEngine.h5
-rw-r--r--include/llvm-c/Initialization.h4
-rw-r--r--include/llvm-c/Linker.h9
-rw-r--r--include/llvm-c/Support.h11
-rw-r--r--include/llvm-c/Transforms/Scalar.h9
-rw-r--r--include/llvm-c/lto.h50
-rw-r--r--include/llvm/ADT/APFloat.h103
-rw-r--r--include/llvm/ADT/APInt.h23
-rw-r--r--include/llvm/ADT/APSInt.h16
-rw-r--r--include/llvm/ADT/ArrayRef.h71
-rw-r--r--include/llvm/ADT/BitVector.h3
-rw-r--r--include/llvm/ADT/DenseMap.h209
-rw-r--r--include/llvm/ADT/DenseSet.h54
-rw-r--r--include/llvm/ADT/DepthFirstIterator.h16
-rw-r--r--include/llvm/ADT/IntrusiveRefCntPtr.h3
-rw-r--r--include/llvm/ADT/MapVector.h48
-rw-r--r--include/llvm/ADT/Optional.h68
-rw-r--r--include/llvm/ADT/PostOrderIterator.h7
-rw-r--r--include/llvm/ADT/STLExtras.h33
-rw-r--r--include/llvm/ADT/ScopedHashTable.h4
-rw-r--r--include/llvm/ADT/SetVector.h4
-rw-r--r--include/llvm/ADT/SmallBitVector.h8
-rw-r--r--include/llvm/ADT/SmallPtrSet.h21
-rw-r--r--include/llvm/ADT/SmallSet.h16
-rw-r--r--include/llvm/ADT/SmallVector.h145
-rw-r--r--include/llvm/ADT/SparseBitVector.h2
-rw-r--r--include/llvm/ADT/SparseMultiSet.h2
-rw-r--r--include/llvm/ADT/SparseSet.h2
-rw-r--r--include/llvm/ADT/StringMap.h45
-rw-r--r--include/llvm/ADT/StringRef.h34
-rw-r--r--include/llvm/ADT/StringSet.h15
-rw-r--r--include/llvm/ADT/TinyPtrVector.h9
-rw-r--r--include/llvm/ADT/Triple.h52
-rw-r--r--include/llvm/ADT/Twine.h14
-rw-r--r--include/llvm/ADT/VariadicFunction.h8
-rw-r--r--include/llvm/ADT/ilist.h54
-rw-r--r--include/llvm/ADT/ilist_node.h4
-rw-r--r--include/llvm/ADT/iterator.h2
-rw-r--r--include/llvm/ADT/iterator_range.h5
-rw-r--r--include/llvm/Analysis/AliasAnalysis.h55
-rw-r--r--include/llvm/Analysis/AliasSetTracker.h61
-rw-r--r--include/llvm/Analysis/AssumptionCache.h142
-rw-r--r--include/llvm/Analysis/BlockFrequencyInfoImpl.h2
-rw-r--r--include/llvm/Analysis/BranchProbabilityInfo.h4
-rw-r--r--include/llvm/Analysis/CFGPrinter.h14
-rw-r--r--include/llvm/Analysis/CGSCCPassManager.h196
-rw-r--r--include/llvm/Analysis/CallGraph.h39
-rw-r--r--include/llvm/Analysis/CodeMetrics.h16
-rw-r--r--include/llvm/Analysis/DOTGraphTraitsPass.h12
-rw-r--r--include/llvm/Analysis/DependenceAnalysis.h16
-rw-r--r--include/llvm/Analysis/DominanceFrontier.h2
-rw-r--r--include/llvm/Analysis/DominanceFrontierImpl.h8
-rw-r--r--include/llvm/Analysis/FindUsedTypes.h66
-rw-r--r--include/llvm/Analysis/FunctionTargetTransformInfo.h49
-rw-r--r--include/llvm/Analysis/IVUsers.h2
-rw-r--r--include/llvm/Analysis/InlineCost.h2
-rw-r--r--include/llvm/Analysis/InstructionSimplify.h134
-rw-r--r--include/llvm/Analysis/IntervalIterator.h4
-rw-r--r--include/llvm/Analysis/JumpInstrTableInfo.h15
-rw-r--r--include/llvm/Analysis/LazyCallGraph.h20
-rw-r--r--include/llvm/Analysis/LazyValueInfo.h37
-rw-r--r--include/llvm/Analysis/Loads.h6
-rw-r--r--include/llvm/Analysis/LoopPass.h9
-rw-r--r--include/llvm/Analysis/MemoryDependenceAnalysis.h26
-rw-r--r--include/llvm/Analysis/PHITransAddr.h10
-rw-r--r--include/llvm/Analysis/Passes.h16
-rw-r--r--include/llvm/Analysis/PostDominators.h2
-rw-r--r--include/llvm/Analysis/RegionInfo.h4
-rw-r--r--include/llvm/Analysis/RegionInfoImpl.h8
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h36
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpressions.h6
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h36
-rw-r--r--include/llvm/Analysis/ValueTracking.h53
-rw-r--r--include/llvm/AsmParser/Parser.h52
-rw-r--r--include/llvm/Bitcode/BitCodes.h12
-rw-r--r--include/llvm/Bitcode/BitcodeWriterPass.h6
-rw-r--r--include/llvm/Bitcode/BitstreamReader.h333
-rw-r--r--include/llvm/Bitcode/BitstreamWriter.h33
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h15
-rw-r--r--include/llvm/Bitcode/ReaderWriter.h70
-rw-r--r--include/llvm/CMakeLists.txt13
-rw-r--r--include/llvm/CodeGen/Analysis.h28
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h29
-rw-r--r--include/llvm/CodeGen/CalcSpillWeights.h6
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h54
-rw-r--r--include/llvm/CodeGen/CommandFlags.h65
-rw-r--r--include/llvm/CodeGen/DFAPacketizer.h5
-rw-r--r--include/llvm/CodeGen/DIE.h587
-rw-r--r--include/llvm/CodeGen/FastISel.h543
-rw-r--r--include/llvm/CodeGen/ForwardControlFlowIntegrity.h122
-rw-r--r--include/llvm/CodeGen/FunctionLoweringInfo.h19
-rw-r--r--include/llvm/CodeGen/GCMetadata.h36
-rw-r--r--include/llvm/CodeGen/GCMetadataPrinter.h26
-rw-r--r--include/llvm/CodeGen/GCStrategy.h173
-rw-r--r--include/llvm/CodeGen/GCs.h2
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h13
-rw-r--r--include/llvm/CodeGen/JITCodeEmitter.h344
-rw-r--r--include/llvm/CodeGen/JumpInstrTables.h31
-rw-r--r--include/llvm/CodeGen/LexicalScopes.h18
-rw-r--r--include/llvm/CodeGen/LinkAllCodegenComponents.h1
-rw-r--r--include/llvm/CodeGen/LiveInterval.h180
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h53
-rw-r--r--include/llvm/CodeGen/LiveIntervalUnion.h10
-rw-r--r--include/llvm/CodeGen/LivePhysRegs.h6
-rw-r--r--include/llvm/CodeGen/LiveRangeEdit.h20
-rw-r--r--include/llvm/CodeGen/LiveVariables.h10
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h6
-rw-r--r--include/llvm/CodeGen/MachineCodeEmitter.h334
-rw-r--r--include/llvm/CodeGen/MachineCodeInfo.h53
-rw-r--r--include/llvm/CodeGen/MachineCombinerPattern.h29
-rw-r--r--include/llvm/CodeGen/MachineDominators.h142
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h58
-rw-r--r--include/llvm/CodeGen/MachineFunction.h28
-rw-r--r--include/llvm/CodeGen/MachineInstr.h71
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h49
-rw-r--r--include/llvm/CodeGen/MachineMemOperand.h10
-rw-r--r--include/llvm/CodeGen/MachineModuleInfo.h56
-rw-r--r--include/llvm/CodeGen/MachineOperand.h12
-rw-r--r--include/llvm/CodeGen/MachinePostDominators.h2
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h31
-rw-r--r--include/llvm/CodeGen/MachineRelocation.h342
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h3
-rw-r--r--include/llvm/CodeGen/MachineTraceMetrics.h15
-rw-r--r--include/llvm/CodeGen/MachineValueType.h63
-rw-r--r--include/llvm/CodeGen/PBQP/CostAllocator.h151
-rw-r--r--include/llvm/CodeGen/PBQP/Graph.h185
-rw-r--r--include/llvm/CodeGen/PBQP/Math.h65
-rw-r--r--include/llvm/CodeGen/PBQP/ReductionRules.h10
-rw-r--r--include/llvm/CodeGen/PBQP/RegAllocSolver.h359
-rw-r--r--include/llvm/CodeGen/PBQP/Solution.h4
-rw-r--r--include/llvm/CodeGen/PBQPRAConstraint.h69
-rw-r--r--include/llvm/CodeGen/Passes.h82
-rw-r--r--include/llvm/CodeGen/RegAllocPBQP.h613
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h62
-rw-r--r--include/llvm/CodeGen/RuntimeLibcalls.h10
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h6
-rw-r--r--include/llvm/CodeGen/ScheduleDAGInstrs.h6
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h82
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h14
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h130
-rw-r--r--include/llvm/CodeGen/StackMapLivenessAnalysis.h6
-rw-r--r--include/llvm/CodeGen/StackMaps.h70
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h2
-rw-r--r--include/llvm/CodeGen/TargetSchedule.h3
-rw-r--r--include/llvm/Config/config.h.cmake15
-rw-r--r--include/llvm/Config/config.h.in6
-rw-r--r--include/llvm/Config/llvm-config.h.cmake3
-rw-r--r--include/llvm/Config/llvm-config.h.in3
-rw-r--r--include/llvm/DebugInfo/DIContext.h15
-rw-r--r--include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h60
-rw-r--r--include/llvm/DebugInfo/DWARFAcceleratorTable.h49
-rw-r--r--include/llvm/DebugInfo/DWARFCompileUnit.h31
-rw-r--r--include/llvm/DebugInfo/DWARFContext.h292
-rw-r--r--include/llvm/DebugInfo/DWARFDebugAbbrev.h63
-rw-r--r--include/llvm/DebugInfo/DWARFDebugArangeSet.h70
-rw-r--r--include/llvm/DebugInfo/DWARFDebugAranges.h87
-rw-r--r--include/llvm/DebugInfo/DWARFDebugFrame.h43
-rw-r--r--include/llvm/DebugInfo/DWARFDebugInfoEntry.h160
-rw-r--r--include/llvm/DebugInfo/DWARFDebugLine.h238
-rw-r--r--include/llvm/DebugInfo/DWARFDebugLoc.h81
-rw-r--r--include/llvm/DebugInfo/DWARFDebugRangeList.h77
-rw-r--r--include/llvm/DebugInfo/DWARFFormValue.h8
-rw-r--r--include/llvm/DebugInfo/DWARFRelocMap.h22
-rw-r--r--include/llvm/DebugInfo/DWARFSection.h24
-rw-r--r--include/llvm/DebugInfo/DWARFTypeUnit.h38
-rw-r--r--include/llvm/DebugInfo/DWARFUnit.h245
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h202
-rw-r--r--include/llvm/ExecutionEngine/JIT.h38
-rw-r--r--include/llvm/ExecutionEngine/JITEventListener.h36
-rw-r--r--include/llvm/ExecutionEngine/JITMemoryManager.h164
-rw-r--r--include/llvm/ExecutionEngine/ObjectBuffer.h83
-rw-r--r--include/llvm/ExecutionEngine/ObjectCache.h11
-rw-r--r--include/llvm/ExecutionEngine/ObjectImage.h71
-rw-r--r--include/llvm/ExecutionEngine/RTDyldMemoryManager.h21
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyld.h51
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyldChecker.h53
-rw-r--r--include/llvm/IR/Argument.h8
-rw-r--r--include/llvm/IR/AssemblyAnnotationWriter.h4
-rw-r--r--include/llvm/IR/BasicBlock.h16
-rw-r--r--include/llvm/IR/CFG.h6
-rw-r--r--include/llvm/IR/CallingConv.h11
-rw-r--r--include/llvm/IR/Constant.h8
-rw-r--r--include/llvm/IR/ConstantRange.h99
-rw-r--r--include/llvm/IR/Constants.h158
-rw-r--r--include/llvm/IR/DIBuilder.h224
-rw-r--r--include/llvm/IR/DataLayout.h311
-rw-r--r--include/llvm/IR/DebugInfo.h776
-rw-r--r--include/llvm/IR/DebugLoc.h98
-rw-r--r--include/llvm/IR/DerivedTypes.h17
-rw-r--r--include/llvm/IR/DiagnosticInfo.h17
-rw-r--r--include/llvm/IR/DiagnosticPrinter.h4
-rw-r--r--include/llvm/IR/Dominators.h49
-rw-r--r--include/llvm/IR/Function.h33
-rw-r--r--include/llvm/IR/GVMaterializer.h10
-rw-r--r--include/llvm/IR/GlobalObject.h16
-rw-r--r--include/llvm/IR/GlobalValue.h12
-rw-r--r--include/llvm/IR/IRBuilder.h139
-rw-r--r--include/llvm/IR/IRPrintingPasses.h8
-rw-r--r--include/llvm/IR/InlineAsm.h12
-rw-r--r--include/llvm/IR/InstrTypes.h88
-rw-r--r--include/llvm/IR/Instruction.h42
-rw-r--r--include/llvm/IR/Instructions.h24
-rw-r--r--include/llvm/IR/IntrinsicInst.h46
-rw-r--r--include/llvm/IR/Intrinsics.h44
-rw-r--r--include/llvm/IR/Intrinsics.td59
-rw-r--r--include/llvm/IR/IntrinsicsARM.td12
-rw-r--r--include/llvm/IR/IntrinsicsNVVM.td18
-rw-r--r--include/llvm/IR/IntrinsicsPowerPC.td70
-rw-r--r--include/llvm/IR/IntrinsicsR600.td17
-rw-r--r--include/llvm/IR/IntrinsicsX86.td780
-rw-r--r--include/llvm/IR/LLVMContext.h34
-rw-r--r--include/llvm/IR/LeakDetector.h92
-rw-r--r--include/llvm/IR/LegacyPassManager.h12
-rw-r--r--include/llvm/IR/LegacyPassManagers.h10
-rw-r--r--include/llvm/IR/MDBuilder.h48
-rw-r--r--include/llvm/IR/Mangler.h6
-rw-r--r--include/llvm/IR/Metadata.def59
-rw-r--r--include/llvm/IR/Metadata.h954
-rw-r--r--include/llvm/IR/MetadataTracking.h99
-rw-r--r--include/llvm/IR/Module.h96
-rw-r--r--include/llvm/IR/Operator.h72
-rw-r--r--include/llvm/IR/PassManager.h821
-rw-r--r--include/llvm/IR/PassManagerInternal.h349
-rw-r--r--include/llvm/IR/PatternMatch.h766
-rw-r--r--include/llvm/IR/PredIteratorCache.h6
-rw-r--r--include/llvm/IR/Statepoint.h215
-rw-r--r--include/llvm/IR/TrackingMDRef.h170
-rw-r--r--include/llvm/IR/Type.h9
-rw-r--r--include/llvm/IR/TypeFinder.h1
-rw-r--r--include/llvm/IR/UseListOrder.h62
-rw-r--r--include/llvm/IR/User.h45
-rw-r--r--include/llvm/IR/Value.h334
-rw-r--r--include/llvm/IR/ValueHandle.h165
-rw-r--r--include/llvm/IR/ValueMap.h45
-rw-r--r--include/llvm/IR/Verifier.h4
-rw-r--r--include/llvm/IRReader/IRReader.h17
-rw-r--r--include/llvm/InitializePasses.h15
-rw-r--r--include/llvm/LTO/LTOCodeGenerator.h24
-rw-r--r--include/llvm/LTO/LTOModule.h37
-rw-r--r--include/llvm/LinkAllPasses.h13
-rw-r--r--include/llvm/Linker/Linker.h84
-rw-r--r--include/llvm/MC/ConstantPools.h6
-rw-r--r--include/llvm/MC/MCAnalysis/MCAtom.h199
-rw-r--r--include/llvm/MC/MCAnalysis/MCFunction.h142
-rw-r--r--include/llvm/MC/MCAnalysis/MCModule.h134
-rw-r--r--include/llvm/MC/MCAnalysis/MCModuleYAML.h40
-rw-r--r--include/llvm/MC/MCAsmBackend.h18
-rw-r--r--include/llvm/MC/MCAsmInfo.h84
-rw-r--r--include/llvm/MC/MCAsmInfoDarwin.h2
-rw-r--r--include/llvm/MC/MCAsmInfoELF.h3
-rw-r--r--include/llvm/MC/MCAssembler.h80
-rw-r--r--include/llvm/MC/MCContext.h15
-rw-r--r--include/llvm/MC/MCDisassembler.h31
-rw-r--r--include/llvm/MC/MCDwarf.h14
-rw-r--r--include/llvm/MC/MCELFStreamer.h13
-rw-r--r--include/llvm/MC/MCExpr.h51
-rw-r--r--include/llvm/MC/MCInst.h9
-rw-r--r--include/llvm/MC/MCInstPrinter.h2
-rw-r--r--include/llvm/MC/MCInstrDesc.h69
-rw-r--r--include/llvm/MC/MCInstrItineraries.h59
-rw-r--r--include/llvm/MC/MCLinkerOptimizationHint.h4
-rw-r--r--include/llvm/MC/MCMachObjectWriter.h34
-rw-r--r--include/llvm/MC/MCObjectDisassembler.h174
-rw-r--r--include/llvm/MC/MCObjectFileInfo.h9
-rw-r--r--include/llvm/MC/MCObjectStreamer.h13
-rw-r--r--include/llvm/MC/MCObjectSymbolizer.h83
-rw-r--r--include/llvm/MC/MCObjectWriter.h6
-rw-r--r--include/llvm/MC/MCParser/AsmLexer.h2
-rw-r--r--include/llvm/MC/MCParser/MCAsmLexer.h43
-rw-r--r--include/llvm/MC/MCParser/MCAsmParser.h73
-rw-r--r--include/llvm/MC/MCParser/MCAsmParserExtension.h9
-rw-r--r--include/llvm/MC/MCRegisterInfo.h85
-rw-r--r--include/llvm/MC/MCSchedule.h57
-rw-r--r--include/llvm/MC/MCStreamer.h51
-rw-r--r--include/llvm/MC/MCSubtargetInfo.h23
-rw-r--r--include/llvm/MC/MCSymbol.h18
-rw-r--r--include/llvm/MC/MCTargetAsmParser.h41
-rw-r--r--include/llvm/MC/MCTargetOptions.h14
-rw-r--r--include/llvm/MC/MCTargetOptionsCommandFlags.h8
-rw-r--r--include/llvm/MC/MCWin64EH.h40
-rw-r--r--include/llvm/MC/MCWinCOFFStreamer.h8
-rw-r--r--include/llvm/MC/MCWinEH.h55
-rw-r--r--include/llvm/MC/StringTableBuilder.h16
-rw-r--r--include/llvm/MC/SubtargetFeature.h8
-rw-r--r--include/llvm/Object/Archive.h31
-rw-r--r--include/llvm/Object/Binary.h62
-rw-r--r--include/llvm/Object/COFF.h500
-rw-r--r--include/llvm/Object/COFFYAML.h32
-rw-r--r--include/llvm/Object/ELF.h2
-rw-r--r--include/llvm/Object/ELFObjectFile.h299
-rw-r--r--include/llvm/Object/ELFTypes.h8
-rw-r--r--include/llvm/Object/ELFYAML.h10
-rw-r--r--include/llvm/Object/Error.h3
-rw-r--r--include/llvm/Object/IRObjectFile.h29
-rw-r--r--include/llvm/Object/MachO.h265
-rw-r--r--include/llvm/Object/MachOUniversal.h21
-rw-r--r--include/llvm/Object/ObjectFile.h195
-rw-r--r--include/llvm/Object/RelocVisitor.h319
-rw-r--r--include/llvm/Object/SymbolicFile.h22
-rw-r--r--include/llvm/Option/ArgList.h1
-rw-r--r--include/llvm/PassRegistry.h48
-rw-r--r--include/llvm/PassSupport.h9
-rw-r--r--include/llvm/ProfileData/CoverageMapping.h448
-rw-r--r--include/llvm/ProfileData/CoverageMappingReader.h208
-rw-r--r--include/llvm/ProfileData/CoverageMappingWriter.h63
-rw-r--r--include/llvm/ProfileData/InstrProfReader.h62
-rw-r--r--include/llvm/ProfileData/InstrProfWriter.h16
-rw-r--r--include/llvm/ProfileData/SampleProf.h247
-rw-r--r--include/llvm/ProfileData/SampleProfReader.h170
-rw-r--r--include/llvm/ProfileData/SampleProfWriter.h110
-rw-r--r--include/llvm/Support/ARMBuildAttributes.h17
-rw-r--r--include/llvm/Support/ARMEHABI.h6
-rw-r--r--include/llvm/Support/ARMWinEH.h16
-rw-r--r--include/llvm/Support/Allocator.h66
-rw-r--r--include/llvm/Support/CBindingWrapping.h4
-rw-r--r--include/llvm/Support/COFF.h67
-rw-r--r--include/llvm/Support/Casting.h34
-rw-r--r--include/llvm/Support/CodeGen.h4
-rw-r--r--include/llvm/Support/CommandLine.h843
-rw-r--r--include/llvm/Support/Compiler.h61
-rw-r--r--include/llvm/Support/Compression.h2
-rw-r--r--include/llvm/Support/CrashRecoveryContext.h11
-rw-r--r--include/llvm/Support/DataExtractor.h11
-rw-r--r--include/llvm/Support/DataTypes.h.cmake13
-rw-r--r--include/llvm/Support/DataTypes.h.in6
-rw-r--r--include/llvm/Support/Dwarf.h171
-rw-r--r--include/llvm/Support/DynamicLibrary.h11
-rw-r--r--include/llvm/Support/ELF.h767
-rw-r--r--include/llvm/Support/ELFRelocs/AArch64.def147
-rw-r--r--include/llvm/Support/ELFRelocs/ARM.def138
-rw-r--r--include/llvm/Support/ELFRelocs/Hexagon.def92
-rw-r--r--include/llvm/Support/ELFRelocs/Mips.def112
-rw-r--r--include/llvm/Support/ELFRelocs/PowerPC.def61
-rw-r--r--include/llvm/Support/ELFRelocs/PowerPC64.def88
-rw-r--r--include/llvm/Support/ELFRelocs/Sparc.def89
-rw-r--r--include/llvm/Support/ELFRelocs/SystemZ.def67
-rw-r--r--include/llvm/Support/ELFRelocs/i386.def47
-rw-r--r--include/llvm/Support/ELFRelocs/x86_64.def44
-rw-r--r--include/llvm/Support/Endian.h43
-rw-r--r--include/llvm/Support/EndianStream.h10
-rw-r--r--include/llvm/Support/ErrorOr.h52
-rw-r--r--include/llvm/Support/FileOutputBuffer.h4
-rw-r--r--include/llvm/Support/FileSystem.h81
-rw-r--r--include/llvm/Support/Format.h76
-rw-r--r--include/llvm/Support/GCOV.h10
-rw-r--r--include/llvm/Support/GenericDomTree.h298
-rw-r--r--include/llvm/Support/GenericDomTreeConstruction.h6
-rw-r--r--include/llvm/Support/IncludeFile.h79
-rw-r--r--include/llvm/Support/LEB128.h22
-rw-r--r--include/llvm/Support/LineIterator.h17
-rw-r--r--include/llvm/Support/MD5.h8
-rw-r--r--include/llvm/Support/MachO.h374
-rw-r--r--include/llvm/Support/ManagedStatic.h4
-rw-r--r--include/llvm/Support/MathExtras.h45
-rw-r--r--include/llvm/Support/MemoryBuffer.h105
-rw-r--r--include/llvm/Support/MemoryObject.h70
-rw-r--r--include/llvm/Support/Mutex.h21
-rw-r--r--include/llvm/Support/MutexGuard.h4
-rw-r--r--include/llvm/Support/OnDiskHashTable.h8
-rw-r--r--include/llvm/Support/Options.h120
-rw-r--r--include/llvm/Support/Path.h68
-rw-r--r--include/llvm/Support/Process.h117
-rw-r--r--include/llvm/Support/Program.h56
-rw-r--r--include/llvm/Support/RWMutex.h33
-rw-r--r--include/llvm/Support/RandomNumberGenerator.h35
-rw-r--r--include/llvm/Support/Registry.h1
-rw-r--r--include/llvm/Support/ScaledNumber.h1
-rw-r--r--include/llvm/Support/SourceMgr.h18
-rw-r--r--include/llvm/Support/SpecialCaseList.h16
-rw-r--r--include/llvm/Support/StreamableMemoryObject.h178
-rw-r--r--include/llvm/Support/StreamingMemoryObject.h92
-rw-r--r--include/llvm/Support/StringPool.h2
-rw-r--r--include/llvm/Support/StringRefMemoryObject.h41
-rw-r--r--include/llvm/Support/SwapByteOrder.h7
-rw-r--r--include/llvm/Support/TargetRegistry.h22
-rw-r--r--include/llvm/Support/ThreadLocal.h2
-rw-r--r--include/llvm/Support/Threading.h3
-rw-r--r--include/llvm/Support/TimeValue.h20
-rw-r--r--include/llvm/Support/ToolOutputFile.h14
-rw-r--r--include/llvm/Support/UniqueLock.h67
-rw-r--r--include/llvm/Support/Win64EH.h12
-rw-r--r--include/llvm/Support/WindowsError.h4
-rw-r--r--include/llvm/Support/YAMLParser.h5
-rw-r--r--include/llvm/Support/YAMLTraits.h12
-rw-r--r--include/llvm/Support/raw_ostream.h19
-rw-r--r--include/llvm/TableGen/Record.h95
-rw-r--r--include/llvm/TableGen/SetTheory.h4
-rw-r--r--include/llvm/TableGen/StringToOffsetTable.h12
-rw-r--r--include/llvm/Target/Target.td72
-rw-r--r--include/llvm/Target/TargetFrameLowering.h14
-rw-r--r--include/llvm/Target/TargetInstrInfo.h230
-rw-r--r--include/llvm/Target/TargetIntrinsicInfo.h2
-rw-r--r--include/llvm/Target/TargetJITInfo.h137
-rw-r--r--include/llvm/Target/TargetLibraryInfo.h27
-rw-r--r--include/llvm/Target/TargetLowering.h377
-rw-r--r--include/llvm/Target/TargetLoweringObjectFile.h8
-rw-r--r--include/llvm/Target/TargetMachine.h95
-rw-r--r--include/llvm/Target/TargetOpcodes.h19
-rw-r--r--include/llvm/Target/TargetOptions.h49
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h55
-rw-r--r--include/llvm/Target/TargetSelectionDAG.td20
-rw-r--r--include/llvm/Target/TargetSelectionDAGInfo.h2
-rw-r--r--include/llvm/Target/TargetSubtargetInfo.h61
-rw-r--r--include/llvm/Transforms/IPO/PassManagerBuilder.h16
-rw-r--r--include/llvm/Transforms/Instrumentation.h46
-rw-r--r--include/llvm/Transforms/Scalar.h18
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h5
-rw-r--r--include/llvm/Transforms/Utils/BuildLibCalls.h14
-rw-r--r--include/llvm/Transforms/Utils/Cloning.h11
-rw-r--r--include/llvm/Transforms/Utils/CodeExtractor.h4
-rw-r--r--include/llvm/Transforms/Utils/CtorUtils.h4
-rw-r--r--include/llvm/Transforms/Utils/Local.h25
-rw-r--r--include/llvm/Transforms/Utils/LoopUtils.h9
-rw-r--r--include/llvm/Transforms/Utils/ModuleUtils.h4
-rw-r--r--include/llvm/Transforms/Utils/PromoteMemToReg.h4
-rw-r--r--include/llvm/Transforms/Utils/SimplifyLibCalls.h175
-rw-r--r--include/llvm/Transforms/Utils/SymbolRewriter.h155
-rw-r--r--include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h4
-rw-r--r--include/llvm/Transforms/Utils/UnrollLoop.h3
-rw-r--r--include/llvm/Transforms/Utils/ValueMapper.h21
-rw-r--r--include/llvm/Transforms/Utils/VectorUtils.h14
-rw-r--r--include/llvm/module.modulemap27
426 files changed, 19812 insertions, 11209 deletions
diff --git a/include/llvm-c/BitReader.h b/include/llvm-c/BitReader.h
index 7af209bdfdce..f3b388bc4fb4 100644
--- a/include/llvm-c/BitReader.h
+++ b/include/llvm-c/BitReader.h
@@ -16,8 +16,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef LLVM_C_BITCODEREADER_H
-#define LLVM_C_BITCODEREADER_H
+#ifndef LLVM_C_BITREADER_H
+#define LLVM_C_BITREADER_H
#include "llvm-c/Core.h"
diff --git a/include/llvm-c/BitWriter.h b/include/llvm-c/BitWriter.h
index f605e2453f1c..f25ad3a445f5 100644
--- a/include/llvm-c/BitWriter.h
+++ b/include/llvm-c/BitWriter.h
@@ -16,8 +16,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef LLVM_C_BITCODEWRITER_H
-#define LLVM_C_BITCODEWRITER_H
+#ifndef LLVM_C_BITWRITER_H
+#define LLVM_C_BITWRITER_H
#include "llvm-c/Core.h"
@@ -45,6 +45,9 @@ int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose,
descriptor. Returns 0 on success. Closes the Handle. */
int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle);
+/** Writes a module to a new memory buffer and returns it. */
+LLVMMemoryBufferRef LLVMWriteBitcodeToMemoryBuffer(LLVMModuleRef M);
+
/**
* @}
*/
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index fdff77bc5e51..8873fdb67730 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -560,6 +560,10 @@ LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID);
*/
LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID,
LLVMContextRef C);
+/**
+ * Return an exact copy of the specified module.
+ */
+LLVMModuleRef LLVMCloneModule(LLVMModuleRef M);
/**
* Destroy a module instance.
@@ -1153,8 +1157,6 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(Argument) \
macro(BasicBlock) \
macro(InlineAsm) \
- macro(MDNode) \
- macro(MDString) \
macro(User) \
macro(Constant) \
macro(BlockAddress) \
@@ -1303,6 +1305,9 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val);
LLVMValueRef LLVMIsA##name(LLVMValueRef Val);
LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST)
+LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val);
+LLVMValueRef LLVMIsAMDString(LLVMValueRef Val);
+
/**
* @}
*/
@@ -1378,6 +1383,13 @@ LLVMValueRef LLVMGetUsedValue(LLVMUseRef U);
LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index);
/**
+ * Obtain the use of an operand at a specific index in a llvm::User value.
+ *
+ * @see llvm::User::getOperandUse()
+ */
+LLVMUseRef LLVMGetOperandUse(LLVMValueRef Val, unsigned Index);
+
+/**
* Set an operand at a specific index in a llvm::User value.
*
* @see llvm::User::setOperand()
@@ -1538,6 +1550,14 @@ unsigned long long LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal);
long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal);
/**
+ * Obtain the double value for an floating point constant value.
+ * losesInfo indicates if some precision was lost in the conversion.
+ *
+ * @see llvm::ConstantFP::getDoubleValue
+ */
+double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *losesInfo);
+
+/**
* @}
*/
@@ -1570,6 +1590,20 @@ LLVMValueRef LLVMConstString(const char *Str, unsigned Length,
LLVMBool DontNullTerminate);
/**
+ * Returns true if the specified constant is an array of i8.
+ *
+ * @see ConstantDataSequential::getAsString()
+ */
+LLVMBool LLVMIsConstantString(LLVMValueRef c);
+
+/**
+ * Get the given constant data sequential as a string.
+ *
+ * @see ConstantDataSequential::getAsString()
+ */
+const char *LLVMGetAsString(LLVMValueRef c, size_t* out);
+
+/**
* Create an anonymous ConstantStruct with the specified values.
*
* @see llvm::ConstantStruct::getAnon()
@@ -1607,6 +1641,13 @@ LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy,
unsigned Count);
/**
+ * Get an element at specified index as a constant.
+ *
+ * @see ConstantDataSequential::getElementAsConstant()
+ */
+LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef c, unsigned idx);
+
+/**
* Create a ConstantVector from values.
*
* @see llvm::ConstantVector::get()
@@ -2377,6 +2418,26 @@ LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst);
LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst);
/**
+ * Obtain the float predicate of an instruction.
+ *
+ * This is only valid for instructions that correspond to llvm::FCmpInst
+ * or llvm::ConstantExpr whose opcode is llvm::Instruction::FCmp.
+ *
+ * @see llvm::FCmpInst::getPredicate()
+ */
+LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst);
+
+/**
+ * Create a copy of 'this' instruction that is identical in all ways
+ * except the following:
+ * * The instruction has no parent
+ * * The instruction has no name
+ *
+ * @see llvm::Instruction::clone()
+ */
+LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
+
+/**
* @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations
*
* Functions in this group apply to instructions that refer to call
@@ -2437,6 +2498,63 @@ void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall);
*/
/**
+ * @defgroup LLVMCCoreValueInstructionTerminator Terminators
+ *
+ * Functions in this group only apply to instructions that map to
+ * llvm::TerminatorInst instances.
+ *
+ * @{
+ */
+
+/**
+ * Return the number of successors that this terminator has.
+ *
+ * @see llvm::TerminatorInst::getNumSuccessors
+ */
+unsigned LLVMGetNumSuccessors(LLVMValueRef Term);
+
+/**
+ * Return the specified successor.
+ *
+ * @see llvm::TerminatorInst::getSuccessor
+ */
+LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i);
+
+/**
+ * Update the specified successor to point at the provided block.
+ *
+ * @see llvm::TerminatorInst::setSuccessor
+ */
+void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block);
+
+/**
+ * Return if a branch is conditional.
+ *
+ * This only works on llvm::BranchInst instructions.
+ *
+ * @see llvm::BranchInst::isConditional
+ */
+LLVMBool LLVMIsConditional(LLVMValueRef Branch);
+
+/**
+ * Return the condition of a branch instruction.
+ *
+ * This only works on llvm::BranchInst instructions.
+ *
+ * @see llvm::BranchInst::getCondition
+ */
+LLVMValueRef LLVMGetCondition(LLVMValueRef Branch);
+
+/**
+ * Set the condition of a branch instruction.
+ *
+ * This only works on llvm::BranchInst instructions.
+ *
+ * @see llvm::BranchInst::setCondition
+ */
+void LLVMSetCondition(LLVMValueRef Branch, LLVMValueRef Cond);
+
+/**
* Obtain the default destination basic block of a switch instruction.
*
* This only works on llvm::SwitchInst instructions.
@@ -2446,6 +2564,10 @@ void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall);
LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef SwitchInstr);
/**
+ * @}
+ */
+
+/**
* @defgroup LLVMCCoreValueInstructionPHINode PHI Nodes
*
* Functions in this group only apply to instructions that map to
diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h
index 8f31150ad91d..d6cbe31cbb4e 100644
--- a/include/llvm-c/Disassembler.h
+++ b/include/llvm-c/Disassembler.h
@@ -174,8 +174,8 @@ extern "C" {
* by passing a block of information in the DisInfo parameter and specifying the
* TagType and callback functions as described above. These can all be passed
* as NULL. If successful, this returns a disassembler context. If not, it
- * returns NULL. This function is equivalent to calling LLVMCreateDisasmCPU()
- * with an empty CPU name.
+ * returns NULL. This function is equivalent to calling
+ * LLVMCreateDisasmCPUFeatures() with an empty CPU name and feature set.
*/
LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo,
int TagType, LLVMOpInfoCallback GetOpInfo,
@@ -186,7 +186,8 @@ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo,
* disassembly is supported by passing a block of information in the DisInfo
* parameter and specifying the TagType and callback functions as described
* above. These can all be passed * as NULL. If successful, this returns a
- * disassembler context. If not, it returns NULL.
+ * disassembler context. If not, it returns NULL. This function is equivalent
+ * to calling LLVMCreateDisasmCPUFeatures() with an empty feature set.
*/
LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
void *DisInfo, int TagType,
@@ -194,6 +195,19 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
LLVMSymbolLookupCallback SymbolLookUp);
/**
+ * Create a disassembler for the TripleName, a specific CPU and specific feature
+ * string. Symbolic disassembly is supported by passing a block of information
+ * in the DisInfo parameter and specifying the TagType and callback functions as
+ * described above. These can all be passed * as NULL. If successful, this
+ * returns a disassembler context. If not, it returns NULL.
+ */
+LLVMDisasmContextRef
+LLVMCreateDisasmCPUFeatures(const char *Triple, const char *CPU,
+ const char *Features, void *DisInfo, int TagType,
+ LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp);
+
+/**
* Set the disassembler's options. Returns 1 if it can set the Options and 0
* otherwise.
*/
diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h
index 7cdf0d78d5b6..eb3ecabfa8a8 100644
--- a/include/llvm-c/ExecutionEngine.h
+++ b/include/llvm-c/ExecutionEngine.h
@@ -34,7 +34,6 @@ extern "C" {
* @{
*/
-void LLVMLinkInJIT(void);
void LLVMLinkInMCJIT(void);
void LLVMLinkInInterpreter(void);
@@ -171,6 +170,10 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global);
+uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name);
+
+uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name);
+
/*===-- Operations on memory managers -------------------------------------===*/
typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)(
diff --git a/include/llvm-c/Initialization.h b/include/llvm-c/Initialization.h
index ada473818da6..44194f8ea311 100644
--- a/include/llvm-c/Initialization.h
+++ b/include/llvm-c/Initialization.h
@@ -13,8 +13,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef LLVM_C_INITIALIZEPASSES_H
-#define LLVM_C_INITIALIZEPASSES_H
+#ifndef LLVM_C_INITIALIZATION_H
+#define LLVM_C_INITIALIZATION_H
#include "llvm-c/Core.h"
diff --git a/include/llvm-c/Linker.h b/include/llvm-c/Linker.h
index 9f337cfba477..cedde5ea8e3a 100644
--- a/include/llvm-c/Linker.h
+++ b/include/llvm-c/Linker.h
@@ -20,20 +20,13 @@
extern "C" {
#endif
-
-typedef enum {
- LLVMLinkerDestroySource = 0, /* Allow source module to be destroyed. */
- LLVMLinkerPreserveSource = 1 /* Preserve the source module. */
-} LLVMLinkerMode;
-
-
/* Links the source module into the destination module, taking ownership
* of the source module away from the caller. Optionally returns a
* human-readable description of any errors that occurred in linking.
* OutMessage must be disposed with LLVMDisposeMessage. The return value
* is true if an error occurred, false otherwise. */
LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src,
- LLVMLinkerMode Mode, char **OutMessage);
+ unsigned Unused, char **OutMessage);
#ifdef __cplusplus
}
diff --git a/include/llvm-c/Support.h b/include/llvm-c/Support.h
index 4e6ff220b100..a9216d0364ad 100644
--- a/include/llvm-c/Support.h
+++ b/include/llvm-c/Support.h
@@ -47,6 +47,17 @@ typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef;
*/
LLVMBool LLVMLoadLibraryPermanently(const char* Filename);
+/**
+ * This function parses the given arguments using the LLVM command line parser.
+ * Note that the only stable thing about this function is its signature; you
+ * cannot rely on any particular set of command line arguments being interpreted
+ * the same way across LLVM versions.
+ *
+ * @see llvm::cl::ParseCommandLineOptions()
+ */
+void LLVMParseCommandLineOptions(int argc, const char *const *argv,
+ const char *Overview);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h
index 0ca72cec0cd2..7ad1ad1d0564 100644
--- a/include/llvm-c/Transforms/Scalar.h
+++ b/include/llvm-c/Transforms/Scalar.h
@@ -35,6 +35,9 @@ extern "C" {
/** See llvm::createAggressiveDCEPass function. */
void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM);
+/** See llvm::createAlignmentFromAssumptionsPass function. */
+void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM);
+
/** See llvm::createCFGSimplificationPass function. */
void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM);
@@ -86,6 +89,9 @@ 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);
@@ -132,6 +138,9 @@ void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM);
/** See llvm::createTypeBasedAliasAnalysisPass function */
void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM);
+/** See llvm::createScopedNoAliasAAPass function */
+void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM);
+
/** See llvm::createBasicAliasAnalysisPass function */
void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM);
diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h
index c525710ae1a1..3f30d6d535d2 100644
--- a/include/llvm-c/lto.h
+++ b/include/llvm-c/lto.h
@@ -40,7 +40,7 @@ typedef bool lto_bool_t;
* @{
*/
-#define LTO_API_VERSION 10
+#define LTO_API_VERSION 11
/**
* \since prior to LTO_API_VERSION=3
@@ -178,6 +178,35 @@ 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 LLVMContext. This function call is
+ * thread-safe. However, modules created this way should not be merged into an
+ * lto_code_gen_t using \a lto_codegen_add_module().
+ *
+ * Returns NULL on error (check lto_get_error_message() for details).
+ *
+ * \since LTO_API_VERSION=11
+ */
+extern lto_module_t
+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 into the same context as \c cg. The module is safe to
+ * add using \a lto_codegen_add_module().
+ *
+ * Returns NULL on error (check lto_get_error_message() for details).
+ *
+ * \since LTO_API_VERSION=11
+ */
+extern lto_module_t
+lto_module_create_in_codegen_context(const void *mem, size_t length,
+ const char *path, lto_code_gen_t cg);
+
+/**
* Loads an object file from disk. The seek point of fd is not preserved.
* Returns NULL on error (check lto_get_error_message() for details).
*
@@ -324,12 +353,27 @@ extern void lto_codegen_set_diagnostic_handler(lto_code_gen_t,
* Instantiates a code generator.
* Returns NULL on error (check lto_get_error_message() for details).
*
+ * All modules added using \a lto_codegen_add_module() must have been created
+ * in the same context as the codegen.
+ *
* \since prior to LTO_API_VERSION=3
*/
extern lto_code_gen_t
lto_codegen_create(void);
/**
+ * \brief 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,
+ * using \a lto_module_create_in_codegen_context().
+ *
+ * \since LTO_API_VERSION=11
+ */
+extern lto_code_gen_t
+lto_codegen_create_in_local_context(void);
+
+/**
* Frees all code generator and all memory it internally allocated.
* Upon return the lto_code_gen_t is no longer valid.
*
@@ -342,6 +386,10 @@ lto_codegen_dispose(lto_code_gen_t);
* Add an object module to the set of modules for which code will be generated.
* Returns true on error (check lto_get_error_message() for details).
*
+ * \c cg and \c mod must both be in the same context. See \a
+ * lto_codegen_create_in_local_context() and \a
+ * lto_module_create_in_codegen_context().
+ *
* \since prior to LTO_API_VERSION=3
*/
extern lto_bool_t
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index 50f1463d7eaa..26aae773624c 100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -304,6 +304,38 @@ public:
/// IEEE-754R 5.3.1: nextUp/nextDown.
opStatus next(bool nextDown);
+ /// \brief Operator+ overload which provides the default
+ /// \c nmNearestTiesToEven rounding mode and *no* error checking.
+ APFloat operator+(const APFloat &RHS) const {
+ APFloat Result = *this;
+ Result.add(RHS, rmNearestTiesToEven);
+ return Result;
+ }
+
+ /// \brief Operator- overload which provides the default
+ /// \c nmNearestTiesToEven rounding mode and *no* error checking.
+ APFloat operator-(const APFloat &RHS) const {
+ APFloat Result = *this;
+ Result.subtract(RHS, rmNearestTiesToEven);
+ return Result;
+ }
+
+ /// \brief Operator* overload which provides the default
+ /// \c nmNearestTiesToEven rounding mode and *no* error checking.
+ APFloat operator*(const APFloat &RHS) const {
+ APFloat Result = *this;
+ Result.multiply(RHS, rmNearestTiesToEven);
+ return Result;
+ }
+
+ /// \brief Operator/ overload which provides the default
+ /// \c nmNearestTiesToEven rounding mode and *no* error checking.
+ APFloat operator/(const APFloat &RHS) const {
+ APFloat Result = *this;
+ Result.divide(RHS, rmNearestTiesToEven);
+ return Result;
+ }
+
/// @}
/// \name Sign operations.
@@ -313,6 +345,13 @@ public:
void clearSign();
void copySign(const APFloat &);
+ /// \brief A static helper to produce a copy of an APFloat value with its sign
+ /// copied from some other APFloat.
+ static APFloat copySign(APFloat Value, const APFloat &Sign) {
+ Value.copySign(Sign);
+ return std::move(Value);
+ }
+
/// @}
/// \name Conversions
@@ -452,6 +491,36 @@ public:
/// return true.
bool getExactInverse(APFloat *inv) const;
+ /// \brief Enumeration of \c ilogb error results.
+ enum IlogbErrorKinds {
+ IEK_Zero = INT_MIN+1,
+ IEK_NaN = INT_MIN,
+ IEK_Inf = INT_MAX
+ };
+
+ /// \brief Returns the exponent of the internal representation of the APFloat.
+ ///
+ /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)).
+ /// For special APFloat values, this returns special error codes:
+ ///
+ /// NaN -> \c IEK_NaN
+ /// 0 -> \c IEK_Zero
+ /// Inf -> \c IEK_Inf
+ ///
+ friend int ilogb(const APFloat &Arg) {
+ if (Arg.isNaN())
+ return IEK_NaN;
+ if (Arg.isZero())
+ return IEK_Zero;
+ if (Arg.isInfinity())
+ return IEK_Inf;
+
+ return Arg.exponent;
+ }
+
+ /// \brief Returns: X * 2^Exp for integral exponents.
+ friend APFloat scalbn(APFloat X, int Exp);
+
private:
/// \name Simple Queries
@@ -573,11 +642,41 @@ private:
unsigned int sign : 1;
};
-/// See friend declaration above.
+/// See friend declarations above.
///
-/// This additional declaration is required in order to compile LLVM with IBM
+/// These additional declarations are required in order to compile LLVM with IBM
/// xlC compiler.
hash_code hash_value(const APFloat &Arg);
+APFloat scalbn(APFloat X, int Exp);
+
+/// \brief Returns the absolute value of the argument.
+inline APFloat abs(APFloat X) {
+ X.clearSign();
+ return X;
+}
+
+/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if
+/// both are not NaN. If either argument is a NaN, returns the other argument.
+LLVM_READONLY
+inline APFloat minnum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return B;
+ if (B.isNaN())
+ return A;
+ return (B.compare(A) == APFloat::cmpLessThan) ? B : A;
+}
+
+/// Implements IEEE maxNum semantics. Returns the larger of the 2 arguments if
+/// both are not NaN. If either argument is a NaN, returns the other argument.
+LLVM_READONLY
+inline APFloat maxnum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return B;
+ if (B.isNaN())
+ return A;
+ return (A.compare(B) == APFloat::cmpLessThan) ? B : A;
+}
+
} // namespace llvm
#endif // LLVM_ADT_APFLOAT_H
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index aa3c3f67ec10..025397d9ce45 100644
--- a/include/llvm/ADT/APInt.h
+++ b/include/llvm/ADT/APInt.h
@@ -91,6 +91,8 @@ class APInt {
APINT_WORD_SIZE = static_cast<unsigned int>(sizeof(uint64_t))
};
+ friend struct DenseMapAPIntKeyInfo;
+
/// \brief Fast internal constructor
///
/// This constructor is used only internally for speed of construction of
@@ -277,7 +279,6 @@ public:
/// Simply makes *this a copy of that.
/// @brief Copy Constructor.
APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) {
- assert(BitWidth && "bitwidth too small");
if (isSingleWord())
VAL = that.VAL;
else
@@ -656,13 +657,24 @@ public:
/// @brief Move assignment operator.
APInt &operator=(APInt &&that) {
- if (!isSingleWord())
+ if (!isSingleWord()) {
+ // The MSVC STL shipped in 2013 requires that self move assignment be a
+ // no-op. Otherwise algorithms like stable_sort will produce answers
+ // where half of the output is left in a moved-from state.
+ if (this == &that)
+ return *this;
delete[] pVal;
+ }
- BitWidth = that.BitWidth;
- VAL = that.VAL;
+ // Use memcpy so that type based alias analysis sees both VAL and pVal
+ // as modified.
+ memcpy(&VAL, &that.VAL, sizeof(uint64_t));
+ // If 'this == &that', avoid zeroing our own bitwidth by storing to 'that'
+ // first.
+ unsigned ThatBitWidth = that.BitWidth;
that.BitWidth = 0;
+ BitWidth = ThatBitWidth;
return *this;
}
@@ -936,7 +948,8 @@ public:
APInt sdiv_ov(const APInt &RHS, bool &Overflow) const;
APInt smul_ov(const APInt &RHS, bool &Overflow) const;
APInt umul_ov(const APInt &RHS, bool &Overflow) const;
- APInt sshl_ov(unsigned Amt, bool &Overflow) const;
+ APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
+ APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
/// \brief Array-indexing support.
///
diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h
index ee34e9b53088..a6693f7992cd 100644
--- a/include/llvm/ADT/APSInt.h
+++ b/include/llvm/ADT/APSInt.h
@@ -269,19 +269,15 @@ public:
else if (I2.getBitWidth() > I1.getBitWidth())
return isSameValue(I1.extend(I2.getBitWidth()), I2);
- // We have a signedness mismatch. Turn the signed value into an unsigned
- // value.
- if (I1.isSigned()) {
- if (I1.isNegative())
- return false;
+ assert(I1.isSigned() != I2.isSigned());
- return APSInt(I1, true) == I2;
- }
-
- if (I2.isNegative())
+ // We have a signedness mismatch. Check for negative values and do an
+ // unsigned compare if signs match.
+ if ((I1.isSigned() && I1.isNegative()) ||
+ (!I1.isSigned() && I2.isNegative()))
return false;
- return I1 == APSInt(I2, true);
+ return I1.eq(I2);
}
/// Profile - Used to insert APSInt objects, or objects that contain APSInt
diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h
index 0fff505d8d01..8c14a423c8f5 100644
--- a/include/llvm/ADT/ArrayRef.h
+++ b/include/llvm/ADT/ArrayRef.h
@@ -11,6 +11,7 @@
#define LLVM_ADT_ARRAYREF_H
#include "llvm/ADT/None.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
@@ -43,6 +44,19 @@ namespace llvm {
/// The number of elements.
size_type Length;
+ /// \brief A dummy "optional" type that is only created by implicit
+ /// conversion from a reference to T.
+ ///
+ /// This type must *only* be used in a function argument or as a copy of
+ /// a function argument, as otherwise it will hold a pointer to a temporary
+ /// past that temporaries' lifetime.
+ struct TRefOrNothing {
+ const T *TPtr;
+
+ TRefOrNothing() : TPtr(nullptr) {}
+ TRefOrNothing(const T &TRef) : TPtr(&TRef) {}
+ };
+
public:
/// @name Constructors
/// @{
@@ -90,6 +104,14 @@ namespace llvm {
Length(Vec.size()) {}
#endif
+ /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
+ /// ensure that only ArrayRefs of pointers can be converted.
+ template <typename U>
+ ArrayRef(const ArrayRef<U *> &A,
+ typename std::enable_if<
+ std::is_convertible<U *const *, T const *>::value>::type* = 0)
+ : Data(A.data()), Length(A.size()) {}
+
/// @}
/// @name Simple Operations
/// @{
@@ -131,7 +153,13 @@ namespace llvm {
bool equals(ArrayRef RHS) const {
if (Length != RHS.Length)
return false;
- return std::equal(begin(), end(), RHS.begin());
+ // Don't use std::equal(), since it asserts in MSVC on nullptr iterators.
+ for (auto L = begin(), LE = end(), R = RHS.begin(); L != LE; ++L, ++R)
+ // Match std::equal() in using == (instead of !=) to minimize API
+ // requirements of ArrayRef'ed types.
+ if (!(*L == *R))
+ return false;
+ return true;
}
/// slice(n) - Chop off the first N elements of the array.
@@ -176,6 +204,47 @@ namespace llvm {
}
/// @}
+ /// @{
+ /// @name Convenience methods
+
+ /// @brief Predicate for testing that the array equals the exact sequence of
+ /// arguments.
+ ///
+ /// Will return false if the size is not equal to the exact number of
+ /// arguments given or if the array elements don't equal the argument
+ /// elements in order. Currently supports up to 16 arguments, but can
+ /// easily be extended.
+ bool equals(TRefOrNothing Arg0 = TRefOrNothing(),
+ TRefOrNothing Arg1 = TRefOrNothing(),
+ TRefOrNothing Arg2 = TRefOrNothing(),
+ TRefOrNothing Arg3 = TRefOrNothing(),
+ TRefOrNothing Arg4 = TRefOrNothing(),
+ TRefOrNothing Arg5 = TRefOrNothing(),
+ TRefOrNothing Arg6 = TRefOrNothing(),
+ TRefOrNothing Arg7 = TRefOrNothing(),
+ TRefOrNothing Arg8 = TRefOrNothing(),
+ TRefOrNothing Arg9 = TRefOrNothing(),
+ TRefOrNothing Arg10 = TRefOrNothing(),
+ TRefOrNothing Arg11 = TRefOrNothing(),
+ TRefOrNothing Arg12 = TRefOrNothing(),
+ TRefOrNothing Arg13 = TRefOrNothing(),
+ TRefOrNothing Arg14 = TRefOrNothing(),
+ TRefOrNothing Arg15 = TRefOrNothing()) {
+ TRefOrNothing Args[] = {Arg0, Arg1, Arg2, Arg3, Arg4, Arg5,
+ Arg6, Arg7, Arg8, Arg9, Arg10, Arg11,
+ Arg12, Arg13, Arg14, Arg15};
+ if (size() > array_lengthof(Args))
+ return false;
+
+ for (unsigned i = 0, e = size(); i != e; ++i)
+ if (Args[i].TPtr == nullptr || (*this)[i] != *Args[i].TPtr)
+ return false;
+
+ // Either the size is exactly as many args, or the next arg must be null.
+ return size() == array_lengthof(Args) || Args[size()].TPtr == nullptr;
+ }
+
+ /// @}
};
/// MutableArrayRef - Represent a mutable reference to an array (0 or more
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h
index 34e2284311b3..a40f694485bf 100644
--- a/include/llvm/ADT/BitVector.h
+++ b/include/llvm/ADT/BitVector.h
@@ -239,6 +239,7 @@ public:
}
BitVector &set(unsigned Idx) {
+ assert(Bits && "Bits never allocated");
Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE);
return *this;
}
@@ -450,6 +451,7 @@ public:
// Grow the bitvector to have enough elements.
Capacity = RHSWords;
+ assert(Capacity > 0 && "negative capacity?");
BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord));
@@ -545,6 +547,7 @@ private:
void grow(unsigned NewSize) {
Capacity = std::max(NumBitWords(NewSize), Capacity * 2);
+ assert(Capacity > 0 && "realloc-ing zero space");
Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord));
clear_unused_bits();
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h
index 85f37b9051b1..050f8ac150dd 100644
--- a/include/llvm/ADT/DenseMap.h
+++ b/include/llvm/ADT/DenseMap.h
@@ -31,26 +31,35 @@
namespace llvm {
-template<typename KeyT, typename ValueT,
- typename KeyInfoT = DenseMapInfo<KeyT>,
- bool IsConst = false>
+namespace detail {
+// We extend a pair to allow users to override the bucket type with their own
+// implementation without requiring two members.
+template <typename KeyT, typename ValueT>
+struct DenseMapPair : public std::pair<KeyT, ValueT> {
+ KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
+ const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
+ ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
+ const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; }
+};
+}
+
+template <
+ typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false>
class DenseMapIterator;
-template<typename DerivedT,
- typename KeyT, typename ValueT, typename KeyInfoT>
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
class DenseMapBase {
-protected:
- typedef std::pair<KeyT, ValueT> BucketT;
-
public:
typedef unsigned size_type;
typedef KeyT key_type;
typedef ValueT mapped_type;
typedef BucketT value_type;
- typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator;
- typedef DenseMapIterator<KeyT, ValueT,
- KeyInfoT, true> const_iterator;
+ typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT> iterator;
+ typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>
+ const_iterator;
inline iterator begin() {
// When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
return empty() ? end() : iterator(getBuckets(), getBucketsEnd());
@@ -88,12 +97,12 @@ public:
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
- if (!KeyInfoT::isEqual(P->first, EmptyKey)) {
- if (!KeyInfoT::isEqual(P->first, TombstoneKey)) {
- P->second.~ValueT();
+ if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
+ if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
+ P->getSecond().~ValueT();
decrementNumEntries();
}
- P->first = EmptyKey;
+ P->getFirst() = EmptyKey;
}
}
assert(getNumEntries() == 0 && "Node count imbalance!");
@@ -144,7 +153,7 @@ public:
ValueT lookup(const KeyT &Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
- return TheBucket->second;
+ return TheBucket->getSecond();
return ValueT();
}
@@ -191,16 +200,16 @@ public:
if (!LookupBucketFor(Val, TheBucket))
return false; // not in map.
- TheBucket->second.~ValueT();
- TheBucket->first = getTombstoneKey();
+ TheBucket->getSecond().~ValueT();
+ TheBucket->getFirst() = getTombstoneKey();
decrementNumEntries();
incrementNumTombstones();
return true;
}
void erase(iterator I) {
BucketT *TheBucket = &*I;
- TheBucket->second.~ValueT();
- TheBucket->first = getTombstoneKey();
+ TheBucket->getSecond().~ValueT();
+ TheBucket->getFirst() = getTombstoneKey();
decrementNumEntries();
incrementNumTombstones();
}
@@ -250,10 +259,10 @@ protected:
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
- if (!KeyInfoT::isEqual(P->first, EmptyKey) &&
- !KeyInfoT::isEqual(P->first, TombstoneKey))
- P->second.~ValueT();
- P->first.~KeyT();
+ if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))
+ P->getSecond().~ValueT();
+ P->getFirst().~KeyT();
}
#ifndef NDEBUG
@@ -269,7 +278,7 @@ protected:
"# initial buckets must be a power of two!");
const KeyT EmptyKey = getEmptyKey();
for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
- new (&B->first) KeyT(EmptyKey);
+ new (&B->getFirst()) KeyT(EmptyKey);
}
void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
@@ -279,21 +288,21 @@ protected:
const KeyT EmptyKey = getEmptyKey();
const KeyT TombstoneKey = getTombstoneKey();
for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
- if (!KeyInfoT::isEqual(B->first, EmptyKey) &&
- !KeyInfoT::isEqual(B->first, TombstoneKey)) {
+ if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {
// Insert the key/value into the new table.
BucketT *DestBucket;
- bool FoundVal = LookupBucketFor(B->first, DestBucket);
+ bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);
(void)FoundVal; // silence warning.
assert(!FoundVal && "Key already in new map?");
- DestBucket->first = std::move(B->first);
- new (&DestBucket->second) ValueT(std::move(B->second));
+ DestBucket->getFirst() = std::move(B->getFirst());
+ new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond()));
incrementNumEntries();
// Free the value.
- B->second.~ValueT();
+ B->getSecond().~ValueT();
}
- B->first.~KeyT();
+ B->getFirst().~KeyT();
}
#ifndef NDEBUG
@@ -304,7 +313,9 @@ protected:
}
template <typename OtherBaseT>
- void copyFrom(const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT>& other) {
+ void copyFrom(
+ const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {
+ assert(&other != this);
assert(getNumBuckets() == other.getNumBuckets());
setNumEntries(other.getNumEntries());
@@ -315,10 +326,12 @@ protected:
getNumBuckets() * sizeof(BucketT));
else
for (size_t i = 0; i < getNumBuckets(); ++i) {
- new (&getBuckets()[i].first) KeyT(other.getBuckets()[i].first);
- if (!KeyInfoT::isEqual(getBuckets()[i].first, getEmptyKey()) &&
- !KeyInfoT::isEqual(getBuckets()[i].first, getTombstoneKey()))
- new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second);
+ new (&getBuckets()[i].getFirst())
+ KeyT(other.getBuckets()[i].getFirst());
+ if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&
+ !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))
+ new (&getBuckets()[i].getSecond())
+ ValueT(other.getBuckets()[i].getSecond());
}
}
@@ -395,8 +408,8 @@ private:
BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, TheBucket);
- TheBucket->first = Key;
- new (&TheBucket->second) ValueT(Value);
+ TheBucket->getFirst() = Key;
+ new (&TheBucket->getSecond()) ValueT(Value);
return TheBucket;
}
@@ -404,16 +417,16 @@ private:
BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, TheBucket);
- TheBucket->first = Key;
- new (&TheBucket->second) ValueT(std::move(Value));
+ TheBucket->getFirst() = Key;
+ new (&TheBucket->getSecond()) ValueT(std::move(Value));
return TheBucket;
}
BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, TheBucket);
- TheBucket->first = std::move(Key);
- new (&TheBucket->second) ValueT(std::move(Value));
+ TheBucket->getFirst() = std::move(Key);
+ new (&TheBucket->getSecond()) ValueT(std::move(Value));
return TheBucket;
}
@@ -445,7 +458,7 @@ private:
// If we are writing over a tombstone, remember this.
const KeyT EmptyKey = getEmptyKey();
- if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey))
+ if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
decrementNumTombstones();
return TheBucket;
@@ -479,14 +492,14 @@ private:
while (1) {
const BucketT *ThisBucket = BucketsPtr + BucketNo;
// Found Val's bucket? If so, return it.
- if (KeyInfoT::isEqual(Val, ThisBucket->first)) {
+ if (KeyInfoT::isEqual(Val, ThisBucket->getFirst())) {
FoundBucket = ThisBucket;
return true;
}
// If we found an empty bucket, the key doesn't exist in the set.
// Insert it and return the default value.
- if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) {
+ if (KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey)) {
// If we've already seen a tombstone while probing, fill it in instead
// of the empty bucket we eventually probed to.
FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
@@ -495,7 +508,8 @@ private:
// If this is a tombstone, remember it. If Val ends up not in the map, we
// prefer to return it than something that would require more probing.
- if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone)
+ if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
+ !FoundTombstone)
FoundTombstone = ThisBucket; // Remember the first tombstone found.
// Otherwise, it's a hash collision or a tombstone, continue quadratic
@@ -524,16 +538,15 @@ public:
}
};
-template<typename KeyT, typename ValueT,
- typename KeyInfoT = DenseMapInfo<KeyT> >
-class DenseMap
- : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT>,
- KeyT, ValueT, KeyInfoT> {
+template <typename KeyT, typename ValueT,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
+class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
+ KeyT, ValueT, KeyInfoT, BucketT> {
// Lift some types from the dependent base class into this class for
// simplicity of referring to them.
- typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT> BaseT;
- typedef typename BaseT::BucketT BucketT;
- friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT>;
+ typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
+ friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
BucketT *Buckets;
unsigned NumEntries;
@@ -574,7 +587,8 @@ public:
}
DenseMap& operator=(const DenseMap& other) {
- copyFrom(other);
+ if (&other != this)
+ copyFrom(other);
return *this;
}
@@ -675,17 +689,17 @@ private:
}
};
-template<typename KeyT, typename ValueT,
- unsigned InlineBuckets = 4,
- typename KeyInfoT = DenseMapInfo<KeyT> >
+template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
class SmallDenseMap
- : public DenseMapBase<SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT>,
- KeyT, ValueT, KeyInfoT> {
+ : public DenseMapBase<
+ SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
+ ValueT, KeyInfoT, BucketT> {
// Lift some types from the dependent base class into this class for
// simplicity of referring to them.
- typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT> BaseT;
- typedef typename BaseT::BucketT BucketT;
- friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT>;
+ typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
+ friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
unsigned Small : 1;
unsigned NumEntries : 31;
@@ -742,23 +756,23 @@ public:
for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
BucketT *LHSB = &getInlineBuckets()[i],
*RHSB = &RHS.getInlineBuckets()[i];
- bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) &&
- !KeyInfoT::isEqual(LHSB->first, TombstoneKey));
- bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) &&
- !KeyInfoT::isEqual(RHSB->first, TombstoneKey));
+ bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey));
+ bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey));
if (hasLHSValue && hasRHSValue) {
// Swap together if we can...
std::swap(*LHSB, *RHSB);
continue;
}
// Swap separately and handle any assymetry.
- std::swap(LHSB->first, RHSB->first);
+ std::swap(LHSB->getFirst(), RHSB->getFirst());
if (hasLHSValue) {
- new (&RHSB->second) ValueT(std::move(LHSB->second));
- LHSB->second.~ValueT();
+ new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond()));
+ LHSB->getSecond().~ValueT();
} else if (hasRHSValue) {
- new (&LHSB->second) ValueT(std::move(RHSB->second));
- RHSB->second.~ValueT();
+ new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond()));
+ RHSB->getSecond().~ValueT();
}
}
return;
@@ -783,12 +797,12 @@ public:
for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
BucketT *NewB = &LargeSide.getInlineBuckets()[i],
*OldB = &SmallSide.getInlineBuckets()[i];
- new (&NewB->first) KeyT(std::move(OldB->first));
- OldB->first.~KeyT();
- if (!KeyInfoT::isEqual(NewB->first, EmptyKey) &&
- !KeyInfoT::isEqual(NewB->first, TombstoneKey)) {
- new (&NewB->second) ValueT(std::move(OldB->second));
- OldB->second.~ValueT();
+ new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst()));
+ OldB->getFirst().~KeyT();
+ if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) {
+ new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond()));
+ OldB->getSecond().~ValueT();
}
}
@@ -799,7 +813,8 @@ public:
}
SmallDenseMap& operator=(const SmallDenseMap& other) {
- copyFrom(other);
+ if (&other != this)
+ copyFrom(other);
return *this;
}
@@ -849,16 +864,16 @@ public:
const KeyT EmptyKey = this->getEmptyKey();
const KeyT TombstoneKey = this->getTombstoneKey();
for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) {
- if (!KeyInfoT::isEqual(P->first, EmptyKey) &&
- !KeyInfoT::isEqual(P->first, TombstoneKey)) {
+ if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
assert(size_t(TmpEnd - TmpBegin) < InlineBuckets &&
"Too many inline buckets!");
- new (&TmpEnd->first) KeyT(std::move(P->first));
- new (&TmpEnd->second) ValueT(std::move(P->second));
+ new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst()));
+ new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond()));
++TmpEnd;
- P->second.~ValueT();
+ P->getSecond().~ValueT();
}
- P->first.~KeyT();
+ P->getFirst().~KeyT();
}
// Now make this map use the large rep, and move all the entries back
@@ -969,13 +984,12 @@ private:
}
};
-template<typename KeyT, typename ValueT,
- typename KeyInfoT, bool IsConst>
+template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
+ bool IsConst>
class DenseMapIterator {
- typedef std::pair<KeyT, ValueT> Bucket;
- typedef DenseMapIterator<KeyT, ValueT,
- KeyInfoT, true> ConstIterator;
- friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, true>;
+ typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator;
+ friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
+
public:
typedef ptrdiff_t difference_type;
typedef typename std::conditional<IsConst, const Bucket, Bucket>::type
@@ -996,9 +1010,9 @@ public:
// If IsConst is true this is a converting constructor from iterator to
// const_iterator and the default copy constructor is used.
// Otherwise this is a copy constructor for iterator.
- DenseMapIterator(const DenseMapIterator<KeyT, ValueT,
- KeyInfoT, false>& I)
- : Ptr(I.Ptr), End(I.End) {}
+ DenseMapIterator(
+ const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false> &I)
+ : Ptr(I.Ptr), End(I.End) {}
reference operator*() const {
return *Ptr;
@@ -1028,9 +1042,8 @@ private:
const KeyT Empty = KeyInfoT::getEmptyKey();
const KeyT Tombstone = KeyInfoT::getTombstoneKey();
- while (Ptr != End &&
- (KeyInfoT::isEqual(Ptr->first, Empty) ||
- KeyInfoT::isEqual(Ptr->first, Tombstone)))
+ while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) ||
+ KeyInfoT::isEqual(Ptr->getFirst(), Tombstone)))
++Ptr;
}
};
diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h
index 37a81b0c7ee2..d34024005dfe 100644
--- a/include/llvm/ADT/DenseSet.h
+++ b/include/llvm/ADT/DenseSet.h
@@ -18,18 +18,34 @@
namespace llvm {
+namespace detail {
+struct DenseSetEmpty {};
+
+// Use the empty base class trick so we can create a DenseMap where the buckets
+// contain only a single item.
+template <typename KeyT> class DenseSetPair : public DenseSetEmpty {
+ KeyT key;
+
+public:
+ KeyT &getFirst() { return key; }
+ const KeyT &getFirst() const { return key; }
+ DenseSetEmpty &getSecond() { return *this; }
+ const DenseSetEmpty &getSecond() const { return *this; }
+};
+}
+
/// DenseSet - This implements a dense probed hash-table based set.
-///
-/// FIXME: This is currently implemented directly in terms of DenseMap, this
-/// should be optimized later if there is a need.
template<typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT> >
class DenseSet {
- typedef DenseMap<ValueT, char, ValueInfoT> MapTy;
+ typedef DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
+ detail::DenseSetPair<ValueT>> MapTy;
+ static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
+ "DenseMap buckets unexpectedly large!");
MapTy TheMap;
public:
typedef ValueT key_type;
typedef ValueT value_type;
- typedef unsigned size_type;
+ typedef unsigned size_type;
explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {}
@@ -45,7 +61,7 @@ public:
TheMap.clear();
}
- /// Return 1 if the specified key is in the set, 0 otherwise.
+ /// Return 1 if the specified key is in the set, 0 otherwise.
size_type count(const ValueT &V) const {
return TheMap.count(V);
}
@@ -72,8 +88,8 @@ public:
Iterator(const typename MapTy::iterator &i) : I(i) {}
- ValueT& operator*() { return I->first; }
- ValueT* operator->() { return &I->first; }
+ ValueT &operator*() { return I->getFirst(); }
+ ValueT *operator->() { return &I->getFirst(); }
Iterator& operator++() { ++I; return *this; }
bool operator==(const Iterator& X) const { return I == X.I; }
@@ -92,8 +108,8 @@ public:
ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
- const ValueT& operator*() { return I->first; }
- const ValueT* operator->() { return &I->first; }
+ const ValueT &operator*() { return I->getFirst(); }
+ const ValueT *operator->() { return &I->getFirst(); }
ConstIterator& operator++() { ++I; return *this; }
bool operator==(const ConstIterator& X) const { return I == X.I; }
@@ -110,11 +126,27 @@ public:
const_iterator end() const { return ConstIterator(TheMap.end()); }
iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); }
+
+ /// Alternative version of find() which allows a different, and possibly less
+ /// expensive, key type.
+ /// The DenseMapInfo is responsible for supplying methods
+ /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type
+ /// used.
+ template <class LookupKeyT>
+ iterator find_as(const LookupKeyT &Val) {
+ return Iterator(TheMap.find_as(Val));
+ }
+ template <class LookupKeyT>
+ const_iterator find_as(const LookupKeyT &Val) const {
+ return ConstIterator(TheMap.find_as(Val));
+ }
+
void erase(Iterator I) { return TheMap.erase(I.I); }
void erase(ConstIterator CI) { return TheMap.erase(CI.I); }
std::pair<iterator, bool> insert(const ValueT &V) {
- return TheMap.insert(std::make_pair(V, 0));
+ detail::DenseSetEmpty Empty;
+ return TheMap.insert(std::make_pair(V, Empty));
}
// Range insertion of values.
diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h
index dfba43f3ac85..6cd9e68aea56 100644
--- a/include/llvm/ADT/DepthFirstIterator.h
+++ b/include/llvm/ADT/DepthFirstIterator.h
@@ -33,10 +33,10 @@
#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H
#define LLVM_ADT_DEPTHFIRSTITERATOR_H
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/iterator_range.h"
#include <set>
#include <vector>
@@ -231,6 +231,13 @@ df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) {
return df_ext_iterator<T, SetTy>::end(G, S);
}
+template <class T, class SetTy>
+iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G,
+ SetTy &S) {
+ return iterator_range<df_ext_iterator<T, SetTy>>(df_ext_begin(G, S),
+ df_ext_end(G, S));
+}
+
// Provide global definitions of inverse depth first iterators...
template <class T,
@@ -276,6 +283,13 @@ idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) {
return idf_ext_iterator<T, SetTy>::end(Inverse<T>(G), S);
}
+template <class T, class SetTy>
+iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G,
+ SetTy &S) {
+ return iterator_range<idf_ext_iterator<T, SetTy>>(idf_ext_begin(G, S),
+ idf_ext_end(G, S));
+}
+
} // End llvm namespace
#endif
diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h
index f9df3781257e..c859c98d06b2 100644
--- a/include/llvm/ADT/IntrusiveRefCntPtr.h
+++ b/include/llvm/ADT/IntrusiveRefCntPtr.h
@@ -197,6 +197,9 @@ public:
private:
void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
+
+ template <typename X>
+ friend class IntrusiveRefCntPtr;
};
template<class T, class U>
diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h
index 4e1fc1527270..1331b15b2d29 100644
--- a/include/llvm/ADT/MapVector.h
+++ b/include/llvm/ADT/MapVector.h
@@ -18,6 +18,7 @@
#define LLVM_ADT_MAPVECTOR_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
#include <vector>
namespace llvm {
@@ -37,26 +38,20 @@ class MapVector {
public:
typedef typename VectorType::iterator iterator;
typedef typename VectorType::const_iterator const_iterator;
+ typedef typename VectorType::reverse_iterator reverse_iterator;
+ typedef typename VectorType::const_reverse_iterator const_reverse_iterator;
- size_type size() const {
- return Vector.size();
- }
-
- iterator begin() {
- return Vector.begin();
- }
+ size_type size() const { return Vector.size(); }
- const_iterator begin() const {
- return Vector.begin();
- }
-
- iterator end() {
- return Vector.end();
- }
+ iterator begin() { return Vector.begin(); }
+ const_iterator begin() const { return Vector.begin(); }
+ iterator end() { return Vector.end(); }
+ const_iterator end() const { return Vector.end(); }
- const_iterator end() const {
- return Vector.end();
- }
+ reverse_iterator rbegin() { return Vector.rbegin(); }
+ const_reverse_iterator rbegin() const { return Vector.rbegin(); }
+ reverse_iterator rend() { return Vector.rend(); }
+ const_reverse_iterator rend() const { return Vector.rend(); }
bool empty() const {
return Vector.empty();
@@ -147,6 +142,17 @@ public:
return Next;
}
+ /// \brief Remove all elements with the key value Key.
+ ///
+ /// Returns the number of elements removed.
+ size_type erase(const KeyT &Key) {
+ auto Iterator = find(Key);
+ if (Iterator == end())
+ return 0;
+ erase(Iterator);
+ return 1;
+ }
+
/// \brief Remove the elements that match the predicate.
///
/// Erase all elements that match \c Pred in a single pass. Takes linear
@@ -176,6 +182,14 @@ void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) {
Vector.erase(O, Vector.end());
}
+/// \brief A MapVector that performs no allocations if smaller than a certain
+/// size.
+template <typename KeyT, typename ValueT, unsigned N>
+struct SmallMapVector
+ : MapVector<KeyT, ValueT, SmallDenseMap<KeyT, unsigned, N>,
+ SmallVector<std::pair<KeyT, ValueT>, N>> {
+};
+
} // end namespace llvm
#endif
diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h
index ae8344da76a6..591872e6591a 100644
--- a/include/llvm/ADT/Optional.h
+++ b/include/llvm/ADT/Optional.h
@@ -20,6 +20,7 @@
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
+#include <new>
#include <utility>
namespace llvm {
@@ -29,6 +30,8 @@ class Optional {
AlignedCharArrayUnion<T> storage;
bool hasVal;
public:
+ typedef T value_type;
+
Optional(NoneType) : hasVal(false) {}
explicit Optional() : hasVal(false) {}
Optional(const T &y) : hasVal(true) {
@@ -67,6 +70,61 @@ public:
return *this;
}
+#if LLVM_HAS_VARIADIC_TEMPLATES
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename ...ArgTypes>
+ void emplace(ArgTypes &&...Args) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
+ }
+
+#else
+
+ /// Create a new object by default-constructing it in place.
+ void emplace() {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T();
+ }
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename T1>
+ void emplace(T1 &&A1) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<T1>(A1));
+ }
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename T1, typename T2>
+ void emplace(T1 &&A1, T2 &&A2) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2));
+ }
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename T1, typename T2, typename T3>
+ void emplace(T1 &&A1, T2 &&A2, T3 &&A3) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
+ std::forward<T3>(A3));
+ }
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename T1, typename T2, typename T3, typename T4>
+ void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
+ std::forward<T3>(A3), std::forward<T4>(A4));
+ }
+
+#endif // LLVM_HAS_VARIADIC_TEMPLATES
+
static inline Optional create(const T* y) {
return y ? Optional(*y) : Optional();
}
@@ -117,9 +175,19 @@ public:
const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
+ template <typename U>
+ LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
+ return hasValue() ? getValue() : std::forward<U>(value);
+ }
+
#if LLVM_HAS_RVALUE_REFERENCE_THIS
T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
+
+ template <typename U>
+ T getValueOr(U &&value) && {
+ return hasValue() ? std::move(getValue()) : std::forward<U>(value);
+ }
#endif
};
diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h
index dd8cc74b714e..dfadc3b85db6 100644
--- a/include/llvm/ADT/PostOrderIterator.h
+++ b/include/llvm/ADT/PostOrderIterator.h
@@ -57,7 +57,7 @@ public:
// Return true if edge destination should be visited.
template<typename NodeType>
bool insertEdge(NodeType *From, NodeType *To) {
- return Visited.insert(To);
+ return Visited.insert(To).second;
}
// Called after all children of BB have been visited.
@@ -76,8 +76,9 @@ public:
// Return true if edge destination should be visited, called with From = 0 for
// the root node.
// Graph edges can be pruned by specializing this function.
- template<class NodeType>
- bool insertEdge(NodeType *From, NodeType *To) { return Visited.insert(To); }
+ template <class NodeType> bool insertEdge(NodeType *From, NodeType *To) {
+ return Visited.insert(To).second;
+ }
// Called after all children of BB have been visited.
template<class NodeType>
diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h
index 1cef3933b5d6..4e56e4d74470 100644
--- a/include/llvm/ADT/STLExtras.h
+++ b/include/llvm/ADT/STLExtras.h
@@ -77,8 +77,11 @@ class function_ref<Ret(Params...)> {
}
public:
- template<typename Callable>
- function_ref(Callable &&callable)
+ template <typename Callable>
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Params ...params) const {
@@ -100,7 +103,10 @@ class function_ref<Ret()> {
public:
template<typename Callable>
- function_ref(Callable &&callable)
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()() const { return callback(callable); }
@@ -119,7 +125,10 @@ class function_ref<Ret(Param1)> {
public:
template<typename Callable>
- function_ref(Callable &&callable)
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1) {
@@ -141,7 +150,10 @@ class function_ref<Ret(Param1, Param2)> {
public:
template<typename Callable>
- function_ref(Callable &&callable)
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1, Param2 param2) {
@@ -167,7 +179,10 @@ class function_ref<Ret(Param1, Param2, Param3)> {
public:
template<typename Callable>
- function_ref(Callable &&callable)
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1, Param2 param2, Param3 param3) {
@@ -530,6 +545,12 @@ make_unique(size_t n) {
#endif
+struct FreeDeleter {
+ void operator()(void* v) {
+ ::free(v);
+ }
+};
+
template<typename First, typename Second>
struct pair_hash {
size_t operator()(const std::pair<First, Second> &P) const {
diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h
index 02a6ea345834..2f60ecc92043 100644
--- a/include/llvm/ADT/ScopedHashTable.h
+++ b/include/llvm/ADT/ScopedHashTable.h
@@ -148,7 +148,7 @@ public:
/// ScopeTy - This is a helpful typedef that allows clients to get easy access
/// to the name of the scope for this hash table.
typedef ScopedHashTableScope<K, V, KInfo, AllocatorTy> ScopeTy;
- typedef unsigned size_type;
+ typedef unsigned size_type;
private:
typedef ScopedHashTableVal<K, V> ValTy;
DenseMap<K, ValTy*, KInfo> TopLevelMap;
@@ -171,7 +171,7 @@ public:
AllocatorTy &getAllocator() { return Allocator; }
const AllocatorTy &getAllocator() const { return Allocator; }
- /// Return 1 if the specified key is in the table, 0 otherwise.
+ /// Return 1 if the specified key is in the table, 0 otherwise.
size_type count(const K &Key) const {
return TopLevelMap.count(Key);
}
diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h
index 1e7d237045aa..a7fd408c854a 100644
--- a/include/llvm/ADT/SetVector.h
+++ b/include/llvm/ADT/SetVector.h
@@ -100,7 +100,7 @@ public:
/// \brief Insert a new element into the SetVector.
/// \returns true iff the element was inserted into the SetVector.
bool insert(const value_type &X) {
- bool result = set_.insert(X);
+ bool result = set_.insert(X).second;
if (result)
vector_.push_back(X);
return result;
@@ -110,7 +110,7 @@ public:
template<typename It>
void insert(It Start, It End) {
for (; Start != End; ++Start)
- if (set_.insert(*Start))
+ if (set_.insert(*Start).second)
vector_.push_back(*Start);
}
diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h
index 0922017ea61a..1e2f365b1040 100644
--- a/include/llvm/ADT/SmallBitVector.h
+++ b/include/llvm/ADT/SmallBitVector.h
@@ -54,7 +54,7 @@ class SmallBitVector {
};
public:
- typedef unsigned size_type;
+ typedef unsigned size_type;
// Encapsulation of a single bit.
class reference {
SmallBitVector &TheVector;
@@ -292,8 +292,12 @@ public:
}
SmallBitVector &set(unsigned Idx) {
- if (isSmall())
+ if (isSmall()) {
+ assert(Idx <= static_cast<unsigned>(
+ std::numeric_limits<uintptr_t>::digits) &&
+ "undefined behavior");
setSmallBits(getSmallBits() | (uintptr_t(1) << Idx));
+ }
else
getPointer()->set(Idx);
return *this;
diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h
index 74f3fd43cec4..cb1c5e1fa96a 100644
--- a/include/llvm/ADT/SmallPtrSet.h
+++ b/include/llvm/ADT/SmallPtrSet.h
@@ -22,6 +22,7 @@
#include <cstddef>
#include <cstring>
#include <iterator>
+#include <utility>
namespace llvm {
@@ -100,7 +101,7 @@ protected:
/// insert_imp - This returns true if the pointer was new to the set, false if
/// it was already in the set. This is hidden from the client so that the
/// derived class can check that the right type of pointer is passed in.
- bool insert_imp(const void * Ptr);
+ std::pair<const void *const *, bool> insert_imp(const void *Ptr);
/// erase_imp - If the set contains the specified pointer, remove it and
/// return true, otherwise return false. This is hidden from the client so
@@ -240,6 +241,8 @@ struct RoundUpToPowerOfTwo {
template <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
+
+ SmallPtrSetImpl(const SmallPtrSetImpl&) LLVM_DELETED_FUNCTION;
protected:
// Constructors that forward to the base.
SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)
@@ -251,10 +254,16 @@ protected:
: SmallPtrSetImplBase(SmallStorage, SmallSize) {}
public:
- /// insert - This returns true if the pointer was new to the set, false if it
- /// was already in the set.
- bool insert(PtrType Ptr) {
- return insert_imp(PtrTraits::getAsVoidPointer(Ptr));
+ typedef SmallPtrSetIterator<PtrType> iterator;
+ typedef SmallPtrSetIterator<PtrType> const_iterator;
+
+ /// Inserts Ptr if and only if there is no element in the container equal to
+ /// Ptr. The bool component of the returned pair is true if and only if the
+ /// insertion takes place, and the iterator component of the pair points to
+ /// the element equal to Ptr.
+ std::pair<iterator, bool> insert(PtrType Ptr) {
+ auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
+ return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second);
}
/// erase - If the set contains the specified pointer, remove it and return
@@ -274,8 +283,6 @@ public:
insert(*I);
}
- typedef SmallPtrSetIterator<PtrType> iterator;
- typedef SmallPtrSetIterator<PtrType> const_iterator;
inline iterator begin() const {
return iterator(CurArray, CurArray+CurArraySize);
}
diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h
index bb1971eb7c5d..bc6493554c8b 100644
--- a/include/llvm/ADT/SmallSet.h
+++ b/include/llvm/ADT/SmallSet.h
@@ -14,6 +14,7 @@
#ifndef LLVM_ADT_SMALLSET_H
#define LLVM_ADT_SMALLSET_H
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include <set>
@@ -60,16 +61,21 @@ public:
/// insert - Insert an element into the set if it isn't already there.
/// Returns true if the element is inserted (it was not in the set before).
- bool insert(const T &V) {
+ /// The first value of the returned pair is unused and provided for
+ /// partial compatibility with the standard library self-associative container
+ /// concept.
+ // FIXME: Add iterators that abstract over the small and large form, and then
+ // return those here.
+ std::pair<NoneType, bool> insert(const T &V) {
if (!isSmall())
- return Set.insert(V).second;
+ return std::make_pair(None, Set.insert(V).second);
VIterator I = vfind(V);
if (I != Vector.end()) // Don't reinsert if it already exists.
- return false;
+ return std::make_pair(None, false);
if (Vector.size() < N) {
Vector.push_back(V);
- return true;
+ return std::make_pair(None, true);
}
// Otherwise, grow from vector to set.
@@ -78,7 +84,7 @@ public:
Vector.pop_back();
}
Set.insert(V);
- return true;
+ return std::make_pair(None, true);
}
template <typename IterT>
diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h
index 82538e9bd108..44a352119b09 100644
--- a/include/llvm/ADT/SmallVector.h
+++ b/include/llvm/ADT/SmallVector.h
@@ -29,8 +29,7 @@
namespace llvm {
-/// SmallVectorBase - This is all the non-templated stuff common to all
-/// SmallVectors.
+/// This is all the non-templated stuff common to all SmallVectors.
class SmallVectorBase {
protected:
void *BeginX, *EndX, *CapacityX;
@@ -39,12 +38,12 @@ protected:
SmallVectorBase(void *FirstEl, size_t Size)
: BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {}
- /// grow_pod - This is an implementation of the grow() method which only works
+ /// 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);
public:
- /// size_in_bytes - This returns size()*sizeof(T).
+ /// This returns size()*sizeof(T).
size_t size_in_bytes() const {
return size_t((char*)EndX - (char*)BeginX);
}
@@ -59,10 +58,9 @@ public:
template <typename T, unsigned N> struct SmallVectorStorage;
-/// SmallVectorTemplateCommon - This is the part of SmallVectorTemplateBase
-/// which does not depend on whether the type T is a POD. The extra dummy
-/// template argument is used by ArrayRef to avoid unnecessarily requiring T
-/// to be complete.
+/// This is the part of SmallVectorTemplateBase which does not depend on whether
+/// the type T is a POD. The extra dummy template argument is used by ArrayRef
+/// to avoid unnecessarily requiring T to be complete.
template <typename T, typename = void>
class SmallVectorTemplateCommon : public SmallVectorBase {
private:
@@ -82,13 +80,13 @@ protected:
SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize);
}
- /// isSmall - Return true if this is a smallvector which has not had dynamic
+ /// 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);
}
- /// resetToSmall - Put this vector in a state of being small.
+ /// Put this vector in a state of being small.
void resetToSmall() {
BeginX = EndX = CapacityX = &FirstEl;
}
@@ -128,21 +126,20 @@ public:
size_type size() const { return end()-begin(); }
size_type max_size() const { return size_type(-1) / sizeof(T); }
- /// capacity - Return the total number of elements in the currently allocated
- /// buffer.
+ /// Return the total number of elements in the currently allocated buffer.
size_t capacity() const { return capacity_ptr() - begin(); }
- /// data - Return a pointer to the vector's buffer, even if empty().
+ /// Return a pointer to the vector's buffer, even if empty().
pointer data() { return pointer(begin()); }
- /// data - Return a pointer to the vector's buffer, even if empty().
+ /// Return a pointer to the vector's buffer, even if empty().
const_pointer data() const { return const_pointer(begin()); }
- reference operator[](unsigned idx) {
- assert(begin() + idx < end());
+ reference operator[](size_type idx) {
+ assert(idx < size());
return begin()[idx];
}
- const_reference operator[](unsigned idx) const {
- assert(begin() + idx < end());
+ const_reference operator[](size_type idx) const {
+ assert(idx < size());
return begin()[idx];
}
@@ -179,7 +176,7 @@ protected:
}
}
- /// move - Use move-assignment to move the range [I, E) onto the
+ /// Use move-assignment to move the range [I, E) onto the
/// objects starting with "Dest". This is just <memory>'s
/// std::move, but not all stdlibs actually provide that.
template<typename It1, typename It2>
@@ -189,7 +186,7 @@ protected:
return Dest;
}
- /// move_backward - Use move-assignment to move the range
+ /// Use move-assignment to move the range
/// [I, E) onto the objects ending at "Dest", moving objects
/// in reverse order. This is just <algorithm>'s
/// std::move_backward, but not all stdlibs actually provide that.
@@ -200,25 +197,24 @@ protected:
return Dest;
}
- /// uninitialized_move - Move the range [I, E) into the uninitialized
- /// memory starting with "Dest", constructing elements as needed.
+ /// Move the range [I, E) into the uninitialized memory starting with "Dest",
+ /// constructing elements as needed.
template<typename It1, typename It2>
static void uninitialized_move(It1 I, It1 E, It2 Dest) {
for (; I != E; ++I, ++Dest)
::new ((void*) &*Dest) T(::std::move(*I));
}
- /// uninitialized_copy - Copy the range [I, E) onto the uninitialized
- /// memory starting with "Dest", constructing elements as needed.
+ /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
+ /// constructing elements as needed.
template<typename It1, typename It2>
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
std::uninitialized_copy(I, E, Dest);
}
- /// grow - Grow the allocated memory (without initializing new
- /// elements), doubling the size of the allocated memory.
- /// Guarantees space for at least one more element, or MinSize more
- /// elements if specified.
+ /// Grow the allocated memory (without initializing new elements), doubling
+ /// the size of the allocated memory. Guarantees space for at least one more
+ /// element, or MinSize more elements if specified.
void grow(size_t MinSize = 0);
public:
@@ -240,6 +236,51 @@ public:
this->setEnd(this->end()-1);
this->end()->~T();
}
+
+#if LLVM_HAS_VARIADIC_TEMPLATES
+ template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
+ if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+ this->grow();
+ ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
+ this->setEnd(this->end() + 1);
+ }
+#else
+private:
+ template <typename Constructor> void emplace_back_impl(Constructor construct) {
+ if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+ this->grow();
+ construct((void *)this->end());
+ this->setEnd(this->end() + 1);
+ }
+
+public:
+ void emplace_back() {
+ emplace_back_impl([](void *Mem) { ::new (Mem) T(); });
+ }
+ template <typename T1> void emplace_back(T1 &&A1) {
+ emplace_back_impl([&](void *Mem) { ::new (Mem) T(std::forward<T1>(A1)); });
+ }
+ template <typename T1, typename T2> void emplace_back(T1 &&A1, T2 &&A2) {
+ emplace_back_impl([&](void *Mem) {
+ ::new (Mem) T(std::forward<T1>(A1), std::forward<T2>(A2));
+ });
+ }
+ template <typename T1, typename T2, typename T3>
+ void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3) {
+ T(std::forward<T1>(A1), std::forward<T2>(A2), std::forward<T3>(A3));
+ emplace_back_impl([&](void *Mem) {
+ ::new (Mem)
+ T(std::forward<T1>(A1), std::forward<T2>(A2), std::forward<T3>(A3));
+ });
+ }
+ template <typename T1, typename T2, typename T3, typename T4>
+ void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) {
+ emplace_back_impl([&](void *Mem) {
+ ::new (Mem) T(std::forward<T1>(A1), std::forward<T2>(A2),
+ std::forward<T3>(A3), std::forward<T4>(A4));
+ });
+ }
+#endif // LLVM_HAS_VARIADIC_TEMPLATES
};
// Define this out-of-line to dissuade the C++ compiler from inlining it.
@@ -279,22 +320,21 @@ protected:
// No need to do a destroy loop for POD's.
static void destroy_range(T *, T *) {}
- /// move - Use move-assignment to move the range [I, E) onto the
+ /// Use move-assignment to move the range [I, E) onto the
/// objects starting with "Dest". For PODs, this is just memcpy.
template<typename It1, typename It2>
static It2 move(It1 I, It1 E, It2 Dest) {
return ::std::copy(I, E, Dest);
}
- /// move_backward - Use move-assignment to move the range
- /// [I, E) onto the objects ending at "Dest", moving objects
- /// in reverse order.
+ /// Use move-assignment to move the range [I, E) onto the objects ending at
+ /// "Dest", moving objects in reverse order.
template<typename It1, typename It2>
static It2 move_backward(It1 I, It1 E, It2 Dest) {
return ::std::copy_backward(I, E, Dest);
}
- /// uninitialized_move - Move the range [I, E) onto the uninitialized memory
+ /// Move the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
template<typename It1, typename It2>
static void uninitialized_move(It1 I, It1 E, It2 Dest) {
@@ -302,7 +342,7 @@ protected:
uninitialized_copy(I, E, Dest);
}
- /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
+ /// Copy the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
template<typename It1, typename It2>
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
@@ -310,7 +350,7 @@ protected:
std::uninitialized_copy(I, E, Dest);
}
- /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
+ /// Copy the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
template<typename T1, typename T2>
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) {
@@ -320,7 +360,7 @@ protected:
memcpy(Dest, I, (E-I)*sizeof(T));
}
- /// grow - double the size of the allocated memory, guaranteeing space for at
+ /// 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));
@@ -339,9 +379,8 @@ public:
};
-/// SmallVectorImpl - This class consists of common code factored out of the
-/// SmallVector class to reduce code duplication based on the SmallVector 'N'
-/// template parameter.
+/// This class consists of common code factored out of the SmallVector class to
+/// reduce code duplication based on the SmallVector 'N' template parameter.
template <typename T>
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
@@ -373,7 +412,7 @@ public:
this->EndX = this->BeginX;
}
- void resize(unsigned N) {
+ void resize(size_type N) {
if (N < this->size()) {
this->destroy_range(this->begin()+N, this->end());
this->setEnd(this->begin()+N);
@@ -386,7 +425,7 @@ public:
}
}
- void resize(unsigned N, const T &NV) {
+ void resize(size_type N, const T &NV) {
if (N < this->size()) {
this->destroy_range(this->begin()+N, this->end());
this->setEnd(this->begin()+N);
@@ -398,7 +437,7 @@ public:
}
}
- void reserve(unsigned N) {
+ void reserve(size_type N) {
if (this->capacity() < N)
this->grow(N);
}
@@ -411,8 +450,7 @@ public:
void swap(SmallVectorImpl &RHS);
- /// append - Add the specified range to the end of the SmallVector.
- ///
+ /// Add the specified range to the end of the SmallVector.
template<typename in_iter>
void append(in_iter in_start, in_iter in_end) {
size_type NumInputs = std::distance(in_start, in_end);
@@ -427,8 +465,7 @@ public:
this->setEnd(this->end() + NumInputs);
}
- /// append - Add the specified range to the end of the SmallVector.
- ///
+ /// 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()))
@@ -439,7 +476,7 @@ public:
this->setEnd(this->end() + NumInputs);
}
- void assign(unsigned NumElts, const T &Elt) {
+ void assign(size_type NumElts, const T &Elt) {
clear();
if (this->capacity() < NumElts)
this->grow(NumElts);
@@ -545,7 +582,7 @@ public:
assert(I <= this->end() && "Inserting past the end of the vector.");
// Ensure there is enough space.
- reserve(static_cast<unsigned>(this->size() + NumToInsert));
+ reserve(this->size() + NumToInsert);
// Uninvalidate the iterator.
I = this->begin()+InsertElt;
@@ -599,7 +636,7 @@ public:
size_t NumToInsert = std::distance(From, To);
// Ensure there is enough space.
- reserve(static_cast<unsigned>(this->size() + NumToInsert));
+ reserve(this->size() + NumToInsert);
// Uninvalidate the iterator.
I = this->begin()+InsertElt;
@@ -666,7 +703,7 @@ public:
/// of the buffer when they know that more elements are available, and only
/// update the size later. This avoids the cost of value initializing elements
/// which will only be overwritten.
- void set_size(unsigned N) {
+ void set_size(size_type N) {
assert(N <= this->capacity());
this->setEnd(this->begin() + N);
}
@@ -692,7 +729,7 @@ void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
// Swap the shared elements.
size_t NumShared = this->size();
if (NumShared > RHS.size()) NumShared = RHS.size();
- for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i)
+ for (size_type i = 0; i != NumShared; ++i)
std::swap((*this)[i], RHS[i]);
// Copy over the extra elts.
@@ -833,7 +870,7 @@ struct SmallVectorStorage {
template <typename T> struct SmallVectorStorage<T, 1> {};
template <typename T> struct SmallVectorStorage<T, 0> {};
-/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized
+/// This is a 'vector' (really, a variable-sized array), optimized
/// for the case when the array is small. It contains some number of elements
/// in-place, which allows it to avoid heap allocation when the actual number of
/// elements is below that threshold. This allows normal "small" cases to be
@@ -843,13 +880,13 @@ template <typename T> struct SmallVectorStorage<T, 0> {};
///
template <typename T, unsigned N>
class SmallVector : public SmallVectorImpl<T> {
- /// Storage - Inline space for elements which aren't stored in the base class.
+ /// Inline space for elements which aren't stored in the base class.
SmallVectorStorage<T, N> Storage;
public:
SmallVector() : SmallVectorImpl<T>(N) {
}
- explicit SmallVector(unsigned Size, const T &Value = T())
+ explicit SmallVector(size_t Size, const T &Value = T())
: SmallVectorImpl<T>(N) {
this->assign(Size, Value);
}
diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h
index 36754d682355..d5bde2963fbd 100644
--- a/include/llvm/ADT/SparseBitVector.h
+++ b/include/llvm/ADT/SparseBitVector.h
@@ -45,7 +45,7 @@ struct SparseBitVectorElement
: public ilist_node<SparseBitVectorElement<ElementSize> > {
public:
typedef unsigned long BitWord;
- typedef unsigned size_type;
+ typedef unsigned size_type;
enum {
BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE,
diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h
index dc1273eb7ff6..f858536b6ed8 100644
--- a/include/llvm/ADT/SparseMultiSet.h
+++ b/include/llvm/ADT/SparseMultiSet.h
@@ -185,7 +185,7 @@ public:
typedef const ValueT &const_reference;
typedef ValueT *pointer;
typedef const ValueT *const_pointer;
- typedef unsigned size_type;
+ typedef unsigned size_type;
SparseMultiSet()
: Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {}
diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h
index 632d52ad9d82..9a13440000ac 100644
--- a/include/llvm/ADT/SparseSet.h
+++ b/include/llvm/ADT/SparseSet.h
@@ -124,7 +124,7 @@ class SparseSet {
typedef typename KeyFunctorT::argument_type KeyT;
typedef SmallVector<ValueT, 8> DenseT;
- typedef unsigned size_type;
+ typedef unsigned size_type;
DenseT Dense;
SparseT *Sparse;
unsigned Universe;
diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h
index c40e5e2b3d87..3437607a0bd0 100644
--- a/include/llvm/ADT/StringMap.h
+++ b/include/llvm/ADT/StringMap.h
@@ -117,8 +117,9 @@ public:
explicit StringMapEntry(unsigned strLen)
: StringMapEntryBase(strLen), second() {}
- StringMapEntry(unsigned strLen, ValueTy V)
- : StringMapEntryBase(strLen), second(std::move(V)) {}
+ template <class InitTy>
+ StringMapEntry(unsigned strLen, InitTy &&V)
+ : StringMapEntryBase(strLen), second(std::forward<InitTy>(V)) {}
StringRef getKey() const {
return StringRef(getKeyData(), getKeyLength());
@@ -138,10 +139,9 @@ public:
/// Create - Create a StringMapEntry for the specified key and default
/// construct the value.
- template<typename AllocatorTy, typename InitType>
- static StringMapEntry *Create(StringRef Key,
- AllocatorTy &Allocator,
- InitType InitVal) {
+ template <typename AllocatorTy, typename InitType>
+ static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
+ InitType &&InitVal) {
unsigned KeyLength = Key.size();
// Allocate a new item with space for the string at the end and a null
@@ -154,7 +154,7 @@ public:
static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
// Default construct the value.
- new (NewItem) StringMapEntry(KeyLength, std::move(InitVal));
+ new (NewItem) StringMapEntry(KeyLength, std::forward<InitType>(InitVal));
// Copy the string information.
char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
@@ -170,28 +170,15 @@ public:
/// Create - Create a StringMapEntry with normal malloc/free.
template<typename InitType>
- static StringMapEntry *Create(StringRef Key, InitType InitVal) {
+ static StringMapEntry *Create(StringRef Key, InitType &&InitVal) {
MallocAllocator A;
- return Create(Key, A, std::move(InitVal));
+ return Create(Key, A, std::forward<InitType>(InitVal));
}
static StringMapEntry *Create(StringRef Key) {
return Create(Key, ValueTy());
}
- /// GetStringMapEntryFromValue - Given a value that is known to be embedded
- /// into a StringMapEntry, return the StringMapEntry itself.
- static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) {
- StringMapEntry *EPtr = 0;
- char *Ptr = reinterpret_cast<char*>(&V) -
- (reinterpret_cast<char*>(&EPtr->second) -
- reinterpret_cast<char*>(EPtr));
- return *reinterpret_cast<StringMapEntry*>(Ptr);
- }
- static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) {
- return GetStringMapEntryFromValue(const_cast<ValueTy&>(V));
- }
-
/// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
/// into a StringMapEntry, return the StringMapEntry itself.
static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
@@ -296,7 +283,7 @@ public:
}
ValueTy &operator[](StringRef Key) {
- return GetOrCreateValue(Key).getValue();
+ return insert(std::make_pair(Key, ValueTy())).first->second;
}
/// count - Return 1 if the element is in the map, 0 otherwise.
@@ -363,18 +350,6 @@ public:
NumTombstones = 0;
}
- /// GetOrCreateValue - Look up the specified key in the table. If a value
- /// exists, return it. Otherwise, default construct a value, insert it, and
- /// return.
- template <typename InitTy>
- MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) {
- return *insert(std::make_pair(Key, std::move(Val))).first;
- }
-
- MapEntryTy &GetOrCreateValue(StringRef Key) {
- return GetOrCreateValue(Key, ValueTy());
- }
-
/// remove - Remove the specified key/value pair from the map, but do not
/// erase it. This aborts if the key is not in the map.
void remove(MapEntryTy *KeyValue) {
diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h
index 1f413e80553f..6111c42da9dc 100644
--- a/include/llvm/ADT/StringRef.h
+++ b/include/llvm/ADT/StringRef.h
@@ -51,12 +51,6 @@ namespace llvm {
/// The length of the string.
size_t Length;
- // Workaround PR5482: nearly all gcc 4.x miscompile StringRef and std::min()
- // Changing the arg of min to be an integer, instead of a reference to an
- // integer works around this bug.
- static size_t min(size_t a, size_t b) { return a < b ? a : b; }
- static size_t max(size_t a, size_t b) { return a > b ? a : b; }
-
// Workaround memcmp issue with null pointers (undefined behavior)
// by providing a specialized version
static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) {
@@ -97,6 +91,13 @@ namespace llvm {
iterator end() const { return Data + Length; }
+ const unsigned char *bytes_begin() const {
+ return reinterpret_cast<const unsigned char *>(begin());
+ }
+ const unsigned char *bytes_end() const {
+ return reinterpret_cast<const unsigned char *>(end());
+ }
+
/// @}
/// @name String Operations
/// @{
@@ -124,7 +125,7 @@ namespace llvm {
}
// copy - Allocate copy in Allocator and return StringRef to it.
- template <typename Allocator> StringRef copy(Allocator &A) {
+ template <typename Allocator> StringRef copy(Allocator &A) const {
char *S = A.template Allocate<char>(Length);
std::copy(begin(), end(), S);
return StringRef(S, Length);
@@ -146,7 +147,7 @@ namespace llvm {
/// is lexicographically less than, equal to, or greater than the \p RHS.
int compare(StringRef RHS) const {
// Check the prefix for a mismatch.
- if (int Res = compareMemory(Data, RHS.Data, min(Length, RHS.Length)))
+ if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length)))
return Res < 0 ? -1 : 1;
// Otherwise the prefixes match, so we only need to check the lengths.
@@ -237,7 +238,7 @@ namespace llvm {
/// \returns The index of the first occurrence of \p C, or npos if not
/// found.
size_t find(char C, size_t From = 0) const {
- for (size_t i = min(From, Length), e = Length; i != e; ++i)
+ for (size_t i = std::min(From, Length), e = Length; i != e; ++i)
if (Data[i] == C)
return i;
return npos;
@@ -254,7 +255,7 @@ namespace llvm {
/// \returns The index of the last occurrence of \p C, or npos if not
/// found.
size_t rfind(char C, size_t From = npos) const {
- From = min(From, Length);
+ From = std::min(From, Length);
size_t i = From;
while (i != 0) {
--i;
@@ -353,8 +354,11 @@ namespace llvm {
typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
getAsInteger(unsigned Radix, T &Result) const {
unsigned long long ULLVal;
+ // The additional cast to unsigned long long is required to avoid the
+ // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type
+ // 'unsigned __int64' when instantiating getAsInteger with T = bool.
if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
- static_cast<T>(ULLVal) != ULLVal)
+ static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal)
return true;
Result = ULLVal;
return false;
@@ -396,8 +400,8 @@ namespace llvm {
/// exceeds the number of characters remaining in the string, the string
/// suffix (starting with \p Start) will be returned.
StringRef substr(size_t Start, size_t N = npos) const {
- Start = min(Start, Length);
- return StringRef(Data + Start, min(N, Length - Start));
+ Start = std::min(Start, Length);
+ return StringRef(Data + Start, std::min(N, Length - Start));
}
/// Return a StringRef equal to 'this' but with the first \p N elements
@@ -425,8 +429,8 @@ namespace llvm {
/// number of characters remaining in the string, the string suffix
/// (starting with \p Start) will be returned.
StringRef slice(size_t Start, size_t End) const {
- Start = min(Start, Length);
- End = min(max(Start, End), Length);
+ Start = std::min(Start, Length);
+ End = std::min(std::max(Start, End), Length);
return StringRef(Data + Start, End - Start);
}
diff --git a/include/llvm/ADT/StringSet.h b/include/llvm/ADT/StringSet.h
index 7bea577f34d3..3e0cc200b6dd 100644
--- a/include/llvm/ADT/StringSet.h
+++ b/include/llvm/ADT/StringSet.h
@@ -24,20 +24,9 @@ namespace llvm {
typedef llvm::StringMap<char, AllocatorTy> base;
public:
- /// insert - Insert the specified key into the set. If the key already
- /// exists in the set, return false and ignore the request, otherwise insert
- /// it and return true.
- bool insert(StringRef Key) {
- // Get or create the map entry for the key; if it doesn't exist the value
- // type will be default constructed which we use to detect insert.
- //
- // We use '+' as the sentinel value in the map.
+ std::pair<typename base::iterator, bool> insert(StringRef Key) {
assert(!Key.empty());
- StringMapEntry<char> &Entry = this->GetOrCreateValue(Key);
- if (Entry.getValue() == '+')
- return false;
- Entry.setValue('+');
- return true;
+ return base::insert(std::make_pair(Key, '\0'));
}
};
}
diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h
index 5669b2a81a40..15137f5ebf8c 100644
--- a/include/llvm/ADT/TinyPtrVector.h
+++ b/include/llvm/ADT/TinyPtrVector.h
@@ -96,10 +96,17 @@ public:
return *this;
}
+ /// Constructor from a single element.
+ explicit TinyPtrVector(EltTy Elt) : Val(Elt) {}
+
+ /// Constructor from an ArrayRef.
+ explicit TinyPtrVector(ArrayRef<EltTy> Elts)
+ : Val(new VecTy(Elts.begin(), Elts.end())) {}
+
// implicit conversion operator to ArrayRef.
operator ArrayRef<EltTy>() const {
if (Val.isNull())
- return ArrayRef<EltTy>();
+ return None;
if (Val.template is<EltTy>())
return *Val.getAddrOfPtr1();
return *Val.template get<VecTy*>();
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index b96f11435520..8a685995256b 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -48,8 +48,6 @@ public:
arm, // ARM (little endian): arm, armv.*, xscale
armeb, // ARM (big endian): armeb
- arm64, // ARM64 (little endian): arm64
- arm64_be, // ARM64 (big endian): arm64_be
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
hexagon, // Hexagon: hexagon
@@ -62,6 +60,7 @@ public:
ppc64, // PPC64: powerpc64, ppu
ppc64le, // PPC64LE: powerpc64le
r600, // R600: AMD GPUs HD2XXX - HD6XXX
+ amdgcn, // AMDGCN: AMD GCN GPUs
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
systemz, // SystemZ: s390x
@@ -74,7 +73,11 @@ public:
nvptx, // NVPTX: 32-bit
nvptx64, // NVPTX: 64-bit
le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten)
- amdil, // amdil: amd IL
+ le64, // le64: generic little-endian 64-bit CPU (PNaCl / Emscripten)
+ amdil, // AMDIL
+ amdil64, // AMDIL with 64-bit pointers
+ hsail, // AMD HSAIL
+ hsail64, // AMD HSAIL with 64-bit pointers
spir, // SPIR: standard portable IR for OpenCL 32-bit version
spir64, // SPIR: standard portable IR for OpenCL 64-bit version
kalimba // Kalimba: generic kalimba
@@ -92,7 +95,11 @@ public:
ARMSubArch_v6t2,
ARMSubArch_v5,
ARMSubArch_v5te,
- ARMSubArch_v4t
+ ARMSubArch_v4t,
+
+ KalimbaSubArch_v3,
+ KalimbaSubArch_v4,
+ KalimbaSubArch_v5
};
enum VendorType {
UnknownVendor,
@@ -112,8 +119,6 @@ public:
enum OSType {
UnknownOS,
- AuroraUX,
- Cygwin,
Darwin,
DragonFly,
FreeBSD,
@@ -122,7 +127,6 @@ public:
Linux,
Lv2, // PS3
MacOSX,
- MinGW32, // i*86-pc-mingw32, *-w64-mingw32
NetBSD,
OpenBSD,
Solaris,
@@ -135,7 +139,8 @@ public:
Bitrig,
AIX,
CUDA, // NVIDIA CUDA
- NVCL // NVIDIA OpenCL
+ NVCL, // NVIDIA OpenCL
+ AMDHSA // AMD HSA Runtime
};
enum EnvironmentType {
UnknownEnvironment,
@@ -361,10 +366,28 @@ public:
return isMacOSX() || isiOS();
}
+ bool isOSNetBSD() const {
+ return getOS() == Triple::NetBSD;
+ }
+
+ bool isOSOpenBSD() const {
+ return getOS() == Triple::OpenBSD;
+ }
+
bool isOSFreeBSD() const {
return getOS() == Triple::FreeBSD;
}
+ bool isOSDragonFly() const { return getOS() == Triple::DragonFly; }
+
+ bool isOSSolaris() const {
+ return getOS() == Triple::Solaris;
+ }
+
+ bool isOSBitrig() const {
+ return getOS() == Triple::Bitrig;
+ }
+
bool isWindowsMSVCEnvironment() const {
return getOS() == Triple::Win32 &&
(getEnvironment() == Triple::UnknownEnvironment ||
@@ -380,13 +403,11 @@ public:
}
bool isWindowsCygwinEnvironment() const {
- return getOS() == Triple::Cygwin ||
- (getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus);
+ return getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus;
}
bool isWindowsGNUEnvironment() const {
- return getOS() == Triple::MinGW32 ||
- (getOS() == Triple::Win32 && getEnvironment() == Triple::GNU);
+ return getOS() == Triple::Win32 && getEnvironment() == Triple::GNU;
}
/// \brief Tests for either Cygwin or MinGW OS
@@ -396,7 +417,8 @@ public:
/// \brief Is this a "Windows" OS targeting a "MSVCRT.dll" environment.
bool isOSMSVCRT() const {
- return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment();
+ return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment() ||
+ isWindowsItaniumEnvironment();
}
/// \brief Tests whether the OS is Windows.
@@ -475,10 +497,6 @@ public:
/// environment components with a single string.
void setOSAndEnvironmentName(StringRef Str);
- /// getArchNameForAssembler - Get an architecture name that is understood by
- /// the target assembler.
- const char *getArchNameForAssembler();
-
/// @}
/// @name Helpers to build variants of a particular triple.
/// @{
diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h
index 4be3ee6f82db..05d2fea117cf 100644
--- a/include/llvm/ADT/Twine.h
+++ b/include/llvm/ADT/Twine.h
@@ -80,7 +80,7 @@ namespace llvm {
/// StringRef) codegen as desired.
class Twine {
/// NodeKind - Represent the type of an argument.
- enum NodeKind {
+ enum NodeKind : unsigned char {
/// An empty string; the result of concatenating anything with it is also
/// empty.
NullKind,
@@ -153,12 +153,10 @@ namespace llvm {
/// RHS - The suffix in the concatenation, which may be uninitialized for
/// Null or Empty kinds.
Child RHS;
- // enums stored as unsigned chars to save on space while some compilers
- // don't support specifying the backing type for an enum
/// LHSKind - The NodeKind of the left hand side, \see getLHSKind().
- unsigned char LHSKind;
- /// RHSKind - The NodeKind of the left hand side, \see getLHSKind().
- unsigned char RHSKind;
+ NodeKind LHSKind;
+ /// RHSKind - The NodeKind of the right hand side, \see getRHSKind().
+ NodeKind RHSKind;
private:
/// Construct a nullary twine; the kind must be NullKind or EmptyKind.
@@ -238,10 +236,10 @@ namespace llvm {
}
/// getLHSKind - Get the NodeKind of the left-hand side.
- NodeKind getLHSKind() const { return (NodeKind) LHSKind; }
+ NodeKind getLHSKind() const { return LHSKind; }
/// getRHSKind - Get the NodeKind of the right-hand side.
- NodeKind getRHSKind() const { return (NodeKind) RHSKind; }
+ NodeKind getRHSKind() const { return RHSKind; }
/// printOneChild - Print one child from a twine.
void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
diff --git a/include/llvm/ADT/VariadicFunction.h b/include/llvm/ADT/VariadicFunction.h
index 0497aa70887c..403130c623eb 100644
--- a/include/llvm/ADT/VariadicFunction.h
+++ b/include/llvm/ADT/VariadicFunction.h
@@ -105,7 +105,7 @@ template <typename ResultT, typename ArgT,
ResultT (*Func)(ArrayRef<const ArgT *>)>
struct VariadicFunction {
ResultT operator()() const {
- return Func(ArrayRef<const ArgT *>());
+ return Func(None);
}
#define LLVM_DEFINE_OVERLOAD(N) \
@@ -152,7 +152,7 @@ template <typename ResultT, typename Param0T, typename ArgT,
ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)>
struct VariadicFunction1 {
ResultT operator()(Param0T P0) const {
- return Func(P0, ArrayRef<const ArgT *>());
+ return Func(P0, None);
}
#define LLVM_DEFINE_OVERLOAD(N) \
@@ -199,7 +199,7 @@ template <typename ResultT, typename Param0T, typename Param1T, typename ArgT,
ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)>
struct VariadicFunction2 {
ResultT operator()(Param0T P0, Param1T P1) const {
- return Func(P0, P1, ArrayRef<const ArgT *>());
+ return Func(P0, P1, None);
}
#define LLVM_DEFINE_OVERLOAD(N) \
@@ -248,7 +248,7 @@ template <typename ResultT, typename Param0T, typename Param1T,
ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)>
struct VariadicFunction3 {
ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const {
- return Func(P0, P1, P2, ArrayRef<const ArgT *>());
+ return Func(P0, P1, P2, None);
}
#define LLVM_DEFINE_OVERLOAD(N) \
diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h
index bc148452f217..8c19a6f4547a 100644
--- a/include/llvm/ADT/ilist.h
+++ b/include/llvm/ADT/ilist.h
@@ -579,60 +579,6 @@ public:
void splice(iterator where, iplist &L2, iterator first, iterator last) {
if (first != last) transfer(where, L2, first, last);
}
-
-
-
- //===----------------------------------------------------------------------===
- // High-Level Functionality that shouldn't really be here, but is part of list
- //
-
- // These two functions are actually called remove/remove_if in list<>, but
- // they actually do the job of erase, rename them accordingly.
- //
- void erase(const NodeTy &val) {
- for (iterator I = begin(), E = end(); I != E; ) {
- iterator next = I; ++next;
- if (*I == val) erase(I);
- I = next;
- }
- }
- template<class Pr1> void erase_if(Pr1 pred) {
- for (iterator I = begin(), E = end(); I != E; ) {
- iterator next = I; ++next;
- if (pred(*I)) erase(I);
- I = next;
- }
- }
-
- template<class Pr2> void unique(Pr2 pred) {
- if (empty()) return;
- for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) {
- if (pred(*I))
- erase(Next);
- else
- I = Next;
- Next = I;
- }
- }
- void unique() { unique(op_equal); }
-
- template<class Pr3> void merge(iplist &right, Pr3 pred) {
- iterator first1 = begin(), last1 = end();
- iterator first2 = right.begin(), last2 = right.end();
- while (first1 != last1 && first2 != last2)
- if (pred(*first2, *first1)) {
- iterator next = first2;
- transfer(first1, right, first2, ++next);
- first2 = next;
- } else {
- ++first1;
- }
- if (first2 != last2) transfer(last1, right, first2, last2);
- }
- void merge(iplist &right) { return merge(right, op_less); }
-
- template<class Pr3> void sort(Pr3 pred);
- void sort() { sort(op_less); }
};
diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h
index 85aa7a4b1f7f..26d0b55e4093 100644
--- a/include/llvm/ADT/ilist_node.h
+++ b/include/llvm/ADT/ilist_node.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_ADT_ILISTNODE_H
-#define LLVM_ADT_ILISTNODE_H
+#ifndef LLVM_ADT_ILIST_NODE_H
+#define LLVM_ADT_ILIST_NODE_H
namespace llvm {
diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h
index 56041dbb106c..e2c9e5ea6bda 100644
--- a/include/llvm/ADT/iterator.h
+++ b/include/llvm/ADT/iterator.h
@@ -10,8 +10,8 @@
#ifndef LLVM_ADT_ITERATOR_H
#define LLVM_ADT_ITERATOR_H
-#include <iterator>
#include <cstddef>
+#include <iterator>
namespace llvm {
diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h
index dd17d6c8f7b4..523a86f02e08 100644
--- a/include/llvm/ADT/iterator_range.h
+++ b/include/llvm/ADT/iterator_range.h
@@ -32,7 +32,6 @@ class iterator_range {
IteratorT begin_iterator, end_iterator;
public:
- iterator_range() {}
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
: begin_iterator(std::move(begin_iterator)),
end_iterator(std::move(end_iterator)) {}
@@ -48,6 +47,10 @@ public:
template <class T> iterator_range<T> make_range(T x, T y) {
return iterator_range<T>(std::move(x), std::move(y));
}
+
+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));
+}
}
#endif
diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h
index 689766446445..763f37298811 100644
--- a/include/llvm/Analysis/AliasAnalysis.h
+++ b/include/llvm/Analysis/AliasAnalysis.h
@@ -39,6 +39,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/IR/Metadata.h"
namespace llvm {
@@ -112,13 +113,14 @@ public:
/// there are restrictions on stepping out of one object and into another.
/// See http://llvm.org/docs/LangRef.html#pointeraliasing
uint64_t Size;
- /// TBAATag - The metadata node which describes the TBAA type of
- /// the location, or null if there is no known unique tag.
- const MDNode *TBAATag;
+ /// AATags - The metadata nodes which describes the aliasing of the
+ /// location (each member is null if that kind of information is
+ /// unavailable)..
+ AAMDNodes AATags;
explicit Location(const Value *P = nullptr, uint64_t S = UnknownSize,
- const MDNode *N = nullptr)
- : Ptr(P), Size(S), TBAATag(N) {}
+ const AAMDNodes &N = AAMDNodes())
+ : Ptr(P), Size(S), AATags(N) {}
Location getWithNewPtr(const Value *NewPtr) const {
Location Copy(*this);
@@ -132,9 +134,9 @@ public:
return Copy;
}
- Location getWithoutTBAATag() const {
+ Location getWithoutAATags() const {
Location Copy(*this);
- Copy.TBAATag = nullptr;
+ Copy.AATags = AAMDNodes();
return Copy;
}
};
@@ -500,7 +502,7 @@ public:
///
/// canBasicBlockModify - Return true if it is possible for execution of the
- /// specified basic block to modify the value pointed to by Ptr.
+ /// specified basic block to modify the location Loc.
bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc);
/// canBasicBlockModify - A convenience wrapper.
@@ -508,17 +510,20 @@ public:
return canBasicBlockModify(BB, Location(P, Size));
}
- /// canInstructionRangeModify - Return true if it is possible for the
- /// execution of the specified instructions to modify the value pointed to by
- /// Ptr. The instructions to consider are all of the instructions in the
- /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block.
- bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2,
- const Location &Loc);
+ /// canInstructionRangeModRef - Return true if it is possible for the
+ /// execution of the specified instructions to mod\ref (according to the
+ /// mode) the location Loc. The instructions to consider are all
+ /// of the instructions in the range of [I1,I2] INCLUSIVE.
+ /// I1 and I2 must be in the same basic block.
+ bool canInstructionRangeModRef(const Instruction &I1,
+ const Instruction &I2, const Location &Loc,
+ const ModRefResult Mode);
- /// canInstructionRangeModify - A convenience wrapper.
- bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2,
- const Value *Ptr, uint64_t Size) {
- return canInstructionRangeModify(I1, I2, Location(Ptr, Size));
+ /// canInstructionRangeModRef - A convenience wrapper.
+ bool canInstructionRangeModRef(const Instruction &I1,
+ const Instruction &I2, const Value *Ptr,
+ uint64_t Size, const ModRefResult Mode) {
+ return canInstructionRangeModRef(I1, I2, Location(Ptr, Size), Mode);
}
//===--------------------------------------------------------------------===//
@@ -566,25 +571,23 @@ public:
template<>
struct DenseMapInfo<AliasAnalysis::Location> {
static inline AliasAnalysis::Location getEmptyKey() {
- return
- AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(),
- 0, nullptr);
+ return AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(),
+ 0);
}
static inline AliasAnalysis::Location getTombstoneKey() {
- return
- AliasAnalysis::Location(DenseMapInfo<const Value *>::getTombstoneKey(),
- 0, nullptr);
+ return AliasAnalysis::Location(
+ DenseMapInfo<const Value *>::getTombstoneKey(), 0);
}
static unsigned getHashValue(const AliasAnalysis::Location &Val) {
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^
- DenseMapInfo<const MDNode *>::getHashValue(Val.TBAATag);
+ DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags);
}
static bool isEqual(const AliasAnalysis::Location &LHS,
const AliasAnalysis::Location &RHS) {
return LHS.Ptr == RHS.Ptr &&
LHS.Size == RHS.Size &&
- LHS.TBAATag == RHS.TBAATag;
+ LHS.AATags == RHS.AATags;
}
};
diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h
index e32b6d628b7f..036d58dfa810 100644
--- a/include/llvm/Analysis/AliasSetTracker.h
+++ b/include/llvm/Analysis/AliasSetTracker.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/ValueHandle.h"
#include <vector>
@@ -40,11 +41,11 @@ class AliasSet : public ilist_node<AliasSet> {
PointerRec **PrevInList, *NextInList;
AliasSet *AS;
uint64_t Size;
- const MDNode *TBAAInfo;
+ AAMDNodes AAInfo;
public:
PointerRec(Value *V)
: Val(V), PrevInList(nullptr), NextInList(nullptr), AS(nullptr), Size(0),
- TBAAInfo(DenseMapInfo<const MDNode *>::getEmptyKey()) {}
+ AAInfo(DenseMapInfo<AAMDNodes>::getEmptyKey()) {}
Value *getValue() const { return Val; }
@@ -56,27 +57,27 @@ class AliasSet : public ilist_node<AliasSet> {
return &NextInList;
}
- void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) {
+ void updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) {
if (NewSize > Size) Size = NewSize;
- if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey())
- // We don't have a TBAAInfo yet. Set it to NewTBAAInfo.
- TBAAInfo = NewTBAAInfo;
- else if (TBAAInfo != NewTBAAInfo)
- // NewTBAAInfo conflicts with TBAAInfo.
- TBAAInfo = DenseMapInfo<const MDNode *>::getTombstoneKey();
+ if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey())
+ // We don't have a AAInfo yet. Set it to NewAAInfo.
+ AAInfo = NewAAInfo;
+ else if (AAInfo != NewAAInfo)
+ // NewAAInfo conflicts with AAInfo.
+ AAInfo = DenseMapInfo<AAMDNodes>::getTombstoneKey();
}
uint64_t getSize() const { return Size; }
- /// getTBAAInfo - Return the TBAAInfo, or null if there is no
+ /// getAAInfo - Return the AAInfo, or null if there is no
/// information or conflicting information.
- const MDNode *getTBAAInfo() const {
- // If we have missing or conflicting TBAAInfo, return null.
- if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey() ||
- TBAAInfo == DenseMapInfo<const MDNode *>::getTombstoneKey())
- return nullptr;
- return TBAAInfo;
+ AAMDNodes getAAInfo() const {
+ // If we have missing or conflicting AAInfo, return null.
+ if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey() ||
+ AAInfo == DenseMapInfo<AAMDNodes>::getTombstoneKey())
+ return AAMDNodes();
+ return AAInfo;
}
AliasSet *getAliasSet(AliasSetTracker &AST) {
@@ -204,7 +205,7 @@ public:
Value *getPointer() const { return CurNode->getValue(); }
uint64_t getSize() const { return CurNode->getSize(); }
- const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); }
+ AAMDNodes getAAInfo() const { return CurNode->getAAInfo(); }
iterator& operator++() { // Preincrement
assert(CurNode && "Advancing past AliasSet.end()!");
@@ -250,7 +251,7 @@ private:
void removeFromTracker(AliasSetTracker &AST);
void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size,
- const MDNode *TBAAInfo,
+ const AAMDNodes &AAInfo,
bool KnownMustAlias = false);
void addUnknownInst(Instruction *I, AliasAnalysis &AA);
void removeUnknownInst(AliasSetTracker &AST, Instruction *I) {
@@ -270,7 +271,7 @@ public:
/// aliasesPointer - Return true if the specified pointer "may" (or must)
/// alias one of the members in the set.
///
- bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo,
+ bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo,
AliasAnalysis &AA) const;
bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const;
};
@@ -325,7 +326,7 @@ 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).
///
- bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location
+ bool add(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); // Add a loc.
bool add(LoadInst *LI);
bool add(StoreInst *SI);
bool add(VAArgInst *VAAI);
@@ -338,7 +339,7 @@ public:
/// be aliased by the specified instruction. These methods return true if any
/// alias sets were eliminated.
// Remove a location
- bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo);
+ bool remove(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo);
bool remove(LoadInst *LI);
bool remove(StoreInst *SI);
bool remove(VAArgInst *VAAI);
@@ -357,20 +358,24 @@ public:
/// true if a new alias set is created to contain the pointer (because the
/// pointer didn't alias anything).
AliasSet &getAliasSetForPointer(Value *P, uint64_t Size,
- const MDNode *TBAAInfo,
+ const AAMDNodes &AAInfo,
bool *New = nullptr);
/// getAliasSetForPointerIfExists - Return the alias set containing the
/// location specified if one exists, otherwise return null.
AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size,
- const MDNode *TBAAInfo) {
- return findAliasSetForPointer(P, Size, TBAAInfo);
+ const AAMDNodes &AAInfo) {
+ return findAliasSetForPointer(P, Size, AAInfo);
}
/// containsPointer - Return true if the specified location is represented by
/// this alias set, false otherwise. This does not modify the AST object or
/// alias sets.
- bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const;
+ bool containsPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo) const;
+
+ /// Return true if the specified instruction "may" (or must) alias one of the
+ /// members in any of the sets.
+ bool containsUnknown(Instruction *I) const;
/// getAliasAnalysis - Return the underlying alias analysis object used by
/// this tracker.
@@ -417,16 +422,16 @@ private:
return *Entry;
}
- AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo,
+ AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo,
AliasSet::AccessType E,
bool &NewSet) {
NewSet = false;
- AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet);
+ AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet);
AS.AccessTy |= E;
return AS;
}
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
- const MDNode *TBAAInfo);
+ const AAMDNodes &AAInfo);
AliasSet *findAliasSetForUnknownInst(Instruction *Inst);
};
diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h
new file mode 100644
index 000000000000..b129e6796328
--- /dev/null
+++ b/include/llvm/Analysis/AssumptionCache.h
@@ -0,0 +1,142 @@
+//===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that keeps track of @llvm.assume intrinsics in
+// the functions of a module (allowing assumptions within any function to be
+// found cheaply by other parts of the optimizer).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H
+#define LLVM_ANALYSIS_ASSUMPTIONCACHE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Pass.h"
+#include <memory>
+
+namespace llvm {
+
+/// \brief A cache of @llvm.assume calls within a function.
+///
+/// This cache provides fast lookup of assumptions within a function by caching
+/// them and amortizing the cost of scanning for them across all queries. The
+/// cache is also conservatively self-updating so that it will never return
+/// incorrect results about a function even as the function is being mutated.
+/// However, flushing the cache and rebuilding it (or explicitly updating it)
+/// may allow it to discover new assumptions.
+class AssumptionCache {
+ /// \brief The function for which this cache is handling assumptions.
+ ///
+ /// We track this to lazily populate our assumptions.
+ Function &F;
+
+ /// \brief Vector of weak value handles to calls of the @llvm.assume
+ /// intrinsic.
+ SmallVector<WeakVH, 4> AssumeHandles;
+
+ /// \brief Flag tracking whether we have scanned the function yet.
+ ///
+ /// We want to be as lazy about this as possible, and so we scan the function
+ /// at the last moment.
+ bool Scanned;
+
+ /// \brief Scan the function for assumptions and add them to the cache.
+ void scanFunction();
+
+public:
+ /// \brief Construct an AssumptionCache from a function by scanning all of
+ /// its instructions.
+ AssumptionCache(Function &F) : F(F), Scanned(false) {}
+
+ /// \brief Add an @llvm.assume intrinsic to this function's cache.
+ ///
+ /// The call passed in must be an instruction within this fuction and must
+ /// not already be in the cache.
+ void registerAssumption(CallInst *CI);
+
+ /// \brief Clear the cache of @llvm.assume intrinsics for a function.
+ ///
+ /// It will be re-scanned the next time it is requested.
+ void clear() {
+ AssumeHandles.clear();
+ Scanned = false;
+ }
+
+ /// \brief Access the list of assumption handles currently tracked for this
+ /// fuction.
+ ///
+ /// Note that these produce weak handles that may be null. The caller must
+ /// handle that case.
+ /// FIXME: We should replace this with pointee_iterator<filter_iterator<...>>
+ /// when we can write that to filter out the null values. Then caller code
+ /// will become simpler.
+ MutableArrayRef<WeakVH> assumptions() {
+ if (!Scanned)
+ scanFunction();
+ return AssumeHandles;
+ }
+};
+
+/// \brief An immutable pass that tracks lazily created \c AssumptionCache
+/// objects.
+///
+/// This is essentially a workaround for the legacy pass manager's weaknesses
+/// which associates each assumption cache with Function and clears it if the
+/// function is deleted. The nature of the AssumptionCache is that it is not
+/// invalidated by any changes to the function body and so this is sufficient
+/// to be conservatively correct.
+class AssumptionCacheTracker : public ImmutablePass {
+ /// A callback value handle applied to function objects, which we use to
+ /// delete our cache of intrinsics for a function when it is deleted.
+ class FunctionCallbackVH : public CallbackVH {
+ AssumptionCacheTracker *ACT;
+ void deleted() override;
+
+ public:
+ typedef DenseMapInfo<Value *> DMI;
+
+ FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr)
+ : CallbackVH(V), ACT(ACT) {}
+ };
+
+ friend FunctionCallbackVH;
+
+ typedef DenseMap<FunctionCallbackVH, std::unique_ptr<AssumptionCache>,
+ FunctionCallbackVH::DMI> FunctionCallsMap;
+ FunctionCallsMap AssumptionCaches;
+
+public:
+ /// \brief Get the cached assumptions for a function.
+ ///
+ /// If no assumptions are cached, this will scan the function. Otherwise, the
+ /// existing cache will be returned.
+ AssumptionCache &getAssumptionCache(Function &F);
+
+ AssumptionCacheTracker();
+ ~AssumptionCacheTracker();
+
+ void releaseMemory() override { AssumptionCaches.shrink_and_clear(); }
+
+ void verifyAnalysis() const override;
+ bool doFinalization(Module &) override {
+ verifyAnalysis();
+ return false;
+ }
+
+ static char ID; // Pass identification, replacement for typeid
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h
index bb256c7bbcc8..57b515420925 100644
--- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h
+++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -260,7 +260,7 @@ public:
/// loop.
///
/// This function should only be called when distributing mass. As long as
- /// there are no irreducilbe edges to Node, then it will have complexity
+ /// there are no irreducible edges to Node, then it will have complexity
/// O(1) in this context.
///
/// In general, the complexity is O(L), where L is the number of loop
diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h
index 4414c84f6b7a..89eef68d8431 100644
--- a/include/llvm/Analysis/BranchProbabilityInfo.h
+++ b/include/llvm/Analysis/BranchProbabilityInfo.h
@@ -111,6 +111,10 @@ public:
void setEdgeWeight(const BasicBlock *Src, unsigned IndexInSuccessors,
uint32_t Weight);
+ static uint32_t getBranchWeightStackProtector(bool IsLikely) {
+ return IsLikely ? (1u << 20) - 1 : 1;
+ }
+
private:
// Since we allow duplicate edges from one basic block to another, we use
// a pair (PredBlock and an index in the successors) to specify an edge.
diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h
index e6d2ed1a6864..035764837e6f 100644
--- a/include/llvm/Analysis/CFGPrinter.h
+++ b/include/llvm/Analysis/CFGPrinter.h
@@ -72,13 +72,13 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
--i;
} else if (ColNum == MaxColumns) { // Wrap lines.
- if (LastSpace) {
- OutStr.insert(LastSpace, "\\l...");
- ColNum = i - LastSpace;
- LastSpace = 0;
- i += 3; // The loop will advance 'i' again.
- }
- // Else keep trying to find a space.
+ // Wrap very long names even though we can't find a space.
+ if (!LastSpace)
+ LastSpace = i;
+ OutStr.insert(LastSpace, "\\l...");
+ ColNum = i - LastSpace;
+ LastSpace = 0;
+ i += 3; // The loop will advance 'i' again.
}
else
++ColNum;
diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h
index 09101ae6d0d1..0d4fe932481b 100644
--- a/include/llvm/Analysis/CGSCCPassManager.h
+++ b/include/llvm/Analysis/CGSCCPassManager.h
@@ -18,138 +18,28 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H
-#define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H
+#ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H
+#define LLVM_ANALYSIS_CGSCCPASSMANAGER_H
-#include "llvm/IR/PassManager.h"
#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/IR/PassManager.h"
namespace llvm {
-class CGSCCAnalysisManager;
-
-class CGSCCPassManager {
-public:
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- CGSCCPassManager() {}
- CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
- CGSCCPassManager &operator=(CGSCCPassManager &&RHS) {
- Passes = std::move(RHS.Passes);
- return *this;
- }
-
- /// \brief Run all of the CGSCC passes in this pass manager over a SCC.
- PreservedAnalyses run(LazyCallGraph::SCC *C,
- CGSCCAnalysisManager *AM = nullptr);
-
- template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) {
- Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass)));
- }
-
- static StringRef name() { return "CGSCCPassManager"; }
-
-private:
- // Pull in the concept type and model template specialized for SCCs.
- typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager>
- CGSCCPassConcept;
- template <typename PassT>
- struct CGSCCPassModel
- : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> {
- CGSCCPassModel(PassT Pass)
- : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>(
- std::move(Pass)) {}
- };
-
- CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
- CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
-
- std::vector<std::unique_ptr<CGSCCPassConcept>> Passes;
-};
-
-/// \brief A function analysis manager to coordinate and cache analyses run over
-/// a module.
-class CGSCCAnalysisManager : public detail::AnalysisManagerBase<
- CGSCCAnalysisManager, LazyCallGraph::SCC *> {
- friend class detail::AnalysisManagerBase<CGSCCAnalysisManager,
- LazyCallGraph::SCC *>;
- typedef detail::AnalysisManagerBase<CGSCCAnalysisManager,
- LazyCallGraph::SCC *> BaseT;
- typedef BaseT::ResultConceptT ResultConceptT;
- typedef BaseT::PassConceptT PassConceptT;
-
-public:
- // Most public APIs are inherited from the CRTP base class.
-
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- CGSCCAnalysisManager() {}
- CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg)
- : BaseT(std::move(static_cast<BaseT &>(Arg))),
- CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {}
- CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) {
- BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
- CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults);
- return *this;
- }
-
- /// \brief Returns true if the analysis manager has an empty results cache.
- bool empty() const;
-
- /// \brief Clear the function analysis result cache.
- ///
- /// This routine allows cleaning up when the set of functions itself has
- /// potentially changed, and thus we can't even look up a a result and
- /// invalidate it directly. Notably, this does *not* call invalidate
- /// functions as there is nothing to be done for them.
- void clear();
-
-private:
- CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION;
- CGSCCAnalysisManager &
- operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION;
-
- /// \brief Get a function pass result, running the pass if necessary.
- ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C);
-
- /// \brief Get a cached function pass result or return null.
- ResultConceptT *getCachedResultImpl(void *PassID,
- LazyCallGraph::SCC *C) const;
-
- /// \brief Invalidate a function pass result.
- void invalidateImpl(void *PassID, LazyCallGraph::SCC *C);
-
- /// \brief Invalidate the results for a function..
- void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA);
+/// \brief The CGSCC pass manager.
+///
+/// See the documentation for the PassManager template for details. It runs
+/// a sequency of SCC passes over each SCC that the manager is run over. This
+/// typedef serves as a convenient way to refer to this construct.
+typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager;
- /// \brief List of function analysis pass IDs and associated concept pointers.
- ///
- /// Requires iterators to be valid across appending new entries and arbitrary
- /// erases. Provides both the pass ID and concept pointer such that it is
- /// half of a bijection and provides storage for the actual result concept.
- typedef std::list<
- std::pair<void *, std::unique_ptr<detail::AnalysisResultConcept<
- LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT;
-
- /// \brief Map type from function pointer to our custom list type.
- typedef DenseMap<LazyCallGraph::SCC *, CGSCCAnalysisResultListT>
- CGSCCAnalysisResultListMapT;
-
- /// \brief Map from function to a list of function analysis results.
- ///
- /// Provides linear time removal of all analysis results for a function and
- /// the ultimate storage for a particular cached analysis result.
- CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists;
-
- /// \brief Map type from a pair of analysis ID and function pointer to an
- /// iterator into a particular result list.
- typedef DenseMap<std::pair<void *, LazyCallGraph::SCC *>,
- CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT;
-
- /// \brief Map from an analysis ID and function to a particular cached
- /// analysis result.
- CGSCCAnalysisResultMapT CGSCCAnalysisResults;
-};
+/// \brief The CGSCC analysis manager.
+///
+/// See the documentation for the AnalysisManager template for detail
+/// documentation. This typedef serves as a convenient way to refer to this
+/// construct in the adaptors and proxies used to integrate this into the larger
+/// pass manager infrastructure.
+typedef AnalysisManager<LazyCallGraph::SCC> CGSCCAnalysisManager;
/// \brief A module analysis which acts as a proxy for a CGSCC analysis
/// manager.
@@ -187,7 +77,7 @@ public:
/// Regardless of whether this analysis is marked as preserved, all of the
/// analyses in the \c CGSCCAnalysisManager are potentially invalidated
/// based on the set of preserved analyses.
- bool invalidate(Module *M, const PreservedAnalyses &PA);
+ bool invalidate(Module &M, const PreservedAnalyses &PA);
private:
CGSCCAnalysisManager *CGAM;
@@ -195,12 +85,13 @@ public:
static void *ID() { return (void *)&PassID; }
+ static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; }
+
explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM)
: CGAM(&CGAM) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- CGSCCAnalysisManagerModuleProxy(
- const CGSCCAnalysisManagerModuleProxy &Arg)
+ CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg)
: CGAM(Arg.CGAM) {}
CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg)
: CGAM(std::move(Arg.CGAM)) {}
@@ -219,7 +110,7 @@ public:
/// In debug builds, it will also assert that the analysis manager is empty
/// as no queries should arrive at the CGSCC analysis manager prior to
/// this analysis being requested.
- Result run(Module *M);
+ Result run(Module &M);
private:
static char PassID;
@@ -257,7 +148,7 @@ public:
const ModuleAnalysisManager &getManager() const { return *MAM; }
/// \brief Handle invalidation by ignoring it, this pass is immutable.
- bool invalidate(LazyCallGraph::SCC *) { return false; }
+ bool invalidate(LazyCallGraph::SCC &) { return false; }
private:
const ModuleAnalysisManager *MAM;
@@ -265,12 +156,13 @@ public:
static void *ID() { return (void *)&PassID; }
+ static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; }
+
ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM)
: MAM(&MAM) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- ModuleAnalysisManagerCGSCCProxy(
- const ModuleAnalysisManagerCGSCCProxy &Arg)
+ ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg)
: MAM(Arg.MAM) {}
ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg)
: MAM(std::move(Arg.MAM)) {}
@@ -283,7 +175,7 @@ public:
/// \brief Run the analysis pass and create our proxy result object.
/// Nothing to see here, it just forwards the \c MAM reference into the
/// result.
- Result run(LazyCallGraph::SCC *) { return Result(*MAM); }
+ Result run(LazyCallGraph::SCC &) { return Result(*MAM); }
private:
static char PassID;
@@ -323,7 +215,7 @@ public:
}
/// \brief Runs the CGSCC pass across every SCC in the module.
- PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
assert(AM && "We need analyses to compute the call graph!");
// Setup the CGSCC analysis manager from its proxy.
@@ -335,15 +227,17 @@ public:
PreservedAnalyses PA = PreservedAnalyses::all();
for (LazyCallGraph::SCC &C : CG.postorder_sccs()) {
- PreservedAnalyses PassPA = Pass.run(&C, &CGAM);
+ PreservedAnalyses PassPA = Pass.run(C, &CGAM);
// We know that the CGSCC pass couldn't have invalidated any other
// SCC's analyses (that's the contract of a CGSCC pass), so
- // directly handle the CGSCC analysis manager's invalidation here.
+ // directly handle the CGSCC analysis manager's invalidation here. We
+ // also update the preserved set of analyses to reflect that invalidated
+ // analyses are now safe to preserve.
// FIXME: This isn't quite correct. We need to handle the case where the
// pass updated the CG, particularly some child of the current SCC, and
// invalidate its analyses.
- CGAM.invalidate(&C, PassPA);
+ PassPA = CGAM.invalidate(C, std::move(PassPA));
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@@ -409,7 +303,7 @@ public:
/// Regardless of whether this analysis is marked as preserved, all of the
/// analyses in the \c FunctionAnalysisManager are potentially invalidated
/// based on the set of preserved analyses.
- bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA);
+ bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA);
private:
FunctionAnalysisManager *FAM;
@@ -417,6 +311,8 @@ public:
static void *ID() { return (void *)&PassID; }
+ static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; }
+
explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM)
: FAM(&FAM) {}
// We have to explicitly define all the special member functions because MSVC
@@ -441,7 +337,7 @@ public:
/// In debug builds, it will also assert that the analysis manager is empty
/// as no queries should arrive at the function analysis manager prior to
/// this analysis being requested.
- Result run(LazyCallGraph::SCC *C);
+ Result run(LazyCallGraph::SCC &C);
private:
static char PassID;
@@ -479,7 +375,7 @@ public:
const CGSCCAnalysisManager &getManager() const { return *CGAM; }
/// \brief Handle invalidation by ignoring it, this pass is immutable.
- bool invalidate(Function *) { return false; }
+ bool invalidate(Function &) { return false; }
private:
const CGSCCAnalysisManager *CGAM;
@@ -487,6 +383,8 @@ public:
static void *ID() { return (void *)&PassID; }
+ static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; }
+
CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM)
: CGAM(&CGAM) {}
// We have to explicitly define all the special member functions because MSVC
@@ -505,7 +403,7 @@ public:
/// \brief Run the analysis pass and create our proxy result object.
/// Nothing to see here, it just forwards the \c CGAM reference into the
/// result.
- Result run(Function *) { return Result(*CGAM); }
+ Result run(Function &) { return Result(*CGAM); }
private:
static char PassID;
@@ -531,7 +429,8 @@ public:
: Pass(Arg.Pass) {}
CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
- friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) {
+ friend void swap(CGSCCToFunctionPassAdaptor &LHS,
+ CGSCCToFunctionPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
}
@@ -541,21 +440,23 @@ public:
}
/// \brief Runs the function pass across every function in the module.
- PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) {
+ PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) {
FunctionAnalysisManager *FAM = nullptr;
if (AM)
// Setup the function analysis manager from its proxy.
FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
PreservedAnalyses PA = PreservedAnalyses::all();
- for (LazyCallGraph::Node *N : *C) {
- PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM);
+ for (LazyCallGraph::Node *N : C) {
+ PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM);
// We know that the function pass couldn't have invalidated any other
// function's analyses (that's the contract of a function pass), so
// directly handle the function analysis manager's invalidation here.
+ // Also, update the preserved analyses to reflect that once invalidated
+ // these can again be preserved.
if (FAM)
- FAM->invalidate(&N->getFunction(), PassPA);
+ PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA));
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@@ -585,7 +486,6 @@ CGSCCToFunctionPassAdaptor<FunctionPassT>
createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
}
-
}
#endif
diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h
index 9a6a4a76eb73..76d9073799f8 100644
--- a/include/llvm/Analysis/CallGraph.h
+++ b/include/llvm/Analysis/CallGraph.h
@@ -58,7 +58,6 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
-#include "llvm/Support/IncludeFile.h"
#include <map>
namespace llvm {
@@ -418,13 +417,24 @@ template <> struct GraphTraits<CallGraphNode *> {
template <> struct GraphTraits<const CallGraphNode *> {
typedef const CallGraphNode NodeType;
- typedef NodeType::const_iterator ChildIteratorType;
+
+ typedef CallGraphNode::CallRecord CGNPairTy;
+ typedef std::pointer_to_unary_function<CGNPairTy, const CallGraphNode *>
+ CGNDerefFun;
static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; }
+
+ typedef mapped_iterator<NodeType::const_iterator, CGNDerefFun>
+ ChildIteratorType;
+
static inline ChildIteratorType child_begin(NodeType *N) {
- return N->begin();
+ return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
}
- static inline ChildIteratorType child_end(NodeType *N) { return N->end(); }
+ static inline ChildIteratorType child_end(NodeType *N) {
+ return map_iterator(N->end(), CGNDerefFun(CGNDeref));
+ }
+
+ static const CallGraphNode *CGNDeref(CGNPairTy P) { return P.second; }
};
template <>
@@ -451,17 +461,24 @@ template <>
struct GraphTraits<const CallGraph *> : public GraphTraits<
const CallGraphNode *> {
static NodeType *getEntryNode(const CallGraph *CGN) {
- return CGN->getExternalCallingNode();
+ return CGN->getExternalCallingNode(); // Start at the external node!
}
+ typedef std::pair<const Function *, const CallGraphNode *> PairTy;
+ typedef std::pointer_to_unary_function<PairTy, const CallGraphNode &>
+ DerefFun;
+
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
- typedef CallGraph::const_iterator nodes_iterator;
- static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); }
- static nodes_iterator nodes_end(const CallGraph *CG) { return CG->end(); }
+ typedef mapped_iterator<CallGraph::const_iterator, DerefFun> nodes_iterator;
+ static nodes_iterator nodes_begin(const CallGraph *CG) {
+ return map_iterator(CG->begin(), DerefFun(CGdereference));
+ }
+ static nodes_iterator nodes_end(const CallGraph *CG) {
+ return map_iterator(CG->end(), DerefFun(CGdereference));
+ }
+
+ static const CallGraphNode &CGdereference(PairTy P) { return *P.second; }
};
} // End llvm namespace
-// Make sure that any clients of this file link in CallGraph.cpp
-FORCE_DEFINING_FILE_TO_BE_LINKED(CallGraph)
-
#endif
diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h
index 04b39c176946..2f5969129e02 100644
--- a/include/llvm/Analysis/CodeMetrics.h
+++ b/include/llvm/Analysis/CodeMetrics.h
@@ -16,10 +16,13 @@
#define LLVM_ANALYSIS_CODEMETRICS_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/CallSite.h"
namespace llvm {
+class AssumptionCache;
class BasicBlock;
+class Loop;
class Function;
class Instruction;
class DataLayout;
@@ -85,7 +88,18 @@ struct CodeMetrics {
NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {}
/// \brief Add information about a block to the current state.
- void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI);
+ void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI,
+ SmallPtrSetImpl<const Value*> &EphValues);
+
+ /// \brief Collect a loop's ephemeral values (those used only by an assume
+ /// or similar intrinsics in the loop).
+ static void collectEphemeralValues(const Loop *L, AssumptionCache *AC,
+ SmallPtrSetImpl<const Value *> &EphValues);
+
+ /// \brief Collect a functions's ephemeral values (those used only by an
+ /// assume or similar intrinsics in the function).
+ static void collectEphemeralValues(const Function *L, AssumptionCache *AC,
+ SmallPtrSetImpl<const Value *> &EphValues);
};
}
diff --git a/include/llvm/Analysis/DOTGraphTraitsPass.h b/include/llvm/Analysis/DOTGraphTraitsPass.h
index 53c832cbebee..cb74e9f32d3d 100644
--- a/include/llvm/Analysis/DOTGraphTraitsPass.h
+++ b/include/llvm/Analysis/DOTGraphTraitsPass.h
@@ -66,15 +66,15 @@ public:
bool runOnFunction(Function &F) override {
GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
std::string Filename = Name + "." + F.getName().str() + ".dot";
- std::string ErrorInfo;
+ std::error_code EC;
errs() << "Writing '" << Filename << "'...";
- raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
+ raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
std::string Title = GraphName + " for '" + F.getName().str() + "' function";
- if (ErrorInfo.empty())
+ if (!EC)
WriteGraph(File, Graph, IsSimple, Title);
else
errs() << " error opening file for writing!";
@@ -129,14 +129,14 @@ public:
bool runOnModule(Module &M) override {
GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
std::string Filename = Name + ".dot";
- std::string ErrorInfo;
+ std::error_code EC;
errs() << "Writing '" << Filename << "'...";
- raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
+ raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
- if (ErrorInfo.empty())
+ if (!EC)
WriteGraph(File, Graph, IsSimple, Title);
else
errs() << " error opening file for writing!";
diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h
index 279755e47622..1041e3f0a4a9 100644
--- a/include/llvm/Analysis/DependenceAnalysis.h
+++ b/include/llvm/Analysis/DependenceAnalysis.h
@@ -287,9 +287,9 @@ namespace llvm {
/// The flag PossiblyLoopIndependent should be set by the caller
/// if it appears that control flow can reach from Src to Dst
/// without traversing a loop back edge.
- Dependence *depends(Instruction *Src,
- Instruction *Dst,
- bool PossiblyLoopIndependent);
+ std::unique_ptr<Dependence> depends(Instruction *Src,
+ Instruction *Dst,
+ bool PossiblyLoopIndependent);
/// getSplitIteration - Give a dependence that's splittable at some
/// particular level, return the iteration that should be used to split
@@ -331,7 +331,7 @@ namespace llvm {
///
/// breaks the dependence and allows us to vectorize/parallelize
/// both loops.
- const SCEV *getSplitIteration(const Dependence *Dep, unsigned Level);
+ const SCEV *getSplitIteration(const Dependence &Dep, unsigned Level);
private:
AliasAnalysis *AA;
@@ -523,6 +523,12 @@ namespace llvm {
/// in LoopNest.
bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const;
+ /// Makes sure both subscripts (i.e. Pair->Src and Pair->Dst) share the same
+ /// integer type by sign-extending one of them when necessary.
+ /// Sign-extending a subscript is safe because getelementptr assumes the
+ /// array subscripts are signed.
+ void unifySubscriptType(Subscript *Pair);
+
/// removeMatchingExtensions - Examines a subscript pair.
/// If the source and destination are identically sign (or zero)
/// extended, it strips off the extension in an effort to
@@ -911,7 +917,7 @@ namespace llvm {
bool tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV,
SmallVectorImpl<Subscript> &Pair,
- const SCEV *ElementSize) const;
+ const SCEV *ElementSize);
public:
static char ID; // Class identification, replacement for typeinfo
diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h
index f42b9cbbfedd..996700efdb60 100644
--- a/include/llvm/Analysis/DominanceFrontier.h
+++ b/include/llvm/Analysis/DominanceFrontier.h
@@ -102,7 +102,9 @@ public:
void print(raw_ostream &OS) const;
/// dump - Dump the dominance frontier to dbgs().
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dump() const;
+#endif
};
//===-------------------------------------
diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h
index 04df2cc35d46..735bfb83671d 100644
--- a/include/llvm/Analysis/DominanceFrontierImpl.h
+++ b/include/llvm/Analysis/DominanceFrontierImpl.h
@@ -15,8 +15,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H
-#define LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H
+#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H
+#define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
@@ -172,9 +172,7 @@ ForwardDominanceFrontierBase<BlockT>::calculate(const DomTreeT &DT,
DomSetType &S = this->Frontiers[currentBB];
// Visit each block only once.
- if (visited.count(currentBB) == 0) {
- visited.insert(currentBB);
-
+ if (visited.insert(currentBB).second) {
// Loop over CFG successors to calculate DFlocal[currentNode]
for (auto SI = BlockTraits::child_begin(currentBB),
SE = BlockTraits::child_end(currentBB);
diff --git a/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h
deleted file mode 100644
index 574c947f4ebb..000000000000
--- a/include/llvm/Analysis/FindUsedTypes.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass is used to seek out all of the types in use by the program.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H
-#define LLVM_ANALYSIS_FINDUSEDTYPES_H
-
-#include "llvm/ADT/SetVector.h"
-#include "llvm/Pass.h"
-
-namespace llvm {
-
-class Type;
-class Value;
-
-class FindUsedTypes : public ModulePass {
- SetVector<Type *> UsedTypes;
-public:
- static char ID; // Pass identification, replacement for typeid
- FindUsedTypes() : ModulePass(ID) {
- initializeFindUsedTypesPass(*PassRegistry::getPassRegistry());
- }
-
- /// getTypes - After the pass has been run, return the set containing all of
- /// the types used in the module.
- ///
- const SetVector<Type *> &getTypes() const { return UsedTypes; }
-
- /// Print the types found in the module. If the optional Module parameter is
- /// passed in, then the types are printed symbolically if possible, using the
- /// symbol table from the module.
- ///
- void print(raw_ostream &o, const Module *M) const override;
-
-private:
- /// IncorporateType - Incorporate one type and all of its subtypes into the
- /// collection of used types.
- ///
- void IncorporateType(Type *Ty);
-
- /// IncorporateValue - Incorporate all of the types used by this value.
- ///
- void IncorporateValue(const Value *V);
-
-public:
- /// run - This incorporates all types used by the specified module
- bool runOnModule(Module &M) override;
-
- /// getAnalysisUsage - We do not modify anything.
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/Analysis/FunctionTargetTransformInfo.h b/include/llvm/Analysis/FunctionTargetTransformInfo.h
new file mode 100644
index 000000000000..fce5a1a92bd9
--- /dev/null
+++ b/include/llvm/Analysis/FunctionTargetTransformInfo.h
@@ -0,0 +1,49 @@
+//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass wraps a TargetTransformInfo in a FunctionPass so that it can
+// forward along the current Function so that we can make target specific
+// decisions based on the particular subtarget specified for each Function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H
+#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H
+
+#include "TargetTransformInfo.h"
+#include "llvm/Pass.h"
+
+namespace llvm {
+class FunctionTargetTransformInfo final : public FunctionPass {
+private:
+ const Function *Fn;
+ const TargetTransformInfo *TTI;
+
+ FunctionTargetTransformInfo(const FunctionTargetTransformInfo &)
+ LLVM_DELETED_FUNCTION;
+ void operator=(const FunctionTargetTransformInfo &) LLVM_DELETED_FUNCTION;
+
+public:
+ static char ID;
+ FunctionTargetTransformInfo();
+
+ // Implementation boilerplate.
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+ void releaseMemory() override;
+ bool runOnFunction(Function &F) override;
+
+ // Shimmed functions from TargetTransformInfo.
+ void
+ getUnrollingPreferences(Loop *L,
+ TargetTransformInfo::UnrollingPreferences &UP) const {
+ TTI->getUnrollingPreferences(Fn, L, UP);
+ }
+};
+}
+#endif
diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h
index 6038872207c3..d1f037021773 100644
--- a/include/llvm/Analysis/IVUsers.h
+++ b/include/llvm/Analysis/IVUsers.h
@@ -174,7 +174,7 @@ public:
/// dump - This method is used for debugging.
void dump() const;
protected:
- bool AddUsersImpl(Instruction *I, SmallPtrSet<Loop*,16> &SimpleLoopNests);
+ bool AddUsersImpl(Instruction *I, SmallPtrSetImpl<Loop*> &SimpleLoopNests);
};
Pass *createIVUsersPass();
diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h
index aaed716b6a11..a064cfc897b0 100644
--- a/include/llvm/Analysis/InlineCost.h
+++ b/include/llvm/Analysis/InlineCost.h
@@ -19,6 +19,7 @@
#include <climits>
namespace llvm {
+class AssumptionCacheTracker;
class CallSite;
class DataLayout;
class Function;
@@ -100,6 +101,7 @@ public:
/// \brief Cost analyzer used by inliner.
class InlineCostAnalysis : public CallGraphSCCPass {
const TargetTransformInfo *TTI;
+ AssumptionCacheTracker *ACT;
public:
static char ID;
diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h
index 2367c0bf77aa..b88e0899f19a 100644
--- a/include/llvm/Analysis/InstructionSimplify.h
+++ b/include/llvm/Analysis/InstructionSimplify.h
@@ -37,6 +37,7 @@
namespace llvm {
template<typename T>
class ArrayRef;
+ class AssumptionCache;
class DominatorTree;
class Instruction;
class DataLayout;
@@ -50,150 +51,193 @@ namespace llvm {
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifySubInst - Given operands for a Sub, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// Given operands for an FAdd, see if we can fold the result. If not, this
/// returns null.
Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
- const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DataLayout *TD = nullptr,
+ const TargetLibraryInfo *TLI = nullptr,
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// Given operands for an FSub, see if we can fold the result. If not, this
/// returns null.
Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
- const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DataLayout *TD = nullptr,
+ const TargetLibraryInfo *TLI = nullptr,
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// Given operands for an FMul, see if we can fold the result. If not, this
/// returns null.
- Value *SimplifyFMulInst(Value *LHS, Value *RHS,
- FastMathFlags FMF,
+ Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyMulInst - Given operands for a Mul, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifySDivInst - Given operands for an SDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyUDivInst - Given operands for a UDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyUDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyFDivInst - Given operands for an FDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifySRemInst - Given operands for an SRem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySRemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyURemInst - Given operands for a URem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyURemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyFRemInst - Given operands for an FRem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFRemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyShlInst - Given operands for a Shl, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyLShrInst - Given operands for a LShr, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyAShrInst - Given operands for a AShr, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyAndInst - Given operands for an And, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyOrInst - Given operands for an Or, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyXorInst - Given operands for a Xor, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ Instruction *CxtI = nullptr);
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
/// can fold the result. If not, this returns null.
@@ -201,13 +245,17 @@ namespace llvm {
ArrayRef<unsigned> Idxs,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
//=== Helper functions for higher up the class hierarchy.
@@ -217,14 +265,18 @@ namespace llvm {
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// \brief Given a function and iterators over arguments, see if we can fold
/// the result.
@@ -233,7 +285,9 @@ namespace llvm {
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
User::op_iterator ArgEnd, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// \brief Given a function and set of arguments, see if we can fold the
/// result.
@@ -242,14 +296,16 @@ namespace llvm {
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// SimplifyInstruction - See if we can compute a simplified version of this
/// instruction. If not, this returns null.
Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
-
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr);
/// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses
/// recursively.
@@ -262,7 +318,8 @@ namespace llvm {
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr);
/// \brief Recursively attempt to simplify an instruction.
///
@@ -273,7 +330,8 @@ namespace llvm {
bool recursivelySimplifyInstruction(Instruction *I,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr);
} // end namespace llvm
#endif
diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h
index 73aff76efe83..3b51d44099fa 100644
--- a/include/llvm/Analysis/IntervalIterator.h
+++ b/include/llvm/Analysis/IntervalIterator.h
@@ -165,10 +165,10 @@ private:
//
bool ProcessInterval(NodeTy *Node) {
BasicBlock *Header = getNodeHeader(Node);
- if (Visited.count(Header)) return false;
+ if (!Visited.insert(Header).second)
+ return false;
Interval *Int = new Interval(Header);
- Visited.insert(Header); // The header has now been visited!
// Check all of our successors to see if they are in the interval...
for (typename GT::ChildIteratorType I = GT::child_begin(Node),
diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h
index 54760aa02466..591e794a3901 100644
--- a/include/llvm/Analysis/JumpInstrTableInfo.h
+++ b/include/llvm/Analysis/JumpInstrTableInfo.h
@@ -16,7 +16,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Pass.h"
-
#include <vector>
namespace llvm {
@@ -37,7 +36,9 @@ class JumpInstrTableInfo : public ImmutablePass {
public:
static char ID;
- JumpInstrTableInfo();
+ /// The default byte alignment for jump tables is 16, which is large but
+ /// usually safe.
+ JumpInstrTableInfo(uint64_t ByteAlign = 16);
virtual ~JumpInstrTableInfo();
const char *getPassName() const override {
return "Jump-Instruction Table Info";
@@ -52,9 +53,19 @@ public:
/// Gets the tables.
const JumpTables &getTables() const { return Tables; }
+ /// Gets the alignment in bytes of a jumptable entry.
+ uint64_t entryByteAlignment() const { return ByteAlignment; }
private:
JumpTables Tables;
+
+ /// A power-of-two alignment of a jumptable entry.
+ uint64_t ByteAlignment;
};
+
+/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This
+/// bound specifies the maximum number of bytes needed to represent an
+/// unconditional jump or a trap instruction in the back end currently in use.
+ModulePass *createJumpInstrTableInfoPass(unsigned Bound);
}
#endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */
diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h
index 70a4df51c1ed..b0b9068de34b 100644
--- a/include/llvm/Analysis/LazyCallGraph.h
+++ b/include/llvm/Analysis/LazyCallGraph.h
@@ -32,8 +32,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_ANALYSIS_LAZY_CALL_GRAPH
-#define LLVM_ANALYSIS_LAZY_CALL_GRAPH
+#ifndef LLVM_ANALYSIS_LAZYCALLGRAPH_H
+#define LLVM_ANALYSIS_LAZYCALLGRAPH_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
@@ -46,11 +46,11 @@
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Support/Allocator.h"
#include <iterator>
namespace llvm {
-class ModuleAnalysisManager;
class PreservedAnalyses;
class raw_ostream;
@@ -252,6 +252,12 @@ public:
/// \brief Test if this SCC is a descendant of \a C.
bool isDescendantOf(const SCC &C) const;
+ /// \brief Short name useful for debugging or logging.
+ ///
+ /// We use the name of the first function in the SCC to name the SCC for
+ /// the purposes of debugging and logging.
+ StringRef getName() const { return (*begin())->getFunction().getName(); }
+
///@{
/// \name Mutation API
///
@@ -537,11 +543,13 @@ public:
static void *ID() { return (void *)&PassID; }
- /// \brief Compute the \c LazyCallGraph for a the module \c M.
+ static StringRef name() { return "Lazy CallGraph Analysis"; }
+
+ /// \brief Compute the \c LazyCallGraph for the module \c M.
///
/// This just builds the set of entry points to the call graph. The rest is
/// built lazily as it is walked.
- LazyCallGraph run(Module *M) { return LazyCallGraph(*M); }
+ LazyCallGraph run(Module &M) { return LazyCallGraph(M); }
private:
static char PassID;
@@ -556,7 +564,7 @@ class LazyCallGraphPrinterPass {
public:
explicit LazyCallGraphPrinterPass(raw_ostream &OS);
- PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM);
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM);
static StringRef name() { return "LazyCallGraphPrinterPass"; }
};
diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h
index 2fe7386e7302..9a67d52c3696 100644
--- a/include/llvm/Analysis/LazyValueInfo.h
+++ b/include/llvm/Analysis/LazyValueInfo.h
@@ -18,16 +18,20 @@
#include "llvm/Pass.h"
namespace llvm {
+ class AssumptionCache;
class Constant;
class DataLayout;
+ class DominatorTree;
+ class Instruction;
class TargetLibraryInfo;
class Value;
-/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint
-/// information.
+/// This pass computes, caches, and vends lazy value constraint information.
class LazyValueInfo : public FunctionPass {
+ AssumptionCache *AC;
const DataLayout *DL;
class TargetLibraryInfo *TLI;
+ DominatorTree *DT;
void *PImpl;
LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
@@ -38,7 +42,7 @@ public:
}
~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); }
- /// Tristate - This is used to return true/false/dunno results.
+ /// This is used to return true/false/dunno results.
enum Tristate {
Unknown = -1, False = 0, True = 1
};
@@ -46,26 +50,33 @@ public:
// Public query interface.
- /// getPredicateOnEdge - Determine whether the specified value comparison
- /// with a constant is known to be true or false on the specified CFG edge.
+ /// Determine whether the specified value comparison with a constant is known
+ /// to be true or false on the specified CFG edge.
/// Pred is a CmpInst predicate.
Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
- BasicBlock *FromBB, BasicBlock *ToBB);
+ BasicBlock *FromBB, BasicBlock *ToBB,
+ Instruction *CxtI = nullptr);
-
- /// getConstant - Determine whether the specified value is known to be a
+ /// Determine whether the specified value comparison with a constant is known
+ /// to be true or false at the specified instruction
+ /// (from an assume intrinsic). Pred is a CmpInst predicate.
+ Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C,
+ Instruction *CxtI);
+
+ /// Determine whether the specified value is known to be a
/// constant at the end of the specified block. Return null if not.
- Constant *getConstant(Value *V, BasicBlock *BB);
+ Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr);
- /// getConstantOnEdge - Determine whether the specified value is known to be a
+ /// Determine whether the specified value is known to be a
/// constant on the specified edge. Return null if not.
- Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB);
+ Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
+ Instruction *CxtI = nullptr);
- /// threadEdge - Inform the analysis cache that we have threaded an edge from
+ /// Inform the analysis cache that we have threaded an edge from
/// PredBB to OldSucc to be from PredBB to NewSucc instead.
void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);
- /// eraseBlock - Inform the analysis cache that we have erased a block.
+ /// Inform the analysis cache that we have erased a block.
void eraseBlock(BasicBlock *BB);
// Implementation boilerplate.
diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h
index 25c59288f34b..0fe34539f8f7 100644
--- a/include/llvm/Analysis/Loads.h
+++ b/include/llvm/Analysis/Loads.h
@@ -44,14 +44,14 @@ bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
/// If it is set to 0, it will scan the whole block. You can also optionally
/// specify an alias analysis implementation, which makes this more precise.
///
-/// If TBAATag is non-null and a load or store is found, the TBAA tag from the
-/// load or store is recorded there. If there is no TBAA tag or if no access
+/// If AATags is non-null and a load or store is found, the AA tags from the
+/// load or store are recorded there. If there are no AA tags or if no access
/// is found, it is left unmodified.
Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB,
BasicBlock::iterator &ScanFrom,
unsigned MaxInstsToScan = 6,
AliasAnalysis *AA = nullptr,
- MDNode **TBAATag = nullptr);
+ AAMDNodes *AATags = nullptr);
}
diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h
index 726e28636ac6..8650000fcfb6 100644
--- a/include/llvm/Analysis/LoopPass.h
+++ b/include/llvm/Analysis/LoopPass.h
@@ -82,6 +82,11 @@ public:
/// deleteAnalysisValue - Delete analysis info associated with value V.
virtual void deleteAnalysisValue(Value *V, Loop *L) {}
+ /// Delete analysis info associated with Loop L.
+ /// Called to notify a Pass that a loop has been deleted and any
+ /// associated analysis values can be deleted.
+ virtual void deleteAnalysisLoop(Loop *L) {}
+
protected:
/// skipOptnoneFunction - Containing function has Attribute::OptimizeNone
/// and most transformation passes should skip it.
@@ -152,6 +157,10 @@ public:
/// that implement simple analysis interface.
void deleteSimpleAnalysisValue(Value *V, Loop *L);
+ /// Invoke deleteAnalysisLoop hook for all passes that implement simple
+ /// analysis interface.
+ void deleteSimpleAnalysisLoop(Loop *L);
+
private:
std::deque<Loop *> LQ;
bool skipThisLoop;
diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h
index 1c4441bea670..67fd70a4561f 100644
--- a/include/llvm/Analysis/MemoryDependenceAnalysis.h
+++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h
@@ -28,6 +28,7 @@ namespace llvm {
class Instruction;
class CallSite;
class AliasAnalysis;
+ class AssumptionCache;
class DataLayout;
class MemoryDependenceAnalysis;
class PredIteratorCache;
@@ -281,12 +282,12 @@ namespace llvm {
/// Size - The maximum size of the dereferences of the
/// pointer. May be UnknownSize if the sizes are unknown.
uint64_t Size;
- /// TBAATag - The TBAA tag associated with dereferences of the
- /// pointer. May be null if there are no tags or conflicting tags.
- const MDNode *TBAATag;
+ /// AATags - The AA tags associated with dereferences of the
+ /// pointer. The members may be null if there are no tags or
+ /// conflicting tags.
+ AAMDNodes AATags;
- NonLocalPointerInfo()
- : Size(AliasAnalysis::UnknownSize), TBAATag(nullptr) {}
+ NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize) {}
};
/// CachedNonLocalPointerInfo - This map stores the cached results of doing
@@ -325,6 +326,7 @@ namespace llvm {
AliasAnalysis *AA;
const DataLayout *DL;
DominatorTree *DT;
+ AssumptionCache *AC;
std::unique_ptr<PredIteratorCache> PredCache;
public:
@@ -364,12 +366,16 @@ namespace llvm {
/// getNonLocalPointerDependency - Perform a full dependency query for an
- /// access to the specified (non-volatile) memory location, returning the
- /// set of instructions that either define or clobber the value.
+ /// access to the QueryInst's specified memory location, returning the set
+ /// of instructions that either define or clobber the value.
///
- /// This method assumes the pointer has a "NonLocal" dependency within BB.
- void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc,
- bool isLoad, BasicBlock *BB,
+ /// Warning: For a volatile query instruction, the dependencies will be
+ /// accurate, and thus usable for reordering, but it is never legal to
+ /// remove the query instruction.
+ ///
+ /// This method assumes the pointer has a "NonLocal" dependency within
+ /// QueryInst's parent basic block.
+ void getNonLocalPointerDependency(Instruction *QueryInst,
SmallVectorImpl<NonLocalDepResult> &Result);
/// removeInstruction - Remove an instruction from the dependence analysis,
diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h
index 69f59071f94f..38730d8ea4f3 100644
--- a/include/llvm/Analysis/PHITransAddr.h
+++ b/include/llvm/Analysis/PHITransAddr.h
@@ -18,6 +18,7 @@
#include "llvm/IR/Instruction.h"
namespace llvm {
+ class AssumptionCache;
class DominatorTree;
class DataLayout;
class TargetLibraryInfo;
@@ -41,12 +42,15 @@ class PHITransAddr {
/// TLI - The target library info if known, otherwise null.
const TargetLibraryInfo *TLI;
-
+
+ /// A cache of @llvm.assume calls used by SimplifyInstruction.
+ AssumptionCache *AC;
+
/// InstInputs - The inputs for our symbolic address.
SmallVector<Instruction*, 4> InstInputs;
public:
- PHITransAddr(Value *addr, const DataLayout *DL)
- : Addr(addr), DL(DL), TLI(nullptr) {
+ PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC)
+ : Addr(addr), DL(DL), TLI(nullptr), AC(AC) {
// If the address is an instruction, the whole thing is considered an input.
if (Instruction *I = dyn_cast<Instruction>(Addr))
InstInputs.push_back(I);
diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h
index fd65ae5ca5b2..10a56059ae10 100644
--- a/include/llvm/Analysis/Passes.h
+++ b/include/llvm/Analysis/Passes.h
@@ -66,6 +66,13 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
+ // createCFLAliasAnalysisPass - This pass implements a set-based approach to
+ // alias analysis.
+ //
+ ImmutablePass *createCFLAliasAnalysisPass();
+
+ //===--------------------------------------------------------------------===//
+ //
/// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows
/// about the semantics of a set of libcalls specified by LCI. The newly
/// constructed pass takes ownership of the pointer that is provided.
@@ -88,11 +95,20 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
+ // createScopedNoAliasAAPass - This pass implements metadata-based
+ // scoped noalias analysis.
+ //
+ ImmutablePass *createScopedNoAliasAAPass();
+
+ //===--------------------------------------------------------------------===//
+ //
// createObjCARCAliasAnalysisPass - This pass implements ObjC-ARC-based
// alias analysis.
//
ImmutablePass *createObjCARCAliasAnalysisPass();
+ FunctionPass *createPAEvalPass();
+
//===--------------------------------------------------------------------===//
//
/// createLazyValueInfoPass - This creates an instance of the LazyValueInfo
diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h
index d330755a0871..72cd35754c8a 100644
--- a/include/llvm/Analysis/PostDominators.h
+++ b/include/llvm/Analysis/PostDominators.h
@@ -19,7 +19,7 @@
namespace llvm {
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to
-/// compute the a post-dominator tree.
+/// compute the post-dominator tree.
///
struct PostDominatorTree : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h
index 49c88fd5caeb..6ff7f97d01f5 100644
--- a/include/llvm/Analysis/RegionInfo.h
+++ b/include/llvm/Analysis/RegionInfo.h
@@ -424,8 +424,10 @@ public:
void print(raw_ostream &OS, bool printTree = true, unsigned level = 0,
PrintStyle Style = PrintNone) const;
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// @brief Print the region to stderr.
void dump() const;
+#endif
/// @brief Check if the region contains a BasicBlock.
///
@@ -732,7 +734,9 @@ public:
static typename RegionT::PrintStyle printStyle;
void print(raw_ostream &OS) const;
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dump() const;
+#endif
void releaseMemory();
diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h
index 4266b84c32c4..b0dc26312aaa 100644
--- a/include/llvm/Analysis/RegionInfoImpl.h
+++ b/include/llvm/Analysis/RegionInfoImpl.h
@@ -12,11 +12,11 @@
#ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H
#define LLVM_ANALYSIS_REGIONINFOIMPL_H
-#include "llvm/Analysis/RegionInfo.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/Analysis/DominanceFrontier.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/PostDominators.h"
+#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -25,7 +25,7 @@
#include <iterator>
#include <set>
-using namespace llvm;
+namespace llvm {
#define DEBUG_TYPE "region"
@@ -916,4 +916,8 @@ void RegionInfoBase<Tr>::calculate(FuncT &F) {
buildRegionsTree(DT->getNode(BB), TopLevelRegion);
}
+#undef DEBUG_TYPE
+
+} // end namespace llvm
+
#endif
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index 617e54541ee1..f394e335257f 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -35,6 +35,7 @@
namespace llvm {
class APInt;
+ class AssumptionCache;
class Constant;
class ConstantInt;
class DominatorTree;
@@ -128,9 +129,11 @@ namespace llvm {
/// purposes.
void print(raw_ostream &OS) const;
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// dump - This method is used for debugging.
///
void dump() const;
+#endif
};
// Specialize FoldingSetTrait for SCEV to avoid needing to compute
@@ -221,6 +224,9 @@ namespace llvm {
///
Function *F;
+ /// The tracker for @llvm.assume intrinsics in this function.
+ AssumptionCache *AC;
+
/// LI - The loop information for the function we are currently analyzing.
///
LoopInfo *LI;
@@ -257,24 +263,13 @@ namespace llvm {
/// loop exit's branch condition evaluates to the not-taken path. This is a
/// temporary pair of exact and max expressions that are eventually
/// summarized in ExitNotTakenInfo and BackedgeTakenInfo.
- ///
- /// If MustExit is true, then the exit must be taken when the BECount
- /// reaches Exact (and before surpassing Max). If MustExit is false, then
- /// BECount may exceed Exact or Max if the loop exits via another branch. In
- /// either case, the loop may exit early via another branch.
- ///
- /// MustExit is true for most cases. However, an exit guarded by an
- /// (in)equality on a nonunit stride may be skipped.
struct ExitLimit {
const SCEV *Exact;
const SCEV *Max;
- bool MustExit;
- /*implicit*/ ExitLimit(const SCEV *E)
- : Exact(E), Max(E), MustExit(true) {}
+ /*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {}
- ExitLimit(const SCEV *E, const SCEV *M, bool MustExit)
- : Exact(E), Max(M), MustExit(MustExit) {}
+ ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {}
/// hasAnyInfo - Test whether this ExitLimit contains any computed
/// information, or whether it's all SCEVCouldNotCompute values.
@@ -749,6 +744,13 @@ namespace llvm {
bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
+ /// \brief Returns the maximum trip count of the loop if it is a single-exit
+ /// loop and we can compute a small maximum for that loop.
+ ///
+ /// Implemented in terms of the \c getSmallConstantTripCount overload with
+ /// the single exiting block passed to it. See that routine for details.
+ unsigned getSmallConstantTripCount(Loop *L);
+
/// getSmallConstantTripCount - Returns the maximum trip count of this loop
/// as a normal unsigned value. Returns 0 if the trip count is unknown or
/// not constant. This "trip count" assumes that control exits via
@@ -758,6 +760,14 @@ namespace llvm {
/// the loop exits prematurely via another branch.
unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock);
+ /// \brief Returns the largest constant divisor of the trip count of the
+ /// loop if it is a single-exit loop and we can compute a small maximum for
+ /// that loop.
+ ///
+ /// Implemented in terms of the \c getSmallConstantTripMultiple overload with
+ /// the single exiting block passed to it. See that routine for details.
+ unsigned getSmallConstantTripMultiple(Loop *L);
+
/// getSmallConstantTripMultiple - Returns the largest constant divisor of
/// the trip count of this loop as a normal unsigned value, if
/// possible. This means that the actual trip count is always a multiple of
diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h
index 2f1b1c3841f3..ff82db19b9e7 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -14,8 +14,8 @@
#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H
#define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Support/ErrorHandling.h"
@@ -577,7 +577,7 @@ namespace llvm {
SmallPtrSet<const SCEV *, 8> Visited;
void push(const SCEV *S) {
- if (Visited.insert(S) && Visitor.follow(S))
+ if (Visited.insert(S).second && Visitor.follow(S))
Worklist.push_back(S);
}
public:
@@ -624,7 +624,7 @@ namespace llvm {
}
};
- /// Use SCEVTraversal to visit all nodes in the givien expression tree.
+ /// Use SCEVTraversal to visit all nodes in the given expression tree.
template<typename SV>
void visitAll(const SCEV *Root, SV& Visitor) {
SCEVTraversal<SV> T(Visitor);
diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h
index f57f3eb009a1..4bd5dd8a221e 100644
--- a/include/llvm/Analysis/TargetTransformInfo.h
+++ b/include/llvm/Analysis/TargetTransformInfo.h
@@ -28,6 +28,7 @@
namespace llvm {
+class Function;
class GlobalValue;
class Loop;
class Type;
@@ -183,7 +184,7 @@ public:
/// should probably move to simpler cost metrics using the above.
/// Alternatively, we could split the cost interface into distinct code-size
/// and execution-speed costs. This would allow modelling the core of this
- /// query more accurately as the a call is a single small instruction, but
+ /// query more accurately as a call is a single small instruction, but
/// incurs significant execution cost.
virtual bool isLoweredToCall(const Function *F) const;
@@ -227,7 +228,8 @@ public:
/// \brief Get target-customized preferences for the generic loop unrolling
/// transformation. The caller will initialize UP with the current
/// target-independent defaults.
- virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const;
+ virtual void getUnrollingPreferences(const Function *F, Loop *L,
+ UnrollingPreferences &UP) const;
/// @}
@@ -268,6 +270,13 @@ public:
int64_t BaseOffset, bool HasBaseReg,
int64_t Scale) const;
+ /// \brief Return true if the target works with masked instruction
+ /// AVX2 allows masks for consecutive load and store for i32 and i64 elements.
+ /// AVX-512 architecture will also allow masks for non-consecutive memory
+ /// accesses.
+ virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) const;
+ virtual bool isLegalMaskedLoad (Type *DataType, int Consecutive) const;
+
/// \brief Return the cost of the scaling factor used in the addressing
/// mode represented by AM for this target, for a load/store
/// of the specified type.
@@ -335,6 +344,9 @@ public:
OK_NonUniformConstantValue // Operand is a non uniform constant value.
};
+ /// \brief 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.
/// If 'Vectors' is true, it returns the number of vector registers. If it is
/// set to false, it returns the number of scalar registers.
@@ -343,15 +355,18 @@ public:
/// \return The width of the largest scalar or vector register type.
virtual unsigned getRegisterBitWidth(bool Vector) const;
- /// \return The maximum unroll factor that the vectorizer should try to
+ /// \return The maximum interleave factor that any transform should try to
/// perform for this target. This number depends on the level of parallelism
/// and the number of execution units in the CPU.
- virtual unsigned getMaximumUnrollFactor() const;
+ virtual unsigned getMaxInterleaveFactor() const;
/// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc.
- virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty,
- OperandValueKind Opd1Info = OK_AnyValue,
- OperandValueKind Opd2Info = OK_AnyValue) const;
+ virtual unsigned
+ getArithmeticInstrCost(unsigned Opcode, Type *Ty,
+ OperandValueKind Opd1Info = OK_AnyValue,
+ OperandValueKind Opd2Info = OK_AnyValue,
+ OperandValueProperties Opd1PropInfo = OP_None,
+ OperandValueProperties Opd2PropInfo = OP_None) const;
/// \return The cost of a shuffle instruction of kind Kind and of type Tp.
/// The index and subtype parameters are used by the subvector insertion and
@@ -416,6 +431,13 @@ public:
virtual unsigned getAddressComputationCost(Type *Ty,
bool IsComplex = false) const;
+ /// \returns The cost, if any, of keeping values of the given types alive
+ /// over a callsite.
+ ///
+ /// Some types may require the use of register classes that do not have
+ /// any callee-saved registers, so would require a spill and fill.
+ virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const;
+
/// @}
/// Analysis group identification.
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index 83b5408fb1c2..cc588381727d 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -25,6 +25,8 @@ namespace llvm {
class DataLayout;
class StringRef;
class MDNode;
+ class AssumptionCache;
+ class DominatorTree;
class TargetLibraryInfo;
/// Determine which bits of V are known to be either zero or one and return
@@ -35,8 +37,11 @@ namespace llvm {
/// where V is a vector, the known zero and known one values are the
/// same width as the vector element, and the bit is set only if it is true
/// for all of the elements in the vector.
- void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne,
- const DataLayout *TD = nullptr, unsigned Depth = 0);
+ void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne,
+ const DataLayout *TD = nullptr, unsigned Depth = 0,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
/// Compute known bits from the range metadata.
/// \p KnownZero the set of bits that are known to be zero
void computeKnownBitsFromRangeMetadata(const MDNode &Ranges,
@@ -45,21 +50,29 @@ namespace llvm {
/// ComputeSignBit - Determine whether the sign bit is known to be zero or
/// one. Convenience wrapper around computeKnownBits.
void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
- const DataLayout *TD = nullptr, unsigned Depth = 0);
+ const DataLayout *TD = nullptr, unsigned Depth = 0,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
/// isKnownToBeAPowerOfTwo - Return true if the given value is known to have
/// exactly one bit set when defined. For vectors return true if every
/// element is known to be a power of two when defined. Supports values with
/// integer or pointer type and vectors of integers. If 'OrZero' is set then
/// returns true if the given value is either a power of two or zero.
- bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0);
+ bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
/// isKnownNonZero - Return true if the given value is known to be non-zero
/// when defined. For vectors return true if every element is known to be
/// non-zero when defined. Supports values with integer or pointer type and
/// vectors of integers.
bool isKnownNonZero(Value *V, const DataLayout *TD = nullptr,
- unsigned Depth = 0);
+ unsigned Depth = 0, AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
/// this predicate to simplify operations downstream. Mask is known to be
@@ -70,10 +83,12 @@ namespace llvm {
/// where V is a vector, the mask, known zero, and known one values are the
/// same width as the vector element, and the bit is set only if it is true
/// for all of the elements in the vector.
- bool MaskedValueIsZero(Value *V, const APInt &Mask,
- const DataLayout *TD = nullptr, unsigned Depth = 0);
+ bool MaskedValueIsZero(Value *V, const APInt &Mask,
+ const DataLayout *TD = nullptr, unsigned Depth = 0,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
-
/// ComputeNumSignBits - Return the number of times the sign bit of the
/// register is replicated into the other bits. We know that at least 1 bit
/// is always equal to the sign bit (itself), but other cases can give us
@@ -83,7 +98,9 @@ namespace llvm {
/// 'Op' must have a scalar integer type.
///
unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr,
- unsigned Depth = 0);
+ unsigned Depth = 0, AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
/// ComputeMultiple - This function computes the integer multiple of Base that
/// equals V. If successful, it returns true and returns the multiple in
@@ -191,6 +208,24 @@ namespace llvm {
/// and byval arguments.
bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr);
+ /// Return true if it is valid to use the assumptions provided by an
+ /// assume intrinsic, I, at the point in the control-flow identified by the
+ /// context instruction, CxtI.
+ bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI,
+ const DataLayout *DL = nullptr,
+ const DominatorTree *DT = nullptr);
+
+ enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows };
+ OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS,
+ const DataLayout *DL,
+ AssumptionCache *AC,
+ const Instruction *CxtI,
+ const DominatorTree *DT);
+ OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS,
+ const DataLayout *DL,
+ AssumptionCache *AC,
+ const Instruction *CxtI,
+ const DominatorTree *DT);
} // end namespace llvm
#endif
diff --git a/include/llvm/AsmParser/Parser.h b/include/llvm/AsmParser/Parser.h
index 165c46d6f271..7ef78d73da17 100644
--- a/include/llvm/AsmParser/Parser.h
+++ b/include/llvm/AsmParser/Parser.h
@@ -14,12 +14,11 @@
#ifndef LLVM_ASMPARSER_PARSER_H
#define LLVM_ASMPARSER_PARSER_H
-#include <string>
+#include "llvm/Support/MemoryBuffer.h"
namespace llvm {
class Module;
-class MemoryBuffer;
class SMDiagnostic;
class LLVMContext;
@@ -29,11 +28,12 @@ class LLVMContext;
/// that this does not verify that the generated Module is valid, so you should
/// run the verifier after parsing the file to check that it is okay.
/// @brief Parse LLVM Assembly from a file
-Module *ParseAssemblyFile(
- const std::string &Filename, ///< The name of the file to parse
- SMDiagnostic &Error, ///< Error result info.
- LLVMContext &Context ///< Context in which to allocate globals info.
-);
+/// @param Filename The name of the file to parse
+/// @param Error Error result info.
+/// @param Context Context in which to allocate globals info.
+std::unique_ptr<Module> parseAssemblyFile(StringRef Filename,
+ SMDiagnostic &Error,
+ LLVMContext &Context);
/// 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
@@ -41,23 +41,31 @@ Module *ParseAssemblyFile(
/// that this does not verify that the generated Module is valid, so you should
/// run the verifier after parsing the file to check that it is okay.
/// @brief Parse LLVM Assembly from a string
-Module *ParseAssemblyString(
- const char *AsmString, ///< The string containing assembly
- Module *M, ///< A module to add the assembly too.
- SMDiagnostic &Error, ///< Error result info.
- LLVMContext &Context
-);
+/// @param AsmString The string containing assembly
+/// @param Error Error result info.
+/// @param Context Context in which to allocate globals info.
+std::unique_ptr<Module> parseAssemblyString(StringRef AsmString,
+ SMDiagnostic &Error,
+ LLVMContext &Context);
+
+/// parseAssemblyFile and parseAssemblyString are wrappers around this function.
+/// @brief Parse LLVM Assembly from a MemoryBuffer.
+/// @param F The MemoryBuffer containing assembly
+/// @param Err Error result info.
+/// @param Context Context in which to allocate globals info.
+std::unique_ptr<Module> parseAssembly(MemoryBufferRef F, SMDiagnostic &Err,
+ LLVMContext &Context);
/// This function is the low-level interface to the LLVM Assembly Parser.
-/// ParseAssemblyFile and ParseAssemblyString are wrappers around this function.
-/// @brief Parse LLVM Assembly from a MemoryBuffer. This function *always*
-/// takes ownership of the MemoryBuffer.
-Module *ParseAssembly(
- MemoryBuffer *F, ///< The MemoryBuffer containing assembly
- Module *M, ///< A module to add the assembly too.
- SMDiagnostic &Err, ///< Error result info.
- LLVMContext &Context
-);
+/// This is kept as an independent function instead of being inlined into
+/// parseAssembly for the convenience of interactive users that want to add
+/// recently parsed bits to an existing module.
+///
+/// @param F The MemoryBuffer containing assembly
+/// @param M The module to add data to.
+/// @param Err Error result info.
+/// @return true on error.
+bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err);
} // End llvm namespace
diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h
index b510daf33147..ed2dcf84f924 100644
--- a/include/llvm/Bitcode/BitCodes.h
+++ b/include/llvm/Bitcode/BitCodes.h
@@ -18,6 +18,7 @@
#ifndef LLVM_BITCODE_BITCODES_H
#define LLVM_BITCODE_BITCODES_H
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
@@ -161,16 +162,13 @@ template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; };
/// BitCodeAbbrev - This class represents an abbreviation record. An
/// abbreviation allows a complex record that has redundancy to be stored in a
/// specialized format instead of the fully-general, fully-vbr, format.
-class BitCodeAbbrev {
+class BitCodeAbbrev : public RefCountedBase<BitCodeAbbrev> {
SmallVector<BitCodeAbbrevOp, 32> OperandList;
- unsigned char RefCount; // Number of things using this.
~BitCodeAbbrev() {}
-public:
- BitCodeAbbrev() : RefCount(1) {}
-
- void addRef() { ++RefCount; }
- void dropRef() { if (--RefCount == 0) delete this; }
+ // Only RefCountedBase is allowed to delete.
+ friend class RefCountedBase<BitCodeAbbrev>;
+public:
unsigned getNumOperandInfos() const {
return static_cast<unsigned>(OperandList.size());
}
diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h
index 898cd523bd08..8fe9b7e8434d 100644
--- a/include/llvm/Bitcode/BitcodeWriterPass.h
+++ b/include/llvm/Bitcode/BitcodeWriterPass.h
@@ -12,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_BITCODE_BITCODE_WRITER_PASS_H
-#define LLVM_BITCODE_BITCODE_WRITER_PASS_H
+#ifndef LLVM_BITCODE_BITCODEWRITERPASS_H
+#define LLVM_BITCODE_BITCODEWRITERPASS_H
#include "llvm/ADT/StringRef.h"
@@ -41,7 +41,7 @@ public:
/// \brief Run the bitcode writer pass, and output the module to the selected
/// output stream.
- PreservedAnalyses run(Module *M);
+ PreservedAnalyses run(Module &M);
static StringRef name() { return "BitcodeWriterPass"; }
};
diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h
index 6f478b72127d..865a3e668428 100644
--- a/include/llvm/Bitcode/BitstreamReader.h
+++ b/include/llvm/Bitcode/BitstreamReader.h
@@ -17,39 +17,37 @@
#include "llvm/Bitcode/BitCodes.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/StreamableMemoryObject.h"
+#include "llvm/Support/StreamingMemoryObject.h"
#include <climits>
#include <string>
#include <vector>
namespace llvm {
- class Deserializer;
+class Deserializer;
-/// BitstreamReader - This class is used to read from an LLVM bitcode stream,
-/// maintaining information that is global to decoding the entire file. While
-/// a file is being read, multiple cursors can be independently advanced or
-/// skipped around within the file. These are represented by the
-/// BitstreamCursor class.
+/// This class is used to read from an LLVM bitcode stream, maintaining
+/// information that is global to decoding the entire file. While a file is
+/// being read, multiple cursors can be independently advanced or skipped around
+/// within the file. These are represented by the BitstreamCursor class.
class BitstreamReader {
public:
- /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
- /// These describe abbreviations that all blocks of the specified ID inherit.
+ /// This contains information emitted to BLOCKINFO_BLOCK blocks. These
+ /// describe abbreviations that all blocks of the specified ID inherit.
struct BlockInfo {
unsigned BlockID;
- std::vector<BitCodeAbbrev*> Abbrevs;
+ std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs;
std::string Name;
std::vector<std::pair<unsigned, std::string> > RecordNames;
};
private:
- std::unique_ptr<StreamableMemoryObject> BitcodeBytes;
+ std::unique_ptr<MemoryObject> BitcodeBytes;
std::vector<BlockInfo> BlockInfoRecords;
- /// IgnoreBlockInfoNames - This is set to true if we don't care about the
- /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer
- /// uses this.
+ /// This is set to true if we don't care about the block/record name
+ /// information in the BlockInfo block. Only llvm-bcanalyzer uses this.
bool IgnoreBlockInfoNames;
BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION;
@@ -58,13 +56,24 @@ public:
BitstreamReader() : IgnoreBlockInfoNames(true) {
}
- BitstreamReader(const unsigned char *Start, const unsigned char *End) {
- IgnoreBlockInfoNames = true;
+ BitstreamReader(const unsigned char *Start, const unsigned char *End)
+ : IgnoreBlockInfoNames(true) {
init(Start, End);
}
- BitstreamReader(StreamableMemoryObject *bytes) {
- BitcodeBytes.reset(bytes);
+ BitstreamReader(std::unique_ptr<MemoryObject> BitcodeBytes)
+ : BitcodeBytes(std::move(BitcodeBytes)), IgnoreBlockInfoNames(true) {}
+
+ BitstreamReader(BitstreamReader &&Other) {
+ *this = std::move(Other);
+ }
+
+ BitstreamReader &operator=(BitstreamReader &&Other) {
+ BitcodeBytes = std::move(Other.BitcodeBytes);
+ // Explicitly swap block info, so that nothing gets destroyed twice.
+ std::swap(BlockInfoRecords, Other.BlockInfoRecords);
+ IgnoreBlockInfoNames = Other.IgnoreBlockInfoNames;
+ return *this;
}
void init(const unsigned char *Start, const unsigned char *End) {
@@ -72,22 +81,9 @@ public:
BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End));
}
- StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
+ MemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
- ~BitstreamReader() {
- // Free the BlockInfoRecords.
- while (!BlockInfoRecords.empty()) {
- BlockInfo &Info = BlockInfoRecords.back();
- // Free blockinfo abbrev info.
- for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size());
- i != e; ++i)
- Info.Abbrevs[i]->dropRef();
- BlockInfoRecords.pop_back();
- }
- }
-
- /// CollectBlockInfoNames - This is called by clients that want block/record
- /// name information.
+ /// This is called by clients that want block/record name information.
void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; }
@@ -95,13 +91,13 @@ public:
// Block Manipulation
//===--------------------------------------------------------------------===//
- /// hasBlockInfoRecords - Return true if we've already read and processed the
- /// block info block for this Bitstream. We only process it for the first
- /// cursor that walks over it.
+ /// Return true if we've already read and processed the block info block for
+ /// this Bitstream. We only process it for the first cursor that walks over
+ /// it.
bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); }
- /// getBlockInfo - If there is block info for the specified ID, return it,
- /// otherwise return null.
+ /// If there is block info for the specified ID, return it, otherwise return
+ /// null.
const BlockInfo *getBlockInfo(unsigned BlockID) const {
// Common case, the most recent entry matches BlockID.
if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
@@ -123,23 +119,26 @@ public:
BlockInfoRecords.back().BlockID = BlockID;
return BlockInfoRecords.back();
}
-};
+ /// Takes block info from the other bitstream reader.
+ ///
+ /// This is a "take" operation because BlockInfo records are non-trivial, and
+ /// indeed rather expensive.
+ void takeBlockInfo(BitstreamReader &&Other) {
+ assert(!hasBlockInfoRecords());
+ BlockInfoRecords = std::move(Other.BlockInfoRecords);
+ }
+};
-/// BitstreamEntry - When advancing through a bitstream cursor, each advance can
-/// discover a few different kinds of entries:
-/// Error - Malformed bitcode was found.
-/// EndBlock - We've reached the end of the current block, (or the end of the
-/// file, which is treated like a series of EndBlock records.
-/// SubBlock - This is the start of a new subblock of a specific ID.
-/// Record - This is a record with a specific AbbrevID.
-///
+/// When advancing through a bitstream cursor, each advance can discover a few
+/// different kinds of entries:
struct BitstreamEntry {
enum {
- Error,
- EndBlock,
- SubBlock,
- Record
+ Error, // Malformed bitcode was found.
+ EndBlock, // We've reached the end of the current block, (or the end of the
+ // file, which is treated like a series of EndBlock records.
+ SubBlock, // This is the start of a new subblock of a specific ID.
+ Record // This is a record with a specific AbbrevID.
} Kind;
unsigned ID;
@@ -158,9 +157,9 @@ struct BitstreamEntry {
}
};
-/// BitstreamCursor - This represents a position within a bitcode file. There
-/// may be multiple independent cursors reading within one bitstream, each
-/// maintaining their own local state.
+/// This represents a position within a bitcode file. There may be multiple
+/// independent cursors reading within one bitstream, each maintaining their own
+/// local state.
///
/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
/// be passed by value.
@@ -169,92 +168,74 @@ class BitstreamCursor {
BitstreamReader *BitStream;
size_t NextChar;
+ // The size of the bicode. 0 if we don't know it yet.
+ size_t Size;
- /// CurWord/word_t - This is the current data we have pulled from the stream
- /// but have not returned to the client. This is specifically and
- /// intentionally defined to follow the word size of the host machine for
- /// efficiency. We use word_t in places that are aware of this to make it
- /// perfectly explicit what is going on.
- typedef uint32_t word_t;
+ /// This is the current data we have pulled from the stream but have not
+ /// returned to the client. This is specifically and intentionally defined to
+ /// follow the word size of the host machine for efficiency. We use word_t in
+ /// places that are aware of this to make it perfectly explicit what is going
+ /// on.
+ typedef size_t word_t;
word_t CurWord;
- /// BitsInCurWord - This is the number of bits in CurWord that are valid. This
- /// is always from [0...31/63] inclusive (depending on word size).
+ /// This is the number of bits in CurWord that are valid. This is always from
+ /// [0...bits_of(size_t)-1] inclusive.
unsigned BitsInCurWord;
- // CurCodeSize - This is the declared size of code values used for the current
- // block, in bits.
+ // This is the declared size of code values used for the current block, in
+ // bits.
unsigned CurCodeSize;
- /// CurAbbrevs - Abbrevs installed at in this block.
- std::vector<BitCodeAbbrev*> CurAbbrevs;
+ /// Abbrevs installed at in this block.
+ std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs;
struct Block {
unsigned PrevCodeSize;
- std::vector<BitCodeAbbrev*> PrevAbbrevs;
+ std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs;
explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
};
- /// BlockScope - This tracks the codesize of parent blocks.
+ /// This tracks the codesize of parent blocks.
SmallVector<Block, 8> BlockScope;
public:
- BitstreamCursor() : BitStream(nullptr), NextChar(0) {}
- BitstreamCursor(const BitstreamCursor &RHS)
- : BitStream(nullptr), NextChar(0) {
- operator=(RHS);
- }
+ BitstreamCursor() { init(nullptr); }
- explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) {
- NextChar = 0;
- CurWord = 0;
- BitsInCurWord = 0;
- CurCodeSize = 2;
- }
+ explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
- void init(BitstreamReader &R) {
+ void init(BitstreamReader *R) {
freeState();
- BitStream = &R;
+ BitStream = R;
NextChar = 0;
- CurWord = 0;
+ Size = 0;
BitsInCurWord = 0;
CurCodeSize = 2;
}
- ~BitstreamCursor() {
- freeState();
- }
-
- void operator=(const BitstreamCursor &RHS);
-
void freeState();
- bool isEndPos(size_t pos) {
- return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos));
- }
-
bool canSkipToPos(size_t pos) const {
// pos can be skipped to if it is a valid address or one byte past the end.
return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
static_cast<uint64_t>(pos - 1));
}
- uint32_t getWord(size_t pos) {
- uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
- BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf);
- return *reinterpret_cast<support::ulittle32_t *>(buf);
- }
-
bool AtEndOfStream() {
- return BitsInCurWord == 0 && isEndPos(NextChar);
+ if (BitsInCurWord != 0)
+ return false;
+ if (Size != 0)
+ return Size == NextChar;
+ fillCurWord();
+ return BitsInCurWord == 0;
}
- /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
+ /// Return the number of bits used to encode an abbrev #.
unsigned getAbbrevIDWidth() const { return CurCodeSize; }
- /// GetCurrentBitNo - Return the bit # of the bit we are reading.
+ /// Return the bit # of the bit we are reading.
uint64_t GetCurrentBitNo() const {
return NextChar*CHAR_BIT - BitsInCurWord;
}
@@ -268,19 +249,17 @@ public:
/// Flags that modify the behavior of advance().
enum {
- /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does
- /// not automatically pop the block scope when the end of a block is
- /// reached.
+ /// If this flag is used, the advance() method does not automatically pop
+ /// the block scope when the end of a block is reached.
AF_DontPopBlockAtEnd = 1,
- /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are
- /// returned just like normal records.
+ /// If this flag is used, abbrev entries are returned just like normal
+ /// records.
AF_DontAutoprocessAbbrevs = 2
};
- /// advance - Advance the current bitstream, returning the next entry in the
- /// stream.
- BitstreamEntry advance(unsigned Flags = 0) {
+ /// Advance the current bitstream, returning the next entry in the stream.
+ BitstreamEntry advance(unsigned Flags = 0) {
while (1) {
unsigned Code = ReadCode();
if (Code == bitc::END_BLOCK) {
@@ -305,8 +284,8 @@ public:
}
}
- /// advanceSkippingSubblocks - This is a convenience function for clients that
- /// don't expect any subblocks. This just skips over them automatically.
+ /// This is a convenience function for clients that don't expect any
+ /// subblocks. This just skips over them automatically.
BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
while (1) {
// If we found a normal entry, return it.
@@ -320,7 +299,7 @@ public:
}
}
- /// JumpToBit - Reset the stream to the specified bit number.
+ /// Reset the stream to the specified bit number.
void JumpToBit(uint64_t BitNo) {
uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1);
unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
@@ -329,77 +308,74 @@ public:
// Move the cursor to the right word.
NextChar = ByteNo;
BitsInCurWord = 0;
- CurWord = 0;
// Skip over any bits that are already consumed.
- if (WordBitNo) {
- if (sizeof(word_t) > 4)
- Read64(WordBitNo);
- else
- Read(WordBitNo);
+ if (WordBitNo)
+ Read(WordBitNo);
+ }
+
+ void fillCurWord() {
+ assert(Size == 0 || NextChar < (unsigned)Size);
+
+ // Read the next word from the stream.
+ uint8_t Array[sizeof(word_t)] = {0};
+
+ uint64_t BytesRead =
+ BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar);
+
+ // If we run out of data, stop at the end of the stream.
+ if (BytesRead == 0) {
+ Size = NextChar;
+ return;
}
+
+ CurWord =
+ support::endian::read<word_t, support::little, support::unaligned>(
+ Array);
+ NextChar += BytesRead;
+ BitsInCurWord = BytesRead * 8;
}
+ word_t Read(unsigned NumBits) {
+ static const unsigned BitsInWord = sizeof(word_t) * 8;
- uint32_t Read(unsigned NumBits) {
- assert(NumBits && NumBits <= 32 &&
- "Cannot return zero or more than 32 bits!");
+ assert(NumBits && NumBits <= BitsInWord &&
+ "Cannot return zero or more than BitsInWord bits!");
+
+ static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f;
// If the field is fully contained by CurWord, return it quickly.
if (BitsInCurWord >= NumBits) {
- uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits));
- CurWord >>= NumBits;
+ word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits));
+
+ // Use a mask to avoid undefined behavior.
+ CurWord >>= (NumBits & Mask);
+
BitsInCurWord -= NumBits;
return R;
}
- // If we run out of data, stop at the end of the stream.
- if (isEndPos(NextChar)) {
- CurWord = 0;
- BitsInCurWord = 0;
- return 0;
- }
-
- uint32_t R = uint32_t(CurWord);
-
- // Read the next word from the stream.
- uint8_t Array[sizeof(word_t)] = {0};
+ word_t R = BitsInCurWord ? CurWord : 0;
+ unsigned BitsLeft = NumBits - BitsInCurWord;
- BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array);
+ fillCurWord();
- // Handle big-endian byte-swapping if necessary.
- support::detail::packed_endian_specific_integral
- <word_t, support::little, support::unaligned> EndianValue;
- memcpy(&EndianValue, Array, sizeof(Array));
+ // If we run out of data, stop at the end of the stream.
+ if (BitsLeft > BitsInCurWord)
+ return 0;
- CurWord = EndianValue;
+ word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));
- NextChar += sizeof(word_t);
+ // Use a mask to avoid undefined behavior.
+ CurWord >>= (BitsLeft & Mask);
- // Extract NumBits-BitsInCurWord from what we just read.
- unsigned BitsLeft = NumBits-BitsInCurWord;
+ BitsInCurWord -= BitsLeft;
- // Be careful here, BitsLeft is in the range [1..32]/[1..64] inclusive.
- R |= uint32_t((CurWord & (word_t(~0ULL) >> (sizeof(word_t)*8-BitsLeft)))
- << BitsInCurWord);
+ R |= R2 << (NumBits - BitsLeft);
- // BitsLeft bits have just been used up from CurWord. BitsLeft is in the
- // range [1..32]/[1..64] so be careful how we shift.
- if (BitsLeft != sizeof(word_t)*8)
- CurWord >>= BitsLeft;
- else
- CurWord = 0;
- BitsInCurWord = sizeof(word_t)*8-BitsLeft;
return R;
}
- uint64_t Read64(unsigned NumBits) {
- if (NumBits <= 32) return Read(NumBits);
-
- uint64_t V = Read(32);
- return V | (uint64_t)Read(NumBits-32) << 32;
- }
-
uint32_t ReadVBR(unsigned NumBits) {
uint32_t Piece = Read(NumBits);
if ((Piece & (1U << (NumBits-1))) == 0)
@@ -418,8 +394,8 @@ public:
}
}
- // ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The
- // chunk size of the VBR must still be <= 32 bits though.
+ // Read a VBR that may have a value up to 64-bits in size. The chunk size of
+ // the VBR must still be <= 32 bits though.
uint64_t ReadVBR64(unsigned NumBits) {
uint32_t Piece = Read(NumBits);
if ((Piece & (1U << (NumBits-1))) == 0)
@@ -450,7 +426,6 @@ private:
}
BitsInCurWord = 0;
- CurWord = 0;
}
public:
@@ -462,15 +437,13 @@ public:
// Block header:
// [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
- /// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for
- /// the block.
+ /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
unsigned ReadSubBlockID() {
return ReadVBR(bitc::BlockIDWidth);
}
- /// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip
- /// over the body of this block. If the block record is malformed, return
- /// true.
+ /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body
+ /// of this block. If the block record is malformed, return true.
bool SkipBlock() {
// Read and ignore the codelen value. Since we are skipping this block, we
// don't care what code widths are used inside of it.
@@ -488,8 +461,8 @@ public:
return false;
}
- /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
- /// the block, and return true if the block has an error.
+ /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true
+ /// if the block has an error.
bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);
bool ReadBlockEnd() {
@@ -508,12 +481,7 @@ private:
void popBlockScope() {
CurCodeSize = BlockScope.back().PrevCodeSize;
- // Delete abbrevs from popped scope.
- for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
- i != e; ++i)
- CurAbbrevs[i]->dropRef();
-
- BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
+ CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs);
BlockScope.pop_back();
}
@@ -521,23 +489,16 @@ private:
// Record Processing
//===--------------------------------------------------------------------===//
-private:
- void readAbbreviatedLiteral(const BitCodeAbbrevOp &Op,
- SmallVectorImpl<uint64_t> &Vals);
- void readAbbreviatedField(const BitCodeAbbrevOp &Op,
- SmallVectorImpl<uint64_t> &Vals);
- void skipAbbreviatedField(const BitCodeAbbrevOp &Op);
-
public:
- /// getAbbrev - Return the abbreviation for the specified AbbrevId.
+ /// Return the abbreviation for the specified AbbrevId.
const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) {
unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV;
assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
- return CurAbbrevs[AbbrevNo];
+ return CurAbbrevs[AbbrevNo].get();
}
- /// skipRecord - Read the current record and discard it.
+ /// Read the current record and discard it.
void skipRecord(unsigned AbbrevID);
unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals,
diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h
index dcfebd9cc105..9e2c2fa4a156 100644
--- a/include/llvm/Bitcode/BitstreamWriter.h
+++ b/include/llvm/Bitcode/BitstreamWriter.h
@@ -40,12 +40,12 @@ class BitstreamWriter {
unsigned BlockInfoCurBID;
/// CurAbbrevs - Abbrevs installed at in this block.
- std::vector<BitCodeAbbrev*> CurAbbrevs;
+ std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs;
struct Block {
unsigned PrevCodeSize;
unsigned StartSizeWord;
- std::vector<BitCodeAbbrev*> PrevAbbrevs;
+ std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs;
Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {}
};
@@ -56,7 +56,7 @@ class BitstreamWriter {
/// These describe abbreviations that all blocks of the specified ID inherit.
struct BlockInfo {
unsigned BlockID;
- std::vector<BitCodeAbbrev*> Abbrevs;
+ std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs;
};
std::vector<BlockInfo> BlockInfoRecords;
@@ -99,16 +99,6 @@ public:
~BitstreamWriter() {
assert(CurBit == 0 && "Unflushed data remaining");
assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
-
- // Free the BlockInfoRecords.
- while (!BlockInfoRecords.empty()) {
- BlockInfo &Info = BlockInfoRecords.back();
- // Free blockinfo abbrev info.
- for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size());
- i != e; ++i)
- Info.Abbrevs[i]->dropRef();
- BlockInfoRecords.pop_back();
- }
}
/// \brief Retrieve the current position in the stream, in bits.
@@ -231,22 +221,13 @@ public:
// If there is a blockinfo for this BlockID, add all the predefined abbrevs
// to the abbrev list.
if (BlockInfo *Info = getBlockInfo(BlockID)) {
- for (unsigned i = 0, e = static_cast<unsigned>(Info->Abbrevs.size());
- i != e; ++i) {
- CurAbbrevs.push_back(Info->Abbrevs[i]);
- Info->Abbrevs[i]->addRef();
- }
+ CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
+ Info->Abbrevs.end());
}
}
void ExitBlock() {
assert(!BlockScope.empty() && "Block scope imbalance!");
-
- // Delete all abbrevs.
- for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
- i != e; ++i)
- CurAbbrevs[i]->dropRef();
-
const Block &B = BlockScope.back();
// Block tail:
@@ -263,7 +244,7 @@ public:
// Restore the inner block's code size and abbrev table.
CurCodeSize = B.PrevCodeSize;
- BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
+ CurAbbrevs = std::move(B.PrevAbbrevs);
BlockScope.pop_back();
}
@@ -317,7 +298,7 @@ private:
unsigned BlobLen = (unsigned) Blob.size();
unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV;
assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
- BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo];
+ const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get();
EmitCode(Abbrev);
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index ee2efa2257b1..043ecd3d65d7 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -137,14 +137,14 @@ namespace bitc {
enum MetadataCodes {
METADATA_STRING = 1, // MDSTRING: [values]
- // 2 is unused.
- // 3 is unused.
+ METADATA_VALUE = 2, // VALUE: [type num, value num]
+ METADATA_NODE = 3, // NODE: [n x md num]
METADATA_NAME = 4, // STRING: [values]
- // 5 is unused.
+ METADATA_DISTINCT_NODE = 5, // DISTINCT_NODE: [n x md num]
METADATA_KIND = 6, // [n x [id, name]]
- // 7 is unused.
- METADATA_NODE = 8, // NODE: [n x (type num, value num)]
- METADATA_FN_NODE = 9, // FN_NODE: [n x (type num, value num)]
+ METADATA_LOCATION = 7, // [distinct, line, col, scope, inlined-at?]
+ METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)]
+ METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)]
METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]]
};
@@ -330,7 +330,8 @@ namespace bitc {
};
enum UseListCodes {
- USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD.
+ USELIST_CODE_DEFAULT = 1, // DEFAULT: [index..., value-id]
+ USELIST_CODE_BB = 2 // BB: [index..., bb-id]
};
enum AttributeKindCodes {
diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h
index 8cf573544f8d..48bdabc88391 100644
--- a/include/llvm/Bitcode/ReaderWriter.h
+++ b/include/llvm/Bitcode/ReaderWriter.h
@@ -14,12 +14,14 @@
#ifndef LLVM_BITCODE_READERWRITER_H
#define LLVM_BITCODE_READERWRITER_H
+#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <memory>
#include <string>
namespace llvm {
class BitstreamWriter;
- class MemoryBuffer;
class DataStreamer;
class LLVMContext;
class Module;
@@ -27,30 +29,30 @@ namespace llvm {
class raw_ostream;
/// Read the header of the specified bitcode buffer and prepare for lazy
- /// deserialization of function bodies. If successful, this takes ownership
- /// of 'buffer. On error, this *does not* take ownership of Buffer.
- ErrorOr<Module *> getLazyBitcodeModule(MemoryBuffer *Buffer,
- LLVMContext &Context);
-
- /// getStreamedBitcodeModule - Read the header of the specified stream
- /// and prepare for lazy deserialization and streaming of function bodies.
- /// On error, this returns null, and fills in *ErrMsg with an error
- /// description if ErrMsg is non-null.
- Module *getStreamedBitcodeModule(const std::string &name,
- DataStreamer *streamer,
- LLVMContext &Context,
- std::string *ErrMsg = nullptr);
+ /// deserialization of function bodies. If successful, this moves Buffer. On
+ /// error, this *does not* move Buffer.
+ ErrorOr<Module *>
+ getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
+ LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler = nullptr);
+
+ /// Read the header of the specified stream and prepare for lazy
+ /// deserialization and streaming of function bodies.
+ ErrorOr<std::unique_ptr<Module>> getStreamedBitcodeModule(
+ StringRef Name, DataStreamer *Streamer, LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler = nullptr);
/// Read the header of the specified bitcode buffer and extract just the
- /// triple information. If successful, this returns a string and *does not*
- /// take ownership of 'buffer'. On error, this returns "".
- std::string getBitcodeTargetTriple(MemoryBuffer *Buffer,
- LLVMContext &Context);
+ /// triple information. If successful, this returns a string. On error, this
+ /// returns "".
+ std::string
+ getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler = nullptr);
/// Read the specified bitcode file, returning the module.
- /// This method *never* takes ownership of Buffer.
- ErrorOr<Module *> parseBitcodeFile(MemoryBuffer *Buffer,
- LLVMContext &Context);
+ ErrorOr<Module *>
+ parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler = nullptr);
/// WriteBitcodeToFile - Write the specified module to the specified
/// raw output stream. For streams where it matters, the given stream
@@ -139,6 +141,32 @@ namespace llvm {
BufEnd = BufPtr+Size;
return false;
}
+
+ const std::error_category &BitcodeErrorCategory();
+ enum class BitcodeError { InvalidBitcodeSignature, CorruptedBitcode };
+ inline std::error_code make_error_code(BitcodeError E) {
+ return std::error_code(static_cast<int>(E), BitcodeErrorCategory());
+ }
+
+ class BitcodeDiagnosticInfo : public DiagnosticInfo {
+ const Twine &Msg;
+ std::error_code EC;
+
+ public:
+ BitcodeDiagnosticInfo(std::error_code EC, DiagnosticSeverity Severity,
+ const Twine &Msg);
+ void print(DiagnosticPrinter &DP) const override;
+ std::error_code getError() const { return EC; };
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_Bitcode;
+ }
+ };
+
} // End llvm namespace
+namespace std {
+template <> struct is_error_code_enum<llvm::BitcodeError> : std::true_type {};
+}
+
#endif
diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt
index ca4fd1338ed7..ff805396eb0c 100644
--- a/include/llvm/CMakeLists.txt
+++ b/include/llvm/CMakeLists.txt
@@ -1,18 +1,5 @@
add_subdirectory(IR)
-if( MSVC_IDE OR XCODE )
- # Creates a dummy target containing all headers for the benefit of
- # XCode and Visual Studio users.
- file(GLOB_RECURSE headers *.h)
- add_td_sources(headers)
- add_library(llvm_headers_do_not_build EXCLUDE_FROM_ALL
- # We need at least one source file:
- ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp
- ${headers})
- set_target_properties(llvm_headers_do_not_build PROPERTIES FOLDER "Misc"
- EXCLUDE_FROM_DEFAULT_BUILD ON)
-endif()
-
# If we're doing an out-of-tree build, copy a module map for generated
# header files into the build area.
if (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h
index b791ba09adaf..c4b94ede4f55 100644
--- a/include/llvm/CodeGen/Analysis.h
+++ b/include/llvm/CodeGen/Analysis.h
@@ -22,7 +22,7 @@
#include "llvm/IR/Instructions.h"
namespace llvm {
-class GlobalVariable;
+class GlobalValue;
class TargetLoweringBase;
class TargetLowering;
class TargetMachine;
@@ -31,10 +31,21 @@ class SDValue;
class SelectionDAG;
struct EVT;
-/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence
-/// of insertvalue or extractvalue indices that identify a member, return
-/// the linearized index of the start of the member.
+/// \brief Compute the linearized index of a member in a nested
+/// aggregate/struct/array.
///
+/// Given an LLVM IR aggregate type and a sequence of insertvalue or
+/// extractvalue indices that identify a member, return the linearized index of
+/// the start of the member, i.e the number of element in memory before the
+/// seeked one. This is disconnected from the number of bytes.
+///
+/// \param Ty is the type indexed by \p Indices.
+/// \param Indices is an optional pointer in the indices list to the current
+/// index.
+/// \param IndicesEnd is the end of the indices list.
+/// \param CurIndex is the current index in the recursion.
+///
+/// \returns \p CurIndex plus the linear index in \p Ty the indices list.
unsigned ComputeLinearIndex(Type *Ty,
const unsigned *Indices,
const unsigned *IndicesEnd,
@@ -59,7 +70,7 @@ void ComputeValueVTs(const TargetLowering &TLI, Type *Ty,
uint64_t StartingOffset = 0);
/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V.
-GlobalVariable *ExtractTypeInfo(Value *V);
+GlobalValue *ExtractTypeInfo(Value *V);
/// hasInlineAsmMemConstraint - Return true if the inline asm instruction being
/// processed uses a memory 'm' constraint.
@@ -97,6 +108,13 @@ bool returnTypeIsEligibleForTailCall(const Function *F,
const ReturnInst *Ret,
const TargetLoweringBase &TLI);
+// 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 GlobalValue *GV);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index e1c9a14c9009..e3ce57ad1850 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -44,6 +44,7 @@ class MachineModuleInfo;
class MCAsmInfo;
class MCCFIInstruction;
class MCContext;
+class MCExpr;
class MCInst;
class MCInstrInfo;
class MCSection;
@@ -132,6 +133,7 @@ public:
virtual ~AsmPrinter();
DwarfDebug *getDwarfDebug() { return DD; }
+ DwarfDebug *getDwarfDebug() const { return DD; }
/// Return true if assembly output should contain comments.
///
@@ -203,6 +205,8 @@ public:
void emitCFIInstruction(const MachineInstr &MI);
+ void emitFrameAlloc(const MachineInstr &MI);
+
enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug };
CFIMoveType needsCFIMoves();
@@ -238,6 +242,9 @@ public:
/// alignment (if present) and a comment describing it if appropriate.
void EmitBasicBlockStart(const MachineBasicBlock &MBB) const;
+ /// Lower the specified LLVM Constant to an MCExpr.
+ const MCExpr *lowerConstant(const Constant *CV);
+
/// \brief Print a general LLVM constant to the .s file.
void EmitGlobalConstant(const Constant *CV);
@@ -264,6 +271,9 @@ public:
/// function.
virtual void EmitFunctionBodyEnd() {}
+ /// Targets can override this to emit stuff at the end of a basic block.
+ virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {}
+
/// Targets should implement this to emit instructions.
virtual void EmitInstruction(const MachineInstr *) {
llvm_unreachable("EmitInstruction not implemented");
@@ -346,12 +356,6 @@ public:
void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
unsigned Size) const;
- /// Emit something like ".long Hi+Offset-Lo" where the size in bytes of the
- /// directive is specified by Size and Hi/Lo specify the labels. This
- /// implicitly uses .set if it is available.
- void EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset,
- const MCSymbol *Lo, unsigned Size) const;
-
/// 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.
@@ -402,6 +406,13 @@ public:
/// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified.
virtual unsigned getISAEncoding() { return 0; }
+ /// Emit a dwarf register operation for describing
+ /// - a small value occupying only part of a register or
+ /// - a register representing only part of a value.
+ void EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits,
+ unsigned OffsetInBits = 0) const;
+
+
/// \brief Emit a partial DWARF register operation.
/// \param MLoc the register
/// \param PieceSize size and
@@ -418,7 +429,7 @@ public:
unsigned PieceSize = 0,
unsigned PieceOffset = 0) const;
- /// Emit dwarf register operation.
+ /// EmitDwarfRegOp - Emit a dwarf register operation.
/// \param Indirect whether this is a register-indirect address
virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc,
bool Indirect) const;
@@ -461,6 +472,10 @@ public:
unsigned AsmVariant, const char *ExtraCode,
raw_ostream &OS);
+ /// Let the target do anything it needs to do before emitting inlineasm.
+ /// \p StartInfo - the subtarget info before parsing inline asm
+ virtual void emitInlineAsmStart(const MCSubtargetInfo &StartInfo) const;
+
/// Let the target do anything it needs to do after emitting inlineasm.
/// This callback can be used restore the original mode in case the
/// inlineasm contains directives to switch modes.
diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h
index 0d79b1d41bdb..91fb0a9d7e77 100644
--- a/include/llvm/CodeGen/CalcSpillWeights.h
+++ b/include/llvm/CodeGen/CalcSpillWeights.h
@@ -30,8 +30,10 @@ namespace llvm {
/// @param UseDefFreq Expected number of executed use and def instructions
/// per function call. Derived from block frequencies.
/// @param Size Size of live interval as returnexd by getSize()
+ /// @param NumInstr Number of instructions using this live interval
///
- static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size) {
+ static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size,
+ unsigned NumInstr) {
// The constant 25 instructions is added to avoid depending too much on
// accidental SlotIndex gaps for small intervals. The effect is that small
// intervals have a spill weight that is mostly proportional to the number
@@ -44,7 +46,7 @@ namespace llvm {
/// spill weight and allocation hint.
class VirtRegAuxInfo {
public:
- typedef float (*NormalizingFn)(float, unsigned);
+ typedef float (*NormalizingFn)(float, unsigned, unsigned);
private:
MachineFunction &MF;
diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h
index abe00a167fd6..dd7703b1dbf7 100644
--- a/include/llvm/CodeGen/CallingConvLower.h
+++ b/include/llvm/CodeGen/CallingConvLower.h
@@ -35,18 +35,18 @@ public:
SExt, // The value is sign extended in the location.
ZExt, // The value is zero extended in the location.
AExt, // The value is extended with undefined upper bits.
- BCvt, // The value is bit-converted in the location.
- VExt, // The value is vector-widened in the location.
- // FIXME: Not implemented yet. Code that uses AExt to mean
- // vector-widen should be fixed to use VExt instead.
- FPExt, // The floating-point value is fp-extended in the location.
- Indirect, // The location contains pointer to the value.
SExtUpper, // The value is in the upper bits of the location and should be
// sign extended when retrieved.
ZExtUpper, // The value is in the upper bits of the location and should be
// zero extended when retrieved.
- AExtUpper // The value is in the upper bits of the location and should be
+ AExtUpper, // The value is in the upper bits of the location and should be
// extended with undefined upper bits when retrieved.
+ BCvt, // The value is bit-converted in the location.
+ VExt, // The value is vector-widened in the location.
+ // FIXME: Not implemented yet. Code that uses AExt to mean
+ // vector-widen should be fixed to use VExt instead.
+ FPExt, // The floating-point value is fp-extended in the location.
+ Indirect // The location contains pointer to the value.
// TODO: a subset of the value is in the location.
};
@@ -158,6 +158,16 @@ public:
}
};
+/// Describes a register that needs to be forwarded from the prologue to a
+/// musttail call.
+struct ForwardedRegister {
+ ForwardedRegister(unsigned VReg, MCPhysReg PReg, MVT VT)
+ : VReg(VReg), PReg(PReg), VT(VT) {}
+ unsigned VReg;
+ MCPhysReg PReg;
+ MVT VT;
+};
+
/// CCAssignFn - This function assigns a location for Val, updating State to
/// reflect the change. It returns 'true' if it failed to handle Val.
typedef bool CCAssignFn(unsigned ValNo, MVT ValVT,
@@ -184,7 +194,6 @@ private:
CallingConv::ID CallingConv;
bool IsVarArg;
MachineFunction &MF;
- const TargetMachine &TM;
const TargetRegisterInfo &TRI;
SmallVectorImpl<CCValAssign> &Locs;
LLVMContext &Context;
@@ -248,15 +257,13 @@ protected:
public:
CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
- const TargetMachine &TM, SmallVectorImpl<CCValAssign> &locs,
- LLVMContext &C);
+ SmallVectorImpl<CCValAssign> &locs, LLVMContext &C);
void addLoc(const CCValAssign &V) {
Locs.push_back(V);
}
LLVMContext &getContext() const { return Context; }
- const TargetMachine &getTarget() const { return TM; }
MachineFunction &getMachineFunction() const { return MF; }
CallingConv::ID getCallingConv() const { return CallingConv; }
bool isVarArg() const { return IsVarArg; }
@@ -348,8 +355,12 @@ public:
/// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive
/// registers. If this is not possible, return zero. Otherwise, return the first
/// register of the block that were allocated, marking the entire block as allocated.
- unsigned AllocateRegBlock(const uint16_t *Regs, unsigned NumRegs, unsigned RegsRequired) {
- for (unsigned StartIdx = 0; StartIdx <= NumRegs - RegsRequired; ++StartIdx) {
+ unsigned AllocateRegBlock(ArrayRef<uint16_t> Regs, unsigned RegsRequired) {
+ if (RegsRequired > Regs.size())
+ return 0;
+
+ for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired;
+ ++StartIdx) {
bool BlockAvailable = true;
// Check for already-allocated regs in this block
for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) {
@@ -387,8 +398,8 @@ public:
/// AllocateStack - Allocate a chunk of stack space with the specified size
/// and alignment.
unsigned AllocateStack(unsigned Size, unsigned Align) {
- assert(Align && ((Align-1) & Align) == 0); // Align is power of 2.
- StackOffset = ((StackOffset + Align-1) & ~(Align-1));
+ assert(Align && ((Align - 1) & Align) == 0); // Align is power of 2.
+ StackOffset = ((StackOffset + Align - 1) & ~(Align - 1));
unsigned Result = StackOffset;
StackOffset += Size;
MF.getFrameInfo()->ensureMaxAlignment(Align);
@@ -469,6 +480,19 @@ public:
return PendingLocs;
}
+ /// Compute the remaining unused register parameters that would be used for
+ /// the given value type. This is useful when varargs are passed in the
+ /// registers that normal prototyped parameters would be passed in, or for
+ /// implementing perfect forwarding.
+ void getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> &Regs, MVT VT,
+ CCAssignFn Fn);
+
+ /// Compute the set of registers that need to be preserved and forwarded to
+ /// any musttail calls.
+ void analyzeMustTailForwardedRegisters(
+ SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> RegParmTypes,
+ CCAssignFn Fn);
+
private:
/// MarkAllocated - Mark a register and all of its aliases as allocated.
void MarkAllocated(unsigned Reg);
diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h
index 449d93418a4c..973c5954f9ad 100644
--- a/include/llvm/CodeGen/CommandFlags.h
+++ b/include/llvm/CodeGen/CommandFlags.h
@@ -54,6 +54,16 @@ RelocModel("relocation-model",
"Relocatable external references, non-relocatable code"),
clEnumValEnd));
+cl::opt<ThreadModel::Model>
+TMModel("thread-model",
+ cl::desc("Choose threading model"),
+ cl::init(ThreadModel::POSIX),
+ cl::values(clEnumValN(ThreadModel::POSIX, "posix",
+ "POSIX thread model"),
+ clEnumValN(ThreadModel::Single, "single",
+ "Single thread model"),
+ clEnumValEnd));
+
cl::opt<llvm::CodeModel::Model>
CMModel("code-model",
cl::desc("Choose code model"),
@@ -83,11 +93,6 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
clEnumValEnd));
cl::opt<bool>
-DisableRedZone("disable-red-zone",
- cl::desc("Do not emit code that uses the red zone."),
- cl::init(false));
-
-cl::opt<bool>
EnableFPMAD("enable-fp-mad",
cl::desc("Enable less precise MAD instructions to be generated"),
cl::init(false));
@@ -180,8 +185,8 @@ EnablePIE("enable-pie",
cl::init(false));
cl::opt<bool>
-UseInitArray("use-init-array",
- cl::desc("Use .init_array instead of .ctors."),
+UseCtors("use-ctors",
+ cl::desc("Use .ctors instead of .init_array."),
cl::init(false));
cl::opt<std::string> StopAfter("stop-after",
@@ -217,6 +222,44 @@ JTableType("jump-table-type",
"Create one table per unique function type."),
clEnumValEnd));
+cl::opt<bool>
+FCFI("fcfi",
+ cl::desc("Apply forward-edge control-flow integrity"),
+ cl::init(false));
+
+cl::opt<llvm::CFIntegrity>
+CFIType("cfi-type",
+ cl::desc("Choose the type of Control-Flow Integrity check to add"),
+ cl::init(CFIntegrity::Sub),
+ cl::values(
+ clEnumValN(CFIntegrity::Sub, "sub",
+ "Subtract the pointer from the table base, then mask."),
+ clEnumValN(CFIntegrity::Ror, "ror",
+ "Use rotate to check the offset from a table base."),
+ clEnumValN(CFIntegrity::Add, "add",
+ "Mask out the high bits and add to an aligned base."),
+ clEnumValEnd));
+
+cl::opt<bool>
+CFIEnforcing("cfi-enforcing",
+ cl::desc("Enforce CFI or pass the violation to a function."),
+ cl::init(false));
+
+// Note that this option is linked to the cfi-enforcing option above: if
+// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If
+// cfi-enforcing is false and no cfi-func-name is set, then a default function
+// will be generated that ignores all CFI violations. The expected signature for
+// functions called with CFI violations is
+//
+// void (i8*, i8*)
+//
+// The first pointer is a C string containing the name of the function in which
+// the violation occurs, and the second pointer is the pointer that violated
+// CFI.
+cl::opt<std::string>
+CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"),
+ cl::init(""));
+
// Common utility function tightly tied to the options listed here. Initializes
// a TargetOptions object with CodeGen flags and returns it.
static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
@@ -238,12 +281,18 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
Options.StackAlignmentOverride = OverrideStackAlignment;
Options.TrapFuncName = TrapFuncName;
Options.PositionIndependentExecutable = EnablePIE;
- Options.UseInitArray = UseInitArray;
+ Options.UseInitArray = !UseCtors;
Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections;
Options.MCOptions = InitMCTargetOptionsFromFlags();
Options.JTType = JTableType;
+ Options.FCFI = FCFI;
+ Options.CFIType = CFIType;
+ Options.CFIEnforcing = CFIEnforcing;
+ Options.CFIFuncName = CFIFuncName;
+
+ Options.ThreadModel = TMModel;
return Options;
}
diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h
index 9d25fd377b7e..f9cdc2a469ff 100644
--- a/include/llvm/CodeGen/DFAPacketizer.h
+++ b/include/llvm/CodeGen/DFAPacketizer.h
@@ -91,7 +91,6 @@ public:
// API call is made to prune the dependence.
class VLIWPacketizerList {
protected:
- const TargetMachine &TM;
const MachineFunction &MF;
const TargetInstrInfo *TII;
@@ -107,9 +106,7 @@ protected:
std::map<MachineInstr*, SUnit*> MIToSUnit;
public:
- VLIWPacketizerList(
- MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT,
- bool IsPostRA);
+ VLIWPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI, bool IsPostRA);
virtual ~VLIWPacketizerList();
diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h
new file mode 100644
index 000000000000..e310aef3dcbb
--- /dev/null
+++ b/include/llvm/CodeGen/DIE.h
@@ -0,0 +1,587 @@
+//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Data structures for DWARF info entries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H
+
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Dwarf.h"
+#include <vector>
+
+namespace llvm {
+class AsmPrinter;
+class MCExpr;
+class MCSymbol;
+class raw_ostream;
+class DwarfTypeUnit;
+
+//===--------------------------------------------------------------------===//
+/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a
+/// Dwarf abbreviation.
+class DIEAbbrevData {
+ /// Attribute - Dwarf attribute code.
+ ///
+ dwarf::Attribute Attribute;
+
+ /// Form - Dwarf form code.
+ ///
+ dwarf::Form Form;
+
+public:
+ DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {}
+
+ // Accessors.
+ dwarf::Attribute getAttribute() const { return Attribute; }
+ dwarf::Form getForm() const { return Form; }
+
+ /// Profile - Used to gather unique data for the abbreviation folding set.
+ ///
+ void Profile(FoldingSetNodeID &ID) const;
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug
+/// information object.
+class DIEAbbrev : public FoldingSetNode {
+ /// Unique number for node.
+ ///
+ unsigned Number;
+
+ /// Tag - Dwarf tag code.
+ ///
+ dwarf::Tag Tag;
+
+ /// Children - Whether or not this node has children.
+ ///
+ // This cheats a bit in all of the uses since the values in the standard
+ // are 0 and 1 for no children and children respectively.
+ bool Children;
+
+ /// Data - Raw data bytes for abbreviation.
+ ///
+ SmallVector<DIEAbbrevData, 12> Data;
+
+public:
+ DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {}
+
+ // Accessors.
+ dwarf::Tag getTag() const { return Tag; }
+ unsigned getNumber() const { return Number; }
+ bool hasChildren() const { return Children; }
+ const SmallVectorImpl<DIEAbbrevData> &getData() const { return Data; }
+ void setChildrenFlag(bool hasChild) { Children = hasChild; }
+ void setNumber(unsigned N) { Number = N; }
+
+ /// AddAttribute - Adds another set of attribute information to the
+ /// abbreviation.
+ void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) {
+ Data.push_back(DIEAbbrevData(Attribute, Form));
+ }
+
+ /// Profile - Used to gather unique data for the abbreviation folding set.
+ ///
+ void Profile(FoldingSetNodeID &ID) const;
+
+ /// Emit - Print the abbreviation using the specified asm printer.
+ ///
+ void Emit(AsmPrinter *AP) const;
+
+#ifndef NDEBUG
+ void print(raw_ostream &O);
+ void dump();
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIE - A structured debug information entry. Has an abbreviation which
+/// describes its organization.
+class DIEValue;
+
+class DIE {
+protected:
+ /// Offset - Offset in debug info section.
+ ///
+ unsigned Offset;
+
+ /// Size - Size of instance + children.
+ ///
+ unsigned Size;
+
+ /// Abbrev - Buffer for constructing abbreviation.
+ ///
+ DIEAbbrev Abbrev;
+
+ /// Children DIEs.
+ ///
+ // This can't be a vector<DIE> because pointer validity is requirent for the
+ // Parent pointer and DIEEntry.
+ // It can't be a list<DIE> because some clients need pointer validity before
+ // the object has been added to any child list
+ // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may
+ // be more convoluted than beneficial.
+ std::vector<std::unique_ptr<DIE>> Children;
+
+ DIE *Parent;
+
+ /// Attribute values.
+ ///
+ SmallVector<DIEValue *, 12> Values;
+
+protected:
+ DIE()
+ : Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no),
+ Parent(nullptr) {}
+
+public:
+ explicit DIE(dwarf::Tag Tag)
+ : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no),
+ Parent(nullptr) {}
+
+ // Accessors.
+ DIEAbbrev &getAbbrev() { return Abbrev; }
+ const DIEAbbrev &getAbbrev() const { return Abbrev; }
+ unsigned getAbbrevNumber() const { return Abbrev.getNumber(); }
+ dwarf::Tag getTag() const { return Abbrev.getTag(); }
+ unsigned getOffset() const { return Offset; }
+ unsigned getSize() const { return Size; }
+ const std::vector<std::unique_ptr<DIE>> &getChildren() const {
+ return Children;
+ }
+ const SmallVectorImpl<DIEValue *> &getValues() const { return Values; }
+ DIE *getParent() const { return Parent; }
+ /// Climb up the parent chain to get the compile or type unit DIE this DIE
+ /// belongs to.
+ const DIE *getUnit() const;
+ /// Similar to getUnit, returns null when DIE is not added to an
+ /// owner yet.
+ const DIE *getUnitOrNull() const;
+ void setOffset(unsigned O) { Offset = O; }
+ void setSize(unsigned S) { Size = S; }
+
+ /// addValue - Add a value and attributes to a DIE.
+ ///
+ void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) {
+ Abbrev.AddAttribute(Attribute, Form);
+ Values.push_back(Value);
+ }
+
+ /// addChild - Add a child to the DIE.
+ ///
+ void addChild(std::unique_ptr<DIE> Child) {
+ assert(!Child->getParent());
+ Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
+ Child->Parent = this;
+ Children.push_back(std::move(Child));
+ }
+
+ /// findAttribute - Find a value in the DIE with the attribute given,
+ /// returns NULL if no such attribute exists.
+ DIEValue *findAttribute(dwarf::Attribute Attribute) const;
+
+#ifndef NDEBUG
+ void print(raw_ostream &O, unsigned IndentCount = 0) const;
+ void dump();
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEValue - A debug information entry value. Some of these roughly correlate
+/// to DWARF attribute classes.
+///
+class DIEValue {
+ virtual void anchor();
+
+public:
+ enum Type {
+ isInteger,
+ isString,
+ isExpr,
+ isLabel,
+ isDelta,
+ isEntry,
+ isTypeSignature,
+ isBlock,
+ isLoc,
+ isLocList,
+ };
+
+protected:
+ /// Ty - Type of data stored in the value.
+ ///
+ Type Ty;
+
+ explicit DIEValue(Type T) : Ty(T) {}
+ virtual ~DIEValue() {}
+
+public:
+ // Accessors
+ Type getType() const { return Ty; }
+
+ /// EmitValue - Emit value via the Dwarf writer.
+ ///
+ virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0;
+
+ /// SizeOf - Return the size of a value in bytes.
+ ///
+ virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0;
+
+#ifndef NDEBUG
+ virtual void print(raw_ostream &O) const = 0;
+ void dump() const;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEInteger - An integer value DIE.
+///
+class DIEInteger : public DIEValue {
+ uint64_t Integer;
+
+public:
+ explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
+
+ /// BestForm - Choose the best form for integer.
+ ///
+ static dwarf::Form BestForm(bool IsSigned, uint64_t Int) {
+ if (IsSigned) {
+ const int64_t SignedInt = Int;
+ if ((char)Int == SignedInt)
+ return dwarf::DW_FORM_data1;
+ if ((short)Int == SignedInt)
+ return dwarf::DW_FORM_data2;
+ if ((int)Int == SignedInt)
+ return dwarf::DW_FORM_data4;
+ } else {
+ if ((unsigned char)Int == Int)
+ return dwarf::DW_FORM_data1;
+ if ((unsigned short)Int == Int)
+ return dwarf::DW_FORM_data2;
+ if ((unsigned int)Int == Int)
+ return dwarf::DW_FORM_data4;
+ }
+ return dwarf::DW_FORM_data8;
+ }
+
+ /// EmitValue - Emit integer of appropriate size.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ uint64_t getValue() const { return Integer; }
+
+ /// SizeOf - Determine size of integer value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEExpr - An expression DIE.
+//
+class DIEExpr : public DIEValue {
+ const MCExpr *Expr;
+
+public:
+ explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {}
+
+ /// EmitValue - Emit expression value.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// getValue - Get MCExpr.
+ ///
+ const MCExpr *getValue() const { return Expr; }
+
+ /// SizeOf - Determine size of expression value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isExpr; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIELabel - A label DIE.
+//
+class DIELabel : public DIEValue {
+ const MCSymbol *Label;
+
+public:
+ explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {}
+
+ /// EmitValue - Emit label value.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// getValue - Get MCSymbol.
+ ///
+ const MCSymbol *getValue() const { return Label; }
+
+ /// SizeOf - Determine size of label value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEDelta - A simple label difference DIE.
+///
+class DIEDelta : public DIEValue {
+ const MCSymbol *LabelHi;
+ const MCSymbol *LabelLo;
+
+public:
+ DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo)
+ : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
+
+ /// EmitValue - Emit delta value.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of delta value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *D) { return D->getType() == isDelta; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEString - A container for string values.
+///
+class DIEString : public DIEValue {
+ const DIEValue *Access;
+ StringRef Str;
+
+public:
+ DIEString(const DIEValue *Acc, StringRef S)
+ : DIEValue(isString), Access(Acc), Str(S) {}
+
+ /// getString - Grab the string out of the object.
+ StringRef getString() const { return Str; }
+
+ /// EmitValue - Emit delta value.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of delta value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *D) { return D->getType() == isString; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEEntry - A pointer to another debug information entry. An instance of
+/// this class can also be used as a proxy for a debug information entry not
+/// yet defined (ie. types.)
+class DIEEntry : public DIEValue {
+ DIE &Entry;
+
+public:
+ explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) {
+ }
+
+ DIE &getEntry() const { return Entry; }
+
+ /// EmitValue - Emit debug information entry offset.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of debug information entry in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
+ return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
+ : sizeof(int32_t);
+ }
+
+ /// Returns size of a ref_addr entry.
+ static unsigned getRefAddrSize(AsmPrinter *AP);
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// \brief A signature reference to a type unit.
+class DIETypeSignature : public DIEValue {
+ const DwarfTypeUnit &Unit;
+
+public:
+ explicit DIETypeSignature(const DwarfTypeUnit &Unit)
+ : DIEValue(isTypeSignature), Unit(Unit) {}
+
+ /// \brief Emit type unit signature.
+ void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override;
+
+ /// Returns size of a ref_sig8 entry.
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
+ assert(Form == dwarf::DW_FORM_ref_sig8);
+ return 8;
+ }
+
+ // \brief Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) {
+ return E->getType() == isTypeSignature;
+ }
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+ void dump() const;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIELoc - Represents an expression location.
+//
+class DIELoc : public DIEValue, public DIE {
+ mutable unsigned Size; // Size in bytes excluding size header.
+public:
+ DIELoc() : DIEValue(isLoc), Size(0) {}
+
+ /// ComputeSize - Calculate the size of the location expression.
+ ///
+ unsigned ComputeSize(AsmPrinter *AP) const;
+
+ /// BestForm - Choose the best form for data.
+ ///
+ dwarf::Form BestForm(unsigned DwarfVersion) const {
+ if (DwarfVersion > 3)
+ return dwarf::DW_FORM_exprloc;
+ // Pre-DWARF4 location expressions were blocks and not exprloc.
+ if ((unsigned char)Size == Size)
+ return dwarf::DW_FORM_block1;
+ if ((unsigned short)Size == Size)
+ return dwarf::DW_FORM_block2;
+ if ((unsigned int)Size == Size)
+ return dwarf::DW_FORM_block4;
+ return dwarf::DW_FORM_block;
+ }
+
+ /// EmitValue - Emit location data.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of location data in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isLoc; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEBlock - Represents a block of values.
+//
+class DIEBlock : public DIEValue, public DIE {
+ mutable unsigned Size; // Size in bytes excluding size header.
+public:
+ DIEBlock() : DIEValue(isBlock), Size(0) {}
+
+ /// ComputeSize - Calculate the size of the location expression.
+ ///
+ unsigned ComputeSize(AsmPrinter *AP) const;
+
+ /// BestForm - Choose the best form for data.
+ ///
+ dwarf::Form BestForm() const {
+ if ((unsigned char)Size == Size)
+ return dwarf::DW_FORM_block1;
+ if ((unsigned short)Size == Size)
+ return dwarf::DW_FORM_block2;
+ if ((unsigned int)Size == Size)
+ return dwarf::DW_FORM_block4;
+ return dwarf::DW_FORM_block;
+ }
+
+ /// EmitValue - Emit location data.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of location data in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isBlock; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIELocList - Represents a pointer to a location list in the debug_loc
+/// section.
+//
+class DIELocList : public DIEValue {
+ // Index into the .debug_loc vector.
+ size_t Index;
+
+public:
+ DIELocList(size_t I) : DIEValue(isLocList), Index(I) {}
+
+ /// getValue - Grab the current index out.
+ size_t getValue() const { return Index; }
+
+ /// EmitValue - Emit location data.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of location data in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isLocList; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index 0d1b1dc09560..1dca2ce1ab22 100644
--- a/include/llvm/CodeGen/FastISel.h
+++ b/include/llvm/CodeGen/FastISel.h
@@ -18,72 +18,52 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/Target/TargetLowering.h"
#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/Target/TargetLowering.h"
namespace llvm {
-class AllocaInst;
-class Constant;
-class ConstantFP;
-class CallInst;
-class DataLayout;
-class FunctionLoweringInfo;
-class Instruction;
-class IntrinsicInst;
-class LoadInst;
-class MVT;
-class MachineConstantPool;
-class MachineFrameInfo;
-class MachineFunction;
-class MachineInstr;
-class MachineRegisterInfo;
-class TargetInstrInfo;
-class TargetLibraryInfo;
-class TargetLowering;
-class TargetMachine;
-class TargetRegisterClass;
-class TargetRegisterInfo;
-class User;
-class Value;
-
-/// 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.
+/// \brief 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 {
- public:
+public:
struct ArgListEntry {
Value *Val;
Type *Ty;
- bool isSExt : 1;
- bool isZExt : 1;
- bool isInReg : 1;
- bool isSRet : 1;
- bool isNest : 1;
- bool isByVal : 1;
- bool isInAlloca : 1;
- bool isReturned : 1;
+ bool IsSExt : 1;
+ bool IsZExt : 1;
+ bool IsInReg : 1;
+ bool IsSRet : 1;
+ bool IsNest : 1;
+ bool IsByVal : 1;
+ bool IsInAlloca : 1;
+ bool IsReturned : 1;
uint16_t Alignment;
ArgListEntry()
- : Val(nullptr), Ty(nullptr), isSExt(false), isZExt(false), isInReg(false),
- isSRet(false), isNest(false), isByVal(false), isInAlloca(false),
- isReturned(false), Alignment(0) { }
+ : Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false),
+ IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false),
+ IsInAlloca(false), IsReturned(false), Alignment(0) {}
+ /// \brief Set CallLoweringInfo attribute flags based on a call instruction
+ /// and called function attributes.
void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
};
typedef std::vector<ArgListEntry> ArgListTy;
struct CallLoweringInfo {
Type *RetTy;
- bool RetSExt : 1;
- bool RetZExt : 1;
- bool IsVarArg : 1;
- bool IsInReg : 1;
- bool DoesNotReturn : 1;
+ bool RetSExt : 1;
+ bool RetZExt : 1;
+ bool IsVarArg : 1;
+ bool IsInReg : 1;
+ bool DoesNotReturn : 1;
bool IsReturnValueUsed : 1;
- // IsTailCall should be modified by implementations of
- // FastLowerCall that perform tail call conversions.
+ // \brief IsTailCall Should be modified by implementations of FastLowerCall
+ // that perform tail call conversions.
bool IsTailCall;
unsigned NumFixedArgs;
@@ -96,6 +76,8 @@ class FastISel {
unsigned ResultReg;
unsigned NumResultRegs;
+ bool IsPatchPoint;
+
SmallVector<Value *, 16> OutVals;
SmallVector<ISD::ArgFlagsTy, 16> OutFlags;
SmallVector<unsigned, 16> OutRegs;
@@ -103,12 +85,11 @@ class FastISel {
SmallVector<unsigned, 4> InRegs;
CallLoweringInfo()
- : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),
- IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
- IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C),
- Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr),
- ResultReg(0), NumResultRegs(0)
- {}
+ : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),
+ IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
+ IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C),
+ Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr),
+ ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {}
CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy,
const Value *Target, ArgListTy &&ArgsList,
@@ -124,8 +105,8 @@ class FastISel {
RetZExt = Call.paramHasAttr(0, Attribute::ZExt);
CallConv = Call.getCallingConv();
- NumFixedArgs = FuncTy->getNumParams();
Args = std::move(ArgsList);
+ NumFixedArgs = FuncTy->getNumParams();
CS = &Call;
@@ -148,8 +129,8 @@ class FastISel {
RetZExt = Call.paramHasAttr(0, Attribute::ZExt);
CallConv = Call.getCallingConv();
- NumFixedArgs = (FixedArgs == ~0U) ? FuncTy->getNumParams() : FixedArgs;
Args = std::move(ArgsList);
+ NumFixedArgs = (FixedArgs == ~0U) ? FuncTy->getNumParams() : FixedArgs;
CS = &Call;
@@ -162,8 +143,19 @@ class FastISel {
RetTy = ResultTy;
Callee = Target;
CallConv = CC;
+ Args = std::move(ArgsList);
NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs;
+ return *this;
+ }
+
+ CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy,
+ const char *Target, ArgListTy &&ArgsList,
+ unsigned FixedArgs = ~0U) {
+ RetTy = ResultTy;
+ SymName = Target;
+ CallConv = CC;
Args = std::move(ArgsList);
+ NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs;
return *this;
}
@@ -172,10 +164,13 @@ class FastISel {
return *this;
}
- ArgListTy &getArgs() {
- return Args;
+ CallLoweringInfo &setIsPatchPoint(bool Value = true) {
+ IsPatchPoint = Value;
+ return *this;
}
+ ArgListTy &getArgs() { return Args; }
+
void clearOuts() {
OutVals.clear();
OutFlags.clear();
@@ -202,61 +197,64 @@ protected:
const TargetLowering &TLI;
const TargetRegisterInfo &TRI;
const TargetLibraryInfo *LibInfo;
+ bool SkipTargetIndependentISel;
- /// 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
+ /// \brief The position of the last instruction for materializing constants
+ /// for use in the current block. It resets to EmitStartPt when it makes sense
+ /// (for example, it's usually profitable to avoid function calls between the
/// definition and the use)
MachineInstr *LastLocalValue;
- /// The top most instruction in the current block that is allowed for emitting
- /// local variables. LastLocalValue resets to EmitStartPt when it makes sense
- /// (for example, on function calls)
+ /// \brief The top most instruction in the current block that is allowed for
+ /// emitting local variables. LastLocalValue resets to EmitStartPt when it
+ /// makes sense (for example, on function calls)
MachineInstr *EmitStartPt;
public:
- /// Return the position of the last instruction emitted for materializing
- /// constants for use in the current block.
+ /// \brief Return the position of the last instruction emitted for
+ /// materializing constants for use in the current block.
MachineInstr *getLastLocalValue() { return LastLocalValue; }
- /// Update the position of the last instruction emitted for materializing
- /// constants for use in the current block.
+ /// \brief 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;
}
- /// Set the current block to which generated machine instructions will be
- /// appended, and clear the local CSE map.
+ /// \brief Set the current block to which generated machine instructions will
+ /// be appended, and clear the local CSE map.
void startNewBlock();
- /// Return current debug location information.
+ /// \brief Return current debug location information.
DebugLoc getCurDebugLoc() const { return DbgLoc; }
-
- /// Do "fast" instruction selection for function arguments and append machine
- /// instructions to the current block. Return true if it is successful.
- bool LowerArguments();
- /// Do "fast" instruction selection for the given LLVM IR instruction, and
- /// append generated machine instructions to the current block. Return true if
- /// selection was successful.
- bool SelectInstruction(const Instruction *I);
+ /// \brief Do "fast" instruction selection for function arguments and append
+ /// the machine instructions to the current block. Returns true when
+ /// successful.
+ bool lowerArguments();
- /// Do "fast" instruction selection for the given LLVM IR operator
+ /// \brief 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
/// (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);
+ bool selectOperator(const User *I, unsigned Opcode);
- /// Create a virtual register and arrange for it to be assigned the value for
- /// the given LLVM value.
+ /// \brief Create a virtual register and arrange for it to be assigned the
+ /// value for the given LLVM value.
unsigned getRegForValue(const Value *V);
- /// 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.
+ /// \brief 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);
- /// This is a wrapper around getRegForValue that also takes care of truncating
- /// or sign-extending the given getelementptr index value.
+ /// \brief 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);
/// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note
@@ -284,11 +282,11 @@ public:
return false;
}
- /// Reset InsertPt to prepare for inserting instructions into the current
- /// block.
+ /// \brief Reset InsertPt to prepare for inserting instructions into the
+ /// current block.
void recomputeInsertPt();
- /// Remove all dead instructions between the I and E.
+ /// \brief Remove all dead instructions between the I and E.
void removeDeadCode(MachineBasicBlock::iterator I,
MachineBasicBlock::iterator E);
@@ -297,221 +295,195 @@ public:
DebugLoc DL;
};
- /// Prepare InsertPt to begin inserting instructions into the local value area
- /// and return the old insert position.
+ /// \brief Prepare InsertPt to begin inserting instructions into the local
+ /// value area and return the old insert position.
SavePoint enterLocalValueArea();
- /// Reset InsertPt to the given old insert position.
+ /// \brief Reset InsertPt to the given old insert position.
void leaveLocalValueArea(SavePoint Old);
virtual ~FastISel();
protected:
- explicit FastISel(FunctionLoweringInfo &funcInfo,
- const TargetLibraryInfo *libInfo);
-
- /// This method is called by target-independent code when the normal FastISel
- /// process fails to select an instruction. This gives targets a chance to
- /// emit code for anything that doesn't fit into FastISel's framework. It
- /// returns true if it was successful.
- virtual bool TargetSelectInstruction(const Instruction *I) = 0;
-
- /// 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
+ explicit FastISel(FunctionLoweringInfo &FuncInfo,
+ const TargetLibraryInfo *LibInfo,
+ bool SkipTargetIndependentISel = false);
+
+ /// \brief 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-
+ /// 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-
/// specific call lowering. It returns true if it was successful.
- virtual bool FastLowerCall(CallLoweringInfo &CLI);
+ virtual bool fastLowerCall(CallLoweringInfo &CLI);
- /// \brief This method is called by target-independent code to do target
+ /// \brief 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);
+ virtual bool fastLowerIntrinsicCall(const IntrinsicInst *II);
- /// This method is called by target-independent code to request that an
+ /// \brief 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);
+ virtual unsigned fastEmit_(MVT VT, MVT RetVT, unsigned Opcode);
- /// This method is called by target-independent code to request that an
+ /// \brief 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);
+ virtual unsigned fastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
+ bool Op0IsKill);
- /// This method is called by target-independent code to request that an
+ /// \brief 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);
+ virtual unsigned fastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
+ bool Op0IsKill, unsigned Op1, bool Op1IsKill);
- /// This method is called by target-independent code to request that an
+ /// \brief 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);
+ // operands be emitted.
+ virtual unsigned fastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
+ bool Op0IsKill, uint64_t Imm);
- /// This method is called by target-independent code to request that an
+ /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register and floating-point
/// immediate operands be emitted.
- virtual unsigned FastEmit_rf(MVT VT,
- MVT RetVT,
- unsigned Opcode,
- unsigned Op0, bool Op0IsKill,
- const ConstantFP *FPImm);
+ virtual unsigned fastEmit_rf(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
+ bool Op0IsKill, const ConstantFP *FPImm);
- /// This method is called by target-independent code to request that an
+ /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register and immediate
/// operands be emitted.
- virtual unsigned FastEmit_rri(MVT VT,
- MVT RetVT,
- unsigned Opcode,
- unsigned Op0, bool Op0IsKill,
- unsigned Op1, bool Op1IsKill,
- uint64_t Imm);
-
- /// \brief This method is a wrapper of FastEmit_ri.
- ///
+ virtual unsigned fastEmit_rri(MVT VT, MVT RetVT, unsigned Opcode,
+ unsigned Op0, bool Op0IsKill, unsigned Op1,
+ bool Op1IsKill, uint64_t Imm);
+
+ /// \brief This method is a wrapper of fastEmit_ri.
+ ///
/// It first tries to emit an instruction with an immediate operand using
- /// FastEmit_ri. If that fails, it materializes the immediate into a register
- /// and try FastEmit_rr instead.
- unsigned FastEmit_ri_(MVT VT,
- unsigned Opcode,
- unsigned Op0, bool Op0IsKill,
+ /// fastEmit_ri. If that fails, it materializes the immediate into a register
+ /// and try fastEmit_rr instead.
+ unsigned fastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill,
uint64_t Imm, MVT ImmType);
- /// This method is called by target-independent code to request that an
+ /// \brief 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);
+ virtual unsigned fastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm);
- /// This method is called by target-independent code to request that an
+ /// \brief 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,
+ virtual unsigned fastEmit_f(MVT VT, MVT RetVT, unsigned Opcode,
const ConstantFP *FPImm);
- /// Emit a MachineInstr with no operands and a result register in the given
- /// register class.
- unsigned FastEmitInst_(unsigned MachineInstOpcode,
+ /// \brief Emit a MachineInstr with no operands and a result register in the
+ /// given register class.
+ unsigned fastEmitInst_(unsigned MachineInstOpcode,
const TargetRegisterClass *RC);
- /// 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);
-
- /// 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);
-
- /// 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);
-
- /// Emit a MachineInstr with a register operand, an immediate, and a result
+ /// \brief 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
+ /// 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
/// register in the given register class.
- unsigned FastEmitInst_ri(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0, bool Op0IsKill,
- uint64_t Imm);
-
- /// 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);
-
- /// Emit a MachineInstr with two register operands and a result register in
- /// the given register class.
- unsigned FastEmitInst_rf(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0, bool Op0IsKill,
- const ConstantFP *FPImm);
-
- /// Emit a MachineInstr with two register operands, an immediate, and a result
+ 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
+ /// 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
+ /// operands.
+ unsigned fastEmitInst_rii(unsigned MachineInstOpcode,
+ const TargetRegisterClass *RC, unsigned Op0,
+ bool Op0IsKill, uint64_t Imm1, uint64_t Imm2);
+
+ /// \brief Emit a MachineInstr with two register operands 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,
+ unsigned fastEmitInst_rf(unsigned MachineInstOpcode,
+ const TargetRegisterClass *RC, unsigned Op0,
+ bool Op0IsKill, const ConstantFP *FPImm);
+
+ /// \brief 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);
- /// Emit a MachineInstr with two register operands, two immediates operands,
- /// and a result register in the given register class.
- unsigned FastEmitInst_rrii(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0, bool Op0IsKill,
- unsigned Op1, bool Op1IsKill,
+ /// \brief Emit a MachineInstr with two register operands, two immediates
+ /// operands, and a result register in the given register class.
+ unsigned fastEmitInst_rrii(unsigned MachineInstOpcode,
+ const TargetRegisterClass *RC, unsigned Op0,
+ bool Op0IsKill, unsigned Op1, bool Op1IsKill,
uint64_t Imm1, uint64_t Imm2);
- /// Emit a MachineInstr with a single immediate operand, and a result register
- /// in the given register class.
- unsigned FastEmitInst_i(unsigned MachineInstrOpcode,
- const TargetRegisterClass *RC,
- uint64_t Imm);
-
- /// Emit a MachineInstr with a two immediate operands.
- unsigned FastEmitInst_ii(unsigned MachineInstrOpcode,
- const TargetRegisterClass *RC,
- uint64_t Imm1, uint64_t Imm2);
-
- /// 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,
+ /// \brief Emit a MachineInstr with a single immediate operand, and a result
+ /// register in the given register class.
+ unsigned fastEmitInst_i(unsigned MachineInstrOpcode,
+ const TargetRegisterClass *RC, uint64_t Imm);
+
+ /// \brief Emit a MachineInstr with a two immediate operands.
+ unsigned fastEmitInst_ii(unsigned MachineInstrOpcode,
+ const TargetRegisterClass *RC, uint64_t Imm1,
+ uint64_t Imm2);
+
+ /// \brief 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);
- /// 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 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);
- /// Emit an unconditional branch to the given block, unless it is the
+ /// \brief Emit an unconditional branch to the given block, unless it is the
/// immediate (fall-through) successor, and update the CFG.
- void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL);
+ void fastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL);
- void UpdateValueMap(const Value* I, unsigned Reg, unsigned NumRegs = 1);
+ /// \brief Update the value map to include the new mapping for this
+ /// instruction, or insert an extra copy to get the result in a previous
+ /// determined register.
+ ///
+ /// NOTE: This is only necessary because we might select a block that uses a
+ /// value before we select the block that defines the value. It might be
+ /// possible to fix this by selecting blocks in reverse postorder.
+ void updateValueMap(const Value *I, unsigned Reg, unsigned NumRegs = 1);
unsigned createResultReg(const TargetRegisterClass *RC);
- /// 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.
+ /// \brief 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);
- /// Emit a constant in a register using target-specific logic, such as
+ /// \brief Emit a constant in a register using target-specific logic, such as
/// constant pool loads.
- virtual unsigned TargetMaterializeConstant(const Constant* C) {
- return 0;
- }
+ virtual unsigned fastMaterializeConstant(const Constant *C) { return 0; }
- /// Emit an alloca address in a register using target-specific logic.
- virtual unsigned TargetMaterializeAlloca(const AllocaInst* C) {
- return 0;
- }
+ /// \brief Emit an alloca address in a register using target-specific logic.
+ virtual unsigned fastMaterializeAlloca(const AllocaInst *C) { return 0; }
- virtual unsigned TargetMaterializeFloatZero(const ConstantFP* CF) {
+ /// \brief Emit the floating-point constant +0.0 in a register using target-
+ /// specific logic.
+ virtual unsigned fastMaterializeFloatZero(const ConstantFP *CF) {
return 0;
}
@@ -524,36 +496,46 @@ protected:
/// - \c Add has a constant operand.
bool canFoldAddIntoGEP(const User *GEP, const Value *Add);
- /// Test whether the given value has exactly one use.
- bool hasTrivialKill(const Value *V) const;
+ /// \brief Test whether the given value has exactly one use.
+ bool hasTrivialKill(const Value *V);
/// \brief Create a machine mem operand from the given instruction.
MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const;
- bool LowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs);
- bool LowerCallTo(CallLoweringInfo &CLI);
-
-private:
- bool SelectBinaryOp(const User *I, unsigned ISDOpcode);
-
- bool SelectFNeg(const User *I);
-
- bool SelectGetElementPtr(const User *I);
+ CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) const;
- bool SelectStackmap(const CallInst *I);
- bool SelectPatchpoint(const CallInst *I);
- bool LowerCall(const CallInst *I);
- bool SelectCall(const User *Call);
- bool SelectIntrinsicCall(const IntrinsicInst *II);
+ bool lowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs);
+ bool lowerCallTo(CallLoweringInfo &CLI);
- bool SelectBitCast(const User *I);
-
- bool SelectCast(const User *I, unsigned Opcode);
+ bool isCommutativeIntrinsic(IntrinsicInst const *II) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::sadd_with_overflow:
+ case Intrinsic::uadd_with_overflow:
+ case Intrinsic::smul_with_overflow:
+ case Intrinsic::umul_with_overflow:
+ return true;
+ default:
+ return false;
+ }
+ }
- bool SelectExtractValue(const User *I);
- bool SelectInsertValue(const User *I);
+ bool lowerCall(const CallInst *I);
+ /// \brief 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 selectIntrinsicCall(const IntrinsicInst *II);
+ bool selectBitCast(const User *I);
+ bool selectCast(const User *I, unsigned Opcode);
+ bool selectExtractValue(const User *I);
+ bool selectInsertValue(const User *I);
+private:
/// \brief Handle PHI nodes in successor blocks.
///
/// Emit code to ensure constants are copied into registers when needed.
@@ -561,18 +543,27 @@ private:
/// nodes as input. We cannot just directly add them, because expansion might
/// result in multiple MBB's for one BB. As such, the start of the BB might
/// correspond to a different MBB than the end.
- bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
+ bool handlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
+
+ /// \brief Helper for materializeRegForValue to materialize a constant in a
+ /// target-independent way.
+ unsigned materializeConstant(const Value *V, MVT VT);
- /// Helper for getRegForVale. This function is called when the value isn't
- /// already available in a register and must be materialized with new
+ /// \brief 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);
- /// 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.
+ /// \brief 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 Insertion point before trying to select the current instruction.
+ MachineBasicBlock::iterator SavedInsertPt;
+
+ /// \brief 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);
bool lowerCallOperands(const CallInst *CI, unsigned ArgIdx, unsigned NumArgs,
@@ -580,6 +571,6 @@ private:
CallLoweringInfo &CLI);
};
-}
+} // end namespace llvm
#endif
diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
new file mode 100644
index 000000000000..ec8e2ef243b7
--- /dev/null
+++ b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
@@ -0,0 +1,122 @@
+//===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass instruments indirect calls with checks to ensure that these calls
+// pass through the appropriate jump-instruction table generated by
+// JumpInstrTables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H
+#define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Pass.h"
+#include "llvm/Target/TargetOptions.h"
+#include <string>
+
+namespace llvm {
+
+class AnalysisUsage;
+class BasicBlock;
+class Constant;
+class Function;
+class Instruction;
+class Module;
+class Value;
+
+/// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to
+/// prepend checks to indirect calls to make sure that these calls target valid
+/// locations.
+class ForwardControlFlowIntegrity : public ModulePass {
+public:
+ static char ID;
+
+ ForwardControlFlowIntegrity();
+ ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT,
+ CFIntegrity CFIType,
+ bool CFIEnforcing, std::string CFIFuncName);
+ ~ForwardControlFlowIntegrity() override;
+
+ /// Runs the CFI pass on a given module. This works best if the module in
+ /// question is the result of link-time optimization (see lib/LTO).
+ bool runOnModule(Module &M) override;
+ const char *getPassName() const override {
+ return "Forward Control-Flow Integrity";
+ }
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+private:
+ typedef SmallVector<Instruction *, 64> CallSet;
+
+ /// A structure that is used to keep track of constant table information.
+ struct CFIConstants {
+ Constant *StartValue;
+ Constant *MaskValue;
+ Constant *Size;
+ };
+
+ /// A map from function type to the base of the table for this type and a mask
+ /// for the table
+ typedef DenseMap<FunctionType *, CFIConstants> CFITables;
+
+ CallSet IndirectCalls;
+
+ /// The type of jumptable implementation.
+ JumpTable::JumpTableType JTType;
+
+ /// The type of CFI check to add before each indirect call.
+ CFIntegrity CFIType;
+
+ /// A value that controls whether or not CFI violations cause a halt.
+ bool CFIEnforcing;
+
+ /// The name of the function to call in case of a CFI violation when
+ /// CFIEnforcing is false. There is a default function that ignores
+ /// violations.
+ std::string CFIFuncName;
+
+ /// The alignment of each entry in the table, from JumpInstrTableInfo. The
+ /// JumpInstrTableInfo class always makes this a power of two.
+ uint64_t ByteAlignment;
+
+ /// The base-2 logarithm of ByteAlignment, needed for some of the transforms
+ /// (like CFIntegrity::Ror)
+ unsigned LogByteAlignment;
+
+ /// Adds checks to each indirect call site to make sure that it is calling a
+ /// function in our jump table.
+ void updateIndirectCalls(Module &M, CFITables &CFIT);
+
+ /// Walks the instructions to find all the indirect calls.
+ void getIndirectCalls(Module &M);
+
+ /// Adds a function that handles violations in non-enforcing mode
+ /// (!CFIEnforcing). The default warning function simply returns, since the
+ /// exact details of how to handle CFI violations depend on the application.
+ void addWarningFunction(Module &M);
+
+ /// Rewrites a function pointer in a call/invoke instruction to force it into
+ /// a table.
+ void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr,
+ Constant *JumpTableStart, Constant *JumpTableMask,
+ Constant *JumpTableSize);
+
+ /// Inserts a check and a call to a warning function at a given instruction
+ /// that must be an indirect call.
+ void insertWarning(Module &M, BasicBlock *Block, Instruction *I,
+ Value *FunPtr);
+};
+
+ModulePass *
+createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT,
+ CFIntegrity CFIType,
+ bool CFIEnforcing, StringRef CFIFuncName);
+}
+
+#endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H
diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h
index 9636b51e303d..7c574df4ba41 100644
--- a/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/include/llvm/CodeGen/FunctionLoweringInfo.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instructions.h"
@@ -50,10 +51,10 @@ class Value;
/// function that is used when lowering a region of the function.
///
class FunctionLoweringInfo {
- const TargetMachine &TM;
public:
const Function *Fn;
MachineFunction *MF;
+ const TargetLowering *TLI;
MachineRegisterInfo *RegInfo;
BranchProbabilityInfo *BPI;
/// CanLowerReturn - true iff the function's return value can be lowered to
@@ -87,6 +88,12 @@ public:
/// RegFixups - Registers which need to be replaced after isel is done.
DenseMap<unsigned, unsigned> RegFixups;
+ /// StatepointStackSlots - A list of temporary stack slots (frame indices)
+ /// used to spill values at a statepoint. We store them here to enable
+ /// reuse of the same stack slots across different statepoints in different
+ /// basic blocks.
+ SmallVector<unsigned, 50> StatepointStackSlots;
+
/// MBB - The current block.
MachineBasicBlock *MBB;
@@ -106,6 +113,10 @@ public:
KnownZero(1, 0) {}
};
+ /// Record the preferred extend type (ISD::SIGN_EXTEND or ISD::ZERO_EXTEND)
+ /// for a value.
+ DenseMap<const Value *, ISD::NodeType> PreferredExtendType;
+
/// VisitedBBs - The set of basic blocks visited thus far by instruction
/// selection.
SmallPtrSet<const BasicBlock*, 4> VisitedBBs;
@@ -115,14 +126,13 @@ public:
/// TODO: This isn't per-function state, it's per-basic-block state. But
/// there's no other convenient place for it to live right now.
std::vector<std::pair<MachineInstr*, unsigned> > PHINodesToUpdate;
+ unsigned OrigNumPHINodesToUpdate;
/// If the current MBB is a landing pad, the exception pointer and exception
/// selector registers are copied into these virtual registers by
/// SelectionDAGISel::PrepareEHLandingPad().
unsigned ExceptionPointerVirtReg, ExceptionSelectorVirtReg;
- explicit FunctionLoweringInfo(const TargetMachine &TM) : TM(TM) {}
-
/// set - Initialize this FunctionLoweringInfo with the given Function
/// and its associated MachineFunction.
///
@@ -196,6 +206,9 @@ public:
return;
unsigned Reg = It->second;
+ if (Reg == 0)
+ return;
+
LiveOutRegInfo.grow(Reg);
LiveOutRegInfo[Reg].IsValid = false;
}
diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h
index ddcc823ecd9e..c7f1ab87fcb1 100644
--- a/include/llvm/CodeGen/GCMetadata.h
+++ b/include/llvm/CodeGen/GCMetadata.h
@@ -37,7 +37,6 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
-
#include <memory>
namespace llvm {
@@ -80,8 +79,8 @@ namespace llvm {
};
- /// GCFunctionInfo - Garbage collection metadata for a single function.
- ///
+ /// Garbage collection metadata for a single function. Currently, this
+ /// information only applies to GCStrategies which use GCRoot.
class GCFunctionInfo {
public:
typedef std::vector<GCPoint>::iterator iterator;
@@ -160,21 +159,37 @@ namespace llvm {
size_t live_size(const iterator &p) const { return roots_size(); }
};
-
- /// GCModuleInfo - Garbage collection metadata for a whole module.
- ///
+ /// An analysis pass which caches information about the entire Module.
+ /// Records both the function level information used by GCRoots and a
+ /// cache of the 'active' gc strategy objects for the current Module.
class GCModuleInfo : public ImmutablePass {
typedef StringMap<GCStrategy*> strategy_map_type;
typedef std::vector<std::unique_ptr<GCStrategy>> list_type;
- typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type;
strategy_map_type StrategyMap;
list_type StrategyList;
- finfo_map_type FInfoMap;
GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name);
public:
+ /// List of per function info objects. In theory, Each of these
+ /// may be associated with a different GC.
+ typedef std::vector<std::unique_ptr<GCFunctionInfo>> FuncInfoVec;
+
+ FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); }
+ FuncInfoVec::iterator funcinfo_end() { return Functions.end(); }
+
+
+ private:
+ /// Owning list of all GCFunctionInfos associated with this Module
+ FuncInfoVec Functions;
+
+ /// Non-owning map to bypass linear search when finding the GCFunctionInfo
+ /// associated with a particular Function.
+ typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type;
+ finfo_map_type FInfoMap;
+ public:
+
typedef list_type::const_iterator iterator;
static char ID;
@@ -191,8 +206,9 @@ namespace llvm {
iterator begin() const { return StrategyList.begin(); }
iterator end() const { return StrategyList.end(); }
- /// get - Look up function metadata.
- ///
+ /// get - Look up function metadata. This is currently assumed
+ /// have the side effect of initializing the associated GCStrategy. That
+ /// will soon change.
GCFunctionInfo &getFunctionInfo(const Function &F);
};
diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h
index 4a6b5ac19c36..25fafba93f8b 100644
--- a/include/llvm/CodeGen/GCMetadataPrinter.h
+++ b/include/llvm/CodeGen/GCMetadataPrinter.h
@@ -32,16 +32,11 @@ namespace llvm {
/// defaults from Registry.
typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry;
- /// GCMetadataPrinter - Emits GC metadata as assembly code.
- ///
+ /// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are
+ /// created, managed, and owned by the AsmPrinter.
class GCMetadataPrinter {
- public:
- typedef GCStrategy::list_type list_type;
- typedef GCStrategy::iterator iterator;
-
private:
GCStrategy *S;
-
friend class AsmPrinter;
protected:
@@ -55,16 +50,15 @@ namespace llvm {
public:
GCStrategy &getStrategy() { return *S; }
- const Module &getModule() const { return S->getModule(); }
-
- /// begin/end - Iterate over the collected function metadata.
- iterator begin() { return S->begin(); }
- iterator end() { return S->end(); }
-
- /// beginAssembly/finishAssembly - Emit module metadata as assembly code.
- virtual void beginAssembly(AsmPrinter &AP);
- virtual void finishAssembly(AsmPrinter &AP);
+ /// Called before the assembly for the module is generated by
+ /// the AsmPrinter (but after target specific hooks.)
+ virtual void beginAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {}
+ /// Called after the assembly for the module is generated by
+ /// the AsmPrinter (but before target specific hooks)
+ virtual void finishAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {}
virtual ~GCMetadataPrinter();
};
diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h
index 81e1f85286e1..0b0c3124c537 100644
--- a/include/llvm/CodeGen/GCStrategy.h
+++ b/include/llvm/CodeGen/GCStrategy.h
@@ -12,9 +12,14 @@
// specified in a function's 'gc' attribute. Algorithms are enabled by setting
// flags in a subclass's constructor, and some virtual methods can be
// overridden.
+//
+// GCStrategy is relevant for implementations using either gc.root or
+// gc.statepoint based lowering strategies, but is currently focused mostly on
+// options for gc.root. This will change over time.
//
-// When requested, the GCStrategy will be populated with data about each
-// function which uses it. Specifically:
+// When requested by a subclass of GCStrategy, the gc.root implementation will
+// populate GCModuleInfo and GCFunctionInfo with that about each Function in
+// the Module that opts in to garbage collection. Specifically:
//
// - Safe points
// Garbage collection is generally only possible at certain points in code.
@@ -31,40 +36,42 @@
// This information can used to emit the metadata tables which are required by
// the target garbage collector runtime.
//
+// When used with gc.statepoint, information about safepoint and roots can be
+// found in the binary StackMap section after code generation. Safepoint
+// placement is currently the responsibility of the frontend, though late
+// insertion support is planned. gc.statepoint does not currently support
+// custom stack map formats; such can be generated by parsing the standard
+// stack map section if desired.
+//
+// The read and write barrier support can be used with either implementation.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_GCSTRATEGY_H
#define LLVM_CODEGEN_GCSTRATEGY_H
+#include "llvm/ADT/Optional.h"
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Support/Registry.h"
#include <string>
namespace llvm {
-
- class GCStrategy;
-
- /// The GC strategy registry uses all the defaults from Registry.
- ///
- typedef Registry<GCStrategy> GCRegistry;
-
/// GCStrategy describes a garbage collector algorithm's code generation
/// requirements, and provides overridable hooks for those needs which cannot
- /// be abstractly described.
+ /// be abstractly described. GCStrategy objects currently must be looked up
+ /// through the GCModuleInfo analysis pass. They are owned by the analysis
+ /// pass and recreated every time that pass is invalidated.
class GCStrategy {
- public:
- typedef std::vector<std::unique_ptr<GCFunctionInfo>> list_type;
- typedef list_type::iterator iterator;
-
private:
- friend class GCModuleInfo;
- const Module *M;
std::string Name;
-
- list_type Functions;
+ friend class GCModuleInfo;
protected:
+ bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots,
+ /// if set, none of the other options can be
+ /// anything but their default values.
+
unsigned NeededSafePoints; ///< Bitmask of required safe points.
bool CustomReadBarriers; ///< Default is to insert loads.
bool CustomWriteBarriers; ///< Default is to insert stores.
@@ -76,78 +83,114 @@ namespace llvm {
public:
GCStrategy();
-
virtual ~GCStrategy() {}
-
- /// getName - The name of the GC strategy, for debugging.
- ///
+ /// Return the name of the GC strategy. This is the value of the collector
+ /// name string specified on functions which use this strategy.
const std::string &getName() const { return Name; }
- /// getModule - The module within which the GC strategy is operating.
- ///
- const Module &getModule() const { return *M; }
+ /// By default, write barriers are replaced with simple store
+ /// instructions. If true, then performCustomLowering must instead lower
+ /// them.
+ bool customWriteBarrier() const { return CustomWriteBarriers; }
+
+ /// By default, read barriers are replaced with simple load
+ /// instructions. If true, then performCustomLowering must instead lower
+ /// them.
+ bool customReadBarrier() const { return CustomReadBarriers; }
+
+ /// Returns true if this strategy is expecting the use of gc.statepoints,
+ /// and false otherwise.
+ bool useStatepoints() const { return UseStatepoints; }
+
+ /** @name Statepoint Specific Properties */
+ ///@{
- /// needsSafePoitns - True if safe points of any kind are required. By
- // default, none are recorded.
+ /// If the value specified can be reliably distinguished, returns true for
+ /// pointers to GC managed locations and false for pointers to non-GC
+ /// managed locations. Note a GCStrategy can always return 'None' (i.e. an
+ /// empty optional indicating it can't reliably distinguish.
+ virtual Optional<bool> isGCManagedPointer(const Value *V) const {
+ return None;
+ }
+ ///@}
+
+ /** @name GCRoot Specific Properties
+ * These properties and overrides only apply to collector strategies using
+ * GCRoot.
+ */
+ ///@{
+
+ /// True if safe points of any kind are required. By default, none are
+ /// recorded.
bool needsSafePoints() const {
return CustomSafePoints || NeededSafePoints != 0;
}
- /// needsSafePoint(Kind) - True if the given kind of safe point is
- // required. By default, none are recorded.
+ /// True if the given kind of safe point is required. By default, none are
+ /// recorded.
bool needsSafePoint(GC::PointKind Kind) const {
return (NeededSafePoints & 1 << Kind) != 0;
}
-
- /// customWriteBarrier - By default, write barriers are replaced with simple
- /// store instructions. If true, then
- /// performCustomLowering must instead lower them.
- bool customWriteBarrier() const { return CustomWriteBarriers; }
-
- /// customReadBarrier - By default, read barriers are replaced with simple
- /// load instructions. If true, then
- /// performCustomLowering must instead lower them.
- bool customReadBarrier() const { return CustomReadBarriers; }
-
- /// customRoots - By default, roots are left for the code generator so it
- /// can generate a stack map. If true, then
- // performCustomLowering must delete them.
+
+ /// By default, roots are left for the code generator so it can generate a
+ /// stack map. If true, then performCustomLowering must delete them.
bool customRoots() const { return CustomRoots; }
- /// customSafePoints - By default, the GC analysis will find safe
- /// points according to NeededSafePoints. If true,
- /// then findCustomSafePoints must create them.
+ /// By default, the GC analysis will find safe points according to
+ /// NeededSafePoints. If true, then findCustomSafePoints must create them.
bool customSafePoints() const { return CustomSafePoints; }
- /// initializeRoots - If set, gcroot intrinsics should initialize their
- // allocas to null before the first use. This is
- // necessary for most GCs and is enabled by default.
+ /// If set, gcroot intrinsics should initialize their allocas to null
+ /// before the first use. This is necessary for most GCs and is enabled by
+ /// default.
bool initializeRoots() const { return InitRoots; }
- /// usesMetadata - If set, appropriate metadata tables must be emitted by
- /// the back-end (assembler, JIT, or otherwise).
+ /// If set, appropriate metadata tables must be emitted by the back-end
+ /// (assembler, JIT, or otherwise). For statepoint, this method is
+ /// currently unsupported. The stackmap information can be found in the
+ /// StackMap section as described in the documentation.
bool usesMetadata() const { return UsesMetadata; }
-
- /// begin/end - Iterators for function metadata.
- ///
- iterator begin() { return Functions.begin(); }
- iterator end() { return Functions.end(); }
-
- /// insertFunctionMetadata - Creates metadata for a function.
- ///
- GCFunctionInfo *insertFunctionInfo(const Function &F);
+ ///@}
+
/// initializeCustomLowering/performCustomLowering - If any of the actions
/// are set to custom, performCustomLowering must be overriden to transform
/// the corresponding actions to LLVM IR. initializeCustomLowering is
/// optional to override. These are the only GCStrategy methods through
- /// which the LLVM IR can be modified.
- virtual bool initializeCustomLowering(Module &F);
- virtual bool performCustomLowering(Function &F);
- virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF);
+ /// which the LLVM IR can be modified. These methods apply mostly to
+ /// gc.root based implementations, but can be overriden to provide custom
+ /// barrier lowerings with gc.statepoint as well.
+ ///@{
+ virtual bool initializeCustomLowering(Module &F) {
+ // No changes made
+ return false;
+ }
+ virtual bool performCustomLowering(Function &F) {
+ llvm_unreachable("GCStrategy subclass specified a configuration which"
+ "requires a custom lowering without providing one");
+ }
+ ///@}
+ /// Called if customSafepoints returns true, used only by gc.root
+ /// implementations.
+ virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF) {
+ llvm_unreachable("GCStrategy subclass specified a configuration which"
+ "requests custom safepoint identification without"
+ "providing an implementation for such");
+ }
};
-
+
+ /// Subclasses of GCStrategy are made available for use during compilation by
+ /// adding them to the global GCRegistry. This can done either within the
+ /// LLVM source tree or via a loadable plugin. An example registeration
+ /// would be:
+ /// static GCRegistry::Add<CustomGC> X("custom-name",
+ /// "my custom supper fancy gc strategy");
+ ///
+ /// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also
+ /// register your GCMetadataPrinter subclass with the
+ /// GCMetadataPrinterRegistery as well.
+ typedef Registry<GCStrategy> GCRegistry;
}
#endif
diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h
index bb170c85cbf8..51a31842a5c0 100644
--- a/include/llvm/CodeGen/GCs.h
+++ b/include/llvm/CodeGen/GCs.h
@@ -36,6 +36,8 @@ namespace llvm {
/// Creates a shadow stack garbage collector. This collector requires no code
/// generator support.
void linkShadowStackGC();
+
+ void linkStatepointExampleGC();
}
#endif
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index 84447616c989..952362ed6ce3 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -72,6 +72,11 @@ namespace ISD {
/// the parent's frame or return address, and so on.
FRAMEADDR, RETURNADDR,
+ /// FRAME_ALLOC_RECOVER - Represents the llvm.framerecover
+ /// intrinsic. Materializes the offset from the frame pointer of another
+ /// function to the result of llvm.frameallocate.
+ FRAME_ALLOC_RECOVER,
+
/// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on
/// the DAG, which implements the named register global variables extension.
READ_REGISTER,
@@ -485,7 +490,8 @@ namespace ISD {
FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW,
FLOG, FLOG2, FLOG10, FEXP, FEXP2,
FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR,
-
+ FMINNUM, FMAXNUM,
+
/// FSINCOS - Compute both fsin and fcos as a single operation.
FSINCOS,
@@ -674,6 +680,9 @@ namespace ISD {
ATOMIC_LOAD_UMIN,
ATOMIC_LOAD_UMAX,
+ // Masked load and store
+ MLOAD, MSTORE,
+
/// This corresponds to the llvm.lifetime.* intrinsics. The first operand
/// is the chain and the second operand is the alloca pointer.
LIFETIME_START, LIFETIME_END,
@@ -744,7 +753,7 @@ namespace ISD {
LAST_LOADEXT_TYPE
};
- NodeType getExtForLoadExtType(LoadExtType);
+ NodeType getExtForLoadExtType(bool IsFP, LoadExtType);
//===--------------------------------------------------------------------===//
/// ISD::CondCode enum - These are ordered carefully to make the bitfields
diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h
deleted file mode 100644
index dc2a0272db4e..000000000000
--- a/include/llvm/CodeGen/JITCodeEmitter.h
+++ /dev/null
@@ -1,344 +0,0 @@
-//===-- llvm/CodeGen/JITCodeEmitter.h - Code emission ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines an abstract interface that is used by the machine code
-// emission framework to output the code. This allows machine code emission to
-// be separated from concerns such as resolution of call targets, and where the
-// machine code will be written (memory or disk, f.e.).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_JITCODEEMITTER_H
-#define LLVM_CODEGEN_JITCODEEMITTER_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/CodeGen/MachineCodeEmitter.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/MathExtras.h"
-#include <string>
-
-namespace llvm {
-
-class MachineBasicBlock;
-class MachineConstantPool;
-class MachineJumpTableInfo;
-class MachineFunction;
-class MachineModuleInfo;
-class MachineRelocation;
-class Value;
-class GlobalValue;
-class Function;
-
-/// JITCodeEmitter - This class defines two sorts of methods: those for
-/// emitting the actual bytes of machine code, and those for emitting auxiliary
-/// structures, such as jump tables, relocations, etc.
-///
-/// Emission of machine code is complicated by the fact that we don't (in
-/// general) know the size of the machine code that we're about to emit before
-/// we emit it. As such, we preallocate a certain amount of memory, and set the
-/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we
-/// emit machine instructions, we advance the CurBufferPtr to indicate the
-/// location of the next byte to emit. In the case of a buffer overflow (we
-/// need to emit more machine code than we have allocated space for), the
-/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire
-/// function has been emitted, the overflow condition is checked, and if it has
-/// occurred, more memory is allocated, and we reemit the code into it.
-///
-class JITCodeEmitter : public MachineCodeEmitter {
- void anchor() override;
-public:
- virtual ~JITCodeEmitter() {}
-
- /// startFunction - This callback is invoked when the specified function is
- /// about to be code generated. This initializes the BufferBegin/End/Ptr
- /// fields.
- ///
- void startFunction(MachineFunction &F) override = 0;
-
- /// finishFunction - This callback is invoked when the specified function has
- /// finished code generation. If a buffer overflow has occurred, this method
- /// returns true (the callee is required to try again), otherwise it returns
- /// false.
- ///
- bool finishFunction(MachineFunction &F) override = 0;
-
- /// allocIndirectGV - Allocates and fills storage for an indirect
- /// GlobalValue, and returns the address.
- virtual void *allocIndirectGV(const GlobalValue *GV,
- const uint8_t *Buffer, size_t Size,
- unsigned Alignment) = 0;
-
- /// emitByte - This callback is invoked when a byte needs to be written to the
- /// output stream.
- ///
- void emitByte(uint8_t B) {
- if (CurBufferPtr != BufferEnd)
- *CurBufferPtr++ = B;
- }
-
- /// emitWordLE - This callback is invoked when a 32-bit word needs to be
- /// written to the output stream in little-endian format.
- ///
- void emitWordLE(uint32_t W) {
- if (4 <= BufferEnd-CurBufferPtr) {
- *CurBufferPtr++ = (uint8_t)(W >> 0);
- *CurBufferPtr++ = (uint8_t)(W >> 8);
- *CurBufferPtr++ = (uint8_t)(W >> 16);
- *CurBufferPtr++ = (uint8_t)(W >> 24);
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitWordBE - This callback is invoked when a 32-bit word needs to be
- /// written to the output stream in big-endian format.
- ///
- void emitWordBE(uint32_t W) {
- if (4 <= BufferEnd-CurBufferPtr) {
- *CurBufferPtr++ = (uint8_t)(W >> 24);
- *CurBufferPtr++ = (uint8_t)(W >> 16);
- *CurBufferPtr++ = (uint8_t)(W >> 8);
- *CurBufferPtr++ = (uint8_t)(W >> 0);
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitDWordLE - This callback is invoked when a 64-bit word needs to be
- /// written to the output stream in little-endian format.
- ///
- void emitDWordLE(uint64_t W) {
- if (8 <= BufferEnd-CurBufferPtr) {
- *CurBufferPtr++ = (uint8_t)(W >> 0);
- *CurBufferPtr++ = (uint8_t)(W >> 8);
- *CurBufferPtr++ = (uint8_t)(W >> 16);
- *CurBufferPtr++ = (uint8_t)(W >> 24);
- *CurBufferPtr++ = (uint8_t)(W >> 32);
- *CurBufferPtr++ = (uint8_t)(W >> 40);
- *CurBufferPtr++ = (uint8_t)(W >> 48);
- *CurBufferPtr++ = (uint8_t)(W >> 56);
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitDWordBE - This callback is invoked when a 64-bit word needs to be
- /// written to the output stream in big-endian format.
- ///
- void emitDWordBE(uint64_t W) {
- if (8 <= BufferEnd-CurBufferPtr) {
- *CurBufferPtr++ = (uint8_t)(W >> 56);
- *CurBufferPtr++ = (uint8_t)(W >> 48);
- *CurBufferPtr++ = (uint8_t)(W >> 40);
- *CurBufferPtr++ = (uint8_t)(W >> 32);
- *CurBufferPtr++ = (uint8_t)(W >> 24);
- *CurBufferPtr++ = (uint8_t)(W >> 16);
- *CurBufferPtr++ = (uint8_t)(W >> 8);
- *CurBufferPtr++ = (uint8_t)(W >> 0);
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitAlignment - Move the CurBufferPtr pointer up to the specified
- /// alignment (saturated to BufferEnd of course).
- void emitAlignment(unsigned Alignment) {
- if (Alignment == 0) Alignment = 1;
- uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr,
- Alignment);
- CurBufferPtr = std::min(NewPtr, BufferEnd);
- }
-
- /// emitAlignmentWithFill - Similar to emitAlignment, except that the
- /// extra bytes are filled with the provided byte.
- void emitAlignmentWithFill(unsigned Alignment, uint8_t Fill) {
- if (Alignment == 0) Alignment = 1;
- uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr,
- Alignment);
- // Fail if we don't have room.
- if (NewPtr > BufferEnd) {
- CurBufferPtr = BufferEnd;
- return;
- }
- while (CurBufferPtr < NewPtr) {
- *CurBufferPtr++ = Fill;
- }
- }
-
- /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be
- /// written to the output stream.
- void emitULEB128Bytes(uint64_t Value, unsigned PadTo = 0) {
- do {
- uint8_t Byte = Value & 0x7f;
- Value >>= 7;
- if (Value || PadTo != 0) Byte |= 0x80;
- emitByte(Byte);
- } while (Value);
-
- if (PadTo) {
- do {
- uint8_t Byte = (PadTo > 1) ? 0x80 : 0x0;
- emitByte(Byte);
- } while (--PadTo);
- }
- }
-
- /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be
- /// written to the output stream.
- void emitSLEB128Bytes(int64_t Value) {
- int32_t Sign = Value >> (8 * sizeof(Value) - 1);
- bool IsMore;
-
- do {
- uint8_t Byte = Value & 0x7f;
- Value >>= 7;
- IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
- if (IsMore) Byte |= 0x80;
- emitByte(Byte);
- } while (IsMore);
- }
-
- /// emitString - This callback is invoked when a String needs to be
- /// written to the output stream.
- void emitString(const std::string &String) {
- for (size_t i = 0, N = String.size(); i < N; ++i) {
- uint8_t C = String[i];
- emitByte(C);
- }
- emitByte(0);
- }
-
- /// emitInt32 - Emit a int32 directive.
- void emitInt32(uint32_t Value) {
- if (4 <= BufferEnd-CurBufferPtr) {
- *((uint32_t*)CurBufferPtr) = Value;
- CurBufferPtr += 4;
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitInt64 - Emit a int64 directive.
- void emitInt64(uint64_t Value) {
- if (8 <= BufferEnd-CurBufferPtr) {
- *((uint64_t*)CurBufferPtr) = Value;
- CurBufferPtr += 8;
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitInt32At - Emit the Int32 Value in Addr.
- void emitInt32At(uintptr_t *Addr, uintptr_t Value) {
- if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd)
- (*(uint32_t*)Addr) = (uint32_t)Value;
- }
-
- /// emitInt64At - Emit the Int64 Value in Addr.
- void emitInt64At(uintptr_t *Addr, uintptr_t Value) {
- if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd)
- (*(uint64_t*)Addr) = (uint64_t)Value;
- }
-
-
- /// emitLabel - Emits a label
- void emitLabel(MCSymbol *Label) override = 0;
-
- /// allocateSpace - Allocate a block of space in the current output buffer,
- /// returning null (and setting conditions to indicate buffer overflow) on
- /// failure. Alignment is the alignment in bytes of the buffer desired.
- void *allocateSpace(uintptr_t Size, unsigned Alignment) override {
- emitAlignment(Alignment);
- void *Result;
-
- // Check for buffer overflow.
- if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) {
- CurBufferPtr = BufferEnd;
- Result = nullptr;
- } else {
- // Allocate the space.
- Result = CurBufferPtr;
- CurBufferPtr += Size;
- }
-
- return Result;
- }
-
- /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace,
- /// this method does not allocate memory in the current output buffer,
- /// because a global may live longer than the current function.
- virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0;
-
- /// StartMachineBasicBlock - This should be called by the target when a new
- /// basic block is about to be emitted. This way the MCE knows where the
- /// start of the block is, and can implement getMachineBasicBlockAddress.
- void StartMachineBasicBlock(MachineBasicBlock *MBB) override = 0;
-
- /// getCurrentPCValue - This returns the address that the next emitted byte
- /// will be output to.
- ///
- uintptr_t getCurrentPCValue() const override {
- return (uintptr_t)CurBufferPtr;
- }
-
- /// getCurrentPCOffset - Return the offset from the start of the emitted
- /// buffer that we are currently writing to.
- uintptr_t getCurrentPCOffset() const override {
- return CurBufferPtr-BufferBegin;
- }
-
- /// earlyResolveAddresses - True if the code emitter can use symbol addresses
- /// during code emission time. The JIT is capable of doing this because it
- /// creates jump tables or constant pools in memory on the fly while the
- /// object code emitters rely on a linker to have real addresses and should
- /// use relocations instead.
- bool earlyResolveAddresses() const override { return true; }
-
- /// addRelocation - Whenever a relocatable address is needed, it should be
- /// noted with this interface.
- void addRelocation(const MachineRelocation &MR) override = 0;
-
- /// FIXME: These should all be handled with relocations!
-
- /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in
- /// the constant pool that was last emitted with the emitConstantPool method.
- ///
- uintptr_t getConstantPoolEntryAddress(unsigned Index) const override = 0;
-
- /// getJumpTableEntryAddress - Return the address of the jump table with index
- /// 'Index' in the function that last called initJumpTableInfo.
- ///
- uintptr_t getJumpTableEntryAddress(unsigned Index) const override = 0;
-
- /// getMachineBasicBlockAddress - Return the address of the specified
- /// MachineBasicBlock, only usable after the label for the MBB has been
- /// emitted.
- ///
- uintptr_t
- getMachineBasicBlockAddress(MachineBasicBlock *MBB) const override = 0;
-
- /// getLabelAddress - Return the address of the specified Label, only usable
- /// after the Label has been emitted.
- ///
- uintptr_t getLabelAddress(MCSymbol *Label) const override = 0;
-
- /// Specifies the MachineModuleInfo object. This is used for exception handling
- /// purposes.
- void setModuleInfo(MachineModuleInfo* Info) override = 0;
-
- /// getLabelLocations - Return the label locations map of the label IDs to
- /// their address.
- virtual DenseMap<MCSymbol*, uintptr_t> *getLabelLocations() {
- return nullptr;
- }
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/CodeGen/JumpInstrTables.h b/include/llvm/CodeGen/JumpInstrTables.h
index 6ca3d7d1765f..005bc1eb2b2d 100644
--- a/include/llvm/CodeGen/JumpInstrTables.h
+++ b/include/llvm/CodeGen/JumpInstrTables.h
@@ -39,13 +39,14 @@ class Module;
/// jmp f_orig@PLT
/// \endverbatim
///
-/// Support for an architecture depends on two functions in TargetInstrInfo:
-/// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the
-/// appropriate instructions for the jump statement (an unconditional branch)
-/// and for padding to make the table have a size that is a power of two. This
-/// padding uses a trap instruction to ensure that calls to this area halt the
-/// program. The default implementations of these functions call
-/// llvm_unreachable.
+/// Support for an architecture depends on three functions in TargetInstrInfo:
+/// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter
+/// uses these to generate the appropriate instructions for the jump statement
+/// (an unconditional branch) and for padding to make the table have a size that
+/// is a power of two. This padding uses a trap instruction to ensure that calls
+/// to this area halt the program. The default implementations of these
+/// functions call llvm_unreachable, except for getJumpInstrTableEntryBound,
+/// which returns 0 by default.
class JumpInstrTables : public ModulePass {
public:
static char ID;
@@ -64,6 +65,14 @@ public:
/// Checks to see if there is already a table for the given FunctionType.
bool hasTable(FunctionType *FunTy);
+ /// Maps the function into a subset of function types, depending on the
+ /// jump-instruction table style selected from JumpTableTypes in
+ /// JumpInstrTables.cpp. The choice of mapping determines the number of
+ /// jump-instruction tables generated by this pass. E.g., the simplest mapping
+ /// converts every function type into void f(); so, all functions end up in a
+ /// single table.
+ static FunctionType *transformType(JumpTable::JumpTableType JTT,
+ FunctionType *FunTy);
private:
/// The metadata used while a jump table is being built
struct TableMeta {
@@ -76,14 +85,6 @@ private:
typedef DenseMap<FunctionType *, struct TableMeta> JumpMap;
- /// Maps the function into a subset of function types, depending on the
- /// jump-instruction table style selected from JumpTableTypes in
- /// JumpInstrTables.cpp. The choice of mapping determines the number of
- /// jump-instruction tables generated by this pass. E.g., the simplest mapping
- /// converts every function type into void f(); so, all functions end up in a
- /// single table.
- FunctionType *transformType(FunctionType *FunTy);
-
/// The current state of functions and jump entries in the table(s).
JumpMap Metadata;
diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h
index 036aea30a510..11a360a491a7 100644
--- a/include/llvm/CodeGen/LexicalScopes.h
+++ b/include/llvm/CodeGen/LexicalScopes.h
@@ -19,14 +19,14 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/ValueHandle.h"
-#include <utility>
#include <unordered_map>
+#include <utility>
namespace llvm {
class MachineInstr;
@@ -48,6 +48,8 @@ public:
LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A)
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A),
LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) {
+ assert((!D || D->isResolved()) && "Expected resolved node");
+ assert((!I || I->isResolved()) && "Expected resolved node");
if (Parent)
Parent->addChild(this);
}
@@ -116,8 +118,8 @@ public:
private:
LexicalScope *Parent; // Parent to this scope.
- AssertingVH<const MDNode> Desc; // Debug info descriptor.
- AssertingVH<const MDNode> InlinedAtLocation; // Location at which this
+ const MDNode *Desc; // Debug info descriptor.
+ const MDNode *InlinedAtLocation; // Location at which this
// scope is inlined.
bool AbstractScope; // Abstract Scope
SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope.
@@ -148,12 +150,6 @@ public:
/// empty - Return true if there is any lexical scope information available.
bool empty() { return CurrentFnLexicalScope == nullptr; }
- /// isCurrentFunctionScope - Return true if given lexical scope represents
- /// current function.
- bool isCurrentFunctionScope(const LexicalScope *LS) {
- return LS == CurrentFnLexicalScope;
- }
-
/// getCurrentFunctionScope - Return lexical scope for the current function.
LexicalScope *getCurrentFunctionScope() const {
return CurrentFnLexicalScope;
@@ -163,7 +159,7 @@ public:
/// which have machine instructions that belong to lexical scope identified by
/// DebugLoc.
void getMachineBasicBlocks(DebugLoc DL,
- SmallPtrSet<const MachineBasicBlock *, 4> &MBBs);
+ SmallPtrSetImpl<const MachineBasicBlock *> &MBBs);
/// dominates - Return true if DebugLoc's lexical scope dominates at least one
/// machine instruction's lexical scope in a given machine basic block.
diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h
index 372c294da306..e7ccbfa617e5 100644
--- a/include/llvm/CodeGen/LinkAllCodegenComponents.h
+++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h
@@ -39,6 +39,7 @@ namespace {
llvm::linkOcamlGC();
llvm::linkErlangGC();
llvm::linkShadowStackGC();
+ llvm::linkStatepointExampleGC();
(void) llvm::createBURRListDAGScheduler(nullptr,
llvm::CodeGenOpt::Default);
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index 6629e6046532..ce9845ee1673 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/include/llvm/CodeGen/LiveInterval.h
@@ -119,6 +119,12 @@ namespace llvm {
return isDeadDef() ? nullptr : LateVal;
}
+ /// Returns the value alive at the end of the instruction, if any. This can
+ /// be a live-through value, a live def or a dead def.
+ VNInfo *valueOutOrDead() const {
+ return LateVal;
+ }
+
/// Return the value defined by this instruction, if any. This includes
/// dead defs, it is the value created by the instruction's def operands.
VNInfo *valueDefined() const {
@@ -204,6 +210,23 @@ namespace llvm {
const_vni_iterator vni_begin() const { return valnos.begin(); }
const_vni_iterator vni_end() const { return valnos.end(); }
+ /// Constructs a new LiveRange object.
+ LiveRange() {
+ }
+
+ /// Constructs a new LiveRange object by copying segments and valnos from
+ /// another LiveRange.
+ LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) {
+ // Duplicate valnos.
+ for (const VNInfo *VNI : Other.valnos) {
+ createValueCopy(VNI, Allocator);
+ }
+ // Now we can copy segments and remap their valnos.
+ for (const Segment &S : Other.segments) {
+ segments.push_back(Segment(S.start, S.end, valnos[S.valno->id]));
+ }
+ }
+
/// advanceTo - Advance the specified iterator to point to the Segment
/// containing the specified position, or end() if the position is past the
/// end of the range. If no Segment contains this position, but the
@@ -217,6 +240,14 @@ namespace llvm {
return I;
}
+ const_iterator advanceTo(const_iterator I, SlotIndex Pos) const {
+ assert(I != end());
+ if (Pos >= endIndex())
+ return end();
+ while (I->end <= Pos) ++I;
+ return I;
+ }
+
/// find - Return an iterator pointing to the first segment that ends after
/// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster
/// when searching large ranges.
@@ -397,6 +428,12 @@ namespace llvm {
/// scanning the Other range starting at I.
bool overlapsFrom(const LiveRange &Other, const_iterator I) const;
+ /// Returns true if all segments of the @p Other live range are completely
+ /// covered by this live range.
+ /// Adjacent live ranges do not affect the covering:the liverange
+ /// [1,5](5,10] covers (3,7].
+ bool covers(const LiveRange &Other) const;
+
/// Add the specified Segment to this range, merging segments as
/// appropriate. This returns an iterator to the inserted segment (which
/// may have grown since it was inserted).
@@ -435,6 +472,12 @@ namespace llvm {
removeSegment(S.start, S.end, RemoveDeadValNo);
}
+ /// Remove segment pointed to by iterator @p I from this range. This does
+ /// not remove dead value numbers.
+ iterator removeSegment(iterator I) {
+ return segments.erase(I);
+ }
+
/// Query Liveness at Idx.
/// The sub-instruction slot of Idx doesn't matter, only the instruction
/// it refers to is considered.
@@ -484,9 +527,9 @@ namespace llvm {
/// Returns true if the live range is zero length, i.e. no live segments
/// span instructions. It doesn't pay to spill such a range.
bool isZeroLength(SlotIndexes *Indexes) const {
- for (const_iterator i = begin(), e = end(); i != e; ++i)
- if (Indexes->getNextNonNullIndex(i->start).getBaseIndex() <
- i->end.getBaseIndex())
+ for (const Segment &S : segments)
+ if (Indexes->getNextNonNullIndex(S.start).getBaseIndex() <
+ S.end.getBaseIndex())
return false;
return true;
}
@@ -509,6 +552,10 @@ namespace llvm {
void verify() const;
#endif
+ protected:
+ /// Append a segment to the list of segments.
+ void append(const LiveRange::Segment S);
+
private:
iterator addSegmentFrom(Segment S, iterator From);
@@ -529,11 +576,122 @@ namespace llvm {
public:
typedef LiveRange super;
+ /// A live range for subregisters. The LaneMask specifies which parts of the
+ /// super register are covered by the interval.
+ /// (@sa TargetRegisterInfo::getSubRegIndexLaneMask()).
+ class SubRange : public LiveRange {
+ public:
+ SubRange *Next;
+ unsigned LaneMask;
+
+ /// Constructs a new SubRange object.
+ SubRange(unsigned LaneMask)
+ : Next(nullptr), LaneMask(LaneMask) {
+ }
+
+ /// Constructs a new SubRange object by copying liveness from @p Other.
+ SubRange(unsigned LaneMask, const LiveRange &Other,
+ BumpPtrAllocator &Allocator)
+ : LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) {
+ }
+ };
+
+ private:
+ SubRange *SubRanges; ///< Single linked list of subregister live ranges.
+
+ public:
const unsigned reg; // the register or stack slot of this interval.
float weight; // weight of this interval
LiveInterval(unsigned Reg, float Weight)
- : reg(Reg), weight(Weight) {}
+ : SubRanges(nullptr), reg(Reg), weight(Weight) {}
+
+ template<typename T>
+ class SingleLinkedListIterator {
+ T *P;
+ public:
+ SingleLinkedListIterator<T>(T *P) : P(P) {}
+ SingleLinkedListIterator<T> &operator++() {
+ P = P->Next;
+ return *this;
+ }
+ SingleLinkedListIterator<T> &operator++(int) {
+ SingleLinkedListIterator res = *this;
+ ++*this;
+ return res;
+ }
+ bool operator!=(const SingleLinkedListIterator<T> &Other) {
+ return P != Other.operator->();
+ }
+ bool operator==(const SingleLinkedListIterator<T> &Other) {
+ return P == Other.operator->();
+ }
+ T &operator*() const {
+ return *P;
+ }
+ T *operator->() const {
+ return P;
+ }
+ };
+
+ typedef SingleLinkedListIterator<SubRange> subrange_iterator;
+ subrange_iterator subrange_begin() {
+ return subrange_iterator(SubRanges);
+ }
+ subrange_iterator subrange_end() {
+ return subrange_iterator(nullptr);
+ }
+
+ typedef SingleLinkedListIterator<const SubRange> const_subrange_iterator;
+ const_subrange_iterator subrange_begin() const {
+ return const_subrange_iterator(SubRanges);
+ }
+ const_subrange_iterator subrange_end() const {
+ return const_subrange_iterator(nullptr);
+ }
+
+ iterator_range<subrange_iterator> subranges() {
+ return make_range(subrange_begin(), subrange_end());
+ }
+
+ iterator_range<const_subrange_iterator> subranges() const {
+ return make_range(subrange_begin(), subrange_end());
+ }
+
+ /// Creates a new empty subregister live range. The range is added at the
+ /// beginning of the subrange list; subrange iterators stay valid.
+ SubRange *createSubRange(BumpPtrAllocator &Allocator, unsigned LaneMask) {
+ SubRange *Range = new (Allocator) SubRange(LaneMask);
+ appendSubRange(Range);
+ return Range;
+ }
+
+ /// Like createSubRange() but the new range is filled with a copy of the
+ /// liveness information in @p CopyFrom.
+ SubRange *createSubRangeFrom(BumpPtrAllocator &Allocator, unsigned LaneMask,
+ const LiveRange &CopyFrom) {
+ SubRange *Range = new (Allocator) SubRange(LaneMask, CopyFrom, Allocator);
+ appendSubRange(Range);
+ return Range;
+ }
+
+ /// Returns true if subregister liveness information is available.
+ bool hasSubRanges() const {
+ return SubRanges != nullptr;
+ }
+
+ /// Removes all subregister liveness information.
+ void clearSubRanges() {
+ SubRanges = nullptr;
+ }
+
+ /// Removes all subranges without any segments (subranges without segments
+ /// are not considered valid and should only exist temporarily).
+ void removeEmptySubRanges();
+
+ /// Construct main live range by merging the SubRanges of @p LI.
+ void constructMainRangeFromSubranges(const SlotIndexes &Indexes,
+ VNInfo::Allocator &VNIAllocator);
/// getSize - Returns the sum of sizes of all the LiveRange's.
///
@@ -558,9 +716,23 @@ namespace llvm {
void print(raw_ostream &OS) const;
void dump() const;
+ /// \brief Walks the interval and assert if any invariants fail to hold.
+ ///
+ /// Note that this is a no-op when asserts are disabled.
+#ifdef NDEBUG
+ void verify(const MachineRegisterInfo *MRI = nullptr) const {}
+#else
+ void verify(const MachineRegisterInfo *MRI = nullptr) const;
+#endif
+
private:
LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION;
+ /// Appends @p Range to SubRanges list.
+ void appendSubRange(SubRange *Range) {
+ Range->Next = SubRanges;
+ SubRanges = Range;
+ }
};
inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) {
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index 176665bc2566..d8c921fce313 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -17,8 +17,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H
-#define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H
+#ifndef LLVM_CODEGEN_LIVEINTERVALANALYSIS_H
+#define LLVM_CODEGEN_LIVEINTERVALANALYSIS_H
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
@@ -50,7 +50,6 @@ namespace llvm {
class LiveIntervals : public MachineFunctionPass {
MachineFunction* MF;
MachineRegisterInfo* MRI;
- const TargetMachine* TM;
const TargetRegisterInfo* TRI;
const TargetInstrInfo* TII;
AliasAnalysis *AA;
@@ -155,16 +154,11 @@ namespace llvm {
bool shrinkToUses(LiveInterval *li,
SmallVectorImpl<MachineInstr*> *dead = nullptr);
- /// \brief Walk the values in the given interval and compute which ones
- /// are dead. Dead values are not deleted, however:
- /// - Dead PHIDef values are marked as unused.
- /// - New dead machine instructions are added to the dead vector.
- /// - CanSeparate is set to true if the interval may have been separated
- /// into multiple connected components.
- void computeDeadValues(LiveInterval *li,
- LiveRange &LR,
- bool *CanSeparate,
- SmallVectorImpl<MachineInstr*> *dead);
+ /// Specialized version of
+ /// shrinkToUses(LiveInterval *li, SmallVectorImpl<MachineInstr*> *dead)
+ /// that works on a subregister live range and only looks at uses matching
+ /// the lane mask of the subregister range.
+ void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg);
/// extendToIndices - Extend the live range of LI to reach all points in
/// Indices. The points in the Indices array must be jointly dominated by
@@ -176,14 +170,21 @@ namespace llvm {
/// See also LiveRangeCalc::extend().
void extendToIndices(LiveRange &LR, ArrayRef<SlotIndex> Indices);
- /// pruneValue - If an LI value is live at Kill, prune its live range by
- /// removing any liveness reachable from Kill. Add live range end points to
+
+ /// If @p LR has a live value at @p Kill, prune its live range by removing
+ /// any liveness reachable from Kill. Add live range end points to
/// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the
/// value's live range.
///
/// Calling pruneValue() and extendToIndices() can be used to reconstruct
/// SSA form after adding defs to a virtual register.
- void pruneValue(LiveInterval *LI, SlotIndex Kill,
+ void pruneValue(LiveRange &LR, SlotIndex Kill,
+ SmallVectorImpl<SlotIndex> *EndPoints);
+
+ /// Subregister aware variant of pruneValue(LiveRange &LR, SlotIndex Kill,
+ /// SmallVectorImpl<SlotIndex> &EndPoints). Prunes the value in the main
+ /// range and all sub ranges.
+ void pruneValue(LiveInterval &LI, SlotIndex Kill,
SmallVectorImpl<SlotIndex> *EndPoints);
SlotIndexes *getSlotIndexes() const {
@@ -405,6 +406,16 @@ namespace llvm {
/// Compute RegMaskSlots and RegMaskBits.
void computeRegMasks();
+ /// Walk the values in @p LI and check for dead values:
+ /// - Dead PHIDef values are marked as unused.
+ /// - Dead operands are marked as such.
+ /// - Completely dead machine instructions are added to the @p dead vector
+ /// if it is not nullptr.
+ /// Returns true if any PHI value numbers have been removed which may
+ /// have separated the interval into multiple connected components.
+ bool computeDeadValues(LiveInterval &LI,
+ SmallVectorImpl<MachineInstr*> *dead);
+
static LiveInterval* createInterval(unsigned Reg);
void printInstrs(raw_ostream &O) const;
@@ -414,6 +425,16 @@ namespace llvm {
void computeRegUnitRange(LiveRange&, unsigned Unit);
void computeVirtRegInterval(LiveInterval&);
+
+ /// Helper function for repairIntervalsInRange(), walks backwards and
+ /// creates/modifies live segments in @p LR to match the operands found.
+ /// Only full operands or operands with subregisters matching @p LaneMask
+ /// are considered.
+ void repairOldRegInRange(MachineBasicBlock::iterator Begin,
+ MachineBasicBlock::iterator End,
+ const SlotIndex endIdx, LiveRange &LR,
+ unsigned Reg, unsigned LaneMask = ~0u);
+
class HMEditor;
};
} // End llvm namespace
diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h
index 2f40509a1111..1381c46a2750 100644
--- a/include/llvm/CodeGen/LiveIntervalUnion.h
+++ b/include/llvm/CodeGen/LiveIntervalUnion.h
@@ -84,10 +84,16 @@ public:
bool changedSince(unsigned tag) const { return tag != Tag; }
// Add a live virtual register to this union and merge its segments.
- void unify(LiveInterval &VirtReg);
+ void unify(LiveInterval &VirtReg, const LiveRange &Range);
+ void unify(LiveInterval &VirtReg) {
+ unify(VirtReg, VirtReg);
+ }
// Remove a live virtual register's segments from this union.
- void extract(LiveInterval &VirtReg);
+ void extract(LiveInterval &VirtReg, const LiveRange &Range);
+ void extract(LiveInterval &VirtReg) {
+ extract(VirtReg, VirtReg);
+ }
// Remove all inserted virtual registers.
void clear() { Segments.clear(); ++Tag; }
diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h
index 847092b1d824..91e4ddcde170 100644
--- a/include/llvm/CodeGen/LivePhysRegs.h
+++ b/include/llvm/CodeGen/LivePhysRegs.h
@@ -26,8 +26,8 @@
// %XMM0<def> = ..., %YMM0<imp-use> (%YMM0 and all its sub-registers are alive)
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_LIVE_PHYS_REGS_H
-#define LLVM_CODEGEN_LIVE_PHYS_REGS_H
+#ifndef LLVM_CODEGEN_LIVEPHYSREGS_H
+#define LLVM_CODEGEN_LIVEPHYSREGS_H
#include "llvm/ADT/SparseSet.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
@@ -143,4 +143,4 @@ inline raw_ostream &operator<<(raw_ostream &OS, const LivePhysRegs& LR) {
} // namespace llvm
-#endif // LLVM_CODEGEN_LIVE_PHYS_REGS_H
+#endif
diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h
index 5767cab1a4db..44c3c4eaf7b1 100644
--- a/include/llvm/CodeGen/LiveRangeEdit.h
+++ b/include/llvm/CodeGen/LiveRangeEdit.h
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
namespace llvm {
@@ -111,18 +112,15 @@ public:
/// @param vrm Map of virtual registers to physical registers for this
/// function. If NULL, no virtual register map updates will
/// be done. This could be the case if called before Regalloc.
- LiveRangeEdit(LiveInterval *parent,
- SmallVectorImpl<unsigned> &newRegs,
- MachineFunction &MF,
- LiveIntervals &lis,
- VirtRegMap *vrm,
+ LiveRangeEdit(LiveInterval *parent, SmallVectorImpl<unsigned> &newRegs,
+ MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm,
Delegate *delegate = nullptr)
- : Parent(parent), NewRegs(newRegs),
- MRI(MF.getRegInfo()), LIS(lis), VRM(vrm),
- TII(*MF.getTarget().getInstrInfo()),
- TheDelegate(delegate),
- FirstNew(newRegs.size()),
- ScannedRemattable(false) { MRI.setDelegate(this); }
+ : Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis),
+ VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()),
+ TheDelegate(delegate), FirstNew(newRegs.size()),
+ ScannedRemattable(false) {
+ MRI.setDelegate(this);
+ }
~LiveRangeEdit() { MRI.resetDelegate(this); }
diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h
index a4a5fcc31e12..55b97dc3e71d 100644
--- a/include/llvm/CodeGen/LiveVariables.h
+++ b/include/llvm/CodeGen/LiveVariables.h
@@ -134,14 +134,14 @@ private: // Intermediate data structures
// PhysRegInfo - Keep track of which instruction was the last def of a
// physical register. This is a purely local property, because all physical
// register references are presumed dead across basic blocks.
- MachineInstr **PhysRegDef;
+ std::vector<MachineInstr *> PhysRegDef;
// PhysRegInfo - Keep track of which instruction was the last use of a
// physical register. This is a purely local property, because all physical
// register references are presumed dead across basic blocks.
- MachineInstr **PhysRegUse;
+ std::vector<MachineInstr *> PhysRegUse;
- SmallVector<unsigned, 4> *PHIVarInfo;
+ std::vector<SmallVector<unsigned, 4>> PHIVarInfo;
// DistanceMap - Keep track the distance of a MI from the start of the
// current basic block.
@@ -175,6 +175,10 @@ private: // Intermediate data structures
/// register which is used in a PHI node. We map that to the BB the vreg
/// is coming from.
void analyzePHINodes(const MachineFunction& Fn);
+
+ void runOnInstr(MachineInstr *MI, SmallVectorImpl<unsigned> &Defs);
+
+ void runOnBlock(MachineBasicBlock *MBB, unsigned NumRegs);
public:
bool runOnMachineFunction(MachineFunction &MF) override;
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index a08cc2eb508a..1440b967aea2 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -486,11 +486,15 @@ public:
/// Insert a range of instructions into the instruction list before I.
template<typename IT>
void insert(iterator I, IT S, IT E) {
+ assert((I == end() || I->getParent() == this) &&
+ "iterator points outside of basic block");
Insts.insert(I.getInstrIterator(), S, E);
}
/// Insert MI into the instruction list before I.
iterator insert(iterator I, MachineInstr *MI) {
+ assert((I == end() || I->getParent() == this) &&
+ "iterator points outside of basic block");
assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() &&
"Cannot insert instruction with bundle flags");
return Insts.insert(I.getInstrIterator(), MI);
@@ -498,6 +502,8 @@ public:
/// Insert MI into the instruction list after I.
iterator insertAfter(iterator I, MachineInstr *MI) {
+ assert((I == end() || I->getParent() == this) &&
+ "iterator points outside of basic block");
assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() &&
"Cannot insert instruction with bundle flags");
return Insts.insertAfter(I.getInstrIterator(), MI);
diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h
deleted file mode 100644
index 81b0ba1e7c71..000000000000
--- a/include/llvm/CodeGen/MachineCodeEmitter.h
+++ /dev/null
@@ -1,334 +0,0 @@
-//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines an abstract interface that is used by the machine code
-// emission framework to output the code. This allows machine code emission to
-// be separated from concerns such as resolution of call targets, and where the
-// machine code will be written (memory or disk, f.e.).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H
-#define LLVM_CODEGEN_MACHINECODEEMITTER_H
-
-#include "llvm/IR/DebugLoc.h"
-#include "llvm/Support/DataTypes.h"
-#include <string>
-
-namespace llvm {
-
-class MachineBasicBlock;
-class MachineConstantPool;
-class MachineJumpTableInfo;
-class MachineFunction;
-class MachineModuleInfo;
-class MachineRelocation;
-class Value;
-class GlobalValue;
-class Function;
-class MCSymbol;
-
-/// MachineCodeEmitter - This class defines two sorts of methods: those for
-/// emitting the actual bytes of machine code, and those for emitting auxiliary
-/// structures, such as jump tables, relocations, etc.
-///
-/// Emission of machine code is complicated by the fact that we don't (in
-/// general) know the size of the machine code that we're about to emit before
-/// we emit it. As such, we preallocate a certain amount of memory, and set the
-/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we
-/// emit machine instructions, we advance the CurBufferPtr to indicate the
-/// location of the next byte to emit. In the case of a buffer overflow (we
-/// need to emit more machine code than we have allocated space for), the
-/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire
-/// function has been emitted, the overflow condition is checked, and if it has
-/// occurred, more memory is allocated, and we reemit the code into it.
-///
-class MachineCodeEmitter {
- virtual void anchor();
-protected:
- /// BufferBegin/BufferEnd - Pointers to the start and end of the memory
- /// allocated for this code buffer.
- uint8_t *BufferBegin, *BufferEnd;
- /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting
- /// code. This is guaranteed to be in the range [BufferBegin,BufferEnd]. If
- /// this pointer is at BufferEnd, it will never move due to code emission, and
- /// all code emission requests will be ignored (this is the buffer overflow
- /// condition).
- uint8_t *CurBufferPtr;
-
-public:
- virtual ~MachineCodeEmitter() {}
-
- /// startFunction - This callback is invoked when the specified function is
- /// about to be code generated. This initializes the BufferBegin/End/Ptr
- /// fields.
- ///
- virtual void startFunction(MachineFunction &F) = 0;
-
- /// finishFunction - This callback is invoked when the specified function has
- /// finished code generation. If a buffer overflow has occurred, this method
- /// returns true (the callee is required to try again), otherwise it returns
- /// false.
- ///
- virtual bool finishFunction(MachineFunction &F) = 0;
-
- /// emitByte - This callback is invoked when a byte needs to be written to the
- /// output stream.
- ///
- void emitByte(uint8_t B) {
- if (CurBufferPtr != BufferEnd)
- *CurBufferPtr++ = B;
- }
-
- /// emitWordLE - This callback is invoked when a 32-bit word needs to be
- /// written to the output stream in little-endian format.
- ///
- void emitWordLE(uint32_t W) {
- if (4 <= BufferEnd-CurBufferPtr) {
- emitWordLEInto(CurBufferPtr, W);
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitWordLEInto - This callback is invoked when a 32-bit word needs to be
- /// written to an arbitrary buffer in little-endian format. Buf must have at
- /// least 4 bytes of available space.
- ///
- static void emitWordLEInto(uint8_t *&Buf, uint32_t W) {
- *Buf++ = (uint8_t)(W >> 0);
- *Buf++ = (uint8_t)(W >> 8);
- *Buf++ = (uint8_t)(W >> 16);
- *Buf++ = (uint8_t)(W >> 24);
- }
-
- /// emitWordBE - This callback is invoked when a 32-bit word needs to be
- /// written to the output stream in big-endian format.
- ///
- void emitWordBE(uint32_t W) {
- if (4 <= BufferEnd-CurBufferPtr) {
- *CurBufferPtr++ = (uint8_t)(W >> 24);
- *CurBufferPtr++ = (uint8_t)(W >> 16);
- *CurBufferPtr++ = (uint8_t)(W >> 8);
- *CurBufferPtr++ = (uint8_t)(W >> 0);
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitDWordLE - This callback is invoked when a 64-bit word needs to be
- /// written to the output stream in little-endian format.
- ///
- void emitDWordLE(uint64_t W) {
- if (8 <= BufferEnd-CurBufferPtr) {
- *CurBufferPtr++ = (uint8_t)(W >> 0);
- *CurBufferPtr++ = (uint8_t)(W >> 8);
- *CurBufferPtr++ = (uint8_t)(W >> 16);
- *CurBufferPtr++ = (uint8_t)(W >> 24);
- *CurBufferPtr++ = (uint8_t)(W >> 32);
- *CurBufferPtr++ = (uint8_t)(W >> 40);
- *CurBufferPtr++ = (uint8_t)(W >> 48);
- *CurBufferPtr++ = (uint8_t)(W >> 56);
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitDWordBE - This callback is invoked when a 64-bit word needs to be
- /// written to the output stream in big-endian format.
- ///
- void emitDWordBE(uint64_t W) {
- if (8 <= BufferEnd-CurBufferPtr) {
- *CurBufferPtr++ = (uint8_t)(W >> 56);
- *CurBufferPtr++ = (uint8_t)(W >> 48);
- *CurBufferPtr++ = (uint8_t)(W >> 40);
- *CurBufferPtr++ = (uint8_t)(W >> 32);
- *CurBufferPtr++ = (uint8_t)(W >> 24);
- *CurBufferPtr++ = (uint8_t)(W >> 16);
- *CurBufferPtr++ = (uint8_t)(W >> 8);
- *CurBufferPtr++ = (uint8_t)(W >> 0);
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitAlignment - Move the CurBufferPtr pointer up to the specified
- /// alignment (saturated to BufferEnd of course).
- void emitAlignment(unsigned Alignment) {
- if (Alignment == 0) Alignment = 1;
-
- if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) {
- // Move the current buffer ptr up to the specified alignment.
- CurBufferPtr =
- (uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) &
- ~(uintptr_t)(Alignment-1));
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
-
- /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be
- /// written to the output stream.
- void emitULEB128Bytes(uint64_t Value) {
- do {
- uint8_t Byte = Value & 0x7f;
- Value >>= 7;
- if (Value) Byte |= 0x80;
- emitByte(Byte);
- } while (Value);
- }
-
- /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be
- /// written to the output stream.
- void emitSLEB128Bytes(uint64_t Value) {
- uint64_t Sign = Value >> (8 * sizeof(Value) - 1);
- bool IsMore;
-
- do {
- uint8_t Byte = Value & 0x7f;
- Value >>= 7;
- IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
- if (IsMore) Byte |= 0x80;
- emitByte(Byte);
- } while (IsMore);
- }
-
- /// emitString - This callback is invoked when a String needs to be
- /// written to the output stream.
- void emitString(const std::string &String) {
- for (unsigned i = 0, N = static_cast<unsigned>(String.size());
- i < N; ++i) {
- uint8_t C = String[i];
- emitByte(C);
- }
- emitByte(0);
- }
-
- /// emitInt32 - Emit a int32 directive.
- void emitInt32(int32_t Value) {
- if (4 <= BufferEnd-CurBufferPtr) {
- *((uint32_t*)CurBufferPtr) = Value;
- CurBufferPtr += 4;
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitInt64 - Emit a int64 directive.
- void emitInt64(uint64_t Value) {
- if (8 <= BufferEnd-CurBufferPtr) {
- *((uint64_t*)CurBufferPtr) = Value;
- CurBufferPtr += 8;
- } else {
- CurBufferPtr = BufferEnd;
- }
- }
-
- /// emitInt32At - Emit the Int32 Value in Addr.
- void emitInt32At(uintptr_t *Addr, uintptr_t Value) {
- if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd)
- (*(uint32_t*)Addr) = (uint32_t)Value;
- }
-
- /// emitInt64At - Emit the Int64 Value in Addr.
- void emitInt64At(uintptr_t *Addr, uintptr_t Value) {
- if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd)
- (*(uint64_t*)Addr) = (uint64_t)Value;
- }
-
- /// processDebugLoc - Records debug location information about a
- /// MachineInstruction. This is called before emitting any bytes associated
- /// with the instruction. Even if successive instructions have the same debug
- /// location, this method will be called for each one.
- virtual void processDebugLoc(DebugLoc DL, bool BeforePrintintInsn) {}
-
- /// emitLabel - Emits a label
- virtual void emitLabel(MCSymbol *Label) = 0;
-
- /// allocateSpace - Allocate a block of space in the current output buffer,
- /// returning null (and setting conditions to indicate buffer overflow) on
- /// failure. Alignment is the alignment in bytes of the buffer desired.
- virtual void *allocateSpace(uintptr_t Size, unsigned Alignment) {
- emitAlignment(Alignment);
- void *Result;
-
- // Check for buffer overflow.
- if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) {
- CurBufferPtr = BufferEnd;
- Result = nullptr;
- } else {
- // Allocate the space.
- Result = CurBufferPtr;
- CurBufferPtr += Size;
- }
-
- return Result;
- }
-
- /// StartMachineBasicBlock - This should be called by the target when a new
- /// basic block is about to be emitted. This way the MCE knows where the
- /// start of the block is, and can implement getMachineBasicBlockAddress.
- virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0;
-
- /// getCurrentPCValue - This returns the address that the next emitted byte
- /// will be output to.
- ///
- virtual uintptr_t getCurrentPCValue() const {
- return (uintptr_t)CurBufferPtr;
- }
-
- /// getCurrentPCOffset - Return the offset from the start of the emitted
- /// buffer that we are currently writing to.
- virtual uintptr_t getCurrentPCOffset() const {
- return CurBufferPtr-BufferBegin;
- }
-
- /// earlyResolveAddresses - True if the code emitter can use symbol addresses
- /// during code emission time. The JIT is capable of doing this because it
- /// creates jump tables or constant pools in memory on the fly while the
- /// object code emitters rely on a linker to have real addresses and should
- /// use relocations instead.
- virtual bool earlyResolveAddresses() const = 0;
-
- /// addRelocation - Whenever a relocatable address is needed, it should be
- /// noted with this interface.
- virtual void addRelocation(const MachineRelocation &MR) = 0;
-
- /// FIXME: These should all be handled with relocations!
-
- /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in
- /// the constant pool that was last emitted with the emitConstantPool method.
- ///
- virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const = 0;
-
- /// getJumpTableEntryAddress - Return the address of the jump table with index
- /// 'Index' in the function that last called initJumpTableInfo.
- ///
- virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const = 0;
-
- /// getMachineBasicBlockAddress - Return the address of the specified
- /// MachineBasicBlock, only usable after the label for the MBB has been
- /// emitted.
- ///
- virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0;
-
- /// getLabelAddress - Return the address of the specified Label, only usable
- /// after the LabelID has been emitted.
- ///
- virtual uintptr_t getLabelAddress(MCSymbol *Label) const = 0;
-
- /// Specifies the MachineModuleInfo object. This is used for exception handling
- /// purposes.
- virtual void setModuleInfo(MachineModuleInfo* Info) = 0;
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/CodeGen/MachineCodeInfo.h b/include/llvm/CodeGen/MachineCodeInfo.h
deleted file mode 100644
index 820bc87425b9..000000000000
--- a/include/llvm/CodeGen/MachineCodeInfo.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===-- MachineCodeInfo.h - Class used to report JIT info -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines MachineCodeInfo, a class used by the JIT ExecutionEngine
-// to report information about the generated machine code.
-//
-// See JIT::runJITOnFunction for usage.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_MACHINECODEINFO_H
-#define LLVM_CODEGEN_MACHINECODEINFO_H
-
-#include "llvm/Support/DataTypes.h"
-
-namespace llvm {
-
-class MachineCodeInfo {
-private:
- size_t Size; // Number of bytes in memory used
- void *Address; // The address of the function in memory
-
-public:
- MachineCodeInfo() : Size(0), Address(nullptr) {}
-
- void setSize(size_t s) {
- Size = s;
- }
-
- void setAddress(void *a) {
- Address = a;
- }
-
- size_t size() const {
- return Size;
- }
-
- void *address() const {
- return Address;
- }
-
-};
-
-}
-
-#endif
-
diff --git a/include/llvm/CodeGen/MachineCombinerPattern.h b/include/llvm/CodeGen/MachineCombinerPattern.h
new file mode 100644
index 000000000000..176af14dc317
--- /dev/null
+++ b/include/llvm/CodeGen/MachineCombinerPattern.h
@@ -0,0 +1,29 @@
+//===-- llvm/CodeGen/MachineCombinerPattern.h - Instruction pattern supported by
+// combiner ------*- 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 instruction pattern supported by combiner
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINECOMBINERPATTERN_H
+#define LLVM_CODEGEN_MACHINECOMBINERPATTERN_H
+
+namespace llvm {
+
+/// Enumeration of instruction pattern supported by machine combiner
+///
+///
+namespace MachineCombinerPattern {
+// Forward declaration
+enum MC_PATTERN : int;
+} // end namespace MachineCombinerPattern
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h
index f1ae0bf5f9cf..a6980a6daeac 100644
--- a/include/llvm/CodeGen/MachineDominators.h
+++ b/include/llvm/CodeGen/MachineDominators.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H
#define LLVM_CODEGEN_MACHINEDOMINATORS_H
+#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -38,6 +39,103 @@ typedef DomTreeNodeBase<MachineBasicBlock> MachineDomTreeNode;
/// compute a normal dominator tree.
///
class MachineDominatorTree : public MachineFunctionPass {
+ /// \brief Helper structure used to hold all the basic blocks
+ /// involved in the split of a critical edge.
+ struct CriticalEdge {
+ MachineBasicBlock *FromBB;
+ MachineBasicBlock *ToBB;
+ MachineBasicBlock *NewBB;
+ CriticalEdge(MachineBasicBlock *FromBB, MachineBasicBlock *ToBB,
+ MachineBasicBlock *NewBB)
+ : FromBB(FromBB), ToBB(ToBB), NewBB(NewBB) {}
+ };
+
+ /// \brief 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
+ /// edge splitting.
+ /// Invariant: NewBBs == all the basic blocks contained in the NewBB
+ /// field of all the elements of CriticalEdgesToSplit.
+ /// I.e., forall elt in CriticalEdgesToSplit, it exists BB in NewBBs
+ /// such as BB == elt.NewBB.
+ mutable SmallSet<MachineBasicBlock *, 32> NewBBs;
+
+ /// \brief 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.
+ ///
+ /// \post CriticalEdgesToSplit.empty().
+ void applySplitCriticalEdges() const {
+ // Bail out early if there is nothing to do.
+ if (CriticalEdgesToSplit.empty())
+ return;
+
+ // For each element in CriticalEdgesToSplit, remember whether or
+ // not element is the new immediate domminator of its successor.
+ // The mapping is done by index, i.e., the information for the ith
+ // element of CriticalEdgesToSplit is the ith element of IsNewIDom.
+ SmallVector<bool, 32> IsNewIDom;
+ IsNewIDom.resize(CriticalEdgesToSplit.size());
+ size_t Idx = 0;
+
+ // Collect all the dominance properties info, before invalidating
+ // the underlying DT.
+ for (CriticalEdge &Edge : CriticalEdgesToSplit) {
+ // Update dominator information.
+ MachineBasicBlock *Succ = Edge.ToBB;
+ MachineDomTreeNode *SucccDTNode = DT->getNode(Succ);
+
+ IsNewIDom[Idx] = true;
+ for (MachineBasicBlock *PredBB : Succ->predecessors()) {
+ if (PredBB == Edge.NewBB)
+ continue;
+ // If we are in this situation:
+ // FromBB1 FromBB2
+ // + +
+ // + + + +
+ // + + + +
+ // ... Split1 Split2 ...
+ // + +
+ // + +
+ // +
+ // Succ
+ // Instead of checking the domiance property with Split2, we
+ // check it with FromBB2 since Split2 is still unknown of the
+ // underlying DT structure.
+ if (NewBBs.count(PredBB)) {
+ assert(PredBB->pred_size() == 1 && "A basic block resulting from a "
+ "critical edge split has more "
+ "than one predecessor!");
+ PredBB = *PredBB->pred_begin();
+ }
+ if (!DT->dominates(SucccDTNode, DT->getNode(PredBB))) {
+ IsNewIDom[Idx] = false;
+ break;
+ }
+ }
+ ++Idx;
+ }
+
+ // Now, update DT with the collected dominance properties info.
+ Idx = 0;
+ for (CriticalEdge &Edge : CriticalEdgesToSplit) {
+ // We know FromBB dominates NewBB.
+ MachineDomTreeNode *NewDTNode = DT->addNewBlock(Edge.NewBB, Edge.FromBB);
+ MachineDomTreeNode *SucccDTNode = DT->getNode(Edge.ToBB);
+
+ // If all the other predecessors of "Succ" are dominated by "Succ" itself
+ // then the new block is the new immediate dominator of "Succ". Otherwise,
+ // the new block doesn't dominate anything.
+ if (IsNewIDom[Idx])
+ DT->changeImmediateDominator(SucccDTNode, NewDTNode);
+ ++Idx;
+ }
+ NewBBs.clear();
+ CriticalEdgesToSplit.clear();
+ }
+
public:
static char ID; // Pass ID, replacement for typeid
DominatorTreeBase<MachineBasicBlock>* DT;
@@ -46,7 +144,10 @@ public:
~MachineDominatorTree();
- DominatorTreeBase<MachineBasicBlock>& getBase() { return *DT; }
+ DominatorTreeBase<MachineBasicBlock> &getBase() {
+ applySplitCriticalEdges();
+ return *DT;
+ }
void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -55,14 +156,17 @@ public:
/// dominators, this will always be a single block (the entry node).
///
inline const std::vector<MachineBasicBlock*> &getRoots() const {
+ applySplitCriticalEdges();
return DT->getRoots();
}
inline MachineBasicBlock *getRoot() const {
+ applySplitCriticalEdges();
return DT->getRoot();
}
inline MachineDomTreeNode *getRootNode() const {
+ applySplitCriticalEdges();
return DT->getRootNode();
}
@@ -70,17 +174,20 @@ public:
inline bool dominates(const MachineDomTreeNode* A,
const MachineDomTreeNode* B) const {
+ applySplitCriticalEdges();
return DT->dominates(A, B);
}
inline bool dominates(const MachineBasicBlock* A,
const MachineBasicBlock* B) const {
+ applySplitCriticalEdges();
return DT->dominates(A, B);
}
// dominates - Return true if A dominates B. This performs the
// special checks necessary if A and B are in the same basic block.
bool dominates(const MachineInstr *A, const MachineInstr *B) const {
+ applySplitCriticalEdges();
const MachineBasicBlock *BBA = A->getParent(), *BBB = B->getParent();
if (BBA != BBB) return DT->dominates(BBA, BBB);
@@ -100,11 +207,13 @@ public:
inline bool properlyDominates(const MachineDomTreeNode* A,
const MachineDomTreeNode* B) const {
+ applySplitCriticalEdges();
return DT->properlyDominates(A, B);
}
inline bool properlyDominates(const MachineBasicBlock* A,
const MachineBasicBlock* B) const {
+ applySplitCriticalEdges();
return DT->properlyDominates(A, B);
}
@@ -112,10 +221,12 @@ public:
/// for basic block A and B. If there is no such block then return NULL.
inline MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A,
MachineBasicBlock *B) {
+ applySplitCriticalEdges();
return DT->findNearestCommonDominator(A, B);
}
inline MachineDomTreeNode *operator[](MachineBasicBlock *BB) const {
+ applySplitCriticalEdges();
return DT->getNode(BB);
}
@@ -123,6 +234,7 @@ public:
/// block. This is the same as using operator[] on this class.
///
inline MachineDomTreeNode *getNode(MachineBasicBlock *BB) const {
+ applySplitCriticalEdges();
return DT->getNode(BB);
}
@@ -131,6 +243,7 @@ public:
/// the children list of the immediate dominator.
inline MachineDomTreeNode *addNewBlock(MachineBasicBlock *BB,
MachineBasicBlock *DomBB) {
+ applySplitCriticalEdges();
return DT->addNewBlock(BB, DomBB);
}
@@ -139,11 +252,13 @@ public:
///
inline void changeImmediateDominator(MachineBasicBlock *N,
MachineBasicBlock* NewIDom) {
+ applySplitCriticalEdges();
DT->changeImmediateDominator(N, NewIDom);
}
inline void changeImmediateDominator(MachineDomTreeNode *N,
MachineDomTreeNode* NewIDom) {
+ applySplitCriticalEdges();
DT->changeImmediateDominator(N, NewIDom);
}
@@ -151,24 +266,49 @@ public:
/// dominate any other blocks. Removes node from its immediate dominator's
/// children list. Deletes dominator node associated with basic block BB.
inline void eraseNode(MachineBasicBlock *BB) {
+ applySplitCriticalEdges();
DT->eraseNode(BB);
}
/// splitBlock - BB is split and now it has one successor. Update dominator
/// tree to reflect this change.
inline void splitBlock(MachineBasicBlock* NewBB) {
+ applySplitCriticalEdges();
DT->splitBlock(NewBB);
}
/// isReachableFromEntry - Return true if A is dominated by the entry
/// block of the function containing it.
bool isReachableFromEntry(const MachineBasicBlock *A) {
+ applySplitCriticalEdges();
return DT->isReachableFromEntry(A);
}
void releaseMemory() override;
void print(raw_ostream &OS, const Module*) const override;
+
+ /// \brief 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
+ /// number of time the DT information is invalidated.
+ ///
+ /// \note Do not use this method with regular edges.
+ ///
+ /// \note To benefit from the compile time improvement incurred by this
+ /// method, the users of this method have to limit the queries to the DT
+ /// interface between two edges splitting. In other words, they have to
+ /// pack the splitting of critical edges as much as possible.
+ void recordSplitCriticalEdge(MachineBasicBlock *FromBB,
+ MachineBasicBlock *ToBB,
+ MachineBasicBlock *NewBB) {
+ bool Inserted = NewBBs.insert(NewBB).second;
+ (void)Inserted;
+ assert(Inserted &&
+ "A basic block inserted via edge splitting cannot appear twice");
+ CriticalEdgesToSplit.push_back(CriticalEdge(FromBB, ToBB, NewBB));
+ }
};
//===-------------------------------------
diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h
index c51f8fe03bbf..667736021f92 100644
--- a/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/include/llvm/CodeGen/MachineFrameInfo.h
@@ -109,13 +109,23 @@ class MachineFrameInfo {
// block and doesn't need additional handling for allocation beyond that.
bool PreAllocated;
+ // If true, an LLVM IR value might point to this object.
+ // Normally, spill slots and fixed-offset objects don't alias IR-accessible
+ // objects, but there are exceptions (on PowerPC, for example, some byval
+ // arguments have ABI-prescribed offsets).
+ bool isAliased;
+
StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM,
- bool isSS, const AllocaInst *Val)
+ bool isSS, const AllocaInst *Val, bool A)
: SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM),
- isSpillSlot(isSS), Alloca(Val), PreAllocated(false) {}
+ isSpillSlot(isSS), Alloca(Val), PreAllocated(false), isAliased(A) {}
};
- const TargetMachine &TM;
+ /// StackAlignment - The alignment of the stack.
+ unsigned StackAlignment;
+
+ /// StackRealignable - Can the stack be realigned.
+ bool StackRealignable;
/// Objects - The list of stack objects allocated...
///
@@ -230,10 +240,17 @@ class MachineFrameInfo {
/// pointer.
bool HasInlineAsmWithSPAdjust;
- const TargetFrameLowering *getFrameLowering() const;
+ /// True if the function contains a call to the llvm.vastart intrinsic.
+ bool HasVAStart;
+
+ /// True if this is a varargs function that contains a musttail call.
+ bool HasMustTailInVarArgFunc;
+
public:
- explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt)
- : TM(TM), RealignOption(RealignOpt) {
+ explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign,
+ bool RealignOpt)
+ : StackAlignment(StackAlign), StackRealignable(isStackRealign),
+ RealignOption(RealignOpt) {
StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0;
HasVarSizedObjects = false;
FrameAddressTaken = false;
@@ -250,6 +267,8 @@ public:
LocalFrameMaxAlign = 0;
UseLocalStackAllocationBlock = false;
HasInlineAsmWithSPAdjust = false;
+ HasVAStart = false;
+ HasMustTailInVarArgFunc = false;
}
/// hasStackObjects - Return true if there are any stack objects in this
@@ -469,6 +488,14 @@ public:
bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; }
void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; }
+ /// Returns true if the function calls the llvm.va_start intrinsic.
+ bool hasVAStart() const { return HasVAStart; }
+ void setHasVAStart(bool B) { HasVAStart = B; }
+
+ /// Returns true if the function is variadic and contains a musttail call.
+ bool hasMustTailInVarArgFunc() const { return HasMustTailInVarArgFunc; }
+ void setHasMustTailInVarArgFunc(bool B) { HasMustTailInVarArgFunc = B; }
+
/// getMaxCallFrameSize - Return the maximum size of a call frame that must be
/// allocated for an outgoing function call. This is only available if
/// CallFrameSetup/Destroy pseudo instructions are used by the target, and
@@ -479,21 +506,34 @@ public:
/// CreateFixedObject - Create a new object at a fixed location on the stack.
/// All fixed objects should be created before other objects are created for
- /// efficiency. By default, fixed objects are immutable. This returns an
- /// index with a negative value.
+ /// efficiency. By default, fixed objects are not pointed to by LLVM IR
+ /// values. This returns an index with a negative value.
///
- int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable);
+ int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable,
+ bool isAliased = false);
/// CreateFixedSpillStackObject - Create a spill slot at a fixed location
/// on the stack. Returns an index with a negative value.
int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset);
+ /// Allocates memory at a fixed, target-specific offset from the frame
+ /// pointer. Marks the function as having its frame address taken.
+ int CreateFrameAllocation(uint64_t Size);
+
/// isFixedObjectIndex - Returns true if the specified index corresponds to a
/// fixed stack object.
bool isFixedObjectIndex(int ObjectIdx) const {
return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects);
}
+ /// isAliasedObjectIndex - Returns true if the specified index corresponds
+ /// to an object that might be pointed to by an LLVM IR value.
+ bool isAliasedObjectIndex(int ObjectIdx) const {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ return Objects[ObjectIdx+NumFixedObjects].isAliased;
+ }
+
/// isImmutableObjectIndex - Returns true if the specified index corresponds
/// to an immutable object.
bool isImmutableObjectIndex(int ObjectIdx) const {
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index 042c62b4a887..4e9ff9ebb4fe 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/ilist.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ArrayRecycler.h"
#include "llvm/Support/Recycler.h"
@@ -38,6 +39,7 @@ class MachineModuleInfo;
class MCContext;
class Pass;
class TargetMachine;
+class TargetSubtargetInfo;
class TargetRegisterClass;
struct MachinePointerInfo;
@@ -70,15 +72,24 @@ private:
/// MachineFunction is destroyed.
struct MachineFunctionInfo {
virtual ~MachineFunctionInfo();
+
+ /// \brief Factory function: default behavior is to call new using the
+ /// supplied allocator.
+ ///
+ /// This function can be overridden in a derive class.
+ template<typename Ty>
+ static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) {
+ return new (Allocator.Allocate<Ty>()) Ty(MF);
+ }
};
class MachineFunction {
const Function *Fn;
const TargetMachine &Target;
+ const TargetSubtargetInfo *STI;
MCContext &Ctx;
MachineModuleInfo &MMI;
- GCModuleInfo *GMI;
-
+
// RegInfo - Information about each register in use in the function.
MachineRegisterInfo *RegInfo;
@@ -138,12 +149,10 @@ class MachineFunction {
void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION;
public:
MachineFunction(const Function *Fn, const TargetMachine &TM,
- unsigned FunctionNum, MachineModuleInfo &MMI,
- GCModuleInfo* GMI);
+ unsigned FunctionNum, MachineModuleInfo &MMI);
~MachineFunction();
MachineModuleInfo &getMMI() const { return MMI; }
- GCModuleInfo *getGMI() const { return GMI; }
MCContext &getContext() const { return Ctx; }
/// getFunction - Return the LLVM function that this machine code represents
@@ -162,6 +171,11 @@ public:
///
const TargetMachine &getTarget() const { return Target; }
+ /// getSubtarget - Return the subtarget for which this machine code is being
+ /// compiled.
+ const TargetSubtargetInfo &getSubtarget() const { return *STI; }
+ void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; }
+
/// getRegInfo - Return information about the registers currently in use.
///
MachineRegisterInfo &getRegInfo() { return *RegInfo; }
@@ -234,7 +248,7 @@ public:
template<typename Ty>
Ty *getInfo() {
if (!MFInfo)
- MFInfo = new (Allocator.Allocate<Ty>()) Ty(*this);
+ MFInfo = Ty::template create<Ty>(Allocator, *this);
return static_cast<Ty*>(MFInfo);
}
@@ -399,7 +413,7 @@ public:
MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo,
unsigned f, uint64_t s,
unsigned base_alignment,
- const MDNode *TBAAInfo = nullptr,
+ const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
/// getMachineMemOperand - Allocate a new MachineMemOperand by copying
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index 3c828116411e..bcf1f5caaa8c 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -244,12 +244,22 @@ public:
///
DebugLoc getDebugLoc() const { return debugLoc; }
- /// getDebugVariable() - Return the debug variable referenced by
+ /// \brief Return the debug variable referenced by
/// this DBG_VALUE instruction.
DIVariable getDebugVariable() const {
assert(isDebugValue() && "not a DBG_VALUE");
- const MDNode *Var = getOperand(getNumOperands() - 1).getMetadata();
- return DIVariable(Var);
+ DIVariable Var(getOperand(2).getMetadata());
+ assert(Var.Verify() && "not a DIVariable");
+ return Var;
+ }
+
+ /// \brief Return the complex address expression referenced by
+ /// this DBG_VALUE instruction.
+ DIExpression getDebugExpression() const {
+ assert(isDebugValue() && "not a DBG_VALUE");
+ DIExpression Expr(getOperand(3).getMetadata());
+ assert(Expr.Verify() && "not a DIExpression");
+ return Expr;
}
/// emitError - Emit an error referring to the source location of this
@@ -510,6 +520,49 @@ public:
return hasProperty(MCID::FoldableAsLoad, Type);
}
+ /// \brief Return true if this instruction behaves
+ /// the same way as the generic REG_SEQUENCE instructions.
+ /// E.g., on ARM,
+ /// dX VMOVDRR rY, rZ
+ /// is equivalent to
+ /// dX = REG_SEQUENCE rY, ssub_0, rZ, ssub_1.
+ ///
+ /// Note that for the optimizers to be able to take advantage of
+ /// this property, TargetInstrInfo::getRegSequenceLikeInputs has to be
+ /// override accordingly.
+ bool isRegSequenceLike(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::RegSequence, Type);
+ }
+
+ /// \brief Return true if this instruction behaves
+ /// the same way as the generic EXTRACT_SUBREG instructions.
+ /// E.g., on ARM,
+ /// rX, rY VMOVRRD dZ
+ /// is equivalent to two EXTRACT_SUBREG:
+ /// rX = EXTRACT_SUBREG dZ, ssub_0
+ /// rY = EXTRACT_SUBREG dZ, ssub_1
+ ///
+ /// Note that for the optimizers to be able to take advantage of
+ /// this property, TargetInstrInfo::getExtractSubregLikeInputs has to be
+ /// override accordingly.
+ bool isExtractSubregLike(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::ExtractSubreg, Type);
+ }
+
+ /// \brief Return true if this instruction behaves
+ /// the same way as the generic INSERT_SUBREG instructions.
+ /// E.g., on ARM,
+ /// dX = VSETLNi32 dY, rZ, Imm
+ /// is equivalent to a INSERT_SUBREG:
+ /// dX = INSERT_SUBREG dY, rZ, translateImmToSubIdx(Imm)
+ ///
+ /// Note that for the optimizers to be able to take advantage of
+ /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be
+ /// override accordingly.
+ bool isInsertSubregLike(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::InsertSubreg, Type);
+ }
+
//===--------------------------------------------------------------------===//
// Side Effect Analysis
//===--------------------------------------------------------------------===//
@@ -614,7 +667,6 @@ public:
/// are not marking copies from and to the same register class with this flag.
bool isAsCheapAsAMove(QueryType Type = AllInBundle) const {
// Only returns true for a bundle if all bundled instructions are cheap.
- // FIXME: This probably requires a target hook.
return hasProperty(MCID::CheapAsAMove, Type);
}
@@ -672,6 +724,12 @@ public:
/// eraseFromBundle() to erase individual bundled instructions.
void eraseFromParent();
+ /// Unlink 'this' from the containing basic block and delete it.
+ ///
+ /// For all definitions mark their uses in DBG_VALUE nodes
+ /// as undefined. Otherwise like eraseFromParent().
+ void eraseFromParentAndMarkDBGValuesForRemoval();
+
/// Unlink 'this' form its basic block and delete it.
///
/// If the instruction is part of a bundle, the other instructions in the
@@ -1081,7 +1139,10 @@ public:
/// setDebugLoc - Replace current source information with new such.
/// Avoid using this, the constructor argument is preferable.
///
- void setDebugLoc(const DebugLoc dl) { debugLoc = dl; }
+ void setDebugLoc(const DebugLoc dl) {
+ debugLoc = dl;
+ assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
+ }
/// RemoveOperand - Erase an operand from an instruction, leaving it with one
/// fewer operand than it started with.
diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h
index 21a482cdbd4c..8859b6a019ea 100644
--- a/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -58,6 +58,10 @@ public:
MachineInstr *operator->() const { return MI; }
operator MachineBasicBlock::iterator() const { return MI; }
+ /// If conversion operators fail, use this method to get the MachineInstr
+ /// explicitly.
+ MachineInstr *getInstr() const { return MI; }
+
/// addReg - Add a new virtual register operand...
///
const
@@ -170,6 +174,8 @@ public:
const MachineInstrBuilder &addMetadata(const MDNode *MD) const {
MI->addOperand(*MF, MachineOperand::CreateMetadata(MD));
+ assert((MI->isDebugValue() ? MI->getDebugVariable().Verify() : true) &&
+ "first MDNode argument of a DBG_VALUE not a DIVariable");
return *this;
}
@@ -345,24 +351,25 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB,
/// address. The convention is that a DBG_VALUE is indirect iff the
/// second operand is an immediate.
///
-inline MachineInstrBuilder BuildMI(MachineFunction &MF,
- DebugLoc DL,
- const MCInstrDesc &MCID,
- bool IsIndirect,
- unsigned Reg,
- unsigned Offset,
- const MDNode *MD) {
+inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ unsigned Reg, unsigned Offset,
+ const MDNode *Variable, const MDNode *Expr) {
+ assert(DIVariable(Variable).Verify() && "not a DIVariable");
+ assert(DIExpression(Expr).Verify() && "not a DIExpression");
if (IsIndirect)
return BuildMI(MF, DL, MCID)
- .addReg(Reg, RegState::Debug)
- .addImm(Offset)
- .addMetadata(MD);
+ .addReg(Reg, RegState::Debug)
+ .addImm(Offset)
+ .addMetadata(Variable)
+ .addMetadata(Expr);
else {
assert(Offset == 0 && "A direct address cannot have an offset.");
return BuildMI(MF, DL, MCID)
- .addReg(Reg, RegState::Debug)
- .addReg(0U, RegState::Debug)
- .addMetadata(MD);
+ .addReg(Reg, RegState::Debug)
+ .addReg(0U, RegState::Debug)
+ .addMetadata(Variable)
+ .addMetadata(Expr);
}
}
@@ -371,15 +378,15 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF,
/// address and inserts it at position I.
///
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
- MachineBasicBlock::iterator I,
- DebugLoc DL,
- const MCInstrDesc &MCID,
- bool IsIndirect,
- unsigned Reg,
- unsigned Offset,
- const MDNode *MD) {
+ MachineBasicBlock::iterator I, DebugLoc DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ unsigned Reg, unsigned Offset,
+ const MDNode *Variable, const MDNode *Expr) {
+ assert(DIVariable(Variable).Verify() && "not a DIVariable");
+ assert(DIExpression(Expr).Verify() && "not a DIExpression");
MachineFunction &MF = *BB.getParent();
- MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, MD);
+ MachineInstr *MI =
+ BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr);
BB.insert(I, MI);
return MachineInstrBuilder(MF, MI);
}
diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h
index 2532c16271f0..eb5086cbe5a5 100644
--- a/include/llvm/CodeGen/MachineMemOperand.h
+++ b/include/llvm/CodeGen/MachineMemOperand.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/Value.h" // PointerLikeTypeTraits<Value*>
#include "llvm/Support/DataTypes.h"
@@ -91,7 +92,7 @@ class MachineMemOperand {
MachinePointerInfo PtrInfo;
uint64_t Size;
unsigned Flags;
- const MDNode *TBAAInfo;
+ AAMDNodes AAInfo;
const MDNode *Ranges;
public:
@@ -117,7 +118,8 @@ public:
/// MachineMemOperand - Construct an MachineMemOperand object with the
/// specified PtrInfo, flags, size, and base alignment.
MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s,
- unsigned base_alignment, const MDNode *TBAAInfo = nullptr,
+ unsigned base_alignment,
+ const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
const MachinePointerInfo &getPointerInfo() const { return PtrInfo; }
@@ -161,8 +163,8 @@ public:
/// base address, without the offset.
uint64_t getBaseAlignment() const { return (1u << (Flags >> MOMaxBits)) >> 1; }
- /// getTBAAInfo - Return the TBAA tag for the memory reference.
- const MDNode *getTBAAInfo() const { return TBAAInfo; }
+ /// getAAInfo - Return the AA tags for the memory reference.
+ AAMDNodes getAAInfo() const { return AAInfo; }
/// getRanges - Return the range tag for the memory reference.
const MDNode *getRanges() const { return Ranges; }
diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h
index 6d8d05684c56..f0d0b2dbcdbc 100644
--- a/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/include/llvm/CodeGen/MachineModuleInfo.h
@@ -66,6 +66,7 @@ struct LandingPadInfo {
MachineBasicBlock *LandingPadBlock; // Landing pad block.
SmallVector<MCSymbol*, 1> BeginLabels; // Labels prior to invoke.
SmallVector<MCSymbol*, 1> EndLabels; // Labels after invoke.
+ SmallVector<MCSymbol*, 1> ClauseLabels; // Labels for each clause.
MCSymbol *LandingPadLabel; // Label at beginning of landing pad.
const Function *Personality; // Personality function.
std::vector<int> TypeIds; // List of type ids (filters negative)
@@ -110,10 +111,6 @@ class MachineModuleInfo : public ImmutablePass {
/// by debug and exception handling consumers.
std::vector<MCCFIInstruction> FrameInstructions;
- /// CompactUnwindEncoding - If the target supports it, this is the compact
- /// unwind encoding. It replaces a function's CIE and FDE.
- uint32_t CompactUnwindEncoding;
-
/// LandingPads - List of LandingPadInfo describing the landing pad
/// information in the current function.
std::vector<LandingPadInfo> LandingPads;
@@ -131,7 +128,7 @@ class MachineModuleInfo : public ImmutablePass {
unsigned CurCallSite;
/// TypeInfos - List of C++ TypeInfo used in the current function.
- std::vector<const GlobalVariable *> TypeInfos;
+ std::vector<const GlobalValue *> TypeInfos;
/// FilterIds - List of typeids encoding filters used in the current function.
std::vector<unsigned> FilterIds;
@@ -165,13 +162,24 @@ class MachineModuleInfo : public ImmutablePass {
/// to _fltused on Windows targets.
bool UsesVAFloatArgument;
+ /// UsesMorestackAddr - True if the module calls the __morestack function
+ /// indirectly, as is required under the large code model on x86. This is used
+ /// to emit a definition of a symbol, __morestack_addr, containing the
+ /// address. See comments in lib/Target/X86/X86FrameLowering.cpp for more
+ /// details.
+ bool UsesMorestackAddr;
+
public:
static char ID; // Pass identification, replacement for typeid
struct VariableDbgInfo {
- TrackingVH<MDNode> Var;
+ TrackingMDNodeRef Var;
+ TrackingMDNodeRef Expr;
unsigned Slot;
DebugLoc Loc;
+
+ VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc)
+ : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {}
};
typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy;
VariableDbgInfoMapTy VariableDbgInfos;
@@ -234,6 +242,14 @@ public:
UsesVAFloatArgument = b;
}
+ bool usesMorestackAddr() const {
+ return UsesMorestackAddr;
+ }
+
+ void setUsesMorestackAddr(bool b) {
+ UsesMorestackAddr = b;
+ }
+
/// \brief Returns a reference to a list of cfi instructions in the current
/// function's prologue. Used to construct frame maps for debug and exception
/// handling comsumers.
@@ -247,15 +263,6 @@ public:
return FrameInstructions.size() - 1;
}
- /// getCompactUnwindEncoding - Returns the compact unwind encoding for a
- /// function if the target supports the encoding. This encoding replaces a
- /// function's CIE and FDE.
- uint32_t getCompactUnwindEncoding() const { return CompactUnwindEncoding; }
-
- /// setCompactUnwindEncoding - Set the compact unwind encoding for a function
- /// if the target supports the encoding.
- void setCompactUnwindEncoding(uint32_t Enc) { CompactUnwindEncoding = Enc; }
-
/// getAddrLabelSymbol - Return the symbol to be used for the specified basic
/// block when its address is taken. This cannot be its normal LBB label
/// because the block may be accessed outside its containing function.
@@ -313,20 +320,25 @@ public:
/// addCatchTypeInfo - Provide the catch typeinfo for a landing pad.
///
void addCatchTypeInfo(MachineBasicBlock *LandingPad,
- ArrayRef<const GlobalVariable *> TyInfo);
+ ArrayRef<const GlobalValue *> TyInfo);
/// addFilterTypeInfo - Provide the filter typeinfo for a landing pad.
///
void addFilterTypeInfo(MachineBasicBlock *LandingPad,
- ArrayRef<const GlobalVariable *> TyInfo);
+ ArrayRef<const GlobalValue *> TyInfo);
/// addCleanup - Add a cleanup action for a landing pad.
///
void addCleanup(MachineBasicBlock *LandingPad);
+ /// Add a clause for a landing pad. Returns a new label for the clause. This
+ /// is used by EH schemes that have more than one landing pad. In this case,
+ /// each clause gets its own basic block.
+ MCSymbol *addClauseForLandingPad(MachineBasicBlock *LandingPad);
+
/// getTypeIDFor - Return the type id for the specified typeinfo. This is
/// function wide.
- unsigned getTypeIDFor(const GlobalVariable *TI);
+ unsigned getTypeIDFor(const GlobalValue *TI);
/// getFilterIDFor - Return the id of the filter encoded by TyIds. This is
/// function wide.
@@ -387,7 +399,7 @@ public:
/// getTypeInfos - Return a reference to the C++ typeinfo for the current
/// function.
- const std::vector<const GlobalVariable *> &getTypeInfos() const {
+ const std::vector<const GlobalValue *> &getTypeInfos() const {
return TypeInfos;
}
@@ -403,9 +415,9 @@ public:
/// setVariableDbgInfo - Collect information used to emit debugging
/// information of a variable.
- void setVariableDbgInfo(MDNode *N, unsigned Slot, DebugLoc Loc) {
- VariableDbgInfo Info = { N, Slot, Loc };
- VariableDbgInfos.push_back(std::move(Info));
+ void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot,
+ DebugLoc Loc) {
+ VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc);
}
VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; }
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index 22969bc80776..eed1e575f93b 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/include/llvm/CodeGen/MachineOperand.h
@@ -506,6 +506,11 @@ public:
Contents.ImmVal = immVal;
}
+ void setFPImm(const ConstantFP *CFP) {
+ assert(isFPImm() && "Wrong MachineOperand mutator");
+ Contents.CFP = CFP;
+ }
+
void setOffset(int64_t Offset) {
assert((isGlobal() || isSymbol() || isCPI() || isTargetIndex() ||
isBlockAddress()) && "Wrong MachineOperand accessor");
@@ -544,6 +549,11 @@ public:
/// the setImm method should be used.
void ChangeToImmediate(int64_t ImmVal);
+ /// ChangeToFPImmediate - Replace this operand with a new FP immediate operand
+ /// of the specified value. If an operand is known to be an FP immediate
+ /// already, the setFPImm method should be used.
+ void ChangeToFPImmediate(const ConstantFP *FPImm);
+
/// ChangeToRegister - Replace this operand with a new register operand of
/// the specified value. If an operand is known to be an register already,
/// the setReg method should be used.
@@ -702,6 +712,8 @@ public:
friend class MachineInstr;
friend class MachineRegisterInfo;
private:
+ void removeRegFromUses();
+
//===--------------------------------------------------------------------===//
// Methods for handling register use/def lists.
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h
index beb2c4f0c5c0..aab5c407629f 100644
--- a/include/llvm/CodeGen/MachinePostDominators.h
+++ b/include/llvm/CodeGen/MachinePostDominators.h
@@ -22,7 +22,7 @@ namespace llvm {
///
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used
-/// to compute the a post-dominator tree.
+/// to compute the post-dominator tree.
///
struct MachinePostDominatorTree : public MachineFunctionPass {
private:
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index 51139f72ba22..caa48a5cf0cf 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -17,9 +17,10 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
-#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
#include <vector>
namespace llvm {
@@ -39,7 +40,7 @@ public:
};
private:
- const TargetMachine &TM;
+ const MachineFunction *MF;
Delegate *TheDelegate;
/// IsSSA - True when the machine function is in SSA form and virtual
@@ -51,6 +52,9 @@ private:
/// accurate when after this flag is cleared.
bool TracksLiveness;
+ /// True if subregister liveness is tracked.
+ bool TracksSubRegLiveness;
+
/// VRegInfo - Information we keep for each virtual register.
///
/// Each element in this list contains the register class of the vreg and the
@@ -69,7 +73,7 @@ private:
/// PhysRegUseDefLists - This is an array of the head of the use/def list for
/// physical registers.
- MachineOperand **PhysRegUseDefLists;
+ std::vector<MachineOperand *> PhysRegUseDefLists;
/// getRegUseDefListHead - Return the head pointer for the register use/def
/// list for the specified virtual or physical register.
@@ -122,11 +126,10 @@ private:
MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION;
void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION;
public:
- explicit MachineRegisterInfo(const TargetMachine &TM);
- ~MachineRegisterInfo();
+ explicit MachineRegisterInfo(const MachineFunction *MF);
const TargetRegisterInfo *getTargetRegisterInfo() const {
- return TM.getRegisterInfo();
+ return MF->getSubtarget().getRegisterInfo();
}
void resetDelegate(Delegate *delegate) {
@@ -179,6 +182,12 @@ public:
/// information.
void invalidateLiveness() { TracksLiveness = false; }
+ bool tracksSubRegLiveness() const { return TracksSubRegLiveness; }
+
+ void enableSubRegLiveness(bool Enable = true) {
+ TracksSubRegLiveness = Enable;
+ }
+
//===--------------------------------------------------------------------===//
// Register Info
//===--------------------------------------------------------------------===//
@@ -515,8 +524,12 @@ public:
///
/// That function will return NULL 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
+ /// register.
void replaceRegWith(unsigned FromReg, unsigned ToReg);
-
+
/// getVRegDef - Return the machine instr that defines the specified virtual
/// register or null if none is found. This assumes that the code is in SSA
/// form, so there should only be one definition.
@@ -764,6 +777,10 @@ public:
const TargetRegisterInfo &TRI,
const TargetInstrInfo &TII);
+ /// Returns a mask covering all bits that can appear in lane masks of
+ /// subregisters of the virtual register @p Reg.
+ unsigned getMaxLaneMaskForVReg(unsigned Reg) const;
+
/// defusechain_iterator - This class provides iterator support for machine
/// operands in the function that use or define a specific register. If
/// ReturnUses is true it returns uses of registers, if ReturnDefs is true it
diff --git a/include/llvm/CodeGen/MachineRelocation.h b/include/llvm/CodeGen/MachineRelocation.h
deleted file mode 100644
index e77845745165..000000000000
--- a/include/llvm/CodeGen/MachineRelocation.h
+++ /dev/null
@@ -1,342 +0,0 @@
-//===-- llvm/CodeGen/MachineRelocation.h - Target Relocation ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the MachineRelocation class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_MACHINERELOCATION_H
-#define LLVM_CODEGEN_MACHINERELOCATION_H
-
-#include "llvm/Support/DataTypes.h"
-#include <cassert>
-
-namespace llvm {
-class GlobalValue;
-class MachineBasicBlock;
-
-/// MachineRelocation - This represents a target-specific relocation value,
-/// produced by the code emitter. This relocation is resolved after the has
-/// been emitted, either to an object file or to memory, when the target of the
-/// relocation can be resolved.
-///
-/// A relocation is made up of the following logical portions:
-/// 1. An offset in the machine code buffer, the location to modify.
-/// 2. A target specific relocation type (a number from 0 to 63).
-/// 3. A symbol being referenced, either as a GlobalValue* or as a string.
-/// 4. An optional constant value to be added to the reference.
-/// 5. A bit, CanRewrite, which indicates to the JIT that a function stub is
-/// not needed for the relocation.
-/// 6. An index into the GOT, if the target uses a GOT
-///
-class MachineRelocation {
- enum AddressType {
- isResult, // Relocation has be transformed into its result pointer.
- isGV, // The Target.GV field is valid.
- isIndirectSym, // Relocation of an indirect symbol.
- isBB, // Relocation of BB address.
- isExtSym, // The Target.ExtSym field is valid.
- isConstPool, // Relocation of constant pool address.
- isJumpTable, // Relocation of jump table address.
- isGOTIndex // The Target.GOTIndex field is valid.
- };
-
- /// Offset - This is the offset from the start of the code buffer of the
- /// relocation to perform.
- uintptr_t Offset;
-
- /// ConstantVal - A field that may be used by the target relocation type.
- intptr_t ConstantVal;
-
- union {
- void *Result; // If this has been resolved to a resolved pointer
- GlobalValue *GV; // If this is a pointer to a GV or an indirect ref.
- MachineBasicBlock *MBB; // If this is a pointer to an LLVM BB
- const char *ExtSym; // If this is a pointer to a named symbol
- unsigned Index; // Constant pool / jump table index
- unsigned GOTIndex; // Index in the GOT of this symbol/global
- } Target;
-
- unsigned TargetReloType : 6; // The target relocation ID
- AddressType AddrType : 4; // The field of Target to use
- bool MayNeedFarStub : 1; // True if this relocation may require a far-stub
- bool GOTRelative : 1; // Should this relocation be relative to the GOT?
- bool TargetResolve : 1; // True if target should resolve the address
-
-public:
- // Relocation types used in a generic implementation. Currently, relocation
- // entries for all things use the generic VANILLA type until they are refined
- // into target relocation types.
- enum RelocationType {
- VANILLA
- };
-
- /// MachineRelocation::getGV - Return a relocation entry for a GlobalValue.
- ///
- static MachineRelocation getGV(uintptr_t offset, unsigned RelocationType,
- GlobalValue *GV, intptr_t cst = 0,
- bool MayNeedFarStub = 0,
- bool GOTrelative = 0) {
- assert((RelocationType & ~63) == 0 && "Relocation type too large!");
- MachineRelocation Result;
- Result.Offset = offset;
- Result.ConstantVal = cst;
- Result.TargetReloType = RelocationType;
- Result.AddrType = isGV;
- Result.MayNeedFarStub = MayNeedFarStub;
- Result.GOTRelative = GOTrelative;
- Result.TargetResolve = false;
- Result.Target.GV = GV;
- return Result;
- }
-
- /// MachineRelocation::getIndirectSymbol - Return a relocation entry for an
- /// indirect symbol.
- static MachineRelocation getIndirectSymbol(uintptr_t offset,
- unsigned RelocationType,
- GlobalValue *GV, intptr_t cst = 0,
- bool MayNeedFarStub = 0,
- bool GOTrelative = 0) {
- assert((RelocationType & ~63) == 0 && "Relocation type too large!");
- MachineRelocation Result;
- Result.Offset = offset;
- Result.ConstantVal = cst;
- Result.TargetReloType = RelocationType;
- Result.AddrType = isIndirectSym;
- Result.MayNeedFarStub = MayNeedFarStub;
- Result.GOTRelative = GOTrelative;
- Result.TargetResolve = false;
- Result.Target.GV = GV;
- return Result;
- }
-
- /// MachineRelocation::getBB - Return a relocation entry for a BB.
- ///
- static MachineRelocation getBB(uintptr_t offset,unsigned RelocationType,
- MachineBasicBlock *MBB, intptr_t cst = 0) {
- assert((RelocationType & ~63) == 0 && "Relocation type too large!");
- MachineRelocation Result;
- Result.Offset = offset;
- Result.ConstantVal = cst;
- Result.TargetReloType = RelocationType;
- Result.AddrType = isBB;
- Result.MayNeedFarStub = false;
- Result.GOTRelative = false;
- Result.TargetResolve = false;
- Result.Target.MBB = MBB;
- return Result;
- }
-
- /// MachineRelocation::getExtSym - Return a relocation entry for an external
- /// symbol, like "free".
- ///
- static MachineRelocation getExtSym(uintptr_t offset, unsigned RelocationType,
- const char *ES, intptr_t cst = 0,
- bool GOTrelative = 0,
- bool NeedStub = true) {
- assert((RelocationType & ~63) == 0 && "Relocation type too large!");
- MachineRelocation Result;
- Result.Offset = offset;
- Result.ConstantVal = cst;
- Result.TargetReloType = RelocationType;
- Result.AddrType = isExtSym;
- Result.MayNeedFarStub = NeedStub;
- Result.GOTRelative = GOTrelative;
- Result.TargetResolve = false;
- Result.Target.ExtSym = ES;
- return Result;
- }
-
- /// MachineRelocation::getConstPool - Return a relocation entry for a constant
- /// pool entry.
- ///
- static MachineRelocation getConstPool(uintptr_t offset,unsigned RelocationType,
- unsigned CPI, intptr_t cst = 0,
- bool letTargetResolve = false) {
- assert((RelocationType & ~63) == 0 && "Relocation type too large!");
- MachineRelocation Result;
- Result.Offset = offset;
- Result.ConstantVal = cst;
- Result.TargetReloType = RelocationType;
- Result.AddrType = isConstPool;
- Result.MayNeedFarStub = false;
- Result.GOTRelative = false;
- Result.TargetResolve = letTargetResolve;
- Result.Target.Index = CPI;
- return Result;
- }
-
- /// MachineRelocation::getJumpTable - Return a relocation entry for a jump
- /// table entry.
- ///
- static MachineRelocation getJumpTable(uintptr_t offset,unsigned RelocationType,
- unsigned JTI, intptr_t cst = 0,
- bool letTargetResolve = false) {
- assert((RelocationType & ~63) == 0 && "Relocation type too large!");
- MachineRelocation Result;
- Result.Offset = offset;
- Result.ConstantVal = cst;
- Result.TargetReloType = RelocationType;
- Result.AddrType = isJumpTable;
- Result.MayNeedFarStub = false;
- Result.GOTRelative = false;
- Result.TargetResolve = letTargetResolve;
- Result.Target.Index = JTI;
- return Result;
- }
-
- /// getMachineCodeOffset - Return the offset into the code buffer that the
- /// relocation should be performed.
- intptr_t getMachineCodeOffset() const {
- return Offset;
- }
-
- /// getRelocationType - Return the target-specific relocation ID for this
- /// relocation.
- unsigned getRelocationType() const {
- return TargetReloType;
- }
-
- /// getConstantVal - Get the constant value associated with this relocation.
- /// This is often an offset from the symbol.
- ///
- intptr_t getConstantVal() const {
- return ConstantVal;
- }
-
- /// setConstantVal - Set the constant value associated with this relocation.
- /// This is often an offset from the symbol.
- ///
- void setConstantVal(intptr_t val) {
- ConstantVal = val;
- }
-
- /// isGlobalValue - Return true if this relocation is a GlobalValue, as
- /// opposed to a constant string.
- bool isGlobalValue() const {
- return AddrType == isGV;
- }
-
- /// isIndirectSymbol - Return true if this relocation is the address an
- /// indirect symbol
- bool isIndirectSymbol() const {
- return AddrType == isIndirectSym;
- }
-
- /// isBasicBlock - Return true if this relocation is a basic block reference.
- ///
- bool isBasicBlock() const {
- return AddrType == isBB;
- }
-
- /// isExternalSymbol - Return true if this is a constant string.
- ///
- bool isExternalSymbol() const {
- return AddrType == isExtSym;
- }
-
- /// isConstantPoolIndex - Return true if this is a constant pool reference.
- ///
- bool isConstantPoolIndex() const {
- return AddrType == isConstPool;
- }
-
- /// isJumpTableIndex - Return true if this is a jump table reference.
- ///
- bool isJumpTableIndex() const {
- return AddrType == isJumpTable;
- }
-
- /// isGOTRelative - Return true the target wants the index into the GOT of
- /// the symbol rather than the address of the symbol.
- bool isGOTRelative() const {
- return GOTRelative;
- }
-
- /// mayNeedFarStub - This function returns true if the JIT for this target may
- /// need either a stub function or an indirect global-variable load to handle
- /// the relocated GlobalValue reference. For example, the x86-64 call
- /// instruction can only call functions within +/-2GB of the call site.
- /// Anything farther away needs a longer mov+call sequence, which can't just
- /// be written on top of the existing call.
- bool mayNeedFarStub() const {
- return MayNeedFarStub;
- }
-
- /// letTargetResolve - Return true if the target JITInfo is usually
- /// responsible for resolving the address of this relocation.
- bool letTargetResolve() const {
- return TargetResolve;
- }
-
- /// getGlobalValue - If this is a global value reference, return the
- /// referenced global.
- GlobalValue *getGlobalValue() const {
- assert((isGlobalValue() || isIndirectSymbol()) &&
- "This is not a global value reference!");
- return Target.GV;
- }
-
- MachineBasicBlock *getBasicBlock() const {
- assert(isBasicBlock() && "This is not a basic block reference!");
- return Target.MBB;
- }
-
- /// getString - If this is a string value, return the string reference.
- ///
- const char *getExternalSymbol() const {
- assert(isExternalSymbol() && "This is not an external symbol reference!");
- return Target.ExtSym;
- }
-
- /// getConstantPoolIndex - If this is a const pool reference, return
- /// the index into the constant pool.
- unsigned getConstantPoolIndex() const {
- assert(isConstantPoolIndex() && "This is not a constant pool reference!");
- return Target.Index;
- }
-
- /// getJumpTableIndex - If this is a jump table reference, return
- /// the index into the jump table.
- unsigned getJumpTableIndex() const {
- assert(isJumpTableIndex() && "This is not a jump table reference!");
- return Target.Index;
- }
-
- /// getResultPointer - Once this has been resolved to point to an actual
- /// address, this returns the pointer.
- void *getResultPointer() const {
- assert(AddrType == isResult && "Result pointer isn't set yet!");
- return Target.Result;
- }
-
- /// setResultPointer - Set the result to the specified pointer value.
- ///
- void setResultPointer(void *Ptr) {
- Target.Result = Ptr;
- AddrType = isResult;
- }
-
- /// setGOTIndex - Set the GOT index to a specific value.
- void setGOTIndex(unsigned idx) {
- AddrType = isGOTIndex;
- Target.GOTIndex = idx;
- }
-
- /// getGOTIndex - Once this has been resolved to an entry in the GOT,
- /// this returns that index. The index is from the lowest address entry
- /// in the GOT.
- unsigned getGOTIndex() const {
- assert(AddrType == isGOTIndex);
- return Target.GOTIndex;
- }
-};
-}
-
-#endif
diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h
index 7d85432101b5..a31940161ca5 100644
--- a/include/llvm/CodeGen/MachineScheduler.h
+++ b/include/llvm/CodeGen/MachineScheduler.h
@@ -80,7 +80,6 @@
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/RegisterPressure.h"
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
-
#include <memory>
namespace llvm {
@@ -250,7 +249,7 @@ protected:
public:
ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S,
bool IsPostRA)
- : ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, IsPostRA,
+ : ScheduleDAGInstrs(*C->MF, C->MLI, IsPostRA,
/*RemoveKillFlags=*/IsPostRA, C->LIS),
AA(C->AA), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU), CurrentTop(),
CurrentBottom(), NextClusterPred(nullptr), NextClusterSucc(nullptr) {
diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h
index 323b694f3933..bfe6e945b6da 100644
--- a/include/llvm/CodeGen/MachineTraceMetrics.h
+++ b/include/llvm/CodeGen/MachineTraceMetrics.h
@@ -44,8 +44,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_MACHINE_TRACE_METRICS_H
-#define LLVM_CODEGEN_MACHINE_TRACE_METRICS_H
+#ifndef LLVM_CODEGEN_MACHINETRACEMETRICS_H
+#define LLVM_CODEGEN_MACHINETRACEMETRICS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -264,8 +264,9 @@ public:
/// classes are included. For the caller to account for extra machine
/// instructions, it must first resolve each instruction's scheduling class.
unsigned getResourceLength(
- ArrayRef<const MachineBasicBlock*> Extrablocks = None,
- ArrayRef<const MCSchedClassDesc*> ExtraInstrs = None) const;
+ ArrayRef<const MachineBasicBlock *> Extrablocks = None,
+ ArrayRef<const MCSchedClassDesc *> ExtraInstrs = None,
+ ArrayRef<const MCSchedClassDesc *> RemoveInstrs = None) const;
/// Return the length of the (data dependency) critical path through the
/// trace.
@@ -286,6 +287,12 @@ public:
/// Return the Depth of a PHI instruction in a trace center block successor.
/// The PHI does not have to be part of the trace.
unsigned getPHIDepth(const MachineInstr *PHI) const;
+
+ /// A dependence is useful if the basic block of the defining instruction
+ /// is part of the trace of the user instruction. It is assumed that DefMI
+ /// dominates UseMI (see also isUsefulDominator).
+ bool isDepInTrace(const MachineInstr *DefMI,
+ const MachineInstr *UseMI) const;
};
/// A trace ensemble is a collection of traces selected using the same
diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h
index ad215ec09843..e3fbfe89c203 100644
--- a/include/llvm/CodeGen/MachineValueType.h
+++ b/include/llvm/CodeGen/MachineValueType.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H
#define LLVM_CODEGEN_MACHINEVALUETYPE_H
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -118,6 +119,7 @@ namespace llvm {
// unspecified type. The register class
// will be determined by the opcode.
+ FIRST_VALUETYPE = 0, // This is always the beginning of the list.
LAST_VALUETYPE = 58, // This always remains at the end of the list.
// This is the current maximum for LAST_VALUETYPE.
@@ -165,6 +167,12 @@ namespace llvm {
bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; }
bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; }
+ /// isValid - Return true if this is a valid simple valuetype.
+ bool isValid() const {
+ return (SimpleTy >= MVT::FIRST_VALUETYPE &&
+ SimpleTy < MVT::LAST_VALUETYPE);
+ }
+
/// isFloatingPoint - Return true if this is a FP, or a vector FP type.
bool isFloatingPoint() const {
return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE &&
@@ -196,21 +204,24 @@ namespace llvm {
/// is32BitVector - Return true if this is a 32-bit vector type.
bool is32BitVector() const {
return (SimpleTy == MVT::v4i8 || SimpleTy == MVT::v2i16 ||
- SimpleTy == MVT::v1i32);
+ SimpleTy == MVT::v1i32 || SimpleTy == MVT::v2f16 ||
+ SimpleTy == MVT::v1f32);
}
/// is64BitVector - Return true if this is a 64-bit vector type.
bool is64BitVector() const {
return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 ||
SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 ||
- SimpleTy == MVT::v1f64 || SimpleTy == MVT::v2f32);
+ SimpleTy == MVT::v4f16 || SimpleTy == MVT::v2f32 ||
+ SimpleTy == MVT::v1f64);
}
/// is128BitVector - Return true if this is a 128-bit vector type.
bool is128BitVector() const {
return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 ||
SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 ||
- SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64);
+ SimpleTy == MVT::v8f16 || SimpleTy == MVT::v4f32 ||
+ SimpleTy == MVT::v2f64);
}
/// is256BitVector - Return true if this is a 256-bit vector type.
@@ -572,6 +583,52 @@ namespace llvm {
/// returned as Other, otherwise they are invalid.
static MVT getVT(Type *Ty, bool HandleUnknown = false);
+ private:
+ /// A simple iterator over the MVT::SimpleValueType enum.
+ struct mvt_iterator {
+ SimpleValueType VT;
+ mvt_iterator(SimpleValueType VT) : VT(VT) {}
+ MVT operator*() const { return VT; }
+ bool operator!=(const mvt_iterator &LHS) const { return VT != LHS.VT; }
+ mvt_iterator& operator++() {
+ VT = (MVT::SimpleValueType)((int)VT + 1);
+ assert((int)VT <= MVT::MAX_ALLOWED_VALUETYPE &&
+ "MVT iterator overflowed.");
+ return *this;
+ }
+ };
+ /// A range of the MVT::SimpleValueType enum.
+ typedef iterator_range<mvt_iterator> mvt_range;
+
+ public:
+ /// SimpleValueType Iteration
+ /// @{
+ static mvt_range all_valuetypes() {
+ return mvt_range(MVT::FIRST_VALUETYPE, MVT::LAST_VALUETYPE);
+ }
+ static mvt_range integer_valuetypes() {
+ return mvt_range(MVT::FIRST_INTEGER_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_INTEGER_VALUETYPE + 1));
+ }
+ static mvt_range fp_valuetypes() {
+ return mvt_range(MVT::FIRST_FP_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_FP_VALUETYPE + 1));
+ }
+ static mvt_range vector_valuetypes() {
+ return mvt_range(MVT::FIRST_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_VECTOR_VALUETYPE + 1));
+ }
+ static mvt_range integer_vector_valuetypes() {
+ return mvt_range(
+ MVT::FIRST_INTEGER_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_INTEGER_VECTOR_VALUETYPE + 1));
+ }
+ static mvt_range fp_vector_valuetypes() {
+ return mvt_range(
+ MVT::FIRST_FP_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1));
+ }
+ /// @}
};
} // End llvm namespace
diff --git a/include/llvm/CodeGen/PBQP/CostAllocator.h b/include/llvm/CodeGen/PBQP/CostAllocator.h
index ff62c0959344..02d39fe383f1 100644
--- a/include/llvm/CodeGen/PBQP/CostAllocator.h
+++ b/include/llvm/CodeGen/PBQP/CostAllocator.h
@@ -15,117 +15,101 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_COSTALLOCATOR_H
-#define LLVM_COSTALLOCATOR_H
+#ifndef LLVM_CODEGEN_PBQP_COSTALLOCATOR_H
+#define LLVM_CODEGEN_PBQP_COSTALLOCATOR_H
-#include <set>
+#include "llvm/ADT/DenseSet.h"
+#include <memory>
#include <type_traits>
+namespace llvm {
namespace PBQP {
-template <typename CostT,
- typename CostKeyTComparator>
-class CostPool {
+template <typename ValueT>
+class ValuePool {
public:
+ typedef std::shared_ptr<const ValueT> PoolRef;
- class PoolEntry {
+private:
+
+ class PoolEntry : public std::enable_shared_from_this<PoolEntry> {
public:
- template <typename CostKeyT>
- PoolEntry(CostPool &pool, CostKeyT cost)
- : pool(pool), cost(std::move(cost)), refCount(0) {}
- ~PoolEntry() { pool.removeEntry(this); }
- void incRef() { ++refCount; }
- bool decRef() { --refCount; return (refCount == 0); }
- CostT& getCost() { return cost; }
- const CostT& getCost() const { return cost; }
+ template <typename ValueKeyT>
+ PoolEntry(ValuePool &Pool, ValueKeyT Value)
+ : Pool(Pool), Value(std::move(Value)) {}
+ ~PoolEntry() { Pool.removeEntry(this); }
+ const ValueT& getValue() const { return Value; }
private:
- CostPool &pool;
- CostT cost;
- std::size_t refCount;
+ ValuePool &Pool;
+ ValueT Value;
};
- class PoolRef {
+ class PoolEntryDSInfo {
public:
- PoolRef(PoolEntry *entry) : entry(entry) {
- this->entry->incRef();
+ static inline PoolEntry* getEmptyKey() { return nullptr; }
+
+ static inline PoolEntry* getTombstoneKey() {
+ return reinterpret_cast<PoolEntry*>(static_cast<uintptr_t>(1));
}
- PoolRef(const PoolRef &r) {
- entry = r.entry;
- entry->incRef();
+
+ template <typename ValueKeyT>
+ static unsigned getHashValue(const ValueKeyT &C) {
+ return hash_value(C);
}
- PoolRef& operator=(const PoolRef &r) {
- assert(entry != nullptr && "entry should not be null.");
- PoolEntry *temp = r.entry;
- temp->incRef();
- entry->decRef();
- entry = temp;
- return *this;
+
+ static unsigned getHashValue(PoolEntry *P) {
+ return getHashValue(P->getValue());
}
- ~PoolRef() {
- if (entry->decRef())
- delete entry;
+ static unsigned getHashValue(const PoolEntry *P) {
+ return getHashValue(P->getValue());
}
- void reset(PoolEntry *entry) {
- entry->incRef();
- this->entry->decRef();
- this->entry = entry;
+
+ template <typename ValueKeyT1, typename ValueKeyT2>
+ static
+ bool isEqual(const ValueKeyT1 &C1, const ValueKeyT2 &C2) {
+ return C1 == C2;
}
- CostT& operator*() { return entry->getCost(); }
- const CostT& operator*() const { return entry->getCost(); }
- CostT* operator->() { return &entry->getCost(); }
- const CostT* operator->() const { return &entry->getCost(); }
- private:
- PoolEntry *entry;
- };
-private:
- class EntryComparator {
- public:
- template <typename CostKeyT>
- typename std::enable_if<
- !std::is_same<PoolEntry*,
- typename std::remove_const<CostKeyT>::type>::value,
- bool>::type
- operator()(const PoolEntry* a, const CostKeyT &b) {
- return compare(a->getCost(), b);
+ template <typename ValueKeyT>
+ static bool isEqual(const ValueKeyT &C, PoolEntry *P) {
+ if (P == getEmptyKey() || P == getTombstoneKey())
+ return false;
+ return isEqual(C, P->getValue());
}
- bool operator()(const PoolEntry* a, const PoolEntry* b) {
- return compare(a->getCost(), b->getCost());
+
+ static bool isEqual(PoolEntry *P1, PoolEntry *P2) {
+ if (P1 == getEmptyKey() || P1 == getTombstoneKey())
+ return P1 == P2;
+ return isEqual(P1->getValue(), P2);
}
- private:
- CostKeyTComparator compare;
+
};
- typedef std::set<PoolEntry*, EntryComparator> EntrySet;
+ typedef DenseSet<PoolEntry*, PoolEntryDSInfo> EntrySetT;
- EntrySet entrySet;
+ EntrySetT EntrySet;
- void removeEntry(PoolEntry *p) { entrySet.erase(p); }
+ void removeEntry(PoolEntry *P) { EntrySet.erase(P); }
public:
+ template <typename ValueKeyT> PoolRef getValue(ValueKeyT ValueKey) {
+ typename EntrySetT::iterator I = EntrySet.find_as(ValueKey);
- template <typename CostKeyT>
- PoolRef getCost(CostKeyT costKey) {
- typename EntrySet::iterator itr =
- std::lower_bound(entrySet.begin(), entrySet.end(), costKey,
- EntryComparator());
-
- if (itr != entrySet.end() && costKey == (*itr)->getCost())
- return PoolRef(*itr);
+ if (I != EntrySet.end())
+ return PoolRef((*I)->shared_from_this(), &(*I)->getValue());
- PoolEntry *p = new PoolEntry(*this, std::move(costKey));
- entrySet.insert(itr, p);
- return PoolRef(p);
+ auto P = std::make_shared<PoolEntry>(*this, std::move(ValueKey));
+ EntrySet.insert(P.get());
+ return PoolRef(std::move(P), &P->getValue());
}
};
-template <typename VectorT, typename VectorTComparator,
- typename MatrixT, typename MatrixTComparator>
+template <typename VectorT, typename MatrixT>
class PoolCostAllocator {
private:
- typedef CostPool<VectorT, VectorTComparator> VectorCostPool;
- typedef CostPool<MatrixT, MatrixTComparator> MatrixCostPool;
+ typedef ValuePool<VectorT> VectorCostPool;
+ typedef ValuePool<MatrixT> MatrixCostPool;
public:
typedef VectorT Vector;
typedef MatrixT Matrix;
@@ -133,15 +117,16 @@ public:
typedef typename MatrixCostPool::PoolRef MatrixPtr;
template <typename VectorKeyT>
- VectorPtr getVector(VectorKeyT v) { return vectorPool.getCost(std::move(v)); }
+ VectorPtr getVector(VectorKeyT v) { return VectorPool.getValue(std::move(v)); }
template <typename MatrixKeyT>
- MatrixPtr getMatrix(MatrixKeyT m) { return matrixPool.getCost(std::move(m)); }
+ MatrixPtr getMatrix(MatrixKeyT m) { return MatrixPool.getValue(std::move(m)); }
private:
- VectorCostPool vectorPool;
- MatrixCostPool matrixPool;
+ VectorCostPool VectorPool;
+ MatrixCostPool MatrixPool;
};
-}
+} // namespace PBQP
+} // namespace llvm
-#endif // LLVM_COSTALLOCATOR_H
+#endif
diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h
index a55f0ea96c0a..4dc5674ae134 100644
--- a/include/llvm/CodeGen/PBQP/Graph.h
+++ b/include/llvm/CodeGen/PBQP/Graph.h
@@ -17,11 +17,12 @@
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
#include <list>
#include <map>
#include <set>
+namespace llvm {
namespace PBQP {
class GraphBase {
@@ -29,12 +30,12 @@ namespace PBQP {
typedef unsigned NodeId;
typedef unsigned EdgeId;
- /// \brief Returns a value representing an invalid (non-existent) node.
+ /// @brief 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.
+ /// @brief Returns a value representing an invalid (non-existent) edge.
static EdgeId invalidEdgeId() {
return std::numeric_limits<EdgeId>::max();
}
@@ -56,6 +57,7 @@ namespace PBQP {
typedef typename CostAllocator::MatrixPtr MatrixPtr;
typedef typename SolverT::NodeMetadata NodeMetadata;
typedef typename SolverT::EdgeMetadata EdgeMetadata;
+ typedef typename SolverT::GraphMetadata GraphMetadata;
private:
@@ -172,6 +174,7 @@ namespace PBQP {
// ----- MEMBERS -----
+ GraphMetadata Metadata;
CostAllocator CostAlloc;
SolverT *Solver;
@@ -187,13 +190,19 @@ namespace PBQP {
// ----- INTERNAL METHODS -----
- NodeEntry& getNode(NodeId NId) { return Nodes[NId]; }
- const NodeEntry& getNode(NodeId NId) const { return Nodes[NId]; }
+ NodeEntry &getNode(NodeId NId) {
+ assert(NId < Nodes.size() && "Out of bound NodeId");
+ return Nodes[NId];
+ }
+ const NodeEntry &getNode(NodeId NId) const {
+ assert(NId < Nodes.size() && "Out of bound NodeId");
+ return Nodes[NId];
+ }
EdgeEntry& getEdge(EdgeId EId) { return Edges[EId]; }
const EdgeEntry& getEdge(EdgeId EId) const { return Edges[EId]; }
- NodeId addConstructedNode(const NodeEntry &N) {
+ NodeId addConstructedNode(NodeEntry N) {
NodeId NId = 0;
if (!FreeNodeIds.empty()) {
NId = FreeNodeIds.back();
@@ -206,7 +215,7 @@ namespace PBQP {
return NId;
}
- EdgeId addConstructedEdge(const EdgeEntry &E) {
+ EdgeId addConstructedEdge(EdgeEntry E) {
assert(findEdge(E.getN1Id(), E.getN2Id()) == invalidEdgeId() &&
"Attempt to add duplicate edge.");
EdgeId EId = 0;
@@ -235,6 +244,12 @@ namespace PBQP {
class NodeItr {
public:
+ typedef std::forward_iterator_tag iterator_category;
+ typedef NodeId value_type;
+ typedef int difference_type;
+ typedef NodeId* pointer;
+ typedef NodeId& reference;
+
NodeItr(NodeId CurNId, const Graph &G)
: CurNId(CurNId), EndNId(G.Nodes.size()), FreeNodeIds(G.FreeNodeIds) {
this->CurNId = findNextInUse(CurNId); // Move to first in-use node id
@@ -249,7 +264,7 @@ namespace PBQP {
NodeId findNextInUse(NodeId NId) const {
while (NId < EndNId &&
std::find(FreeNodeIds.begin(), FreeNodeIds.end(), NId) !=
- FreeNodeIds.end()) {
+ FreeNodeIds.end()) {
++NId;
}
return NId;
@@ -328,10 +343,19 @@ namespace PBQP {
const NodeEntry &NE;
};
- /// \brief Construct an empty PBQP graph.
- Graph() : Solver(nullptr) { }
+ /// @brief Construct an empty PBQP graph.
+ Graph() : Solver(nullptr) {}
+
+ /// @brief Construct an empty PBQP graph with the given graph metadata.
+ Graph(GraphMetadata Metadata) : Metadata(Metadata), Solver(nullptr) {}
+
+ /// @brief Get a reference to the graph metadata.
+ GraphMetadata& getMetadata() { return Metadata; }
- /// \brief Lock this graph to the given solver instance in preparation
+ /// @brief 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
/// 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.
@@ -344,13 +368,13 @@ namespace PBQP {
Solver->handleAddEdge(EId);
}
- /// \brief Release from solver instance.
+ /// @brief Release from solver instance.
void unsetSolver() {
assert(Solver && "Solver not set.");
Solver = nullptr;
}
- /// \brief Add a node with the given costs.
+ /// @brief 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>
@@ -363,9 +387,29 @@ namespace PBQP {
return NId;
}
- /// \brief Add an edge between the given nodes with the given costs.
+ /// @brief 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.
+ ///
+ /// This method allows for fast addition of a node whose costs don't need
+ /// to be passed through the cost allocator. The most common use case for
+ /// this is when duplicating costs from an existing node (when using a
+ /// pooling allocator). These have already been uniqued, so we can avoid
+ /// re-constructing and re-uniquing them by attaching them directly to the
+ /// new node.
+ template <typename OtherVectorPtrT>
+ NodeId addNodeBypassingCostAllocator(OtherVectorPtrT Costs) {
+ NodeId NId = addConstructedNode(NodeEntry(Costs));
+ if (Solver)
+ Solver->handleAddNode(NId);
+ return NId;
+ }
+
+ /// @brief 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.
/// @return Edge iterator for the added edge.
template <typename OtherVectorT>
EdgeId addEdge(NodeId N1Id, NodeId N2Id, OtherVectorT Costs) {
@@ -380,7 +424,32 @@ namespace PBQP {
return EId;
}
- /// \brief Returns true if the graph is empty.
+ /// @brief Add an edge bypassing the cost allocator.
+ /// @param N1Id First node.
+ /// @param N2Id Second node.
+ /// @param Costs Cost matrix for new edge.
+ /// @return Edge iterator for the added edge.
+ ///
+ /// This method allows for fast addition of an edge whose costs don't need
+ /// to be passed through the cost allocator. The most common use case for
+ /// this is when duplicating costs from an existing edge (when using a
+ /// pooling allocator). These have already been uniqued, so we can avoid
+ /// re-constructing and re-uniquing them by attaching them directly to the
+ /// new edge.
+ template <typename OtherMatrixPtrT>
+ NodeId addEdgeBypassingCostAllocator(NodeId N1Id, NodeId N2Id,
+ OtherMatrixPtrT Costs) {
+ assert(getNodeCosts(N1Id).getLength() == Costs->getRows() &&
+ getNodeCosts(N2Id).getLength() == Costs->getCols() &&
+ "Matrix dimensions mismatch.");
+ // Get cost matrix from the problem domain.
+ EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, Costs));
+ if (Solver)
+ Solver->handleAddEdge(EId);
+ return EId;
+ }
+
+ /// @brief Returns true if the graph is empty.
bool empty() const { return NodeIdSet(*this).empty(); }
NodeIdSet nodeIds() const { return NodeIdSet(*this); }
@@ -388,15 +457,15 @@ namespace PBQP {
AdjEdgeIdSet adjEdgeIds(NodeId NId) { return AdjEdgeIdSet(getNode(NId)); }
- /// \brief Get the number of nodes in the graph.
+ /// @brief 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.
+ /// @brief 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.
+ /// @brief Set a node's cost vector.
/// @param NId Node to update.
/// @param Costs New costs to set.
template <typename OtherVectorT>
@@ -407,11 +476,23 @@ namespace PBQP {
getNode(NId).Costs = AllocatedCosts;
}
- /// \brief Get a node's cost vector (const version).
+ /// @brief 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.
+ ///
+ /// This method is primarily useful for duplicating costs quickly by
+ /// bypassing the cost allocator. See addNodeBypassingCostAllocator. Prefer
+ /// getNodeCosts when dealing with node cost values.
+ const VectorPtr& getNodeCostsPtr(NodeId NId) const {
+ return getNode(NId).Costs;
+ }
+
+ /// @brief Get a node's cost vector.
/// @param NId Node id.
/// @return Node cost vector.
const Vector& getNodeCosts(NodeId NId) const {
- return *getNode(NId).Costs;
+ return *getNodeCostsPtr(NId);
}
NodeMetadata& getNodeMetadata(NodeId NId) {
@@ -426,7 +507,7 @@ namespace PBQP {
return getNode(NId).getAdjEdgeIds().size();
}
- /// \brief Set an edge's cost matrix.
+ /// @brief Set an edge's cost matrix.
/// @param EId Edge id.
/// @param Costs New cost matrix.
template <typename OtherMatrixT>
@@ -437,34 +518,48 @@ namespace PBQP {
getEdge(EId).Costs = AllocatedCosts;
}
- /// \brief Get an edge's cost matrix (const version).
+ /// @brief 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.
+ ///
+ /// This method is primarily useful for duplicating costs quickly by
+ /// bypassing the cost allocator. See addNodeBypassingCostAllocator. Prefer
+ /// getEdgeCosts when dealing with edge cost values.
+ const MatrixPtr& getEdgeCostsPtr(EdgeId EId) const {
+ return getEdge(EId).Costs;
+ }
+
+ /// @brief Get an edge's cost matrix.
/// @param EId Edge id.
/// @return Edge cost matrix.
- const Matrix& getEdgeCosts(EdgeId EId) const { return *getEdge(EId).Costs; }
+ const Matrix& getEdgeCosts(EdgeId EId) const {
+ return *getEdge(EId).Costs;
+ }
- EdgeMetadata& getEdgeMetadata(EdgeId NId) {
- return getEdge(NId).Metadata;
+ EdgeMetadata& getEdgeMetadata(EdgeId EId) {
+ return getEdge(EId).Metadata;
}
- const EdgeMetadata& getEdgeMetadata(EdgeId NId) const {
- return getEdge(NId).Metadata;
+ const EdgeMetadata& getEdgeMetadata(EdgeId EId) const {
+ return getEdge(EId).Metadata;
}
- /// \brief Get the first node connected to this edge.
+ /// @brief Get the first node connected to this edge.
/// @param EId Edge id.
/// @return The first node connected to the given edge.
NodeId getEdgeNode1Id(EdgeId EId) {
return getEdge(EId).getN1Id();
}
- /// \brief Get the second node connected to this edge.
+ /// @brief Get the second node connected to this edge.
/// @param EId Edge id.
/// @return The second node connected to the given edge.
NodeId getEdgeNode2Id(EdgeId EId) {
return getEdge(EId).getN2Id();
}
- /// \brief Get the "other" node connected to this edge.
+ /// @brief 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.
@@ -476,7 +571,7 @@ namespace PBQP {
return E.getN1Id();
}
- /// \brief Get the edge connecting two nodes.
+ /// @brief 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,
@@ -491,7 +586,7 @@ namespace PBQP {
return invalidEdgeId();
}
- /// \brief Remove a node from the graph.
+ /// @brief Remove a node from the graph.
/// @param NId Node id.
void removeNode(NodeId NId) {
if (Solver)
@@ -499,7 +594,7 @@ namespace PBQP {
NodeEntry &N = getNode(NId);
// TODO: Can this be for-each'd?
for (AdjEdgeItr AEItr = N.adjEdgesBegin(),
- AEEnd = N.adjEdgesEnd();
+ AEEnd = N.adjEdgesEnd();
AEItr != AEEnd;) {
EdgeId EId = *AEItr;
++AEItr;
@@ -508,7 +603,7 @@ namespace PBQP {
FreeNodeIds.push_back(NId);
}
- /// \brief Disconnect an edge from the given node.
+ /// @brief 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
@@ -541,14 +636,14 @@ namespace PBQP {
E.disconnectFrom(*this, NId);
}
- /// \brief Convenience method to disconnect all neighbours from the given
+ /// @brief 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.
+ /// @brief 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.
@@ -559,7 +654,7 @@ namespace PBQP {
Solver->handleReconnectEdge(EId, NId);
}
- /// \brief Remove an edge from the graph.
+ /// @brief Remove an edge from the graph.
/// @param EId Edge id.
void removeEdge(EdgeId EId) {
if (Solver)
@@ -570,7 +665,7 @@ namespace PBQP {
Edges[EId].invalidate();
}
- /// \brief Remove all nodes and edges from the graph.
+ /// @brief Remove all nodes and edges from the graph.
void clear() {
Nodes.clear();
FreeNodeIds.clear();
@@ -578,9 +673,9 @@ namespace PBQP {
FreeEdgeIds.clear();
}
- /// \brief Dump a graph to an output stream.
+ /// @brief Dump a graph to an output stream.
template <typename OStream>
- void dump(OStream &OS) {
+ void dumpToStream(OStream &OS) {
OS << nodeIds().size() << " " << edgeIds().size() << "\n";
for (auto NId : nodeIds()) {
@@ -613,7 +708,12 @@ namespace PBQP {
}
}
- /// \brief Print a representation of this graph in DOT format.
+ /// @brief Dump this graph to dbgs().
+ void dump() {
+ dumpToStream(dbgs());
+ }
+
+ /// @brief Print a representation of this graph in DOT format.
/// @param OS Output stream to print on.
template <typename OStream>
void printDot(OStream &OS) {
@@ -637,6 +737,7 @@ namespace PBQP {
}
};
-}
+} // namespace PBQP
+} // namespace llvm
#endif // LLVM_CODEGEN_PBQP_GRAPH_HPP
diff --git a/include/llvm/CodeGen/PBQP/Math.h b/include/llvm/CodeGen/PBQP/Math.h
index 69a9d83cc092..2792608e29cc 100644
--- a/include/llvm/CodeGen/PBQP/Math.h
+++ b/include/llvm/CodeGen/PBQP/Math.h
@@ -10,17 +10,19 @@
#ifndef LLVM_CODEGEN_PBQP_MATH_H
#define LLVM_CODEGEN_PBQP_MATH_H
+#include "llvm/ADT/Hashing.h"
#include <algorithm>
#include <cassert>
#include <functional>
+namespace llvm {
namespace PBQP {
typedef float PBQPNum;
/// \brief PBQP Vector class.
class Vector {
- friend class VectorComparator;
+ friend hash_code hash_value(const Vector &);
public:
/// \brief Construct a PBQP vector of the given size.
@@ -136,21 +138,12 @@ private:
PBQPNum *Data;
};
-class VectorComparator {
-public:
- bool operator()(const Vector &A, const Vector &B) {
- if (A.Length < B.Length)
- return true;
- if (B.Length < A.Length)
- return false;
- char *AData = reinterpret_cast<char*>(A.Data);
- char *BData = reinterpret_cast<char*>(B.Data);
- return std::lexicographical_compare(AData,
- AData + A.Length * sizeof(PBQPNum),
- BData,
- BData + A.Length * sizeof(PBQPNum));
- }
-};
+/// \brief Return a hash_value for the given vector.
+inline hash_code hash_value(const Vector &V) {
+ unsigned *VBegin = reinterpret_cast<unsigned*>(V.Data);
+ unsigned *VEnd = reinterpret_cast<unsigned*>(V.Data + 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 stream.
@@ -166,11 +159,10 @@ OStream& operator<<(OStream &OS, const Vector &V) {
return OS;
}
-
/// \brief PBQP Matrix class
class Matrix {
private:
- friend class MatrixComparator;
+ friend hash_code hash_value(const Matrix &);
public:
/// \brief Construct a PBQP Matrix with the given dimensions.
@@ -384,24 +376,12 @@ private:
PBQPNum *Data;
};
-class MatrixComparator {
-public:
- bool operator()(const Matrix &A, const Matrix &B) {
- if (A.Rows < B.Rows)
- return true;
- if (B.Rows < A.Rows)
- return false;
- if (A.Cols < B.Cols)
- return true;
- if (B.Cols < A.Cols)
- return false;
- char *AData = reinterpret_cast<char*>(A.Data);
- char *BData = reinterpret_cast<char*>(B.Data);
- return std::lexicographical_compare(
- AData, AData + (A.Rows * A.Cols * sizeof(PBQPNum)),
- BData, BData + (A.Rows * A.Cols * sizeof(PBQPNum)));
- }
-};
+/// \brief Return a hash_code for the given matrix.
+inline hash_code hash_value(const Matrix &M) {
+ unsigned *MBegin = reinterpret_cast<unsigned*>(M.Data);
+ unsigned *MEnd = reinterpret_cast<unsigned*>(M.Data + (M.Rows * M.Cols));
+ 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 stream.
@@ -409,7 +389,7 @@ template <typename OStream>
OStream& operator<<(OStream &OS, const Matrix &M) {
assert((M.getRows() != 0) && "Zero-row matrix badness.");
for (unsigned i = 0; i < M.getRows(); ++i)
- OS << M.getRowAsVector(i);
+ OS << M.getRowAsVector(i) << "\n";
return OS;
}
@@ -424,6 +404,11 @@ private:
};
template <typename Metadata>
+inline hash_code hash_value(const MDVector<Metadata> &V) {
+ return hash_value(static_cast<const Vector&>(V));
+}
+
+template <typename Metadata>
class MDMatrix : public Matrix {
public:
MDMatrix(const Matrix &m) : Matrix(m), md(*this) { }
@@ -433,6 +418,12 @@ private:
Metadata md;
};
+template <typename Metadata>
+inline hash_code hash_value(const MDMatrix<Metadata> &M) {
+ return hash_value(static_cast<const Matrix&>(M));
}
+} // namespace PBQP
+} // namespace llvm
+
#endif // LLVM_CODEGEN_PBQP_MATH_H
diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h
index a55a06033c4e..21fde4d8a5cd 100644
--- a/include/llvm/CodeGen/PBQP/ReductionRules.h
+++ b/include/llvm/CodeGen/PBQP/ReductionRules.h
@@ -11,13 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_REDUCTIONRULES_H
-#define LLVM_REDUCTIONRULES_H
+#ifndef LLVM_CODEGEN_PBQP_REDUCTIONRULES_H
+#define LLVM_CODEGEN_PBQP_REDUCTIONRULES_H
#include "Graph.h"
#include "Math.h"
#include "Solution.h"
+namespace llvm {
namespace PBQP {
/// \brief Reduce a node of degree one.
@@ -186,6 +187,7 @@ namespace PBQP {
return s;
}
-}
+} // namespace PBQP
+} // namespace llvm
-#endif // LLVM_REDUCTIONRULES_H
+#endif
diff --git a/include/llvm/CodeGen/PBQP/RegAllocSolver.h b/include/llvm/CodeGen/PBQP/RegAllocSolver.h
deleted file mode 100644
index 977c34843bbd..000000000000
--- a/include/llvm/CodeGen/PBQP/RegAllocSolver.h
+++ /dev/null
@@ -1,359 +0,0 @@
-//===-- RegAllocSolver.h - Heuristic PBQP Solver for reg alloc --*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Heuristic PBQP solver for register allocation problems. This solver uses a
-// graph reduction approach. Nodes of degree 0, 1 and 2 are eliminated with
-// optimality-preserving rules (see ReductionRules.h). When no low-degree (<3)
-// nodes are present, a heuristic derived from Brigg's graph coloring approach
-// is used.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H
-#define LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H
-
-#include "CostAllocator.h"
-#include "Graph.h"
-#include "ReductionRules.h"
-#include "Solution.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <limits>
-#include <vector>
-
-namespace PBQP {
-
- namespace RegAlloc {
-
- /// \brief Metadata to speed allocatability test.
- ///
- /// Keeps track of the number of infinities in each row and column.
- class MatrixMetadata {
- private:
- MatrixMetadata(const MatrixMetadata&);
- void operator=(const MatrixMetadata&);
- public:
- MatrixMetadata(const PBQP::Matrix& M)
- : WorstRow(0), WorstCol(0),
- UnsafeRows(new bool[M.getRows() - 1]()),
- UnsafeCols(new bool[M.getCols() - 1]()) {
-
- unsigned* ColCounts = new unsigned[M.getCols() - 1]();
-
- for (unsigned i = 1; i < M.getRows(); ++i) {
- unsigned RowCount = 0;
- for (unsigned j = 1; j < M.getCols(); ++j) {
- if (M[i][j] == std::numeric_limits<PBQP::PBQPNum>::infinity()) {
- ++RowCount;
- ++ColCounts[j - 1];
- UnsafeRows[i - 1] = true;
- UnsafeCols[j - 1] = true;
- }
- }
- WorstRow = std::max(WorstRow, RowCount);
- }
- unsigned WorstColCountForCurRow =
- *std::max_element(ColCounts, ColCounts + M.getCols() - 1);
- WorstCol = std::max(WorstCol, WorstColCountForCurRow);
- delete[] ColCounts;
- }
-
- ~MatrixMetadata() {
- delete[] UnsafeRows;
- delete[] UnsafeCols;
- }
-
- unsigned getWorstRow() const { return WorstRow; }
- unsigned getWorstCol() const { return WorstCol; }
- const bool* getUnsafeRows() const { return UnsafeRows; }
- const bool* getUnsafeCols() const { return UnsafeCols; }
-
- private:
- unsigned WorstRow, WorstCol;
- bool* UnsafeRows;
- bool* UnsafeCols;
- };
-
- class NodeMetadata {
- public:
- typedef enum { Unprocessed,
- OptimallyReducible,
- ConservativelyAllocatable,
- NotProvablyAllocatable } ReductionState;
-
- NodeMetadata() : RS(Unprocessed), DeniedOpts(0), OptUnsafeEdges(nullptr){}
- ~NodeMetadata() { delete[] OptUnsafeEdges; }
-
- void setup(const Vector& Costs) {
- NumOpts = Costs.getLength() - 1;
- OptUnsafeEdges = new unsigned[NumOpts]();
- }
-
- ReductionState getReductionState() const { return RS; }
- void setReductionState(ReductionState RS) { this->RS = RS; }
-
- void handleAddEdge(const MatrixMetadata& MD, bool Transpose) {
- DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow();
- const bool* UnsafeOpts =
- Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows();
- for (unsigned i = 0; i < NumOpts; ++i)
- OptUnsafeEdges[i] += UnsafeOpts[i];
- }
-
- void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) {
- DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow();
- const bool* UnsafeOpts =
- Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows();
- for (unsigned i = 0; i < NumOpts; ++i)
- OptUnsafeEdges[i] -= UnsafeOpts[i];
- }
-
- bool isConservativelyAllocatable() const {
- return (DeniedOpts < NumOpts) ||
- (std::find(OptUnsafeEdges, OptUnsafeEdges + NumOpts, 0) !=
- OptUnsafeEdges + NumOpts);
- }
-
- private:
- ReductionState RS;
- unsigned NumOpts;
- unsigned DeniedOpts;
- unsigned* OptUnsafeEdges;
- };
-
- class RegAllocSolverImpl {
- private:
- typedef PBQP::MDMatrix<MatrixMetadata> RAMatrix;
- public:
- typedef PBQP::Vector RawVector;
- typedef PBQP::Matrix RawMatrix;
- typedef PBQP::Vector Vector;
- typedef RAMatrix Matrix;
- typedef PBQP::PoolCostAllocator<
- Vector, PBQP::VectorComparator,
- Matrix, PBQP::MatrixComparator> CostAllocator;
-
- typedef PBQP::GraphBase::NodeId NodeId;
- typedef PBQP::GraphBase::EdgeId EdgeId;
-
- typedef RegAlloc::NodeMetadata NodeMetadata;
-
- struct EdgeMetadata { };
-
- typedef PBQP::Graph<RegAllocSolverImpl> Graph;
-
- RegAllocSolverImpl(Graph &G) : G(G) {}
-
- Solution solve() {
- G.setSolver(*this);
- Solution S;
- setup();
- S = backpropagate(G, reduce());
- G.unsetSolver();
- return S;
- }
-
- void handleAddNode(NodeId NId) {
- G.getNodeMetadata(NId).setup(G.getNodeCosts(NId));
- }
- void handleRemoveNode(NodeId NId) {}
- void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {}
-
- void handleAddEdge(EdgeId EId) {
- handleReconnectEdge(EId, G.getEdgeNode1Id(EId));
- handleReconnectEdge(EId, G.getEdgeNode2Id(EId));
- }
-
- void handleRemoveEdge(EdgeId EId) {
- handleDisconnectEdge(EId, G.getEdgeNode1Id(EId));
- handleDisconnectEdge(EId, G.getEdgeNode2Id(EId));
- }
-
- void handleDisconnectEdge(EdgeId EId, NodeId NId) {
- NodeMetadata& NMd = G.getNodeMetadata(NId);
- const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata();
- NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId));
- if (G.getNodeDegree(NId) == 3) {
- // This node is becoming optimally reducible.
- moveToOptimallyReducibleNodes(NId);
- } else if (NMd.getReductionState() ==
- NodeMetadata::NotProvablyAllocatable &&
- NMd.isConservativelyAllocatable()) {
- // This node just became conservatively allocatable.
- moveToConservativelyAllocatableNodes(NId);
- }
- }
-
- void handleReconnectEdge(EdgeId EId, NodeId NId) {
- NodeMetadata& NMd = G.getNodeMetadata(NId);
- const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata();
- NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId));
- }
-
- void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) {
- handleRemoveEdge(EId);
-
- NodeId N1Id = G.getEdgeNode1Id(EId);
- NodeId N2Id = G.getEdgeNode2Id(EId);
- NodeMetadata& N1Md = G.getNodeMetadata(N1Id);
- NodeMetadata& N2Md = G.getNodeMetadata(N2Id);
- const MatrixMetadata& MMd = NewCosts.getMetadata();
- N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId));
- N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId));
- }
-
- private:
-
- void removeFromCurrentSet(NodeId NId) {
- switch (G.getNodeMetadata(NId).getReductionState()) {
- case NodeMetadata::Unprocessed: break;
- case NodeMetadata::OptimallyReducible:
- assert(OptimallyReducibleNodes.find(NId) !=
- OptimallyReducibleNodes.end() &&
- "Node not in optimally reducible set.");
- OptimallyReducibleNodes.erase(NId);
- break;
- case NodeMetadata::ConservativelyAllocatable:
- assert(ConservativelyAllocatableNodes.find(NId) !=
- ConservativelyAllocatableNodes.end() &&
- "Node not in conservatively allocatable set.");
- ConservativelyAllocatableNodes.erase(NId);
- break;
- case NodeMetadata::NotProvablyAllocatable:
- assert(NotProvablyAllocatableNodes.find(NId) !=
- NotProvablyAllocatableNodes.end() &&
- "Node not in not-provably-allocatable set.");
- NotProvablyAllocatableNodes.erase(NId);
- break;
- }
- }
-
- void moveToOptimallyReducibleNodes(NodeId NId) {
- removeFromCurrentSet(NId);
- OptimallyReducibleNodes.insert(NId);
- G.getNodeMetadata(NId).setReductionState(
- NodeMetadata::OptimallyReducible);
- }
-
- void moveToConservativelyAllocatableNodes(NodeId NId) {
- removeFromCurrentSet(NId);
- ConservativelyAllocatableNodes.insert(NId);
- G.getNodeMetadata(NId).setReductionState(
- NodeMetadata::ConservativelyAllocatable);
- }
-
- void moveToNotProvablyAllocatableNodes(NodeId NId) {
- removeFromCurrentSet(NId);
- NotProvablyAllocatableNodes.insert(NId);
- G.getNodeMetadata(NId).setReductionState(
- NodeMetadata::NotProvablyAllocatable);
- }
-
- void setup() {
- // Set up worklists.
- for (auto NId : G.nodeIds()) {
- if (G.getNodeDegree(NId) < 3)
- moveToOptimallyReducibleNodes(NId);
- else if (G.getNodeMetadata(NId).isConservativelyAllocatable())
- moveToConservativelyAllocatableNodes(NId);
- else
- moveToNotProvablyAllocatableNodes(NId);
- }
- }
-
- // Compute a reduction order for the graph by iteratively applying PBQP
- // reduction rules. Locally optimal rules are applied whenever possible (R0,
- // R1, R2). If no locally-optimal rules apply then any conservatively
- // allocatable node is reduced. Finally, if no conservatively allocatable
- // node exists then the node with the lowest spill-cost:degree ratio is
- // selected.
- std::vector<GraphBase::NodeId> reduce() {
- assert(!G.empty() && "Cannot reduce empty graph.");
-
- typedef GraphBase::NodeId NodeId;
- std::vector<NodeId> NodeStack;
-
- // Consume worklists.
- while (true) {
- if (!OptimallyReducibleNodes.empty()) {
- NodeSet::iterator NItr = OptimallyReducibleNodes.begin();
- NodeId NId = *NItr;
- OptimallyReducibleNodes.erase(NItr);
- NodeStack.push_back(NId);
- switch (G.getNodeDegree(NId)) {
- case 0:
- break;
- case 1:
- applyR1(G, NId);
- break;
- case 2:
- applyR2(G, NId);
- break;
- default: llvm_unreachable("Not an optimally reducible node.");
- }
- } else if (!ConservativelyAllocatableNodes.empty()) {
- // Conservatively allocatable nodes will never spill. For now just
- // take the first node in the set and push it on the stack. When we
- // start optimizing more heavily for register preferencing, it may
- // would be better to push nodes with lower 'expected' or worst-case
- // register costs first (since early nodes are the most
- // constrained).
- NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin();
- NodeId NId = *NItr;
- ConservativelyAllocatableNodes.erase(NItr);
- NodeStack.push_back(NId);
- G.disconnectAllNeighborsFromNode(NId);
-
- } else if (!NotProvablyAllocatableNodes.empty()) {
- NodeSet::iterator NItr =
- std::min_element(NotProvablyAllocatableNodes.begin(),
- NotProvablyAllocatableNodes.end(),
- SpillCostComparator(G));
- NodeId NId = *NItr;
- NotProvablyAllocatableNodes.erase(NItr);
- NodeStack.push_back(NId);
- G.disconnectAllNeighborsFromNode(NId);
- } else
- break;
- }
-
- return NodeStack;
- }
-
- class SpillCostComparator {
- public:
- SpillCostComparator(const Graph& G) : G(G) {}
- bool operator()(NodeId N1Id, NodeId N2Id) {
- PBQPNum N1SC = G.getNodeCosts(N1Id)[0] / G.getNodeDegree(N1Id);
- PBQPNum N2SC = G.getNodeCosts(N2Id)[0] / G.getNodeDegree(N2Id);
- return N1SC < N2SC;
- }
- private:
- const Graph& G;
- };
-
- Graph& G;
- typedef std::set<NodeId> NodeSet;
- NodeSet OptimallyReducibleNodes;
- NodeSet ConservativelyAllocatableNodes;
- NodeSet NotProvablyAllocatableNodes;
- };
-
- typedef Graph<RegAllocSolverImpl> Graph;
-
- inline Solution solve(Graph& G) {
- if (G.empty())
- return Solution();
- RegAllocSolverImpl RegAllocSolver(G);
- return RegAllocSolver.solve();
- }
-
- }
-}
-
-#endif // LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H
diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h
index 3556e60f3967..a3bfaeb7e6c7 100644
--- a/include/llvm/CodeGen/PBQP/Solution.h
+++ b/include/llvm/CodeGen/PBQP/Solution.h
@@ -18,6 +18,7 @@
#include "Math.h"
#include <map>
+namespace llvm {
namespace PBQP {
/// \brief Represents a solution to a PBQP problem.
@@ -87,6 +88,7 @@ namespace PBQP {
};
-}
+} // namespace PBQP
+} // namespace llvm
#endif // LLVM_CODEGEN_PBQP_SOLUTION_H
diff --git a/include/llvm/CodeGen/PBQPRAConstraint.h b/include/llvm/CodeGen/PBQPRAConstraint.h
new file mode 100644
index 000000000000..833b9bad613f
--- /dev/null
+++ b/include/llvm/CodeGen/PBQPRAConstraint.h
@@ -0,0 +1,69 @@
+//===-- RegAllocPBQP.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PBQPBuilder interface, for classes which build PBQP
+// instances to represent register allocation problems, and the RegAllocPBQP
+// interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_PBQPRACONSTRAINT_H
+#define LLVM_CODEGEN_PBQPRACONSTRAINT_H
+
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace PBQP {
+namespace RegAlloc {
+// Forward declare PBQP graph class.
+class PBQPRAGraph;
+}
+}
+
+class LiveIntervals;
+class MachineBlockFrequencyInfo;
+class MachineFunction;
+class TargetRegisterInfo;
+
+typedef PBQP::RegAlloc::PBQPRAGraph PBQPRAGraph;
+
+/// @brief Abstract base for classes implementing PBQP register allocation
+/// constraints (e.g. Spill-costs, interference, coalescing).
+class PBQPRAConstraint {
+public:
+ virtual ~PBQPRAConstraint() = 0;
+ virtual void apply(PBQPRAGraph &G) = 0;
+private:
+ virtual void anchor();
+};
+
+/// @brief PBQP register allocation constraint composer.
+///
+/// Constraints added to this list will be applied, in the order that they are
+/// added, to the PBQP graph.
+class PBQPRAConstraintList : public PBQPRAConstraint {
+public:
+ void apply(PBQPRAGraph &G) override {
+ for (auto &C : Constraints)
+ C->apply(G);
+ }
+
+ void addConstraint(std::unique_ptr<PBQPRAConstraint> C) {
+ if (C)
+ Constraints.push_back(std::move(C));
+ }
+private:
+ std::vector<std::unique_ptr<PBQPRAConstraint>> Constraints;
+ void anchor() override;
+};
+
+}
+
+#endif /* LLVM_CODEGEN_PBQPRACONSTRAINT_H */
diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index 87f55e8572fe..8ed32b8a8dd5 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -105,6 +105,7 @@ private:
AnalysisID StopAfter;
bool Started;
bool Stopped;
+ bool AddingMachinePasses;
protected:
TargetMachine *TM;
@@ -178,6 +179,10 @@ public:
/// Return true if the optimized regalloc pipeline is enabled.
bool getOptimizeRegAlloc() 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;
+
/// Add common target configurable passes that perform LLVM IR to IR
/// transforms following machine independent optimization.
virtual void addIRPasses();
@@ -255,12 +260,9 @@ protected:
return false;
}
- /// addPreRegAlloc - This method may be implemented by targets that want to
- /// run passes immediately before register allocation. This should return
- /// true if -print-machineinstrs should print after these passes.
- virtual bool addPreRegAlloc() {
- return false;
- }
+ /// This method may be implemented by targets that want to run passes
+ /// immediately before register allocation.
+ virtual void addPreRegAlloc() { }
/// createTargetRegisterAllocator - Create the register allocator pass for
/// this target at the current optimization level.
@@ -286,24 +288,16 @@ protected:
return false;
}
- /// addPostRegAlloc - This method may be implemented by targets that want to
- /// run passes after register allocation pass pipeline but before
- /// prolog-epilog insertion. This should return true if -print-machineinstrs
- /// should print after these passes.
- virtual bool addPostRegAlloc() {
- return false;
- }
+ /// This method may be implemented by targets that want to run passes after
+ /// register allocation pass pipeline but before prolog-epilog insertion.
+ virtual void addPostRegAlloc() { }
/// Add passes that optimize machine instructions after register allocation.
virtual void addMachineLateOptimization();
- /// addPreSched2 - This method may be implemented by targets that want to
- /// run passes after prolog-epilog insertion and before the second instruction
- /// scheduling pass. This should return true if -print-machineinstrs should
- /// print after these passes.
- virtual bool addPreSched2() {
- return false;
- }
+ /// This method may be implemented by targets that want to run passes after
+ /// prolog-epilog insertion and before the second instruction scheduling pass.
+ virtual void addPreSched2() { }
/// addGCPasses - Add late codegen passes that analyze code for garbage
/// collection. This should return true if GC info should be printed after
@@ -313,24 +307,30 @@ protected:
/// Add standard basic block placement passes.
virtual void addBlockPlacement();
- /// addPreEmitPass - This pass may be implemented by targets that want to run
- /// passes immediately before machine code is emitted. This should return
- /// true if -print-machineinstrs should print out the code after the passes.
- virtual bool addPreEmitPass() {
- return false;
- }
+ /// This pass may be implemented by targets that want to run passes
+ /// immediately before machine code is emitted.
+ virtual void addPreEmitPass() { }
/// Utilities for targets to add passes to the pass manager.
///
/// Add a CodeGen pass at this point in the pipeline after checking overrides.
/// Return the pass that was added, or zero if no pass was added.
- AnalysisID addPass(AnalysisID PassID);
+ /// @p printAfter if true and adding a machine function pass add an extra
+ /// machine printer pass afterwards
+ /// @p verifyAfter if true and adding a machine function pass add an extra
+ /// machine verification pass afterwards.
+ AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true,
+ bool printAfter = true);
/// Add a pass to the PassManager if that pass is supposed to be run, as
/// determined by the StartAfter and StopAfter options. Takes ownership of the
/// pass.
- void addPass(Pass *P);
+ /// @p printAfter if true and adding a machine function pass add an extra
+ /// machine printer pass afterwards
+ /// @p verifyAfter if true and adding a machine function pass add an extra
+ /// machine verification pass afterwards.
+ void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true);
/// addMachinePasses helper to create the target-selected or overriden
/// regalloc pass.
@@ -339,13 +339,20 @@ protected:
/// printAndVerify - Add a pass to dump then verify the machine function, if
/// those steps are enabled.
///
- void printAndVerify(const char *Banner);
+ void printAndVerify(const std::string &Banner);
+
+ /// Add a pass to print the machine function if printing is enabled.
+ void addPrintPass(const std::string &Banner);
+
+ /// Add a pass to perform basic verification of the machine function if
+ /// verification is enabled.
+ void addVerifyPass(const std::string &Banner);
};
} // namespace llvm
/// List of target independent CodeGen pass IDs.
namespace llvm {
- FunctionPass *createAtomicExpandLoadLinkedPass(const TargetMachine *TM);
+ FunctionPass *createAtomicExpandPass(const TargetMachine *TM);
/// \brief Create a basic TargetTransformInfo analysis pass.
///
@@ -372,8 +379,9 @@ namespace llvm {
/// matching during instruction selection.
FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr);
- /// AtomicExpandLoadLinkedID -- FIXME
- extern char &AtomicExpandLoadLinkedID;
+ /// AtomicExpandID -- Lowers atomic operations in terms of either cmpxchg
+ /// load-linked/store-conditional loops.
+ extern char &AtomicExpandID;
/// MachineLoopInfo - This pass is a loop analysis pass.
extern char &MachineLoopInfoID;
@@ -489,6 +497,10 @@ namespace llvm {
/// inserting cmov instructions.
extern char &EarlyIfConverterID;
+ /// This pass performs instruction combining using trace metrics to estimate
+ /// critical-path and resource depth.
+ extern char &MachineCombinerID;
+
/// StackSlotColoring - This pass performs stack coloring and merging.
/// It merges disjoint allocas to reduce the stack size.
extern char &StackColoringID;
@@ -551,7 +563,7 @@ namespace llvm {
/// createMachineVerifierPass - This pass verifies cenerated machine code
/// instructions for correctness.
///
- FunctionPass *createMachineVerifierPass(const char *Banner = nullptr);
+ FunctionPass *createMachineVerifierPass(const std::string& Banner);
/// createDwarfEHPass - This pass mulches exception handling code into a form
/// adapted to code generation. Required if using dwarf exception handling.
@@ -593,6 +605,10 @@ namespace llvm {
/// createJumpInstrTables - This pass creates jump-instruction tables.
ModulePass *createJumpInstrTablesPass();
+
+ /// createForwardControlFlowIntegrityPass - This pass adds control-flow
+ /// integrity.
+ ModulePass *createForwardControlFlowIntegrityPass();
} // End llvm namespace
/// This initializer registers TargetMachine constructor, so the pass being
diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h
index 441b0f084e69..eceb790c547d 100644
--- a/include/llvm/CodeGen/RegAllocPBQP.h
+++ b/include/llvm/CodeGen/RegAllocPBQP.h
@@ -16,150 +16,505 @@
#ifndef LLVM_CODEGEN_REGALLOCPBQP_H
#define LLVM_CODEGEN_REGALLOCPBQP_H
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/PBQP/RegAllocSolver.h"
-#include <map>
-#include <set>
+#include "llvm/CodeGen/PBQP/CostAllocator.h"
+#include "llvm/CodeGen/PBQP/ReductionRules.h"
+#include "llvm/CodeGen/PBQPRAConstraint.h"
+#include "llvm/Support/ErrorHandling.h"
namespace llvm {
-
- class LiveIntervals;
- class MachineBlockFrequencyInfo;
- class MachineFunction;
- class TargetRegisterInfo;
-
- typedef PBQP::RegAlloc::Graph PBQPRAGraph;
-
- /// This class wraps up a PBQP instance representing a register allocation
- /// problem, plus the structures necessary to map back from the PBQP solution
- /// to a register allocation solution. (i.e. The PBQP-node <--> vreg map,
- /// and the PBQP option <--> storage location map).
- class PBQPRAProblem {
- public:
-
- typedef SmallVector<unsigned, 16> AllowedSet;
-
- PBQPRAGraph& getGraph() { return graph; }
-
- const PBQPRAGraph& getGraph() const { return graph; }
-
- /// Record the mapping between the given virtual register and PBQP node,
- /// and the set of allowed pregs for the vreg.
- ///
- /// If you are extending
- /// PBQPBuilder you are unlikely to need this: Nodes and options for all
- /// vregs will already have been set up for you by the base class.
- template <typename AllowedRegsItr>
- void recordVReg(unsigned vreg, PBQPRAGraph::NodeId nodeId,
- AllowedRegsItr arBegin, AllowedRegsItr arEnd) {
- assert(node2VReg.find(nodeId) == node2VReg.end() && "Re-mapping node.");
- assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg.");
- assert(allowedSets[vreg].empty() && "vreg already has pregs.");
-
- node2VReg[nodeId] = vreg;
- vreg2Node[vreg] = nodeId;
- std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg]));
+namespace PBQP {
+namespace RegAlloc {
+
+/// @brief Spill option index.
+inline unsigned getSpillOptionIdx() { return 0; }
+
+/// \brief Metadata to speed allocatability test.
+///
+/// Keeps track of the number of infinities in each row and column.
+class MatrixMetadata {
+private:
+ MatrixMetadata(const MatrixMetadata&);
+ void operator=(const MatrixMetadata&);
+public:
+ MatrixMetadata(const Matrix& M)
+ : WorstRow(0), WorstCol(0),
+ UnsafeRows(new bool[M.getRows() - 1]()),
+ UnsafeCols(new bool[M.getCols() - 1]()) {
+
+ unsigned* ColCounts = new unsigned[M.getCols() - 1]();
+
+ for (unsigned i = 1; i < M.getRows(); ++i) {
+ unsigned RowCount = 0;
+ for (unsigned j = 1; j < M.getCols(); ++j) {
+ if (M[i][j] == std::numeric_limits<PBQPNum>::infinity()) {
+ ++RowCount;
+ ++ColCounts[j - 1];
+ UnsafeRows[i - 1] = true;
+ UnsafeCols[j - 1] = true;
+ }
+ }
+ WorstRow = std::max(WorstRow, RowCount);
}
+ unsigned WorstColCountForCurRow =
+ *std::max_element(ColCounts, ColCounts + M.getCols() - 1);
+ WorstCol = std::max(WorstCol, WorstColCountForCurRow);
+ delete[] ColCounts;
+ }
+
+ unsigned getWorstRow() const { return WorstRow; }
+ unsigned getWorstCol() const { return WorstCol; }
+ const bool* getUnsafeRows() const { return UnsafeRows.get(); }
+ const bool* getUnsafeCols() const { return UnsafeCols.get(); }
+
+private:
+ unsigned WorstRow, WorstCol;
+ std::unique_ptr<bool[]> UnsafeRows;
+ std::unique_ptr<bool[]> UnsafeCols;
+};
+
+/// \brief Holds a vector of the allowed physical regs for a vreg.
+class AllowedRegVector {
+ friend hash_code hash_value(const AllowedRegVector &);
+public:
+
+ AllowedRegVector() : NumOpts(0), Opts(nullptr) {}
+
+ AllowedRegVector(const std::vector<unsigned> &OptVec)
+ : NumOpts(OptVec.size()), Opts(new unsigned[NumOpts]) {
+ std::copy(OptVec.begin(), OptVec.end(), Opts.get());
+ }
+
+ AllowedRegVector(const AllowedRegVector &Other)
+ : NumOpts(Other.NumOpts), Opts(new unsigned[NumOpts]) {
+ std::copy(Other.Opts.get(), Other.Opts.get() + NumOpts, Opts.get());
+ }
+
+ AllowedRegVector(AllowedRegVector &&Other)
+ : NumOpts(std::move(Other.NumOpts)), Opts(std::move(Other.Opts)) {}
+
+ AllowedRegVector& operator=(const AllowedRegVector &Other) {
+ NumOpts = Other.NumOpts;
+ Opts.reset(new unsigned[NumOpts]);
+ std::copy(Other.Opts.get(), Other.Opts.get() + NumOpts, Opts.get());
+ return *this;
+ }
+
+ AllowedRegVector& operator=(AllowedRegVector &&Other) {
+ NumOpts = std::move(Other.NumOpts);
+ Opts = std::move(Other.Opts);
+ return *this;
+ }
+
+ unsigned size() const { return NumOpts; }
+ unsigned operator[](size_t I) const { return Opts[I]; }
+
+ bool operator==(const AllowedRegVector &Other) const {
+ if (NumOpts != Other.NumOpts)
+ return false;
+ return std::equal(Opts.get(), Opts.get() + NumOpts, Other.Opts.get());
+ }
+
+ bool operator!=(const AllowedRegVector &Other) const {
+ return !(*this == Other);
+ }
+
+private:
+ unsigned NumOpts;
+ std::unique_ptr<unsigned[]> Opts;
+};
+
+inline hash_code hash_value(const AllowedRegVector &OptRegs) {
+ unsigned *OStart = OptRegs.Opts.get();
+ unsigned *OEnd = OptRegs.Opts.get() + OptRegs.NumOpts;
+ return hash_combine(OptRegs.NumOpts,
+ hash_combine_range(OStart, OEnd));
+}
- /// Get the virtual register corresponding to the given PBQP node.
- unsigned getVRegForNode(PBQPRAGraph::NodeId nodeId) const;
-
- /// Get the PBQP node corresponding to the given virtual register.
- PBQPRAGraph::NodeId getNodeForVReg(unsigned vreg) const;
-
- /// Returns true if the given PBQP option represents a physical register,
- /// false otherwise.
- bool isPRegOption(unsigned vreg, unsigned option) const {
- // At present we only have spills or pregs, so anything that's not a
- // spill is a preg. (This might be extended one day to support remat).
- return !isSpillOption(vreg, option);
+/// \brief Holds graph-level metadata relevent to PBQP RA problems.
+class GraphMetadata {
+private:
+ typedef ValuePool<AllowedRegVector> AllowedRegVecPool;
+public:
+
+ typedef AllowedRegVecPool::PoolRef AllowedRegVecRef;
+
+ GraphMetadata(MachineFunction &MF,
+ LiveIntervals &LIS,
+ MachineBlockFrequencyInfo &MBFI)
+ : MF(MF), LIS(LIS), MBFI(MBFI) {}
+
+ MachineFunction &MF;
+ LiveIntervals &LIS;
+ MachineBlockFrequencyInfo &MBFI;
+
+ void setNodeIdForVReg(unsigned VReg, GraphBase::NodeId NId) {
+ VRegToNodeId[VReg] = NId;
+ }
+
+ GraphBase::NodeId getNodeIdForVReg(unsigned VReg) const {
+ auto VRegItr = VRegToNodeId.find(VReg);
+ if (VRegItr == VRegToNodeId.end())
+ return GraphBase::invalidNodeId();
+ return VRegItr->second;
+ }
+
+ void eraseNodeIdForVReg(unsigned VReg) {
+ VRegToNodeId.erase(VReg);
+ }
+
+ AllowedRegVecRef getAllowedRegs(AllowedRegVector Allowed) {
+ return AllowedRegVecs.getValue(std::move(Allowed));
+ }
+
+private:
+ DenseMap<unsigned, GraphBase::NodeId> VRegToNodeId;
+ AllowedRegVecPool AllowedRegVecs;
+};
+
+/// \brief Holds solver state and other metadata relevant to each PBQP RA node.
+class NodeMetadata {
+public:
+ typedef RegAlloc::AllowedRegVector AllowedRegVector;
+
+ typedef enum { Unprocessed,
+ OptimallyReducible,
+ ConservativelyAllocatable,
+ NotProvablyAllocatable } ReductionState;
+
+ NodeMetadata()
+ : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr),
+ VReg(0) {}
+
+ // FIXME: Re-implementing default behavior to work around MSVC. Remove once
+ // MSVC synthesizes move constructors properly.
+ NodeMetadata(const NodeMetadata &Other)
+ : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts),
+ OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg),
+ AllowedRegs(Other.AllowedRegs) {
+ if (NumOpts > 0) {
+ std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts],
+ &OptUnsafeEdges[0]);
}
-
- /// Returns true if the given PBQP option represents spilling, false
- /// otherwise.
- bool isSpillOption(unsigned vreg, unsigned option) const {
- // We hardcode option zero as the spill option.
- return option == 0;
+ }
+
+ // FIXME: Re-implementing default behavior to work around MSVC. Remove once
+ // MSVC synthesizes move constructors properly.
+ NodeMetadata(NodeMetadata &&Other)
+ : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts),
+ OptUnsafeEdges(std::move(Other.OptUnsafeEdges)), VReg(Other.VReg),
+ AllowedRegs(std::move(Other.AllowedRegs)) {}
+
+ // FIXME: Re-implementing default behavior to work around MSVC. Remove once
+ // MSVC synthesizes move constructors properly.
+ NodeMetadata& operator=(const NodeMetadata &Other) {
+ RS = Other.RS;
+ NumOpts = Other.NumOpts;
+ DeniedOpts = Other.DeniedOpts;
+ OptUnsafeEdges.reset(new unsigned[NumOpts]);
+ std::copy(Other.OptUnsafeEdges.get(), Other.OptUnsafeEdges.get() + NumOpts,
+ OptUnsafeEdges.get());
+ VReg = Other.VReg;
+ AllowedRegs = Other.AllowedRegs;
+ return *this;
+ }
+
+ // FIXME: Re-implementing default behavior to work around MSVC. Remove once
+ // MSVC synthesizes move constructors properly.
+ NodeMetadata& operator=(NodeMetadata &&Other) {
+ RS = Other.RS;
+ NumOpts = Other.NumOpts;
+ DeniedOpts = Other.DeniedOpts;
+ OptUnsafeEdges = std::move(Other.OptUnsafeEdges);
+ VReg = Other.VReg;
+ AllowedRegs = std::move(Other.AllowedRegs);
+ return *this;
+ }
+
+ void setVReg(unsigned VReg) { this->VReg = VReg; }
+ unsigned getVReg() const { return VReg; }
+
+ void setAllowedRegs(GraphMetadata::AllowedRegVecRef AllowedRegs) {
+ this->AllowedRegs = std::move(AllowedRegs);
+ }
+ const AllowedRegVector& getAllowedRegs() const { return *AllowedRegs; }
+
+ void setup(const Vector& Costs) {
+ NumOpts = Costs.getLength() - 1;
+ OptUnsafeEdges = std::unique_ptr<unsigned[]>(new unsigned[NumOpts]());
+ }
+
+ ReductionState getReductionState() const { return RS; }
+ void setReductionState(ReductionState RS) { this->RS = RS; }
+
+ void handleAddEdge(const MatrixMetadata& MD, bool Transpose) {
+ DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow();
+ const bool* UnsafeOpts =
+ Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows();
+ for (unsigned i = 0; i < NumOpts; ++i)
+ OptUnsafeEdges[i] += UnsafeOpts[i];
+ }
+
+ void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) {
+ DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow();
+ const bool* UnsafeOpts =
+ Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows();
+ for (unsigned i = 0; i < NumOpts; ++i)
+ OptUnsafeEdges[i] -= UnsafeOpts[i];
+ }
+
+ bool isConservativelyAllocatable() const {
+ return (DeniedOpts < NumOpts) ||
+ (std::find(&OptUnsafeEdges[0], &OptUnsafeEdges[NumOpts], 0) !=
+ &OptUnsafeEdges[NumOpts]);
+ }
+
+private:
+ ReductionState RS;
+ unsigned NumOpts;
+ unsigned DeniedOpts;
+ std::unique_ptr<unsigned[]> OptUnsafeEdges;
+ unsigned VReg;
+ GraphMetadata::AllowedRegVecRef AllowedRegs;
+};
+
+class RegAllocSolverImpl {
+private:
+ typedef MDMatrix<MatrixMetadata> RAMatrix;
+public:
+ typedef PBQP::Vector RawVector;
+ typedef PBQP::Matrix RawMatrix;
+ typedef PBQP::Vector Vector;
+ typedef RAMatrix Matrix;
+ typedef PBQP::PoolCostAllocator<Vector, Matrix> CostAllocator;
+
+ typedef GraphBase::NodeId NodeId;
+ typedef GraphBase::EdgeId EdgeId;
+
+ typedef RegAlloc::NodeMetadata NodeMetadata;
+ struct EdgeMetadata { };
+ typedef RegAlloc::GraphMetadata GraphMetadata;
+
+ typedef PBQP::Graph<RegAllocSolverImpl> Graph;
+
+ RegAllocSolverImpl(Graph &G) : G(G) {}
+
+ Solution solve() {
+ G.setSolver(*this);
+ Solution S;
+ setup();
+ S = backpropagate(G, reduce());
+ G.unsetSolver();
+ return S;
+ }
+
+ void handleAddNode(NodeId NId) {
+ G.getNodeMetadata(NId).setup(G.getNodeCosts(NId));
+ }
+ void handleRemoveNode(NodeId NId) {}
+ void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {}
+
+ void handleAddEdge(EdgeId EId) {
+ handleReconnectEdge(EId, G.getEdgeNode1Id(EId));
+ handleReconnectEdge(EId, G.getEdgeNode2Id(EId));
+ }
+
+ void handleRemoveEdge(EdgeId EId) {
+ handleDisconnectEdge(EId, G.getEdgeNode1Id(EId));
+ handleDisconnectEdge(EId, G.getEdgeNode2Id(EId));
+ }
+
+ void handleDisconnectEdge(EdgeId EId, NodeId NId) {
+ NodeMetadata& NMd = G.getNodeMetadata(NId);
+ const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata();
+ NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId));
+ if (G.getNodeDegree(NId) == 3) {
+ // This node is becoming optimally reducible.
+ moveToOptimallyReducibleNodes(NId);
+ } else if (NMd.getReductionState() ==
+ NodeMetadata::NotProvablyAllocatable &&
+ NMd.isConservativelyAllocatable()) {
+ // This node just became conservatively allocatable.
+ moveToConservativelyAllocatableNodes(NId);
+ }
+ }
+
+ void handleReconnectEdge(EdgeId EId, NodeId NId) {
+ NodeMetadata& NMd = G.getNodeMetadata(NId);
+ const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata();
+ NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId));
+ }
+
+ void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) {
+ handleRemoveEdge(EId);
+
+ NodeId N1Id = G.getEdgeNode1Id(EId);
+ NodeId N2Id = G.getEdgeNode2Id(EId);
+ NodeMetadata& N1Md = G.getNodeMetadata(N1Id);
+ NodeMetadata& N2Md = G.getNodeMetadata(N2Id);
+ const MatrixMetadata& MMd = NewCosts.getMetadata();
+ N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId));
+ N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId));
+ }
+
+private:
+
+ void removeFromCurrentSet(NodeId NId) {
+ switch (G.getNodeMetadata(NId).getReductionState()) {
+ case NodeMetadata::Unprocessed: break;
+ case NodeMetadata::OptimallyReducible:
+ assert(OptimallyReducibleNodes.find(NId) !=
+ OptimallyReducibleNodes.end() &&
+ "Node not in optimally reducible set.");
+ OptimallyReducibleNodes.erase(NId);
+ break;
+ case NodeMetadata::ConservativelyAllocatable:
+ assert(ConservativelyAllocatableNodes.find(NId) !=
+ ConservativelyAllocatableNodes.end() &&
+ "Node not in conservatively allocatable set.");
+ ConservativelyAllocatableNodes.erase(NId);
+ break;
+ case NodeMetadata::NotProvablyAllocatable:
+ assert(NotProvablyAllocatableNodes.find(NId) !=
+ NotProvablyAllocatableNodes.end() &&
+ "Node not in not-provably-allocatable set.");
+ NotProvablyAllocatableNodes.erase(NId);
+ break;
+ }
+ }
+
+ void moveToOptimallyReducibleNodes(NodeId NId) {
+ removeFromCurrentSet(NId);
+ OptimallyReducibleNodes.insert(NId);
+ G.getNodeMetadata(NId).setReductionState(
+ NodeMetadata::OptimallyReducible);
+ }
+
+ void moveToConservativelyAllocatableNodes(NodeId NId) {
+ removeFromCurrentSet(NId);
+ ConservativelyAllocatableNodes.insert(NId);
+ G.getNodeMetadata(NId).setReductionState(
+ NodeMetadata::ConservativelyAllocatable);
+ }
+
+ void moveToNotProvablyAllocatableNodes(NodeId NId) {
+ removeFromCurrentSet(NId);
+ NotProvablyAllocatableNodes.insert(NId);
+ G.getNodeMetadata(NId).setReductionState(
+ NodeMetadata::NotProvablyAllocatable);
+ }
+
+ void setup() {
+ // Set up worklists.
+ for (auto NId : G.nodeIds()) {
+ if (G.getNodeDegree(NId) < 3)
+ moveToOptimallyReducibleNodes(NId);
+ else if (G.getNodeMetadata(NId).isConservativelyAllocatable())
+ moveToConservativelyAllocatableNodes(NId);
+ else
+ moveToNotProvablyAllocatableNodes(NId);
+ }
+ }
+
+ // Compute a reduction order for the graph by iteratively applying PBQP
+ // reduction rules. Locally optimal rules are applied whenever possible (R0,
+ // R1, R2). If no locally-optimal rules apply then any conservatively
+ // allocatable node is reduced. Finally, if no conservatively allocatable
+ // node exists then the node with the lowest spill-cost:degree ratio is
+ // selected.
+ std::vector<GraphBase::NodeId> reduce() {
+ assert(!G.empty() && "Cannot reduce empty graph.");
+
+ typedef GraphBase::NodeId NodeId;
+ std::vector<NodeId> NodeStack;
+
+ // Consume worklists.
+ while (true) {
+ if (!OptimallyReducibleNodes.empty()) {
+ NodeSet::iterator NItr = OptimallyReducibleNodes.begin();
+ NodeId NId = *NItr;
+ OptimallyReducibleNodes.erase(NItr);
+ NodeStack.push_back(NId);
+ switch (G.getNodeDegree(NId)) {
+ case 0:
+ break;
+ case 1:
+ applyR1(G, NId);
+ break;
+ case 2:
+ applyR2(G, NId);
+ break;
+ default: llvm_unreachable("Not an optimally reducible node.");
+ }
+ } else if (!ConservativelyAllocatableNodes.empty()) {
+ // Conservatively allocatable nodes will never spill. For now just
+ // take the first node in the set and push it on the stack. When we
+ // start optimizing more heavily for register preferencing, it may
+ // would be better to push nodes with lower 'expected' or worst-case
+ // register costs first (since early nodes are the most
+ // constrained).
+ NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin();
+ NodeId NId = *NItr;
+ ConservativelyAllocatableNodes.erase(NItr);
+ NodeStack.push_back(NId);
+ G.disconnectAllNeighborsFromNode(NId);
+
+ } else if (!NotProvablyAllocatableNodes.empty()) {
+ NodeSet::iterator NItr =
+ std::min_element(NotProvablyAllocatableNodes.begin(),
+ NotProvablyAllocatableNodes.end(),
+ SpillCostComparator(G));
+ NodeId NId = *NItr;
+ NotProvablyAllocatableNodes.erase(NItr);
+ NodeStack.push_back(NId);
+ G.disconnectAllNeighborsFromNode(NId);
+ } else
+ break;
}
- /// Returns the allowed set for the given virtual register.
- const AllowedSet& getAllowedSet(unsigned vreg) const;
-
- /// Get PReg for option.
- unsigned getPRegForOption(unsigned vreg, unsigned option) const;
-
- private:
-
- typedef std::map<PBQPRAGraph::NodeId, unsigned> Node2VReg;
- typedef DenseMap<unsigned, PBQPRAGraph::NodeId> VReg2Node;
- typedef DenseMap<unsigned, AllowedSet> AllowedSetMap;
-
- PBQPRAGraph graph;
- Node2VReg node2VReg;
- VReg2Node vreg2Node;
-
- AllowedSetMap allowedSets;
-
- };
+ return NodeStack;
+ }
- /// Builds PBQP instances to represent register allocation problems. Includes
- /// spill, interference and coalescing costs by default. You can extend this
- /// class to support additional constraints for your architecture.
- class PBQPBuilder {
- private:
- PBQPBuilder(const PBQPBuilder&) LLVM_DELETED_FUNCTION;
- void operator=(const PBQPBuilder&) LLVM_DELETED_FUNCTION;
+ class SpillCostComparator {
public:
-
- typedef std::set<unsigned> RegSet;
-
- /// Default constructor.
- PBQPBuilder() {}
-
- /// Clean up a PBQPBuilder.
- virtual ~PBQPBuilder() {}
-
- /// Build a PBQP instance to represent the register allocation problem for
- /// the given MachineFunction.
- virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis,
- const MachineBlockFrequencyInfo *mbfi,
- const RegSet &vregs);
+ SpillCostComparator(const Graph& G) : G(G) {}
+ bool operator()(NodeId N1Id, NodeId N2Id) {
+ PBQPNum N1SC = G.getNodeCosts(N1Id)[0] / G.getNodeDegree(N1Id);
+ PBQPNum N2SC = G.getNodeCosts(N2Id)[0] / G.getNodeDegree(N2Id);
+ return N1SC < N2SC;
+ }
private:
-
- void addSpillCosts(PBQP::Vector &costVec, PBQP::PBQPNum spillCost);
-
- void addInterferenceCosts(PBQP::Matrix &costMat,
- const PBQPRAProblem::AllowedSet &vr1Allowed,
- const PBQPRAProblem::AllowedSet &vr2Allowed,
- const TargetRegisterInfo *tri);
+ const Graph& G;
};
- /// Extended builder which adds coalescing constraints to a problem.
- class PBQPBuilderWithCoalescing : public PBQPBuilder {
- public:
-
- /// Build a PBQP instance to represent the register allocation problem for
- /// the given MachineFunction.
- PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis,
- const MachineBlockFrequencyInfo *mbfi,
- const RegSet &vregs) override;
-
- private:
+ Graph& G;
+ typedef std::set<NodeId> NodeSet;
+ NodeSet OptimallyReducibleNodes;
+ NodeSet ConservativelyAllocatableNodes;
+ NodeSet NotProvablyAllocatableNodes;
+};
+
+class PBQPRAGraph : public PBQP::Graph<RegAllocSolverImpl> {
+private:
+ typedef PBQP::Graph<RegAllocSolverImpl> BaseT;
+public:
+ PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {}
+};
+
+inline Solution solve(PBQPRAGraph& G) {
+ if (G.empty())
+ return Solution();
+ RegAllocSolverImpl RegAllocSolver(G);
+ return RegAllocSolver.solve();
+}
- void addPhysRegCoalesce(PBQP::Vector &costVec, unsigned pregOption,
- PBQP::PBQPNum benefit);
+} // namespace RegAlloc
+} // namespace PBQP
- void addVirtRegCoalesce(PBQP::Matrix &costMat,
- const PBQPRAProblem::AllowedSet &vr1Allowed,
- const PBQPRAProblem::AllowedSet &vr2Allowed,
- PBQP::PBQPNum benefit);
- };
+/// @brief Create a PBQP register allocator instance.
+FunctionPass *
+createPBQPRegisterAllocator(char *customPassID = nullptr);
- FunctionPass *
- createPBQPRegisterAllocator(std::unique_ptr<PBQPBuilder> builder,
- char *customPassID = nullptr);
-}
+} // namespace llvm
#endif /* LLVM_CODEGEN_REGALLOCPBQP_H */
diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h
index 335dd7f084c1..474861e45df1 100644
--- a/include/llvm/CodeGen/RegisterScavenging.h
+++ b/include/llvm/CodeGen/RegisterScavenging.h
@@ -34,7 +34,7 @@ class RegScavenger {
MachineRegisterInfo* MRI;
MachineBasicBlock *MBB;
MachineBasicBlock::iterator MBBI;
- unsigned NumPhysRegs;
+ unsigned NumRegUnits;
/// Tracking - True if RegScavenger is currently tracking the liveness of
/// registers.
@@ -58,22 +58,19 @@ class RegScavenger {
/// A vector of information on scavenged registers.
SmallVector<ScavengedInfo, 2> Scavenged;
- /// CalleeSavedrRegs - A bitvector of callee saved registers for the target.
- ///
- BitVector CalleeSavedRegs;
-
- /// RegsAvailable - The current state of all the physical registers immediately
- /// before MBBI. One bit per physical register. If bit is set that means it's
- /// available, unset means the register is currently being used.
- BitVector RegsAvailable;
+ /// RegUnitsAvailable - The current state of each reg unit immediatelly
+ /// before MBBI. One bit per register unit. If bit is not set it means any
+ /// register containing that register unit is currently being used.
+ BitVector RegUnitsAvailable;
// These BitVectors are only used internally to forward(). They are members
// to avoid frequent reallocations.
- BitVector KillRegs, DefRegs;
+ BitVector KillRegUnits, DefRegUnits;
+ BitVector TmpRegUnits;
public:
RegScavenger()
- : MBB(nullptr), NumPhysRegs(0), Tracking(false) {}
+ : MBB(nullptr), NumRegUnits(0), Tracking(false) {}
/// enterBasicBlock - Start tracking liveness from the begin of the specific
/// basic block.
@@ -112,9 +109,9 @@ public:
MachineBasicBlock::iterator getCurrentPosition() const {
return MBBI;
}
-
- /// getRegsUsed - return all registers currently in use in used.
- void getRegsUsed(BitVector &used, bool includeReserved);
+
+ /// isRegUsed - return if a specific register is currently used.
+ bool isRegUsed(unsigned Reg, bool includeReserved = true) const;
/// getRegsAvailable - Return all available registers in the register class
/// in Mask.
@@ -157,40 +154,29 @@ public:
return scavengeRegister(RegClass, MBBI, SPAdj);
}
- /// setUsed - Tell the scavenger a register is used.
+ /// setRegUsed - Tell the scavenger a register is used.
///
- void setUsed(unsigned Reg);
+ void setRegUsed(unsigned Reg);
private:
/// isReserved - Returns true if a register is reserved. It is never "unused".
bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); }
- /// isUsed - Test if a register is currently being used. When called by the
- /// isAliasUsed function, we only check isReserved if this is the original
- /// register, not an alias register.
+ /// setUsed / setUnused - Mark the state of one or a number of register units.
///
- bool isUsed(unsigned Reg, bool CheckReserved = true) const {
- return !RegsAvailable.test(Reg) || (CheckReserved && isReserved(Reg));
+ void setUsed(BitVector &RegUnits) {
+ RegUnitsAvailable.reset(RegUnits);
}
-
- /// isAliasUsed - Is Reg or an alias currently in use?
- bool isAliasUsed(unsigned Reg) const;
-
- /// setUsed / setUnused - Mark the state of one or a number of registers.
- ///
- void setUsed(BitVector &Regs) {
- RegsAvailable.reset(Regs);
- }
- void setUnused(BitVector &Regs) {
- RegsAvailable |= Regs;
+ void setUnused(BitVector &RegUnits) {
+ RegUnitsAvailable |= RegUnits;
}
- /// Processes the current instruction and fill the KillRegs and DefRegs bit
- /// vectors.
+ /// Processes the current instruction and fill the KillRegUnits and
+ /// DefRegUnits bit vectors.
void determineKillsAndDefs();
-
- /// Add Reg and all its sub-registers to BV.
- void addRegWithSubRegs(BitVector &BV, unsigned Reg);
-
+
+ /// Add all Reg Units that Reg contains to BV.
+ void addRegUnits(BitVector &BV, unsigned Reg);
+
/// findSurvivorReg - Return the candidate register that is unused for the
/// longest after StartMI. UseMI is set to the instruction where the search
/// stopped.
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index 81db8a2f79b5..64c9c4729e92 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -203,6 +203,16 @@ namespace RTLIB {
COPYSIGN_F80,
COPYSIGN_F128,
COPYSIGN_PPCF128,
+ FMIN_F32,
+ FMIN_F64,
+ FMIN_F80,
+ FMIN_F128,
+ FMIN_PPCF128,
+ FMAX_F32,
+ FMAX_F64,
+ FMAX_F80,
+ FMAX_F128,
+ FMAX_PPCF128,
// CONVERSION
FPEXT_F64_F128,
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index 5a65d590802a..80aee8c62880 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -190,6 +190,12 @@ namespace llvm {
return getKind() == Order && Contents.OrdKind == Barrier;
}
+ /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory
+ /// dependence.
+ bool isNormalMemoryOrBarrier() const {
+ return (isNormalMemory() || isBarrier());
+ }
+
/// isMustAlias - Test if this is an Order dependence that is marked
/// as "must alias", meaning that the SUnits at either end of the edge
/// have a memory dependence on a known memory location.
diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h
index e6754a2c0342..00dd8f9a633e 100644
--- a/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -75,8 +75,7 @@ namespace llvm {
/// MachineInstrs.
class ScheduleDAGInstrs : public ScheduleDAG {
protected:
- const MachineLoopInfo &MLI;
- const MachineDominatorTree &MDT;
+ const MachineLoopInfo *MLI;
const MachineFrameInfo *MFI;
/// Live Intervals provides reaching defs in preRA scheduling.
@@ -154,8 +153,7 @@ namespace llvm {
public:
explicit ScheduleDAGInstrs(MachineFunction &mf,
- const MachineLoopInfo &mli,
- const MachineDominatorTree &mdt,
+ const MachineLoopInfo *mli,
bool IsPostRAFlag,
bool RemoveKillFlags = false,
LiveIntervals *LIS = nullptr);
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index bb87f82d2def..4950797bb1e0 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -16,9 +16,11 @@
#define LLVM_CODEGEN_SELECTIONDAG_H
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/ilist.h"
#include "llvm/CodeGen/DAGCombine.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Support/RecyclingAllocator.h"
#include "llvm/Target/TargetMachine.h"
@@ -126,6 +128,10 @@ public:
DbgValMap[Node].push_back(V);
}
+ /// \brief Invalidate all DbgValues attached to the node and remove
+ /// it from the Node-to-DbgValues map.
+ void erase(const SDNode *Node);
+
void clear() {
DbgValMap.clear();
DbgValues.clear();
@@ -166,7 +172,7 @@ void checkForCycles(const SelectionDAG *DAG, bool force = false);
///
class SelectionDAG {
const TargetMachine &TM;
- const TargetSelectionDAGInfo &TSI;
+ const TargetSelectionDAGInfo *TSI;
const TargetLowering *TLI;
MachineFunction *MF;
LLVMContext *Context;
@@ -266,7 +272,7 @@ public:
/// init - Prepare this SelectionDAG to process code in the given
/// MachineFunction.
///
- void init(MachineFunction &mf, const TargetLowering *TLI);
+ void init(MachineFunction &mf);
/// clear - Clear state and free memory necessary to make this
/// SelectionDAG ready to process a new block.
@@ -275,8 +281,9 @@ public:
MachineFunction &getMachineFunction() const { return *MF; }
const TargetMachine &getTarget() const { return TM; }
+ const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); }
const TargetLowering &getTargetLoweringInfo() const { return *TLI; }
- const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; }
+ const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return *TSI; }
LLVMContext *getContext() const {return Context; }
/// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'.
@@ -364,6 +371,27 @@ public:
/// the graph.
void Legalize();
+ /// \brief 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.
+ ///
+ /// \returns true if \c N is a valid, legal node after calling this.
+ ///
+ /// This essentially runs a single recursive walk of the \c Legalize process
+ /// over the given node (and its operands). This can be used to incrementally
+ /// legalize the DAG. All of the nodes which are directly replaced,
+ /// potentially including N, are added to the output parameter \c
+ /// UpdatedNodes so that the delta to the DAG can be understood by the
+ /// caller.
+ ///
+ /// When this returns false, N has been legalized in a way that make the
+ /// pointer passed in no longer valid. It may have even been deleted from the
+ /// DAG, and so it shouldn't be used further. When this returns true, the
+ /// N passed in is a legal node, and can be immediately processed as such.
+ /// This may still have done some work on the DAG, and will still populate
+ /// UpdatedNodes with any new nodes replacing those originally in the DAG.
+ bool LegalizeOp(SDNode *N, SmallSetVector<SDNode *, 16> &UpdatedNodes);
+
/// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG
/// that only uses vector math operations supported by the target. This is
/// necessary as a separate step from Legalize because unrolling a vector
@@ -725,7 +753,7 @@ public:
SDValue SV, unsigned Align);
/// getAtomicCmpSwap - Gets a node for an atomic cmpxchg op. There are two
- /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces a the value loaded and a
+ /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces the value loaded and a
/// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded,
/// a success flag (initially i1), and a chain.
SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs,
@@ -778,7 +806,8 @@ public:
ArrayRef<SDValue> Ops,
EVT MemVT, MachinePointerInfo PtrInfo,
unsigned Align = 0, bool Vol = false,
- bool ReadMem = true, bool WriteMem = true);
+ bool ReadMem = true, bool WriteMem = true,
+ unsigned Size = 0);
SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList,
ArrayRef<SDValue> Ops,
@@ -793,15 +822,15 @@ public:
SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
MachinePointerInfo PtrInfo, bool isVolatile,
bool isNonTemporal, bool isInvariant, unsigned Alignment,
- const MDNode *TBAAInfo = nullptr,
+ const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
MachineMemOperand *MMO);
SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT,
SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo,
EVT MemVT, bool isVolatile,
- bool isNonTemporal, unsigned Alignment,
- const MDNode *TBAAInfo = nullptr);
+ bool isNonTemporal, bool isInvariant, unsigned Alignment,
+ const AAMDNodes &AAInfo = AAMDNodes());
SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT,
SDValue Chain, SDValue Ptr, EVT MemVT,
MachineMemOperand *MMO);
@@ -812,7 +841,7 @@ public:
SDValue Chain, SDValue Ptr, SDValue Offset,
MachinePointerInfo PtrInfo, EVT MemVT,
bool isVolatile, bool isNonTemporal, bool isInvariant,
- unsigned Alignment, const MDNode *TBAAInfo = nullptr,
+ unsigned Alignment, const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr);
SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
EVT VT, SDLoc dl,
@@ -824,19 +853,23 @@ public:
SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
MachinePointerInfo PtrInfo, bool isVolatile,
bool isNonTemporal, unsigned Alignment,
- const MDNode *TBAAInfo = nullptr);
+ const AAMDNodes &AAInfo = AAMDNodes());
SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
MachineMemOperand *MMO);
SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
MachinePointerInfo PtrInfo, EVT TVT,
bool isNonTemporal, bool isVolatile,
unsigned Alignment,
- const MDNode *TBAAInfo = nullptr);
+ const AAMDNodes &AAInfo = AAMDNodes());
SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
EVT TVT, MachineMemOperand *MMO);
SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base,
SDValue Offset, ISD::MemIndexedMode AM);
+ SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
+ SDValue Mask, SDValue Src0, MachineMemOperand *MMO);
+ SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val,
+ SDValue Ptr, SDValue Mask, MachineMemOperand *MMO);
/// getSrcValue - Construct a node to track a Value* through the backend.
SDValue getSrcValue(const Value *v);
@@ -959,15 +992,18 @@ public:
/// getDbgValue - Creates a SDDbgValue node.
///
- SDDbgValue *getDbgValue(MDNode *MDPtr, SDNode *N, unsigned R,
- bool IsIndirect, uint64_t Off,
- DebugLoc DL, unsigned O);
- /// Constant.
- SDDbgValue *getConstantDbgValue(MDNode *MDPtr, const Value *C, uint64_t Off,
- DebugLoc DL, unsigned O);
- /// Frame index.
- SDDbgValue *getFrameIndexDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off,
- DebugLoc DL, unsigned O);
+ /// SDNode
+ SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R,
+ bool IsIndirect, uint64_t Off, DebugLoc DL,
+ unsigned O);
+
+ /// Constant
+ SDDbgValue *getConstantDbgValue(MDNode *Var, MDNode *Expr, const Value *C,
+ uint64_t Off, DebugLoc DL, unsigned O);
+
+ /// FrameIndex
+ SDDbgValue *getFrameIndexDbgValue(MDNode *Var, MDNode *Expr, unsigned FI,
+ uint64_t Off, DebugLoc DL, unsigned O);
/// RemoveDeadNode - Remove the specified node from the system. If any of its
/// operands then becomes dead, remove them as well. Inform UpdateListener
@@ -1039,7 +1075,10 @@ public:
case ISD::SADDO:
case ISD::UADDO:
case ISD::ADDC:
- case ISD::ADDE: return true;
+ case ISD::ADDE:
+ case ISD::FMINNUM:
+ case ISD::FMAXNUM:
+ return true;
default: return false;
}
}
@@ -1198,6 +1237,7 @@ public:
unsigned getEVTAlignment(EVT MemoryVT) const;
private:
+ void InsertNode(SDNode *N);
bool RemoveNodeFromCSEMaps(SDNode *N);
void AddModifiedNodeToCSEMaps(SDNode *N);
SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos);
diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h
index 520be402cfc5..d53e66da5a71 100644
--- a/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/include/llvm/CodeGen/SelectionDAGISel.h
@@ -19,6 +19,7 @@
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/Pass.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
namespace llvm {
class FastISel;
@@ -50,15 +51,16 @@ public:
AliasAnalysis *AA;
GCFunctionInfo *GFI;
CodeGenOpt::Level OptLevel;
+ const TargetInstrInfo *TII;
+ const TargetLowering *TLI;
+
static char ID;
explicit SelectionDAGISel(TargetMachine &tm,
CodeGenOpt::Level OL = CodeGenOpt::Default);
virtual ~SelectionDAGISel();
- const TargetLowering *getTargetLowering() const {
- return TM.getTargetLowering();
- }
+ const TargetLowering *getTargetLowering() const { return TLI; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -238,6 +240,12 @@ public:
const unsigned char *MatcherTable,
unsigned TableSize);
+ /// \brief Return true if complex patterns for this target can mutate the
+ /// DAG.
+ virtual bool ComplexPatternFuncMutatesDAG() const {
+ return false;
+ }
+
private:
// Calls to these functions are generated by tblgen.
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 223151105b0d..8e7fd547626c 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -19,7 +19,6 @@
#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
#define LLVM_CODEGEN_SELECTIONDAGNODES_H
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/GraphTraits.h"
@@ -27,6 +26,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/ValueTypes.h"
@@ -117,11 +117,13 @@ namespace ISD {
/// of information is represented with the SDValue value type.
///
class SDValue {
+ friend struct DenseMapInfo<SDValue>;
+
SDNode *Node; // The node defining the value we are using.
unsigned ResNo; // Which return value of the node we are using.
public:
SDValue() : Node(nullptr), ResNo(0) {}
- SDValue(SDNode *node, unsigned resno) : Node(node), ResNo(resno) {}
+ SDValue(SDNode *node, unsigned resno);
/// get the index which selects a specific result in the SDNode
unsigned getResNo() const { return ResNo; }
@@ -208,10 +210,14 @@ public:
template<> struct DenseMapInfo<SDValue> {
static inline SDValue getEmptyKey() {
- return SDValue((SDNode*)-1, -1U);
+ SDValue V;
+ V.ResNo = -1U;
+ return V;
}
static inline SDValue getTombstoneKey() {
- return SDValue((SDNode*)-1, 0);
+ SDValue V;
+ V.ResNo = -2U;
+ return V;
}
static unsigned getHashValue(const SDValue &Val) {
return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^
@@ -411,6 +417,16 @@ public:
return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE;
}
+ /// Test if this node is a memory intrinsic (with valid pointer information).
+ /// INTRINSIC_W_CHAIN and INTRINSIC_VOID nodes are sometimes created for
+ /// non-memory intrinsics (with chains) that are not really instances of
+ /// MemSDNode. For such nodes, we need some extra state to determine the
+ /// proper classof relationship.
+ bool isMemIntrinsic() const {
+ return (NodeType == ISD::INTRINSIC_W_CHAIN ||
+ NodeType == ISD::INTRINSIC_VOID) && ((SubclassData >> 13) & 1);
+ }
+
/// isMachineOpcode - Test if this node has a post-isel opcode, directly
/// corresponding to a MachineInstr opcode.
bool isMachineOpcode() const { return NodeType < 0; }
@@ -578,7 +594,7 @@ public:
/// changes.
/// NOTE: This is still very expensive. Use carefully.
bool hasPredecessorHelper(const SDNode *N,
- SmallPtrSet<const SDNode *, 32> &Visited,
+ SmallPtrSetImpl<const SDNode *> &Visited,
SmallVectorImpl<const SDNode *> &Worklist) const;
/// getNumOperands - Return the number of values used by this operation.
@@ -746,7 +762,13 @@ protected:
ValueList(VTs.VTs), UseList(nullptr),
NumOperands(Ops.size()), NumValues(VTs.NumVTs),
debugLoc(dl), IROrder(Order) {
+ assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
+ assert(NumOperands == Ops.size() &&
+ "NumOperands wasn't wide enough for its operands!");
+ assert(NumValues == VTs.NumVTs &&
+ "NumValues wasn't wide enough for its operands!");
for (unsigned i = 0; i != Ops.size(); ++i) {
+ assert(OperandList && "no operands available");
OperandList[i].setUser(this);
OperandList[i].setInitial(Ops[i]);
}
@@ -759,7 +781,11 @@ protected:
: NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false),
SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl),
- IROrder(Order) {}
+ IROrder(Order) {
+ assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
+ assert(NumValues == VTs.NumVTs &&
+ "NumValues wasn't wide enough for its operands!");
+ }
/// InitOperands - Initialize the operands list of this with 1 operand.
void InitOperands(SDUse *Ops, const SDValue &Op0) {
@@ -818,6 +844,8 @@ protected:
Ops[i].setInitial(Vals[i]);
}
NumOperands = N;
+ assert(NumOperands == N &&
+ "NumOperands wasn't wide enough for its operands!");
OperandList = Ops;
checkForCycles(this);
}
@@ -877,6 +905,13 @@ public:
// Define inline functions from the SDValue class.
+inline SDValue::SDValue(SDNode *node, unsigned resno)
+ : Node(node), ResNo(resno) {
+ assert((!Node || ResNo < Node->getNumValues()) &&
+ "Invalid result number for the given node!");
+ assert(ResNo < -2U && "Cannot use result numbers reserved for DenseMaps.");
+}
+
inline unsigned SDValue::getOpcode() const {
return Node->getOpcode();
}
@@ -1088,8 +1123,8 @@ public:
// Returns the offset from the location of the access.
int64_t getSrcValueOffset() const { return MMO->getOffset(); }
- /// Returns the TBAAInfo that describes the dereference.
- const MDNode *getTBAAInfo() const { return MMO->getTBAAInfo(); }
+ /// Returns the AA info that describes the dereference.
+ AAMDNodes getAAInfo() const { return MMO->getAAInfo(); }
/// Returns the Ranges that describes the dereference.
const MDNode *getRanges() const { return MMO->getRanges(); }
@@ -1145,6 +1180,9 @@ public:
N->getOpcode() == ISD::ATOMIC_LOAD_UMAX ||
N->getOpcode() == ISD::ATOMIC_LOAD ||
N->getOpcode() == ISD::ATOMIC_STORE ||
+ N->getOpcode() == ISD::MLOAD ||
+ N->getOpcode() == ISD::MSTORE ||
+ N->isMemIntrinsic() ||
N->isTargetMemoryOpcode();
}
};
@@ -1273,14 +1311,14 @@ public:
ArrayRef<SDValue> Ops, EVT MemoryVT,
MachineMemOperand *MMO)
: MemSDNode(Opc, Order, dl, VTs, Ops, MemoryVT, MMO) {
+ SubclassData |= 1u << 13;
}
// Methods to support isa and dyn_cast
static bool classof(const SDNode *N) {
// We lower some target intrinsics to their target opcode
// early a node with a target opcode can be of this class
- return N->getOpcode() == ISD::INTRINSIC_W_CHAIN ||
- N->getOpcode() == ISD::INTRINSIC_VOID ||
+ return N->isMemIntrinsic() ||
N->getOpcode() == ISD::PREFETCH ||
N->isTargetMemoryOpcode();
}
@@ -1380,6 +1418,12 @@ public:
/// isNaN - Return true if the value is a NaN.
bool isNaN() const { return Value->isNaN(); }
+ /// isInfinity - Return true if the value is an infinity
+ bool isInfinity() const { return Value->isInfinity(); }
+
+ /// isNegative - Return true if the value is negative.
+ bool isNegative() const { return Value->isNegative(); }
+
/// isExactlyValue - We don't rely on operator== working on double values, as
/// it returns true for things that are clearly not equal, like -0.0 and 0.0.
/// As such, this method can be used to do an exact bit-for-bit comparison of
@@ -1893,6 +1937,72 @@ public:
}
};
+/// MaskedLoadStoreSDNode - This is a base class is used to represent MLOAD and
+/// MSTORE nodes
+///
+class MaskedLoadStoreSDNode : public MemSDNode {
+ // Operands
+ SDUse Ops[4];
+public:
+ friend class SelectionDAG;
+ MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl,
+ SDValue *Operands, unsigned numOperands,
+ SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
+ : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
+ InitOperands(Ops, Operands, numOperands);
+ }
+
+ // In the both nodes address is Op1, mask is Op2:
+ // MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value
+ // MaskedStoreSDNode (Chain, ptr, mask, data)
+ // Mask is a vector of i1 elements
+ const SDValue &getBasePtr() const { return getOperand(1); }
+ const SDValue &getMask() const { return getOperand(2); }
+
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::MLOAD ||
+ N->getOpcode() == ISD::MSTORE;
+ }
+};
+
+/// MaskedLoadSDNode - This class is used to represent an MLOAD node
+///
+class MaskedLoadSDNode : public MaskedLoadStoreSDNode {
+public:
+ friend class SelectionDAG;
+ MaskedLoadSDNode(unsigned Order, DebugLoc dl,
+ SDValue *Operands, unsigned numOperands,
+ SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
+ : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands,
+ VTs, MemVT, MMO)
+ {}
+
+ const SDValue &getSrc0() const { return getOperand(3); }
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::MLOAD;
+ }
+};
+
+/// MaskedStoreSDNode - This class is used to represent an MSTORE node
+///
+class MaskedStoreSDNode : public MaskedLoadStoreSDNode {
+
+public:
+ friend class SelectionDAG;
+ MaskedStoreSDNode(unsigned Order, DebugLoc dl,
+ SDValue *Operands, unsigned numOperands,
+ SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
+ : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands,
+ VTs, MemVT, MMO)
+ {}
+
+ const SDValue &getData() const { return getOperand(3); }
+
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::MSTORE;
+ }
+};
+
/// MachineSDNode - An SDNode that represents everything that will be needed
/// to construct a MachineInstr. These nodes are created during the
/// instruction selection proper phase.
diff --git a/include/llvm/CodeGen/StackMapLivenessAnalysis.h b/include/llvm/CodeGen/StackMapLivenessAnalysis.h
index 6f0754616206..f67a6e95191d 100644
--- a/include/llvm/CodeGen/StackMapLivenessAnalysis.h
+++ b/include/llvm/CodeGen/StackMapLivenessAnalysis.h
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H
-#define LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H
+#ifndef LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H
+#define LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -61,4 +61,4 @@ private:
} // llvm namespace
-#endif // LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H
+#endif
diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h
index 5eddbb65259e..4e48afe14004 100644
--- a/include/llvm/CodeGen/StackMaps.h
+++ b/include/llvm/CodeGen/StackMaps.h
@@ -8,8 +8,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_STACKMAPS
-#define LLVM_STACKMAPS
+#ifndef LLVM_CODEGEN_STACKMAPS_H
+#define LLVM_CODEGEN_STACKMAPS_H
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
@@ -81,6 +81,52 @@ public:
unsigned getNextScratchIdx(unsigned StartIdx = 0) const;
};
+/// MI-level Statepoint operands
+///
+/// Statepoint operands take the form:
+/// <num call arguments>, <call target>, [call arguments],
+/// <StackMaps::ConstantOp>, <flags>,
+/// <StackMaps::ConstantOp>, <num other args>, [other args],
+/// [gc values]
+class StatepointOpers {
+private:
+ enum {
+ NCallArgsPos = 0,
+ CallTargetPos = 1
+ };
+
+public:
+ explicit StatepointOpers(const MachineInstr *MI):
+ MI(MI) { }
+
+ /// Get starting index of non call related arguments
+ /// (statepoint flags, vm state and gc state).
+ unsigned getVarIdx() const {
+ return MI->getOperand(NCallArgsPos).getImm() + 2;
+ }
+
+ /// Returns the index of the operand containing the number of non-gc non-call
+ /// arguments.
+ unsigned getNumVMSArgsIdx() const {
+ return getVarIdx() + 3;
+ }
+
+ /// Returns the number of non-gc non-call arguments attached to the
+ /// statepoint. Note that this is the number of arguments, not the number of
+ /// operands required to represent those arguments.
+ unsigned getNumVMSArgs() const {
+ return MI->getOperand(getNumVMSArgsIdx()).getImm();
+ }
+
+ /// Returns the target of the underlying call.
+ const MachineOperand &getCallTarget() const {
+ return MI->getOperand(CallTargetPos);
+ }
+
+private:
+ const MachineInstr *MI;
+};
+
class StackMaps {
public:
struct Location {
@@ -118,6 +164,12 @@ public:
StackMaps(AsmPrinter &AP);
+ void reset() {
+ CSInfos.clear();
+ ConstPool.clear();
+ FnStackSize.clear();
+ }
+
/// \brief Generate a stackmap record for a stackmap instruction.
///
/// MI must be a raw STACKMAP, not a PATCHPOINT.
@@ -126,6 +178,9 @@ public:
/// \brief Generate a stackmap record for a patchpoint instruction.
void recordPatchPoint(const MachineInstr &MI);
+ /// \brief Generate a stackmap record for a statepoint instruction.
+ void recordStatepoint(const MachineInstr &MI);
+
/// If there is any stack map data, create a stack map section and serialize
/// the map info into it. This clears the stack map data structures
/// afterwards.
@@ -133,10 +188,9 @@ public:
private:
static const char *WSMP;
-
typedef SmallVector<Location, 8> LocationVec;
typedef SmallVector<LiveOutReg, 8> LiveOutVec;
- typedef MapVector<int64_t, int64_t> ConstantPool;
+ typedef MapVector<uint64_t, uint64_t> ConstantPool;
typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap;
struct CallsiteInfo {
@@ -146,9 +200,9 @@ private:
LiveOutVec LiveOuts;
CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {}
CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,
- LocationVec &Locations, LiveOutVec &LiveOuts)
- : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations),
- LiveOuts(LiveOuts) {}
+ LocationVec &&Locations, LiveOutVec &&LiveOuts)
+ : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)),
+ LiveOuts(std::move(LiveOuts)) {}
};
typedef std::vector<CallsiteInfo> CallsiteInfoList;
@@ -196,4 +250,4 @@ private:
}
-#endif // LLVM_STACKMAPS
+#endif
diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 87f140190a75..9209e1c67c1b 100644
--- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -89,8 +89,6 @@ public:
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
Mangler &Mang, const TargetMachine &TM) const override;
- bool isSectionAtomizableBySymbols(const MCSection &Section) const override;
-
const MCSection *
SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind, Mangler &Mang,
diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h
index 690b70fad89b..b6136665b968 100644
--- a/include/llvm/CodeGen/TargetSchedule.h
+++ b/include/llvm/CodeGen/TargetSchedule.h
@@ -41,7 +41,7 @@ class TargetSchedModel {
unsigned MicroOpFactor; // Multiply to normalize microops to resource units.
unsigned ResourceLCM; // Resource units per cycle. Latency normalization factor.
public:
- TargetSchedModel(): STI(nullptr), TII(nullptr) {}
+ TargetSchedModel(): SchedModel(MCSchedModel::GetDefaultSchedModel()), STI(nullptr), TII(nullptr) {}
/// \brief Initialize the machine model for instruction scheduling.
///
@@ -167,6 +167,7 @@ public:
/// if converter after moving it to TargetSchedModel).
unsigned computeInstrLatency(const MachineInstr *MI,
bool UseDefaultDefLatency = true) const;
+ unsigned computeInstrLatency(unsigned Opcode) const;
/// \brief Output dependency latency of a pair of defs of the same register.
///
diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake
index 996f9ba29a12..d154135e25b2 100644
--- a/include/llvm/Config/config.h.cmake
+++ b/include/llvm/Config/config.h.cmake
@@ -18,6 +18,9 @@
/* Define to enable crash overrides */
#cmakedefine ENABLE_CRASH_OVERRIDES
+/* Define to disable C++ atexit */
+#cmakedefine DISABLE_LLVM_DYLIB_ATEXIT
+
/* Define if position independent code is enabled */
#cmakedefine ENABLE_PIC
@@ -188,6 +191,9 @@
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H}
+/* Define to 1 if you have the <link.h> header file. */
+#cmakedefine HAVE_LINK_H ${HAVE_LINK_H}
+
/* Define if you can use -rdynamic. */
#define HAVE_LINK_EXPORT_DYNAMIC 1
@@ -456,9 +462,6 @@
/* Have host's ___chkstk */
#cmakedefine HAVE____CHKSTK ${HAVE____CHKSTK}
-/* Linker version detected at compile time. */
-#undef HOST_LINK_VERSION
-
/* Define if we link Polly to the tools */
#cmakedefine LINK_POLLY_INTO_TOOLS
@@ -518,9 +521,6 @@
/* Type of 1st arg on ELM Callback */
#cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR}
-/* Define to empty if `const' does not conform to ANSI C. */
-#undef const
-
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
@@ -542,7 +542,4 @@
/* Define to 1 if you have the `_chsize_s' function. */
#cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S}
-/* Maximum path length */
-#cmakedefine MAXPATHLEN ${MAXPATHLEN}
-
#endif
diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in
index beed1182c3f6..ec09c84c5b71 100644
--- a/include/llvm/Config/config.h.in
+++ b/include/llvm/Config/config.h.in
@@ -9,6 +9,9 @@
/* Define if we have libxml2 */
#undef CLANG_HAVE_LIBXML
+/* Multilib suffix for libdir. */
+#undef CLANG_LIBDIR_SUFFIX
+
/* Relative directory for resource files */
#undef CLANG_RESOURCE_DIR
@@ -543,6 +546,9 @@
/* Patch version of the LLVM API */
#undef LLVM_VERSION_PATCH
+/* LLVM version string */
+#undef LLVM_VERSION_STRING
+
/* The shared library extension */
#undef LTDL_SHLIB_EXT
diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake
index 58111644ffa9..77201e6330bb 100644
--- a/include/llvm/Config/llvm-config.h.cmake
+++ b/include/llvm/Config/llvm-config.h.cmake
@@ -92,6 +92,9 @@
/* Minor version of the LLVM API */
#cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR}
+/* LLVM version string */
+#define LLVM_VERSION_STRING "${PACKAGE_VERSION}"
+
/* Define if we link Polly to the tools */
#cmakedefine LINK_POLLY_INTO_TOOLS
diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in
index 5656240eb127..2d6add71a4e0 100644
--- a/include/llvm/Config/llvm-config.h.in
+++ b/include/llvm/Config/llvm-config.h.in
@@ -92,4 +92,7 @@
/* Minor version of the LLVM API */
#undef LLVM_VERSION_MINOR
+/* LLVM version string */
+#undef LLVM_VERSION_STRING
+
#endif
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index c1aba01fbf75..622aa699c435 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -21,7 +21,6 @@
#include "llvm/Object/RelocVisitor.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
-
#include <string>
namespace llvm {
@@ -66,11 +65,15 @@ class DIInliningInfo {
}
};
+/// A DINameKind is passed to name search methods to specify a
+/// preference regarding the type of name resolution the caller wants.
+enum class DINameKind { None, ShortName, LinkageName };
+
/// DILineInfoSpecifier - controls which fields of DILineInfo container
/// should be filled with data.
struct DILineInfoSpecifier {
enum class FileLineInfoKind { None, Default, AbsoluteFilePath };
- enum class FunctionNameKind { None, ShortName, LinkageName };
+ typedef DINameKind FunctionNameKind;
FileLineInfoKind FLIKind;
FunctionNameKind FNKind;
@@ -103,7 +106,11 @@ enum DIDumpType {
DIDT_GnuPubtypes,
DIDT_Str,
DIDT_StrDwo,
- DIDT_StrOffsetsDwo
+ DIDT_StrOffsetsDwo,
+ DIDT_AppleNames,
+ DIDT_AppleTypes,
+ DIDT_AppleNamespaces,
+ DIDT_AppleObjC
};
// In place of applying the relocations to the data we've read from disk we use
@@ -124,7 +131,7 @@ public:
virtual ~DIContext();
/// getDWARFContext - get a context for binary DWARF data.
- static DIContext *getDWARFContext(object::ObjectFile *);
+ static DIContext *getDWARFContext(const object::ObjectFile &Obj);
virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0;
diff --git a/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h
new file mode 100644
index 000000000000..bb05c302be9a
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h
@@ -0,0 +1,60 @@
+//===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
+#define LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/DataExtractor.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFAbbreviationDeclaration {
+ uint32_t Code;
+ uint32_t Tag;
+ bool HasChildren;
+
+ struct AttributeSpec {
+ AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {}
+ uint16_t Attr;
+ uint16_t Form;
+ };
+ typedef SmallVector<AttributeSpec, 8> AttributeSpecVector;
+ AttributeSpecVector AttributeSpecs;
+public:
+ DWARFAbbreviationDeclaration();
+
+ uint32_t getCode() const { return Code; }
+ uint32_t getTag() const { return Tag; }
+ bool hasChildren() const { return HasChildren; }
+
+ typedef iterator_range<AttributeSpecVector::const_iterator>
+ attr_iterator_range;
+
+ attr_iterator_range attributes() const {
+ return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end());
+ }
+
+ uint16_t getFormByIndex(uint32_t idx) const {
+ return idx < AttributeSpecs.size() ? AttributeSpecs[idx].Form : 0;
+ }
+
+ uint32_t findAttributeIndex(uint16_t attr) const;
+ bool extract(DataExtractor Data, uint32_t* OffsetPtr);
+ void dump(raw_ostream &OS) const;
+
+private:
+ void clear();
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARFAcceleratorTable.h
new file mode 100644
index 000000000000..3fbc1c3b3c79
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFAcceleratorTable.h
@@ -0,0 +1,49 @@
+//===--- DWARFAcceleratorTable.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARFRelocMap.h"
+#include <cstdint>
+
+namespace llvm {
+
+class DWARFAcceleratorTable {
+
+ struct Header {
+ uint32_t Magic;
+ uint16_t Version;
+ uint16_t HashFunction;
+ uint32_t NumBuckets;
+ uint32_t NumHashes;
+ uint32_t HeaderDataLength;
+ };
+
+ struct HeaderData {
+ typedef uint16_t AtomType;
+ typedef uint16_t Form;
+ uint32_t DIEOffsetBase;
+ SmallVector<std::pair<AtomType, Form>, 3> Atoms;
+ };
+
+ struct Header Hdr;
+ struct HeaderData HdrData;
+ DataExtractor AccelSection;
+ DataExtractor StringSection;
+ const RelocAddrMap& Relocs;
+public:
+ DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection,
+ const RelocAddrMap &Relocs)
+ : AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {}
+
+ bool extract();
+ void dump(raw_ostream &OS) const;
+};
+
+}
diff --git a/include/llvm/DebugInfo/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARFCompileUnit.h
new file mode 100644
index 000000000000..dbf777cc71aa
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFCompileUnit.h
@@ -0,0 +1,31 @@
+//===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H
+#define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H
+
+#include "llvm/DebugInfo/DWARFUnit.h"
+
+namespace llvm {
+
+class DWARFCompileUnit : public DWARFUnit {
+public:
+ DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
+ StringRef SOS, StringRef AOS, bool LE,
+ const DWARFUnitSectionBase &UnitSection)
+ : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {}
+ void dump(raw_ostream &OS);
+ // VTable anchor.
+ ~DWARFCompileUnit() override;
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFContext.h b/include/llvm/DebugInfo/DWARFContext.h
new file mode 100644
index 000000000000..82b5bb088477
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFContext.h
@@ -0,0 +1,292 @@
+//===-- DWARFContext.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===/
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H
+#define LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARFDebugAranges.h"
+#include "llvm/DebugInfo/DWARFDebugFrame.h"
+#include "llvm/DebugInfo/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARFSection.h"
+#include "llvm/DebugInfo/DWARFTypeUnit.h"
+#include <vector>
+
+namespace llvm {
+
+/// DWARFContext
+/// This data structure is the top level entity that deals with dwarf debug
+/// information parsing. The actual data is supplied through pure virtual
+/// methods that a concrete implementation provides.
+class DWARFContext : public DIContext {
+
+ DWARFUnitSection<DWARFCompileUnit> CUs;
+ std::vector<DWARFUnitSection<DWARFTypeUnit>> TUs;
+ std::unique_ptr<DWARFDebugAbbrev> Abbrev;
+ std::unique_ptr<DWARFDebugLoc> Loc;
+ std::unique_ptr<DWARFDebugAranges> Aranges;
+ std::unique_ptr<DWARFDebugLine> Line;
+ std::unique_ptr<DWARFDebugFrame> DebugFrame;
+
+ DWARFUnitSection<DWARFCompileUnit> DWOCUs;
+ std::vector<DWARFUnitSection<DWARFTypeUnit>> DWOTUs;
+ std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
+ std::unique_ptr<DWARFDebugLocDWO> LocDWO;
+
+ DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION;
+ DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION;
+
+ /// Read compile units from the debug_info section (if necessary)
+ /// and store them in CUs.
+ void parseCompileUnits();
+
+ /// Read type units from the debug_types sections (if necessary)
+ /// and store them in TUs.
+ void parseTypeUnits();
+
+ /// Read compile units from the debug_info.dwo section (if necessary)
+ /// and store them in DWOCUs.
+ void parseDWOCompileUnits();
+
+ /// Read type units from the debug_types.dwo section (if necessary)
+ /// and store them in DWOTUs.
+ void parseDWOTypeUnits();
+
+public:
+ DWARFContext() : DIContext(CK_DWARF) {}
+
+ static bool classof(const DIContext *DICtx) {
+ return DICtx->getKind() == CK_DWARF;
+ }
+
+ void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override;
+
+ typedef DWARFUnitSection<DWARFCompileUnit>::iterator_range cu_iterator_range;
+ typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range;
+ typedef iterator_range<std::vector<DWARFUnitSection<DWARFTypeUnit>>::iterator> tu_section_iterator_range;
+
+ /// Get compile units in this context.
+ cu_iterator_range compile_units() {
+ parseCompileUnits();
+ return cu_iterator_range(CUs.begin(), CUs.end());
+ }
+
+ /// Get type units in this context.
+ tu_section_iterator_range type_unit_sections() {
+ parseTypeUnits();
+ return tu_section_iterator_range(TUs.begin(), TUs.end());
+ }
+
+ /// Get compile units in the DWO context.
+ cu_iterator_range dwo_compile_units() {
+ parseDWOCompileUnits();
+ return cu_iterator_range(DWOCUs.begin(), DWOCUs.end());
+ }
+
+ /// Get type units in the DWO context.
+ tu_section_iterator_range dwo_type_unit_sections() {
+ parseDWOTypeUnits();
+ return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end());
+ }
+
+ /// Get the number of compile units in this context.
+ unsigned getNumCompileUnits() {
+ parseCompileUnits();
+ return CUs.size();
+ }
+
+ /// Get the number of compile units in this context.
+ unsigned getNumTypeUnits() {
+ parseTypeUnits();
+ return TUs.size();
+ }
+
+ /// Get the number of compile units in the DWO context.
+ unsigned getNumDWOCompileUnits() {
+ parseDWOCompileUnits();
+ return DWOCUs.size();
+ }
+
+ /// Get the number of compile units in the DWO context.
+ unsigned getNumDWOTypeUnits() {
+ parseDWOTypeUnits();
+ return DWOTUs.size();
+ }
+
+ /// Get the compile unit at the specified index for this compile unit.
+ DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) {
+ parseCompileUnits();
+ return CUs[index].get();
+ }
+
+ /// Get the compile unit at the specified index for the DWO compile units.
+ DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) {
+ parseDWOCompileUnits();
+ return DWOCUs[index].get();
+ }
+
+ /// Get a pointer to the parsed DebugAbbrev object.
+ const DWARFDebugAbbrev *getDebugAbbrev();
+
+ /// Get a pointer to the parsed DebugLoc object.
+ const DWARFDebugLoc *getDebugLoc();
+
+ /// Get a pointer to the parsed dwo abbreviations object.
+ const DWARFDebugAbbrev *getDebugAbbrevDWO();
+
+ /// Get a pointer to the parsed DebugLoc object.
+ const DWARFDebugLocDWO *getDebugLocDWO();
+
+ /// Get a pointer to the parsed DebugAranges object.
+ const DWARFDebugAranges *getDebugAranges();
+
+ /// Get a pointer to the parsed frame information object.
+ const DWARFDebugFrame *getDebugFrame();
+
+ /// Get a pointer to a parsed line table corresponding to a compile unit.
+ const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu);
+
+ DILineInfo getLineInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+ DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+ DIInliningInfo getInliningInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+
+ virtual bool isLittleEndian() const = 0;
+ virtual uint8_t getAddressSize() const = 0;
+ virtual const DWARFSection &getInfoSection() = 0;
+ typedef MapVector<object::SectionRef, DWARFSection,
+ std::map<object::SectionRef, unsigned>> TypeSectionMap;
+ virtual const TypeSectionMap &getTypesSections() = 0;
+ virtual StringRef getAbbrevSection() = 0;
+ virtual const DWARFSection &getLocSection() = 0;
+ virtual StringRef getARangeSection() = 0;
+ virtual StringRef getDebugFrameSection() = 0;
+ virtual const DWARFSection &getLineSection() = 0;
+ virtual StringRef getStringSection() = 0;
+ virtual StringRef getRangeSection() = 0;
+ virtual StringRef getPubNamesSection() = 0;
+ virtual StringRef getPubTypesSection() = 0;
+ virtual StringRef getGnuPubNamesSection() = 0;
+ virtual StringRef getGnuPubTypesSection() = 0;
+
+ // Sections for DWARF5 split dwarf proposal.
+ virtual const DWARFSection &getInfoDWOSection() = 0;
+ virtual const TypeSectionMap &getTypesDWOSections() = 0;
+ virtual StringRef getAbbrevDWOSection() = 0;
+ virtual const DWARFSection &getLineDWOSection() = 0;
+ virtual const DWARFSection &getLocDWOSection() = 0;
+ virtual StringRef getStringDWOSection() = 0;
+ virtual StringRef getStringOffsetDWOSection() = 0;
+ virtual StringRef getRangeDWOSection() = 0;
+ virtual StringRef getAddrSection() = 0;
+ virtual const DWARFSection& getAppleNamesSection() = 0;
+ virtual const DWARFSection& getAppleTypesSection() = 0;
+ virtual const DWARFSection& getAppleNamespacesSection() = 0;
+ virtual const DWARFSection& getAppleObjCSection() = 0;
+
+ static bool isSupportedVersion(unsigned version) {
+ return version == 2 || version == 3 || version == 4;
+ }
+private:
+ /// Return the compile unit that includes an offset (relative to .debug_info).
+ DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
+
+ /// Return the compile unit which contains instruction with provided
+ /// address.
+ DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
+};
+
+/// DWARFContextInMemory is the simplest possible implementation of a
+/// DWARFContext. It assumes all content is available in memory and stores
+/// pointers to it.
+class DWARFContextInMemory : public DWARFContext {
+ virtual void anchor();
+ bool IsLittleEndian;
+ uint8_t AddressSize;
+ DWARFSection InfoSection;
+ TypeSectionMap TypesSections;
+ StringRef AbbrevSection;
+ DWARFSection LocSection;
+ StringRef ARangeSection;
+ StringRef DebugFrameSection;
+ DWARFSection LineSection;
+ StringRef StringSection;
+ StringRef RangeSection;
+ StringRef PubNamesSection;
+ StringRef PubTypesSection;
+ StringRef GnuPubNamesSection;
+ StringRef GnuPubTypesSection;
+
+ // Sections for DWARF5 split dwarf proposal.
+ DWARFSection InfoDWOSection;
+ TypeSectionMap TypesDWOSections;
+ StringRef AbbrevDWOSection;
+ DWARFSection LineDWOSection;
+ DWARFSection LocDWOSection;
+ StringRef StringDWOSection;
+ StringRef StringOffsetDWOSection;
+ StringRef RangeDWOSection;
+ StringRef AddrSection;
+ DWARFSection AppleNamesSection;
+ DWARFSection AppleTypesSection;
+ DWARFSection AppleNamespacesSection;
+ DWARFSection AppleObjCSection;
+
+ SmallVector<SmallString<32>, 4> UncompressedSections;
+
+public:
+ DWARFContextInMemory(const object::ObjectFile &Obj);
+ bool isLittleEndian() const override { return IsLittleEndian; }
+ uint8_t getAddressSize() const override { return AddressSize; }
+ const DWARFSection &getInfoSection() override { return InfoSection; }
+ const TypeSectionMap &getTypesSections() override { return TypesSections; }
+ StringRef getAbbrevSection() override { return AbbrevSection; }
+ const DWARFSection &getLocSection() override { return LocSection; }
+ StringRef getARangeSection() override { return ARangeSection; }
+ StringRef getDebugFrameSection() override { return DebugFrameSection; }
+ const DWARFSection &getLineSection() override { return LineSection; }
+ StringRef getStringSection() override { return StringSection; }
+ StringRef getRangeSection() override { return RangeSection; }
+ StringRef getPubNamesSection() override { return PubNamesSection; }
+ StringRef getPubTypesSection() override { return PubTypesSection; }
+ StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; }
+ StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; }
+ const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; }
+ const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; }
+ const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; }
+ const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; }
+
+ // Sections for DWARF5 split dwarf proposal.
+ const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; }
+ const TypeSectionMap &getTypesDWOSections() override {
+ return TypesDWOSections;
+ }
+ StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; }
+ const DWARFSection &getLineDWOSection() override { return LineDWOSection; }
+ const DWARFSection &getLocDWOSection() override { return LocDWOSection; }
+ StringRef getStringDWOSection() override { return StringDWOSection; }
+ StringRef getStringOffsetDWOSection() override {
+ return StringOffsetDWOSection;
+ }
+ StringRef getRangeDWOSection() override { return RangeDWOSection; }
+ StringRef getAddrSection() override {
+ return AddrSection;
+ }
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARFDebugAbbrev.h
new file mode 100644
index 000000000000..6752df9cd728
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFDebugAbbrev.h
@@ -0,0 +1,63 @@
+//===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H
+#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H
+
+#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h"
+#include <list>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+class DWARFAbbreviationDeclarationSet {
+ uint32_t Offset;
+ /// Code of the first abbreviation, if all abbreviations in the set have
+ /// consecutive codes. UINT32_MAX otherwise.
+ uint32_t FirstAbbrCode;
+ std::vector<DWARFAbbreviationDeclaration> Decls;
+
+public:
+ DWARFAbbreviationDeclarationSet();
+
+ uint32_t getOffset() const { return Offset; }
+ void dump(raw_ostream &OS) const;
+ bool extract(DataExtractor Data, uint32_t *OffsetPtr);
+
+ const DWARFAbbreviationDeclaration *
+ getAbbreviationDeclaration(uint32_t AbbrCode) const;
+
+private:
+ void clear();
+};
+
+class DWARFDebugAbbrev {
+ typedef std::map<uint64_t, DWARFAbbreviationDeclarationSet>
+ DWARFAbbreviationDeclarationSetMap;
+
+ DWARFAbbreviationDeclarationSetMap AbbrDeclSets;
+ mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos;
+
+public:
+ DWARFDebugAbbrev();
+
+ const DWARFAbbreviationDeclarationSet *
+ getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const;
+
+ void dump(raw_ostream &OS) const;
+ void extract(DataExtractor Data);
+
+private:
+ void clear();
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARFDebugArangeSet.h
new file mode 100644
index 000000000000..837a8e63469e
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFDebugArangeSet.h
@@ -0,0 +1,70 @@
+//===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H
+#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/DataExtractor.h"
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugArangeSet {
+public:
+ struct Header {
+ // The total length of the entries for that set, not including the length
+ // field itself.
+ uint32_t Length;
+ // The offset from the beginning of the .debug_info section of the
+ // compilation unit entry referenced by the table.
+ uint32_t CuOffset;
+ // The DWARF version number.
+ uint16_t Version;
+ // The size in bytes of an address on the target architecture. For segmented
+ // addressing, this is the size of the offset portion of the address.
+ uint8_t AddrSize;
+ // The size in bytes of a segment descriptor on the target architecture.
+ // If the target system uses a flat address space, this value is 0.
+ uint8_t SegSize;
+ };
+
+ struct Descriptor {
+ uint64_t Address;
+ uint64_t Length;
+ uint64_t getEndAddress() const { return Address + Length; }
+ };
+
+private:
+ typedef std::vector<Descriptor> DescriptorColl;
+ typedef iterator_range<DescriptorColl::const_iterator> desc_iterator_range;
+
+ uint32_t Offset;
+ Header HeaderData;
+ DescriptorColl ArangeDescriptors;
+
+public:
+ DWARFDebugArangeSet() { clear(); }
+ void clear();
+ bool extract(DataExtractor data, uint32_t *offset_ptr);
+ void dump(raw_ostream &OS) const;
+
+ uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; }
+
+ desc_iterator_range descriptors() const {
+ return desc_iterator_range(ArangeDescriptors.begin(),
+ ArangeDescriptors.end());
+ }
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARFDebugAranges.h
new file mode 100644
index 000000000000..791f010a8892
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFDebugAranges.h
@@ -0,0 +1,87 @@
+//===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H
+#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H
+
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/DataExtractor.h"
+#include <vector>
+
+namespace llvm {
+
+class DWARFContext;
+
+class DWARFDebugAranges {
+public:
+ void generate(DWARFContext *CTX);
+ uint32_t findAddress(uint64_t Address) const;
+
+private:
+ void clear();
+ void extract(DataExtractor DebugArangesData);
+
+ // Call appendRange multiple times and then call construct.
+ void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC);
+ void construct();
+
+ struct Range {
+ explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL,
+ uint32_t CUOffset = -1U)
+ : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {}
+
+ void setHighPC(uint64_t HighPC) {
+ if (HighPC == -1ULL || HighPC <= LowPC)
+ Length = 0;
+ else
+ Length = HighPC - LowPC;
+ }
+ uint64_t HighPC() const {
+ if (Length)
+ return LowPC + Length;
+ return -1ULL;
+ }
+
+ bool containsAddress(uint64_t Address) const {
+ return LowPC <= Address && Address < HighPC();
+ }
+ bool operator<(const Range &other) const {
+ return LowPC < other.LowPC;
+ }
+
+ uint64_t LowPC; // Start of address range.
+ uint32_t Length; // End of address range (not including this address).
+ uint32_t CUOffset; // Offset of the compile unit or die.
+ };
+
+ struct RangeEndpoint {
+ uint64_t Address;
+ uint32_t CUOffset;
+ bool IsRangeStart;
+
+ RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart)
+ : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {}
+
+ bool operator<(const RangeEndpoint &Other) const {
+ return Address < Other.Address;
+ }
+ };
+
+
+ typedef std::vector<Range> RangeColl;
+ typedef RangeColl::const_iterator RangeCollIterator;
+
+ std::vector<RangeEndpoint> Endpoints;
+ RangeColl Aranges;
+ DenseSet<uint32_t> ParsedCUOffsets;
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARFDebugFrame.h
new file mode 100644
index 000000000000..be925cbe7519
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFDebugFrame.h
@@ -0,0 +1,43 @@
+//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H
+#define LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H
+
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+
+class FrameEntry;
+
+/// \brief A parsed .debug_frame section
+///
+class DWARFDebugFrame {
+public:
+ DWARFDebugFrame();
+ ~DWARFDebugFrame();
+
+ /// \brief Dump the section data into the given stream.
+ void dump(raw_ostream &OS) const;
+
+ /// \brief Parse the section from raw data.
+ /// data is assumed to be pointing to the beginning of the section.
+ void parse(DataExtractor Data);
+
+private:
+ std::vector<std::unique_ptr<FrameEntry>> Entries;
+};
+
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARFDebugInfoEntry.h
new file mode 100644
index 000000000000..f05d64b6f34b
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFDebugInfoEntry.h
@@ -0,0 +1,160 @@
+//===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H
+#define LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARFDebugRangeList.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+class DWARFDebugAranges;
+class DWARFCompileUnit;
+class DWARFUnit;
+class DWARFContext;
+class DWARFFormValue;
+struct DWARFDebugInfoEntryInlinedChain;
+
+/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data.
+class DWARFDebugInfoEntryMinimal {
+ /// Offset within the .debug_info of the start of this entry.
+ uint32_t Offset;
+
+ /// How many to add to "this" to get the sibling.
+ uint32_t SiblingIdx;
+
+ const DWARFAbbreviationDeclaration *AbbrevDecl;
+public:
+ DWARFDebugInfoEntryMinimal()
+ : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {}
+
+ void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth,
+ unsigned indent = 0) const;
+ void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr,
+ uint16_t attr, uint16_t form, unsigned indent = 0) const;
+
+ /// Extracts a debug info entry, which is a child of a given unit,
+ /// starting at a given offset. If DIE can't be extracted, returns false and
+ /// doesn't change OffsetPtr.
+ bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr);
+
+ uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
+ bool isNULL() const { return AbbrevDecl == nullptr; }
+
+ /// Returns true if DIE represents a subprogram (not inlined).
+ bool isSubprogramDIE() const;
+ /// Returns true if DIE represents a subprogram or an inlined
+ /// subroutine.
+ bool isSubroutineDIE() const;
+
+ uint32_t getOffset() const { return Offset; }
+ bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); }
+
+ // We know we are kept in a vector of contiguous entries, so we know
+ // our sibling will be some index after "this".
+ const DWARFDebugInfoEntryMinimal *getSibling() const {
+ return SiblingIdx > 0 ? this + SiblingIdx : nullptr;
+ }
+
+ // We know we are kept in a vector of contiguous entries, so we know
+ // we don't need to store our child pointer, if we have a child it will
+ // be the next entry in the list...
+ const DWARFDebugInfoEntryMinimal *getFirstChild() const {
+ return hasChildren() ? this + 1 : nullptr;
+ }
+
+ void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) {
+ if (Sibling) {
+ // We know we are kept in a vector of contiguous entries, so we know
+ // our sibling will be some index after "this".
+ SiblingIdx = Sibling - this;
+ } else
+ SiblingIdx = 0;
+ }
+
+ const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
+ return AbbrevDecl;
+ }
+
+ bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr,
+ DWARFFormValue &FormValue) const;
+
+ const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr,
+ const char *FailValue) const;
+
+ uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr,
+ uint64_t FailValue) const;
+
+ uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U,
+ const uint16_t Attr,
+ uint64_t FailValue) const;
+
+ uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr,
+ uint64_t FailValue) const;
+
+ uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U,
+ const uint16_t Attr,
+ uint64_t FailValue) const;
+
+ uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const;
+
+ /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
+ /// Returns true if both attributes are present.
+ bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
+ uint64_t &HighPC) const;
+
+ DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const;
+
+ void collectChildrenAddressRanges(const DWARFUnit *U,
+ DWARFAddressRangesVector &Ranges) const;
+
+ bool addressRangeContainsAddress(const DWARFUnit *U,
+ const uint64_t Address) const;
+
+ /// If a DIE represents a subprogram (or inlined subroutine),
+ /// returns its mangled name (or short name, if mangled is missing).
+ /// This name may be fetched from specification or abstract origin
+ /// for this subprogram. Returns null if no name is found.
+ const char *getSubroutineName(const DWARFUnit *U, DINameKind Kind) const;
+
+ /// Return the DIE name resolving DW_AT_sepcification or
+ /// DW_AT_abstract_origin references if necessary.
+ /// Returns null if no name is found.
+ const char *getName(const DWARFUnit *U, DINameKind Kind) const;
+
+ /// Retrieves values of DW_AT_call_file, DW_AT_call_line and
+ /// DW_AT_call_column from DIE (or zeroes if they are missing).
+ void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile,
+ uint32_t &CallLine, uint32_t &CallColumn) const;
+
+ /// Get inlined chain for a given address, rooted at the current DIE.
+ /// Returns empty chain if address is not contained in address range
+ /// of current DIE.
+ DWARFDebugInfoEntryInlinedChain
+ getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const;
+};
+
+/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine
+/// DIEs, (possibly ending with subprogram DIE), all of which are contained
+/// in some concrete inlined instance tree. Address range for each DIE
+/// (except the last DIE) in this chain is contained in address
+/// range for next DIE in the chain.
+struct DWARFDebugInfoEntryInlinedChain {
+ DWARFDebugInfoEntryInlinedChain() : U(nullptr) {}
+ SmallVector<DWARFDebugInfoEntryMinimal, 4> DIEs;
+ const DWARFUnit *U;
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARFDebugLine.h
new file mode 100644
index 000000000000..c5ee76e39682
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFDebugLine.h
@@ -0,0 +1,238 @@
+//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H
+#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H
+
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARFRelocMap.h"
+#include "llvm/Support/DataExtractor.h"
+#include <map>
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugLine {
+public:
+ DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {}
+ struct FileNameEntry {
+ FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {}
+
+ const char *Name;
+ uint64_t DirIdx;
+ uint64_t ModTime;
+ uint64_t Length;
+ };
+
+ struct Prologue {
+ Prologue();
+
+ // The size in bytes of the statement information for this compilation unit
+ // (not including the total_length field itself).
+ uint32_t TotalLength;
+ // Version identifier for the statement information format.
+ uint16_t Version;
+ // The number of bytes following the prologue_length field to the beginning
+ // of the first byte of the statement program itself.
+ uint32_t PrologueLength;
+ // The size in bytes of the smallest target machine instruction. Statement
+ // program opcodes that alter the address register first multiply their
+ // operands by this value.
+ uint8_t MinInstLength;
+ // The maximum number of individual operations that may be encoded in an
+ // instruction.
+ uint8_t MaxOpsPerInst;
+ // The initial value of theis_stmtregister.
+ uint8_t DefaultIsStmt;
+ // This parameter affects the meaning of the special opcodes. See below.
+ int8_t LineBase;
+ // This parameter affects the meaning of the special opcodes. See below.
+ uint8_t LineRange;
+ // The number assigned to the first special opcode.
+ uint8_t OpcodeBase;
+ std::vector<uint8_t> StandardOpcodeLengths;
+ std::vector<const char*> IncludeDirectories;
+ std::vector<FileNameEntry> FileNames;
+
+ // Length of the prologue in bytes.
+ uint32_t getLength() const {
+ return PrologueLength + sizeof(TotalLength) + sizeof(Version) +
+ sizeof(PrologueLength);
+ }
+ // Length of the line table data in bytes (not including the prologue).
+ uint32_t getStatementTableLength() const {
+ return TotalLength + sizeof(TotalLength) - getLength();
+ }
+ int32_t getMaxLineIncrementForSpecialOpcode() const {
+ return LineBase + (int8_t)LineRange - 1;
+ }
+
+ void clear();
+ void dump(raw_ostream &OS) const;
+ bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr);
+ };
+
+ // Standard .debug_line state machine structure.
+ struct Row {
+ explicit Row(bool default_is_stmt = false);
+
+ /// Called after a row is appended to the matrix.
+ void postAppend();
+ void reset(bool default_is_stmt);
+ void dump(raw_ostream &OS) const;
+
+ static bool orderByAddress(const Row& LHS, const Row& RHS) {
+ return LHS.Address < RHS.Address;
+ }
+
+ // The program-counter value corresponding to a machine instruction
+ // generated by the compiler.
+ uint64_t Address;
+ // An unsigned integer indicating a source line number. Lines are numbered
+ // beginning at 1. The compiler may emit the value 0 in cases where an
+ // instruction cannot be attributed to any source line.
+ uint32_t Line;
+ // An unsigned integer indicating a column number within a source line.
+ // Columns are numbered beginning at 1. The value 0 is reserved to indicate
+ // that a statement begins at the 'left edge' of the line.
+ uint16_t Column;
+ // An unsigned integer indicating the identity of the source file
+ // corresponding to a machine instruction.
+ uint16_t File;
+ // An unsigned integer whose value encodes the applicable instruction set
+ // architecture for the current instruction.
+ uint8_t Isa;
+ // An unsigned integer representing the DWARF path discriminator value
+ // for this location.
+ uint32_t Discriminator;
+ // A boolean indicating that the current instruction is the beginning of a
+ // statement.
+ uint8_t IsStmt:1,
+ // A boolean indicating that the current instruction is the
+ // beginning of a basic block.
+ BasicBlock:1,
+ // A boolean indicating that the current address is that of the
+ // first byte after the end of a sequence of target machine
+ // instructions.
+ EndSequence:1,
+ // A boolean indicating that the current address is one (of possibly
+ // many) where execution should be suspended for an entry breakpoint
+ // of a function.
+ PrologueEnd:1,
+ // A boolean indicating that the current address is one (of possibly
+ // many) where execution should be suspended for an exit breakpoint
+ // of a function.
+ EpilogueBegin:1;
+ };
+
+ // Represents a series of contiguous machine instructions. Line table for each
+ // compilation unit may consist of multiple sequences, which are not
+ // guaranteed to be in the order of ascending instruction address.
+ struct Sequence {
+ // Sequence describes instructions at address range [LowPC, HighPC)
+ // and is described by line table rows [FirstRowIndex, LastRowIndex).
+ uint64_t LowPC;
+ uint64_t HighPC;
+ unsigned FirstRowIndex;
+ unsigned LastRowIndex;
+ bool Empty;
+
+ Sequence();
+ void reset();
+
+ static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) {
+ return LHS.LowPC < RHS.LowPC;
+ }
+ bool isValid() const {
+ return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex);
+ }
+ bool containsPC(uint64_t pc) const {
+ return (LowPC <= pc && pc < HighPC);
+ }
+ };
+
+ struct LineTable {
+ LineTable();
+
+ void appendRow(const DWARFDebugLine::Row &R) {
+ Rows.push_back(R);
+ }
+ void appendSequence(const DWARFDebugLine::Sequence &S) {
+ Sequences.push_back(S);
+ }
+
+ // Returns the index of the row with file/line info for a given address,
+ // or -1 if there is no such row.
+ uint32_t lookupAddress(uint64_t address) const;
+
+ bool lookupAddressRange(uint64_t address, uint64_t size,
+ std::vector<uint32_t> &result) const;
+
+ // Extracts filename by its index in filename table in prologue.
+ // Returns true on success.
+ bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir,
+ DILineInfoSpecifier::FileLineInfoKind Kind,
+ std::string &Result) const;
+
+ // Fills the Result argument with the file and line information
+ // corresponding to Address. Returns true on success.
+ bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir,
+ DILineInfoSpecifier::FileLineInfoKind Kind,
+ DILineInfo &Result) const;
+
+ void dump(raw_ostream &OS) const;
+ void clear();
+
+ /// Parse prologue and all rows.
+ bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap,
+ uint32_t *offset_ptr);
+
+ struct Prologue Prologue;
+ typedef std::vector<Row> RowVector;
+ typedef RowVector::const_iterator RowIter;
+ typedef std::vector<Sequence> SequenceVector;
+ typedef SequenceVector::const_iterator SequenceIter;
+ RowVector Rows;
+ SequenceVector Sequences;
+ };
+
+ const LineTable *getLineTable(uint32_t offset) const;
+ const LineTable *getOrParseLineTable(DataExtractor debug_line_data,
+ uint32_t offset);
+
+private:
+ struct ParsingState {
+ ParsingState(struct LineTable *LT);
+
+ void resetRowAndSequence();
+ void appendRowToMatrix(uint32_t offset);
+
+ // Line table we're currently parsing.
+ struct LineTable *LineTable;
+ // The row number that starts at zero for the prologue, and increases for
+ // each row added to the matrix.
+ unsigned RowNumber;
+ struct Row Row;
+ struct Sequence Sequence;
+ };
+
+ typedef std::map<uint32_t, LineTable> LineTableMapTy;
+ typedef LineTableMapTy::iterator LineTableIter;
+ typedef LineTableMapTy::const_iterator LineTableConstIter;
+
+ const RelocAddrMap *RelocMap;
+ LineTableMapTy LineTableMap;
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARFDebugLoc.h
new file mode 100644
index 000000000000..a6135a0c9291
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFDebugLoc.h
@@ -0,0 +1,81 @@
+//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H
+#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/DWARFRelocMap.h"
+#include "llvm/Support/DataExtractor.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugLoc {
+ /// A single location within a location list.
+ struct Entry {
+ /// The beginning address of the instruction range.
+ uint64_t Begin;
+ /// The ending address of the instruction range.
+ uint64_t End;
+ /// The location of the variable within the specified range.
+ SmallVector<unsigned char, 4> Loc;
+ };
+
+ /// A list of locations that contain one variable.
+ struct LocationList {
+ /// The beginning offset where this location list is stored in the debug_loc
+ /// section.
+ unsigned Offset;
+ /// All the locations in which the variable is stored.
+ SmallVector<Entry, 2> Entries;
+ };
+
+ typedef SmallVector<LocationList, 4> LocationLists;
+
+ /// A list of all the variables in the debug_loc section, each one describing
+ /// the locations in which the variable is stored.
+ LocationLists Locations;
+
+ /// A map used to resolve binary relocations.
+ const RelocAddrMap &RelocMap;
+
+public:
+ DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {}
+ /// Print the location lists found within the debug_loc section.
+ void dump(raw_ostream &OS) const;
+ /// Parse the debug_loc section accessible via the 'data' parameter using the
+ /// specified address size to interpret the address ranges.
+ void parse(DataExtractor data, unsigned AddressSize);
+};
+
+class DWARFDebugLocDWO {
+ struct Entry {
+ uint64_t Start;
+ uint32_t Length;
+ SmallVector<unsigned char, 4> Loc;
+ };
+
+ struct LocationList {
+ unsigned Offset;
+ SmallVector<Entry, 2> Entries;
+ };
+
+ typedef SmallVector<LocationList, 4> LocationLists;
+
+ LocationLists Locations;
+
+public:
+ void parse(DataExtractor data);
+ void dump(raw_ostream &OS) const;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARFDebugRangeList.h
new file mode 100644
index 000000000000..4ee3bdad3299
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFDebugRangeList.h
@@ -0,0 +1,77 @@
+//===-- DWARFDebugRangeList.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H
+#define LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H
+
+#include "llvm/Support/DataExtractor.h"
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+/// DWARFAddressRangesVector - represents a set of absolute address ranges.
+typedef std::vector<std::pair<uint64_t, uint64_t>> DWARFAddressRangesVector;
+
+class DWARFDebugRangeList {
+public:
+ struct RangeListEntry {
+ // A beginning address offset. This address offset has the size of an
+ // address and is relative to the applicable base address of the
+ // compilation unit referencing this range list. It marks the beginning
+ // of an address range.
+ uint64_t StartAddress;
+ // An ending address offset. This address offset again has the size of
+ // an address and is relative to the applicable base address of the
+ // compilation unit referencing this range list. It marks the first
+ // address past the end of the address range. The ending address must
+ // be greater than or equal to the beginning address.
+ uint64_t EndAddress;
+ // The end of any given range list is marked by an end of list entry,
+ // which consists of a 0 for the beginning address offset
+ // and a 0 for the ending address offset.
+ bool isEndOfListEntry() const {
+ return (StartAddress == 0) && (EndAddress == 0);
+ }
+ // A base address selection entry consists of:
+ // 1. The value of the largest representable address offset
+ // (for example, 0xffffffff when the size of an address is 32 bits).
+ // 2. An address, which defines the appropriate base address for
+ // use in interpreting the beginning and ending address offsets of
+ // subsequent entries of the location list.
+ bool isBaseAddressSelectionEntry(uint8_t AddressSize) const {
+ assert(AddressSize == 4 || AddressSize == 8);
+ if (AddressSize == 4)
+ return StartAddress == -1U;
+ else
+ return StartAddress == -1ULL;
+ }
+ };
+
+private:
+ // Offset in .debug_ranges section.
+ uint32_t Offset;
+ uint8_t AddressSize;
+ std::vector<RangeListEntry> Entries;
+
+public:
+ DWARFDebugRangeList() { clear(); }
+ void clear();
+ void dump(raw_ostream &OS) const;
+ bool extract(DataExtractor data, uint32_t *offset_ptr);
+ /// getAbsoluteRanges - Returns absolute address ranges defined by this range
+ /// list. Has to be passed base address of the compile unit referencing this
+ /// range list.
+ DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const;
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H
diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h
index d517a72d62e0..5bb6d1b9ddb0 100644
--- a/include/llvm/DebugInfo/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARFFormValue.h
@@ -57,6 +57,13 @@ public:
bool isFormClass(FormClass FC) const;
void dump(raw_ostream &OS, const DWARFUnit *U) const;
+
+ /// \brief extracts a value in data at offset *offset_ptr.
+ ///
+ /// The passed DWARFUnit is allowed to be nullptr, in which
+ /// case no relocation processing will be performed and some
+ /// kind of forms that depend on Unit information are disallowed.
+ /// \returns wether the extraction succeeded.
bool extractValue(DataExtractor data, uint32_t *offset_ptr,
const DWARFUnit *u);
bool isInlinedCStr() const {
@@ -70,6 +77,7 @@ public:
Optional<const char *> getAsCString(const DWARFUnit *U) const;
Optional<uint64_t> getAsAddress(const DWARFUnit *U) const;
Optional<uint64_t> getAsSectionOffset() const;
+ Optional<ArrayRef<uint8_t>> getAsBlock() const;
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
const DWARFUnit *u) const;
diff --git a/include/llvm/DebugInfo/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARFRelocMap.h
new file mode 100644
index 000000000000..d7fe3032e505
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFRelocMap.h
@@ -0,0 +1,22 @@
+//===-- DWARFRelocMap.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H
+#define LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+
+typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
+
+} // namespace llvm
+
+#endif
+
diff --git a/include/llvm/DebugInfo/DWARFSection.h b/include/llvm/DebugInfo/DWARFSection.h
new file mode 100644
index 000000000000..5f09d9e37d81
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFSection.h
@@ -0,0 +1,24 @@
+//===-- DWARFSection.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFSECTION_H
+#define LLVM_LIB_DEBUGINFO_DWARFSECTION_H
+
+#include "llvm/DebugInfo/DWARFRelocMap.h"
+
+namespace llvm {
+
+struct DWARFSection {
+ StringRef Data;
+ RelocAddrMap Relocs;
+};
+
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARFTypeUnit.h
new file mode 100644
index 000000000000..213b54139e04
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFTypeUnit.h
@@ -0,0 +1,38 @@
+//===-- DWARFTypeUnit.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H
+#define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H
+
+#include "llvm/DebugInfo/DWARFUnit.h"
+
+namespace llvm {
+
+class DWARFTypeUnit : public DWARFUnit {
+private:
+ uint64_t TypeHash;
+ uint32_t TypeOffset;
+public:
+ DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
+ StringRef SOS, StringRef AOS, bool LE,
+ const DWARFUnitSectionBase &UnitSection)
+ : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {}
+ uint32_t getHeaderSize() const override {
+ return DWARFUnit::getHeaderSize() + 12;
+ }
+ void dump(raw_ostream &OS);
+protected:
+ bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override;
+};
+
+}
+
+#endif
+
diff --git a/include/llvm/DebugInfo/DWARFUnit.h b/include/llvm/DebugInfo/DWARFUnit.h
new file mode 100644
index 000000000000..d71a1b60b731
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARFUnit.h
@@ -0,0 +1,245 @@
+//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H
+#define LLVM_LIB_DEBUGINFO_DWARFUNIT_H
+
+#include "llvm/DebugInfo/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARFSection.h"
+#include <vector>
+
+namespace llvm {
+
+namespace object {
+class ObjectFile;
+}
+
+class DWARFContext;
+class DWARFDebugAbbrev;
+class DWARFUnit;
+class StringRef;
+class raw_ostream;
+
+/// Base class for all DWARFUnitSection classes. This provides the
+/// functionality common to all unit types.
+class DWARFUnitSectionBase {
+public:
+ /// Returns the Unit that contains the given section offset in the
+ /// same section this Unit originated from.
+ virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0;
+
+ void parse(DWARFContext &C, const DWARFSection &Section);
+ void parseDWO(DWARFContext &C, const DWARFSection &DWOSection);
+
+protected:
+ virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
+ StringRef SOS, StringRef AOS, bool isLittleEndian) = 0;
+
+ ~DWARFUnitSectionBase() {}
+};
+
+/// Concrete instance of DWARFUnitSection, specialized for one Unit type.
+template<typename UnitType>
+class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
+ public DWARFUnitSectionBase {
+
+ struct UnitOffsetComparator {
+ bool operator()(uint32_t LHS,
+ const std::unique_ptr<UnitType> &RHS) const {
+ return LHS < RHS->getNextUnitOffset();
+ }
+ };
+
+ bool Parsed;
+
+public:
+ DWARFUnitSection() : Parsed(false) {}
+ DWARFUnitSection(DWARFUnitSection &&DUS) :
+ SmallVector<std::unique_ptr<UnitType>, 1>(std::move(DUS)), Parsed(DUS.Parsed) {}
+
+ typedef llvm::SmallVectorImpl<std::unique_ptr<UnitType>> UnitVector;
+ typedef typename UnitVector::iterator iterator;
+ typedef llvm::iterator_range<typename UnitVector::iterator> iterator_range;
+
+ UnitType *getUnitForOffset(uint32_t Offset) const override {
+ auto *CU = std::upper_bound(this->begin(), this->end(), Offset,
+ UnitOffsetComparator());
+ if (CU != this->end())
+ return CU->get();
+ return nullptr;
+ }
+
+private:
+ void parseImpl(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
+ StringRef SOS, StringRef AOS, bool LE) override {
+ if (Parsed)
+ return;
+ DataExtractor Data(Section.Data, LE, 0);
+ uint32_t Offset = 0;
+ while (Data.isValidOffset(Offset)) {
+ auto U = llvm::make_unique<UnitType>(Context, Section, DA, RS, SS, SOS,
+ AOS, LE, *this);
+ if (!U->extract(Data, &Offset))
+ break;
+ this->push_back(std::move(U));
+ Offset = this->back()->getNextUnitOffset();
+ }
+ Parsed = true;
+ }
+};
+
+class DWARFUnit {
+ DWARFContext &Context;
+ // Section containing this DWARFUnit.
+ const DWARFSection &InfoSection;
+
+ const DWARFDebugAbbrev *Abbrev;
+ StringRef RangeSection;
+ uint32_t RangeSectionBase;
+ StringRef StringSection;
+ StringRef StringOffsetSection;
+ StringRef AddrOffsetSection;
+ uint32_t AddrOffsetSectionBase;
+ bool isLittleEndian;
+ const DWARFUnitSectionBase &UnitSection;
+
+ uint32_t Offset;
+ uint32_t Length;
+ uint16_t Version;
+ const DWARFAbbreviationDeclarationSet *Abbrevs;
+ uint8_t AddrSize;
+ uint64_t BaseAddr;
+ // The compile unit debug information entry items.
+ std::vector<DWARFDebugInfoEntryMinimal> DieArray;
+
+ class DWOHolder {
+ object::OwningBinary<object::ObjectFile> DWOFile;
+ std::unique_ptr<DWARFContext> DWOContext;
+ DWARFUnit *DWOU;
+ public:
+ DWOHolder(StringRef DWOPath);
+ DWARFUnit *getUnit() const { return DWOU; }
+ };
+ std::unique_ptr<DWOHolder> DWO;
+
+protected:
+ virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
+ /// Size in bytes of the unit header.
+ virtual uint32_t getHeaderSize() const { return 11; }
+
+public:
+ DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
+ const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
+ StringRef SOS, StringRef AOS, bool LE,
+ const DWARFUnitSectionBase &UnitSection);
+
+ virtual ~DWARFUnit();
+
+ DWARFContext& getContext() const { return Context; }
+
+ StringRef getStringSection() const { return StringSection; }
+ StringRef getStringOffsetSection() const { return StringOffsetSection; }
+ void setAddrOffsetSection(StringRef AOS, uint32_t Base) {
+ AddrOffsetSection = AOS;
+ AddrOffsetSectionBase = Base;
+ }
+ void setRangesSection(StringRef RS, uint32_t Base) {
+ RangeSection = RS;
+ RangeSectionBase = Base;
+ }
+
+ bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
+ // FIXME: Result should be uint64_t in DWARF64.
+ bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const;
+
+ DataExtractor getDebugInfoExtractor() const {
+ return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize);
+ }
+ DataExtractor getStringExtractor() const {
+ return DataExtractor(StringSection, false, 0);
+ }
+
+ const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; }
+
+ bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
+
+ /// extractRangeList - extracts the range list referenced by this compile
+ /// unit from .debug_ranges section. Returns true on success.
+ /// Requires that compile unit is already extracted.
+ bool extractRangeList(uint32_t RangeListOffset,
+ DWARFDebugRangeList &RangeList) const;
+ void clear();
+ uint32_t getOffset() const { return Offset; }
+ uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
+ uint32_t getLength() const { return Length; }
+ uint16_t getVersion() const { return Version; }
+ const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
+ return Abbrevs;
+ }
+ uint8_t getAddressByteSize() const { return AddrSize; }
+ uint64_t getBaseAddress() const { return BaseAddr; }
+
+ void setBaseAddress(uint64_t base_addr) {
+ BaseAddr = base_addr;
+ }
+
+ const DWARFDebugInfoEntryMinimal *
+ getCompileUnitDIE(bool extract_cu_die_only = true) {
+ extractDIEsIfNeeded(extract_cu_die_only);
+ return DieArray.empty() ? nullptr : &DieArray[0];
+ }
+
+ const char *getCompilationDir();
+ uint64_t getDWOId();
+
+ void collectAddressRanges(DWARFAddressRangesVector &CURanges);
+
+ /// getInlinedChainForAddress - fetches inlined chain for a given address.
+ /// Returns empty chain if there is no subprogram containing address. The
+ /// chain is valid as long as parsed compile unit DIEs are not cleared.
+ DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address);
+
+ /// getUnitSection - Return the DWARFUnitSection containing this unit.
+ const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; }
+
+private:
+ /// Size in bytes of the .debug_info data associated with this compile unit.
+ size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); }
+
+ /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
+ /// hasn't already been done. Returns the number of DIEs parsed at this call.
+ size_t extractDIEsIfNeeded(bool CUDieOnly);
+ /// extractDIEsToVector - Appends all parsed DIEs to a vector.
+ void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
+ std::vector<DWARFDebugInfoEntryMinimal> &DIEs) const;
+ /// setDIERelations - We read in all of the DIE entries into our flat list
+ /// of DIE entries and now we need to go back through all of them and set the
+ /// parent, sibling and child pointers for quick DIE navigation.
+ void setDIERelations();
+ /// clearDIEs - Clear parsed DIEs to keep memory usage low.
+ void clearDIEs(bool KeepCUDie);
+
+ /// parseDWO - Parses .dwo file for current compile unit. Returns true if
+ /// it was actually constructed.
+ bool parseDWO();
+
+ /// getSubprogramForAddress - Returns subprogram DIE with address range
+ /// encompassing the provided address. The pointer is alive as long as parsed
+ /// compile unit DIEs are not cleared.
+ const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address);
+};
+
+}
+
+#endif
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index e5dab6191ab6..d79bd3c4dfc8 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -18,9 +18,11 @@
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/MC/MCCodeGenInfo.h"
+#include "llvm/Object/Binary.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Target/TargetMachine.h"
@@ -39,9 +41,7 @@ class Function;
class GlobalVariable;
class GlobalValue;
class JITEventListener;
-class JITMemoryManager;
class MachineCodeInfo;
-class Module;
class MutexGuard;
class ObjectCache;
class RTDyldMemoryManager;
@@ -131,29 +131,20 @@ class ExecutionEngine {
protected:
/// The list of Modules that we are JIT'ing from. We use a SmallVector to
/// optimize for the case where there is only one module.
- SmallVector<Module*, 1> Modules;
+ SmallVector<std::unique_ptr<Module>, 1> Modules;
void setDataLayout(const DataLayout *Val) { DL = Val; }
/// getMemoryforGV - Allocate memory for a global variable.
virtual char *getMemoryForGV(const GlobalVariable *GV);
- // To avoid having libexecutionengine depend on the JIT and interpreter
- // libraries, the execution engine implementations set these functions to ctor
- // pointers at startup time if they are linked in.
- static ExecutionEngine *(*JITCtor)(
- Module *M,
- std::string *ErrorStr,
- JITMemoryManager *JMM,
- bool GVsWithCode,
- TargetMachine *TM);
static ExecutionEngine *(*MCJITCtor)(
- Module *M,
- std::string *ErrorStr,
- RTDyldMemoryManager *MCJMM,
- bool GVsWithCode,
- TargetMachine *TM);
- static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr);
+ std::unique_ptr<Module> M,
+ std::string *ErrorStr,
+ std::unique_ptr<RTDyldMemoryManager> MCJMM,
+ std::unique_ptr<TargetMachine> TM);
+ static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M,
+ std::string *ErrorStr);
/// LazyFunctionCreator - If an unknown function is needed, this function
/// pointer is invoked to create it. If this returns null, the JIT will
@@ -161,9 +152,8 @@ protected:
void *(*LazyFunctionCreator)(const std::string &);
public:
- /// lock - This lock protects the ExecutionEngine, MCJIT, JIT, JITResolver and
- /// JITEmitter classes. It must be held while changing the internal state of
- /// any of those classes.
+ /// lock - This lock protects the ExecutionEngine and MCJIT classes. It must
+ /// be held while changing the internal state of any of those classes.
sys::Mutex lock;
//===--------------------------------------------------------------------===//
@@ -172,44 +162,9 @@ public:
virtual ~ExecutionEngine();
- /// create - This is the factory method for creating an execution engine which
- /// is appropriate for the current machine. This takes ownership of the
- /// module.
- ///
- /// \param GVsWithCode - Allocating globals with code breaks
- /// freeMachineCodeForFunction and is probably unsafe and bad for performance.
- /// However, we have clients who depend on this behavior, so we must support
- /// it. Eventually, when we're willing to break some backwards compatibility,
- /// this flag should be flipped to false, so that by default
- /// freeMachineCodeForFunction works.
- static ExecutionEngine *create(Module *M,
- bool ForceInterpreter = false,
- std::string *ErrorStr = nullptr,
- CodeGenOpt::Level OptLevel =
- CodeGenOpt::Default,
- bool GVsWithCode = true);
-
- /// createJIT - This is the factory method for creating a JIT for the current
- /// machine, it does not fall back to the interpreter. This takes ownership
- /// of the Module and JITMemoryManager if successful.
- ///
- /// Clients should make sure to initialize targets prior to calling this
- /// function.
- static ExecutionEngine *createJIT(Module *M,
- std::string *ErrorStr = nullptr,
- JITMemoryManager *JMM = nullptr,
- CodeGenOpt::Level OptLevel =
- CodeGenOpt::Default,
- bool GVsWithCode = true,
- Reloc::Model RM = Reloc::Default,
- CodeModel::Model CMM =
- CodeModel::JITDefault);
-
- /// addModule - Add a Module to the list of modules that we can JIT from.
- /// Note that this takes ownership of the Module: when the ExecutionEngine is
- /// destroyed, it destroys the Module as well.
- virtual void addModule(Module *M) {
- Modules.push_back(M);
+ /// Add a Module to the list of modules that we can JIT from.
+ virtual void addModule(std::unique_ptr<Module> M) {
+ Modules.push_back(std::move(M));
}
/// addObjectFile - Add an ObjectFile to the execution engine.
@@ -223,6 +178,7 @@ public:
///
/// MCJIT will take ownership of the ObjectFile.
virtual void addObjectFile(std::unique_ptr<object::ObjectFile> O);
+ virtual void addObjectFile(object::OwningBinary<object::ObjectFile> O);
/// addArchive - Add an Archive to the execution engine.
///
@@ -230,11 +186,7 @@ public:
/// resolve external symbols in objects it is loading. If a symbol is found
/// in the Archive the contained object file will be extracted (in memory)
/// and loaded for possible execution.
- ///
- /// MCJIT will take ownership of the Archive.
- virtual void addArchive(object::Archive *A) {
- llvm_unreachable("ExecutionEngine subclass doesn't implement addArchive.");
- }
+ virtual void addArchive(object::OwningBinary<object::Archive> A);
//===--------------------------------------------------------------------===//
@@ -263,11 +215,7 @@ public:
/// it prints a message to stderr and aborts.
///
/// This function is deprecated for the MCJIT execution engine.
- ///
- /// FIXME: the JIT and MCJIT interfaces should be disentangled or united
- /// again, if possible.
- ///
- virtual void *getPointerToNamedFunction(const std::string &Name,
+ virtual void *getPointerToNamedFunction(StringRef Name,
bool AbortOnFailure = true) = 0;
/// mapSectionAddress - map a section to its target address space value.
@@ -279,7 +227,7 @@ public:
"EE!");
}
- /// generateCodeForModule - Run code generationen for the specified module and
+ /// generateCodeForModule - Run code generation for the specified module and
/// load it into memory.
///
/// When this function has completed, all code and data for the specified
@@ -293,7 +241,7 @@ public:
/// locally can use the getFunctionAddress call, which will generate code
/// and apply final preparations all in one step.
///
- /// This method has no effect for the legacy JIT engine or the interpeter.
+ /// This method has no effect for the interpeter.
virtual void generateCodeForModule(Module *M) {}
/// finalizeObject - ensure the module is fully processed and is usable.
@@ -302,8 +250,7 @@ public:
/// object usable for execution. It should be called after sections within an
/// object have been relocated using mapSectionAddress. When this method is
/// called the MCJIT execution engine will reapply relocations for a loaded
- /// object. This method has no effect for the legacy JIT engine or the
- /// interpeter.
+ /// object. This method has no effect for the interpeter.
virtual void finalizeObject() {}
/// runStaticConstructorsDestructors - This method is used to execute all of
@@ -312,11 +259,11 @@ public:
/// \param isDtors - Run the destructors instead of constructors.
virtual void runStaticConstructorsDestructors(bool isDtors);
- /// runStaticConstructorsDestructors - This method is used to execute all of
- /// the static constructors or destructors for a particular module.
+ /// This method is used to execute all of the static constructors or
+ /// destructors for a particular module.
///
/// \param isDtors - Run the destructors instead of constructors.
- void runStaticConstructorsDestructors(Module *module, bool isDtors);
+ void runStaticConstructorsDestructors(Module &module, bool isDtors);
/// runFunctionAsMain - This is a helper function which wraps runFunction to
@@ -373,13 +320,6 @@ public:
/// getFunctionAddress instead.
virtual void *getPointerToFunction(Function *F) = 0;
- /// getPointerToBasicBlock - The different EE's represent basic blocks in
- /// different ways. Return the representation for a blockaddress of the
- /// specified block.
- ///
- /// This function will not be implemented for the MCJIT execution engine.
- virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0;
-
/// getPointerToFunctionOrStub - If the specified function has been
/// code-gen'd, return a pointer to the function. If not, compile it, or use
/// a stub to implement lazy compilation if available. See
@@ -395,9 +335,9 @@ public:
/// getGlobalValueAddress - Return the address of the specified global
/// value. This may involve code generation.
///
- /// This function should not be called with the JIT or interpreter engines.
+ /// This function should not be called with the interpreter engine.
virtual uint64_t getGlobalValueAddress(const std::string &Name) {
- // Default implementation for JIT and interpreter. MCJIT will override this.
+ // Default implementation for the interpreter. MCJIT will override this.
// JIT and interpreter clients should use getPointerToGlobal instead.
return 0;
}
@@ -405,14 +345,11 @@ public:
/// getFunctionAddress - Return the address of the specified function.
/// This may involve code generation.
virtual uint64_t getFunctionAddress(const std::string &Name) {
- // Default implementation for JIT and interpreter. MCJIT will override this.
- // JIT and interpreter clients should use getPointerToFunction instead.
+ // Default implementation for the interpreter. MCJIT will override this.
+ // Interpreter clients should use getPointerToFunction instead.
return 0;
}
- // The JIT overrides a version that actually does this.
- virtual void runJITOnFunction(Function *, MachineCodeInfo * = nullptr) { }
-
/// getGlobalValueAtAddress - Return the LLVM global value object that starts
/// at the specified address.
///
@@ -427,18 +364,6 @@ public:
void InitializeMemory(const Constant *Init, void *Addr);
- /// recompileAndRelinkFunction - This method is used to force a function which
- /// has already been compiled to be compiled again, possibly after it has been
- /// modified. Then the entry to the old copy is overwritten with a branch to
- /// the new copy. If there was no old copy, this acts just like
- /// VM::getPointerToFunction().
- virtual void *recompileAndRelinkFunction(Function *F) = 0;
-
- /// freeMachineCodeForFunction - Release memory in the ExecutionEngine
- /// corresponding to the machine code emitted to execute this function, useful
- /// for garbage-collecting generated code.
- virtual void freeMachineCodeForFunction(Function *F) = 0;
-
/// getOrEmitGlobalVariable - Return the address of the specified global
/// variable, possibly emitting it to memory if needed. This is used by the
/// Emitter.
@@ -457,7 +382,7 @@ public:
virtual void UnregisterJITEventListener(JITEventListener *) {}
/// Sets the pre-compiled object cache. The ownership of the ObjectCache is
- /// not changed. Supported by MCJIT but not JIT.
+ /// not changed. Supported by MCJIT but not the interpreter.
virtual void setObjectCache(ObjectCache *) {
llvm_unreachable("No support for an object cache");
}
@@ -499,11 +424,6 @@ public:
bool isCompilingLazily() const {
return CompilingLazily;
}
- // Deprecated in favor of isCompilingLazily (to reduce double-negatives).
- // Remove this in LLVM 2.8.
- bool isLazyCompilationDisabled() const {
- return !CompilingLazily;
- }
/// DisableGVCompilation - If called, the JIT will abort if it's asked to
/// allocate space and populate a GlobalVariable that is not internal to
@@ -544,7 +464,7 @@ public:
}
protected:
- explicit ExecutionEngine(Module *M);
+ explicit ExecutionEngine(std::unique_ptr<Module> M);
void emitGlobals();
@@ -564,36 +484,33 @@ namespace EngineKind {
const static Kind Either = (Kind)(JIT | Interpreter);
}
-/// EngineBuilder - Builder class for ExecutionEngines. Use this by
-/// stack-allocating a builder, chaining the various set* methods, and
-/// terminating it with a .create() call.
+/// Builder class for ExecutionEngines. Use this by stack-allocating a builder,
+/// chaining the various set* methods, and terminating it with a .create()
+/// call.
class EngineBuilder {
private:
- Module *M;
+ std::unique_ptr<Module> M;
EngineKind::Kind WhichEngine;
std::string *ErrorStr;
CodeGenOpt::Level OptLevel;
- RTDyldMemoryManager *MCJMM;
- JITMemoryManager *JMM;
- bool AllocateGVsWithCode;
+ std::unique_ptr<RTDyldMemoryManager> MCJMM;
TargetOptions Options;
Reloc::Model RelocModel;
CodeModel::Model CMModel;
std::string MArch;
std::string MCPU;
SmallVector<std::string, 4> MAttrs;
- bool UseMCJIT;
bool VerifyModules;
/// InitEngine - Does the common initialization of default options.
void InitEngine();
public:
- /// EngineBuilder - Constructor for EngineBuilder. If create() is called and
- /// is successful, the created engine takes ownership of the module.
- EngineBuilder(Module *m) : M(m) {
- InitEngine();
- }
+ /// Constructor for EngineBuilder.
+ EngineBuilder(std::unique_ptr<Module> M);
+
+ // Out-of-line since we don't have the def'n of RTDyldMemoryManager here.
+ ~EngineBuilder();
/// setEngineKind - Controls whether the user wants the interpreter, the JIT,
/// or whichever engine works. This option defaults to EngineKind::Either.
@@ -607,26 +524,8 @@ public:
/// is only appropriate for the MCJIT; setting this and configuring the builder
/// to create anything other than MCJIT will cause a runtime error. If create()
/// is called and is successful, the created engine takes ownership of the
- /// memory manager. This option defaults to NULL. Using this option nullifies
- /// the setJITMemoryManager() option.
- EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) {
- MCJMM = mcjmm;
- JMM = nullptr;
- return *this;
- }
-
- /// setJITMemoryManager - Sets the JIT memory manager to use. This allows
- /// clients to customize their memory allocation policies. This is only
- /// appropriate for either JIT or MCJIT; setting this and configuring the
- /// builder to create an interpreter will cause a runtime error. If create()
- /// is called and is successful, the created engine takes ownership of the
- /// memory manager. This option defaults to NULL. This option overrides
- /// setMCJITMemoryManager() as well.
- EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) {
- MCJMM = nullptr;
- JMM = jmm;
- return *this;
- }
+ /// memory manager. This option defaults to NULL.
+ EngineBuilder &setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
/// setErrorStr - Set the error string to write to on error. This option
/// defaults to NULL.
@@ -664,18 +563,6 @@ public:
return *this;
}
- /// setAllocateGVsWithCode - Sets whether global values should be allocated
- /// into the same buffer as code. For most applications this should be set
- /// to false. Allocating globals with code breaks freeMachineCodeForFunction
- /// and is probably unsafe and bad for performance. However, we have clients
- /// who depend on this behavior, so we must support it. This option defaults
- /// to false so that users of the new API can safely use the new memory
- /// manager and free machine code.
- EngineBuilder &setAllocateGVsWithCode(bool a) {
- AllocateGVsWithCode = a;
- return *this;
- }
-
/// setMArch - Override the architecture set by the Module's triple.
EngineBuilder &setMArch(StringRef march) {
MArch.assign(march.begin(), march.end());
@@ -688,13 +575,6 @@ public:
return *this;
}
- /// setUseMCJIT - Set whether the MC-JIT implementation should be used
- /// (experimental).
- EngineBuilder &setUseMCJIT(bool Value) {
- UseMCJIT = Value;
- return *this;
- }
-
/// setVerifyModules - Set whether the JIT implementation should verify
/// IR modules during compilation.
EngineBuilder &setVerifyModules(bool Verify) {
diff --git a/include/llvm/ExecutionEngine/JIT.h b/include/llvm/ExecutionEngine/JIT.h
deleted file mode 100644
index 581d6e6c35eb..000000000000
--- a/include/llvm/ExecutionEngine/JIT.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===-- JIT.h - Abstract Execution Engine Interface -------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file forces the JIT to link in on certain operating systems.
-// (Windows).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_JIT_H
-#define LLVM_EXECUTIONENGINE_JIT_H
-
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include <cstdlib>
-
-extern "C" void LLVMLinkInJIT();
-
-namespace {
- struct ForceJITLinking {
- ForceJITLinking() {
- // We must reference JIT in such a way that compilers will not
- // delete it all as dead code, even with whole program optimization,
- // yet is effectively a NO-OP. As the compiler isn't smart enough
- // to know that getenv() never returns -1, this will do the job.
- if (std::getenv("bar") != (char*) -1)
- return;
-
- LLVMLinkInJIT();
- }
- } ForceJITLinking;
-}
-
-#endif
diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h
index 99fe36c6b5f6..c3edec868783 100644
--- a/include/llvm/ExecutionEngine/JITEventListener.h
+++ b/include/llvm/ExecutionEngine/JITEventListener.h
@@ -15,6 +15,7 @@
#ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
#define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
+#include "RuntimeDyld.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Support/DataTypes.h"
@@ -25,7 +26,10 @@ class Function;
class MachineFunction;
class OProfileWrapper;
class IntelJITEventsWrapper;
-class ObjectImage;
+
+namespace object {
+ class ObjectFile;
+}
/// JITEvent_EmittedFunctionDetails - Helper struct for containing information
/// about a generated machine code function.
@@ -57,24 +61,7 @@ public:
public:
JITEventListener() {}
- virtual ~JITEventListener();
-
- /// NotifyFunctionEmitted - Called after a function has been successfully
- /// emitted to memory. The function still has its MachineFunction attached,
- /// if you should happen to need that.
- virtual void NotifyFunctionEmitted(const Function &,
- void *, size_t,
- const EmittedFunctionDetails &) {}
-
- /// NotifyFreeingMachineCode - Called from freeMachineCodeForFunction(), after
- /// the global mapping is removed, but before the machine code is returned to
- /// the allocator.
- ///
- /// OldPtr is the address of the machine code and will be the same as the Code
- /// parameter to a previous NotifyFunctionEmitted call. The Function passed
- /// to NotifyFunctionEmitted may have been destroyed by the time of the
- /// matching NotifyFreeingMachineCode call.
- virtual void NotifyFreeingMachineCode(void *) {}
+ virtual ~JITEventListener() {}
/// NotifyObjectEmitted - Called after an object has been successfully
/// emitted to memory. NotifyFunctionEmitted will not be called for
@@ -84,11 +71,15 @@ public:
/// The ObjectImage contains the generated object image
/// with section headers updated to reflect the address at which sections
/// were loaded and with relocations performed in-place on debug sections.
- virtual void NotifyObjectEmitted(const ObjectImage &Obj) {}
+ virtual void NotifyObjectEmitted(const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &L) {}
/// NotifyFreeingObject - Called just before the memory associated with
/// a previously emitted object is released.
- virtual void NotifyFreeingObject(const ObjectImage &Obj) {}
+ virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {}
+
+ // Get a pointe to the GDB debugger registration listener.
+ static JITEventListener *createGDBRegistrationListener();
#if LLVM_USE_INTEL_JITEVENTS
// Construct an IntelJITEventListener
@@ -122,7 +113,8 @@ public:
return nullptr;
}
#endif // USE_OPROFILE
-
+private:
+ virtual void anchor();
};
} // end namespace llvm.
diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h
deleted file mode 100644
index b22d899c9fec..000000000000
--- a/include/llvm/ExecutionEngine/JITMemoryManager.h
+++ /dev/null
@@ -1,164 +0,0 @@
-//===-- JITMemoryManager.h - Interface JIT uses to Allocate Mem -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_JITMEMORYMANAGER_H
-#define LLVM_EXECUTIONENGINE_JITMEMORYMANAGER_H
-
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
-#include "llvm/Support/DataTypes.h"
-#include <string>
-
-namespace llvm {
-
- class Function;
- class GlobalValue;
-
-/// JITMemoryManager - This interface is used by the JIT to allocate and manage
-/// memory for the code generated by the JIT. This can be reimplemented by
-/// clients that have a strong desire to control how the layout of JIT'd memory
-/// works.
-class JITMemoryManager : public RTDyldMemoryManager {
-protected:
- bool HasGOT;
-
-public:
- JITMemoryManager() : HasGOT(false) {}
- virtual ~JITMemoryManager();
-
- /// CreateDefaultMemManager - This is used to create the default
- /// JIT Memory Manager if the client does not provide one to the JIT.
- static JITMemoryManager *CreateDefaultMemManager();
-
- /// setMemoryWritable - When code generation is in progress,
- /// the code pages may need permissions changed.
- virtual void setMemoryWritable() = 0;
-
- /// setMemoryExecutable - When code generation is done and we're ready to
- /// start execution, the code pages may need permissions changed.
- virtual void setMemoryExecutable() = 0;
-
- /// setPoisonMemory - Setting this flag to true makes the memory manager
- /// garbage values over freed memory. This is useful for testing and
- /// debugging, and may be turned on by default in debug mode.
- virtual void setPoisonMemory(bool poison) = 0;
-
- //===--------------------------------------------------------------------===//
- // Global Offset Table Management
- //===--------------------------------------------------------------------===//
-
- /// AllocateGOT - If the current table requires a Global Offset Table, this
- /// method is invoked to allocate it. This method is required to set HasGOT
- /// to true.
- virtual void AllocateGOT() = 0;
-
- /// isManagingGOT - Return true if the AllocateGOT method is called.
- bool isManagingGOT() const {
- return HasGOT;
- }
-
- /// getGOTBase - If this is managing a Global Offset Table, this method should
- /// return a pointer to its base.
- virtual uint8_t *getGOTBase() const = 0;
-
- //===--------------------------------------------------------------------===//
- // Main Allocation Functions
- //===--------------------------------------------------------------------===//
-
- /// startFunctionBody - When we start JITing a function, the JIT calls this
- /// method to allocate a block of free RWX memory, which returns a pointer to
- /// it. If the JIT wants to request a block of memory of at least a certain
- /// size, it passes that value as ActualSize, and this method returns a block
- /// with at least that much space. If the JIT doesn't know ahead of time how
- /// much space it will need to emit the function, it passes 0 for the
- /// ActualSize. In either case, this method is required to pass back the size
- /// of the allocated block through ActualSize. The JIT will be careful to
- /// not write more than the returned ActualSize bytes of memory.
- virtual uint8_t *startFunctionBody(const Function *F,
- uintptr_t &ActualSize) = 0;
-
- /// allocateStub - This method is called by the JIT to allocate space for a
- /// function stub (used to handle limited branch displacements) while it is
- /// JIT compiling a function. For example, if foo calls bar, and if bar
- /// either needs to be lazily compiled or is a native function that exists too
- /// far away from the call site to work, this method will be used to make a
- /// thunk for it. The stub should be "close" to the current function body,
- /// but should not be included in the 'actualsize' returned by
- /// startFunctionBody.
- virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
- unsigned Alignment) = 0;
-
- /// endFunctionBody - This method is called when the JIT is done codegen'ing
- /// the specified function. At this point we know the size of the JIT
- /// compiled function. This passes in FunctionStart (which was returned by
- /// the startFunctionBody method) and FunctionEnd which is a pointer to the
- /// actual end of the function. This method should mark the space allocated
- /// and remember where it is in case the client wants to deallocate it.
- virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
- uint8_t *FunctionEnd) = 0;
-
- /// allocateSpace - Allocate a memory block of the given size. This method
- /// cannot be called between calls to startFunctionBody and endFunctionBody.
- virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0;
-
- /// allocateGlobal - Allocate memory for a global.
- virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0;
-
- /// deallocateFunctionBody - Free the specified function body. The argument
- /// must be the return value from a call to startFunctionBody() that hasn't
- /// been deallocated yet. This is never called when the JIT is currently
- /// emitting a function.
- virtual void deallocateFunctionBody(void *Body) = 0;
-
- /// CheckInvariants - For testing only. Return true if all internal
- /// invariants are preserved, or return false and set ErrorStr to a helpful
- /// error message.
- virtual bool CheckInvariants(std::string &) {
- return true;
- }
-
- /// GetDefaultCodeSlabSize - For testing only. Returns DefaultCodeSlabSize
- /// from DefaultJITMemoryManager.
- virtual size_t GetDefaultCodeSlabSize() {
- return 0;
- }
-
- /// GetDefaultDataSlabSize - For testing only. Returns DefaultCodeSlabSize
- /// from DefaultJITMemoryManager.
- virtual size_t GetDefaultDataSlabSize() {
- return 0;
- }
-
- /// GetDefaultStubSlabSize - For testing only. Returns DefaultCodeSlabSize
- /// from DefaultJITMemoryManager.
- virtual size_t GetDefaultStubSlabSize() {
- return 0;
- }
-
- /// GetNumCodeSlabs - For testing only. Returns the number of MemoryBlocks
- /// allocated for code.
- virtual unsigned GetNumCodeSlabs() {
- return 0;
- }
-
- /// GetNumDataSlabs - For testing only. Returns the number of MemoryBlocks
- /// allocated for data.
- virtual unsigned GetNumDataSlabs() {
- return 0;
- }
-
- /// GetNumStubSlabs - For testing only. Returns the number of MemoryBlocks
- /// allocated for function stubs.
- virtual unsigned GetNumStubSlabs() {
- return 0;
- }
-};
-
-} // end namespace llvm.
-
-#endif
diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h
deleted file mode 100644
index 6221d3b335df..000000000000
--- a/include/llvm/ExecutionEngine/ObjectBuffer.h
+++ /dev/null
@@ -1,83 +0,0 @@
-//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares a wrapper class to hold the memory into which an
-// object will be generated.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H
-#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-/// ObjectBuffer - This class acts as a container for the memory buffer used during
-/// generation and loading of executable objects using MCJIT and RuntimeDyld. The
-/// underlying memory for the object will be owned by the ObjectBuffer instance
-/// throughout its lifetime. The getMemBuffer() method provides a way to create a
-/// MemoryBuffer wrapper object instance to be owned by other classes (such as
-/// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the
-/// actual memory it points to.
-class ObjectBuffer {
- virtual void anchor();
-public:
- ObjectBuffer() {}
- ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {}
- virtual ~ObjectBuffer() {}
-
- /// getMemBuffer - Like MemoryBuffer::getMemBuffer() this function
- /// returns a pointer to an object that is owned by the caller. However,
- /// the caller does not take ownership of the underlying memory.
- MemoryBuffer *getMemBuffer() const {
- return MemoryBuffer::getMemBuffer(Buffer->getBuffer(),
- Buffer->getBufferIdentifier(), false);
- }
-
- const char *getBufferStart() const { return Buffer->getBufferStart(); }
- size_t getBufferSize() const { return Buffer->getBufferSize(); }
- StringRef getBuffer() const { return Buffer->getBuffer(); }
-
-protected:
- // The memory contained in an ObjectBuffer
- std::unique_ptr<MemoryBuffer> Buffer;
-};
-
-/// ObjectBufferStream - This class encapsulates the SmallVector and
-/// raw_svector_ostream needed to generate an object using MC code emission
-/// while providing a common ObjectBuffer interface for access to the
-/// memory once the object has been generated.
-class ObjectBufferStream : public ObjectBuffer {
- void anchor() override;
-public:
- ObjectBufferStream() : OS(SV) {}
- virtual ~ObjectBufferStream() {}
-
- raw_ostream &getOStream() { return OS; }
- void flush()
- {
- OS.flush();
-
- // Make the data accessible via the ObjectBuffer::Buffer
- Buffer.reset(MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()),
- "",
- false));
- }
-
-protected:
- SmallVector<char, 4096> SV; // Working buffer into which we JIT.
- raw_svector_ostream OS; // streaming wrapper
-};
-
-} // namespace llvm
-
-#endif
diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h
index d1849dfc3bf6..cc01a4e58999 100644
--- a/include/llvm/ExecutionEngine/ObjectCache.h
+++ b/include/llvm/ExecutionEngine/ObjectCache.h
@@ -27,13 +27,12 @@ public:
virtual ~ObjectCache() { }
/// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
- virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) = 0;
+ virtual void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) = 0;
- /// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that
- /// contains the object which corresponds with Module M, or 0 if an object is
- /// not available. The caller owns both the MemoryBuffer returned by this
- /// and the memory it references.
- virtual MemoryBuffer* getObject(const Module* M) = 0;
+ /// Returns a pointer to a newly allocated MemoryBuffer that contains the
+ /// object which corresponds with Module M, or 0 if an object is not
+ /// available.
+ virtual std::unique_ptr<MemoryBuffer> getObject(const Module* M) = 0;
};
}
diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h
deleted file mode 100644
index 1fcedd8d6a92..000000000000
--- a/include/llvm/ExecutionEngine/ObjectImage.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//===---- ObjectImage.h - Format independent executuable object image -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares a file format independent ObjectImage class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_OBJECTIMAGE_H
-#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H
-
-#include "llvm/ExecutionEngine/ObjectBuffer.h"
-#include "llvm/Object/ObjectFile.h"
-
-namespace llvm {
-
-
-/// ObjectImage - A container class that represents an ObjectFile that has been
-/// or is in the process of being loaded into memory for execution.
-class ObjectImage {
- ObjectImage() LLVM_DELETED_FUNCTION;
- ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION;
- virtual void anchor();
-
-protected:
- std::unique_ptr<ObjectBuffer> Buffer;
-
-public:
- ObjectImage(ObjectBuffer *Input) : Buffer(Input) {}
- virtual ~ObjectImage() {}
-
- virtual object::symbol_iterator begin_symbols() const = 0;
- virtual object::symbol_iterator end_symbols() const = 0;
- iterator_range<object::symbol_iterator> symbols() const {
- return iterator_range<object::symbol_iterator>(begin_symbols(),
- end_symbols());
- }
-
- virtual object::section_iterator begin_sections() const = 0;
- virtual object::section_iterator end_sections() const = 0;
- iterator_range<object::section_iterator> sections() const {
- return iterator_range<object::section_iterator>(begin_sections(),
- end_sections());
- }
-
- virtual /* Triple::ArchType */ unsigned getArch() const = 0;
-
- // Subclasses can override these methods to update the image with loaded
- // addresses for sections and common symbols
- virtual void updateSectionAddress(const object::SectionRef &Sec,
- uint64_t Addr) = 0;
- virtual void updateSymbolAddress(const object::SymbolRef &Sym,
- uint64_t Addr) = 0;
-
- virtual StringRef getData() const = 0;
-
- virtual object::ObjectFile* getObjectFile() const = 0;
-
- // Subclasses can override these methods to provide JIT debugging support
- virtual void registerWithDebugger() = 0;
- virtual void deregisterWithDebugger() = 0;
-};
-
-} // end namespace llvm
-
-#endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H
diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
index b1d6810f374b..ef81cd328bdb 100644
--- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
+++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H
-#define LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H
+#ifndef LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H
+#define LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ADT/StringRef.h"
@@ -22,7 +22,10 @@
namespace llvm {
class ExecutionEngine;
-class ObjectImage;
+
+ namespace object {
+ class ObjectFile;
+ }
// RuntimeDyld clients often want to handle the memory management of
// what gets placed where. For JIT clients, this is the subset of
@@ -76,9 +79,15 @@ public:
virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size);
+ /// This method returns the address of the specified function or variable in
+ /// the current process.
+ static uint64_t getSymbolAddressInProcess(const std::string &Name);
+
/// This method returns the address of the specified function or variable.
/// It is used to resolve symbols during module linking.
- virtual uint64_t getSymbolAddress(const std::string &Name);
+ virtual uint64_t getSymbolAddress(const std::string &Name) {
+ return getSymbolAddressInProcess(Name);
+ }
/// This method returns the address of the specified function. As such it is
/// only useful for resolving library symbols, not code generated symbols.
@@ -103,7 +112,7 @@ public:
/// address space can use this call to remap the section addresses for the
/// newly loaded object.
virtual void notifyObjectLoaded(ExecutionEngine *EE,
- const ObjectImage *) {}
+ const object::ObjectFile &) {}
/// This method is called when object loading is complete and section page
/// permissions can be applied. It is up to the memory manager implementation
@@ -123,4 +132,4 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(
} // namespace llvm
-#endif // LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H
+#endif
diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h
index f123ffb803bd..799fc34eb659 100644
--- a/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -15,58 +15,75 @@
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/ObjectBuffer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Support/Memory.h"
+#include <memory>
namespace llvm {
namespace object {
class ObjectFile;
+ template <typename T> class OwningBinary;
}
class RuntimeDyldImpl;
-class ObjectImage;
+class RuntimeDyldCheckerImpl;
class RuntimeDyld {
- friend class RuntimeDyldChecker;
+ friend class RuntimeDyldCheckerImpl;
RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
// RuntimeDyldImpl is the actual class. RuntimeDyld is just the public
// interface.
- RuntimeDyldImpl *Dyld;
+ std::unique_ptr<RuntimeDyldImpl> Dyld;
RTDyldMemoryManager *MM;
bool ProcessAllSections;
+ RuntimeDyldCheckerImpl *Checker;
protected:
// Change the address associated with a section when resolving relocations.
// Any relocations already associated with the symbol will be re-resolved.
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
public:
+
+ /// \brief Information about the loaded object.
+ class LoadedObjectInfo {
+ friend class RuntimeDyldImpl;
+ public:
+ LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
+ unsigned EndIdx)
+ : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { }
+
+ virtual ~LoadedObjectInfo() {}
+
+ virtual object::OwningBinary<object::ObjectFile>
+ getObjectForDebug(const object::ObjectFile &Obj) const = 0;
+
+ uint64_t getSectionLoadAddress(StringRef Name) const;
+
+ protected:
+ virtual void anchor();
+
+ RuntimeDyldImpl &RTDyld;
+ unsigned BeginIdx, EndIdx;
+ };
+
RuntimeDyld(RTDyldMemoryManager *);
~RuntimeDyld();
- /// Prepare the object contained in the input buffer for execution.
- /// Ownership of the input buffer is transferred to the ObjectImage
- /// instance returned from this function if successful. In the case of load
- /// failure, the input buffer will be deleted.
- ObjectImage *loadObject(ObjectBuffer *InputBuffer);
-
- /// Prepare the referenced object file for execution.
- /// Ownership of the input object is transferred to the ObjectImage
- /// instance returned from this function if successful. In the case of load
- /// failure, the input object will be deleted.
- ObjectImage *loadObject(std::unique_ptr<object::ObjectFile> InputObject);
+ /// Add the referenced object file to the list of objects to be loaded and
+ /// relocated.
+ std::unique_ptr<LoadedObjectInfo> loadObject(const object::ObjectFile &O);
/// Get the address of our local copy of the symbol. This may or may not
/// be the address used for relocation (clients can copy the data around
/// and resolve relocatons based on where they put it).
- void *getSymbolAddress(StringRef Name);
+ void *getSymbolAddress(StringRef Name) const;
/// Get the address of the target copy of the symbol. This is the address
/// used for relocation.
- uint64_t getSymbolLoadAddress(StringRef Name);
+ uint64_t getSymbolLoadAddress(StringRef Name) const;
/// Resolve the relocations for all symbols we currently know about.
void resolveRelocations();
diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index 8dd891e83648..35ceba27596c 100644
--- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -7,18 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_RUNTIMEDYLDCHECKER_H
-#define LLVM_RUNTIMEDYLDCHECKER_H
+#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
+#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
-#include "RuntimeDyld.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-#include <map>
+#include "llvm/ADT/StringRef.h"
namespace llvm {
class MCDisassembler;
+class MemoryBuffer;
class MCInstPrinter;
+class RuntimeDyld;
+class RuntimeDyldCheckerImpl;
+class raw_ostream;
/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has
/// correctly applied relocations.
@@ -61,14 +62,16 @@ class MCInstPrinter;
/// | expr '>>' expr
///
class RuntimeDyldChecker {
- friend class RuntimeDyldCheckerExprEval;
public:
- RuntimeDyldChecker(RuntimeDyld &RTDyld,
- MCDisassembler *Disassembler,
- MCInstPrinter *InstPrinter,
- llvm::raw_ostream &ErrStream)
- : RTDyld(*RTDyld.Dyld), Disassembler(Disassembler),
- InstPrinter(InstPrinter), ErrStream(ErrStream) {}
+ RuntimeDyldChecker(RuntimeDyld &RTDyld, MCDisassembler *Disassembler,
+ MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
+ ~RuntimeDyldChecker();
+
+ // \brief Get the associated RTDyld instance.
+ RuntimeDyld& getRTDyld();
+
+ // \brief Get the associated RTDyld instance.
+ const RuntimeDyld& getRTDyld() const;
/// \brief Check a single expression against the attached RuntimeDyld
/// instance.
@@ -79,20 +82,20 @@ public:
/// method to be evaluated as an expression.
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
-private:
+ /// \brief 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 'LinkerAddress' is true, this returns the address of the section
+ /// within the linker's memory. If 'LinkerAddress' is false it returns the
+ /// address within the target process (i.e. the load address).
+ std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
+ StringRef SectionName,
+ bool LinkerAddress);
- bool isSymbolValid(StringRef Symbol) const;
- uint64_t getSymbolAddress(StringRef Symbol) const;
- uint64_t readMemoryAtSymbol(StringRef Symbol, int64_t Offset,
- unsigned Size) const;
- StringRef getSubsectionStartingAt(StringRef Name) const;
-
- RuntimeDyldImpl &RTDyld;
- MCDisassembler *Disassembler;
- MCInstPrinter *InstPrinter;
- llvm::raw_ostream &ErrStream;
+private:
+ std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
};
} // end namespace llvm
-#endif // LLVM_RUNTIMEDYLDCHECKER_H
+#endif
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h
index 7c398a5e5530..dd76a90aa5ea 100644
--- a/include/llvm/IR/Argument.h
+++ b/include/llvm/IR/Argument.h
@@ -105,6 +105,14 @@ public:
/// its containing function.
bool hasInAllocaAttr() const;
+ /// \brief Return true if this argument has the zext attribute on it in its
+ /// containing function.
+ bool hasZExtAttr() const;
+
+ /// \brief Return true if this argument has the sext attribute on it in its
+ /// containing function.
+ bool hasSExtAttr() const;
+
/// \brief Add a Attribute to an argument.
void addAttr(AttributeSet AS);
diff --git a/include/llvm/IR/AssemblyAnnotationWriter.h b/include/llvm/IR/AssemblyAnnotationWriter.h
index a8d52f68176c..19e32a2dcdcc 100644
--- a/include/llvm/IR/AssemblyAnnotationWriter.h
+++ b/include/llvm/IR/AssemblyAnnotationWriter.h
@@ -14,8 +14,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_ASMANNOTATIONWRITER_H
-#define LLVM_IR_ASMANNOTATIONWRITER_H
+#ifndef LLVM_IR_ASSEMBLYANNOTATIONWRITER_H
+#define LLVM_IR_ASSEMBLYANNOTATIONWRITER_H
namespace llvm {
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index a19489aa49b1..7c7dd2ca5643 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -23,6 +23,7 @@
namespace llvm {
+class CallInst;
class LandingPadInst;
class TerminatorInst;
class LLVMContext;
@@ -125,6 +126,14 @@ public:
TerminatorInst *getTerminator();
const TerminatorInst *getTerminator() const;
+ /// \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.
+ CallInst *getTerminatingMustTailCall();
+ const CallInst *getTerminatingMustTailCall() const {
+ return const_cast<BasicBlock *>(this)->getTerminatingMustTailCall();
+ }
+
/// \brief Returns a pointer to the first instruction in this block that is
/// not a PHINode instruction.
///
@@ -173,6 +182,13 @@ public:
/// right after \p MovePos in the function \p MovePos lives in.
void moveAfter(BasicBlock *MovePos);
+ /// \brief 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.
+ ///
+ /// \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
/// block. Otherwise return a null pointer.
diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h
index c8be8bd1f2a7..5400d2384868 100644
--- a/include/llvm/IR/CFG.h
+++ b/include/llvm/IR/CFG.h
@@ -93,6 +93,9 @@ inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);}
inline const_pred_iterator pred_end(const BasicBlock *BB) {
return const_pred_iterator(BB, true);
}
+inline bool pred_empty(const BasicBlock *BB) {
+ return pred_begin(BB) == pred_end(BB);
+}
@@ -257,6 +260,9 @@ inline succ_iterator succ_end(BasicBlock *BB) {
inline succ_const_iterator succ_end(const BasicBlock *BB) {
return succ_const_iterator(BB->getTerminator(), true);
}
+inline bool succ_empty(const BasicBlock *BB) {
+ return succ_begin(BB) == succ_end(BB);
+}
template <typename T, typename U> struct isPodLike<SuccIterator<T, U> > {
static const bool value = isPodLike<T>::value;
diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h
index 1eaf4f7f469f..9872e6ec794d 100644
--- a/include/llvm/IR/CallingConv.h
+++ b/include/llvm/IR/CallingConv.h
@@ -20,10 +20,13 @@ namespace llvm {
/// the well-known calling conventions.
///
namespace CallingConv {
+ /// LLVM IR allows to use arbitrary numbers as calling convention identifiers.
+ typedef unsigned ID;
+
/// A set of enums which specify the assigned numeric values for known llvm
/// calling conventions.
/// @brief LLVM Calling Convention Representation
- enum ID {
+ enum {
/// C - The default llvm calling convention, compatible with C. This
/// convention is the only calling convention that supports varargs calls.
/// As with typical C calling conventions, the callee/caller have to
@@ -137,7 +140,11 @@ namespace CallingConv {
/// convention differs from the more common \c X86_64_SysV convention
/// in a number of ways, most notably in that XMM registers used to pass
/// arguments are shadowed by GPRs, and vice versa.
- X86_64_Win64 = 79
+ X86_64_Win64 = 79,
+
+ /// \brief MSVC calling convention that passes vectors and vector aggregates
+ /// in SSE registers.
+ X86_VectorCall = 80
};
} // End CallingConv namespace
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index 82ad9fc2f407..d26991eaab75 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -48,11 +48,16 @@ protected:
: User(ty, vty, Ops, NumOps) {}
void destroyConstantImpl();
+ void replaceUsesOfWithOnConstantImpl(Constant *Replacement);
+
public:
/// isNullValue - Return true if this is the value that would be returned by
/// getNullValue.
bool isNullValue() const;
+ /// \brief Returns true if the value is one.
+ bool isOneValue() const;
+
/// isAllOnesValue - Return true if this is the value that would be returned by
/// getAllOnesValue.
bool isAllOnesValue() const;
@@ -64,6 +69,9 @@ public:
/// Return true if the value is negative zero or null value.
bool isZeroValue() const;
+ /// \brief Return true if the value is not the smallest signed value.
+ bool isNotMinSignedValue() const;
+
/// \brief Return true if the value is the smallest signed value.
bool isMinSignedValue() const;
diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h
index 342422cbe25f..5e8cd34c4d69 100644
--- a/include/llvm/IR/ConstantRange.h
+++ b/include/llvm/IR/ConstantRange.h
@@ -29,15 +29,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_CONSTANTRANGE_H
-#define LLVM_SUPPORT_CONSTANTRANGE_H
+#ifndef LLVM_IR_CONSTANTRANGE_H
+#define LLVM_IR_CONSTANTRANGE_H
#include "llvm/ADT/APInt.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
-/// ConstantRange - This class represents an range of values.
+/// This class represents a range of values.
///
class ConstantRange {
APInt Lower, Upper;
@@ -59,7 +59,7 @@ public:
/// assert out if the two APInt's are not the same bit width.
ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper);
- /// makeICmpRegion - Produce the smallest range that contains all values that
+ /// Produce the smallest range that contains all values that
/// might satisfy the comparison specified by Pred when compared to any value
/// contained within Other.
///
@@ -69,47 +69,46 @@ public:
static ConstantRange makeICmpRegion(unsigned Pred,
const ConstantRange &Other);
- /// getLower - Return the lower value for this range...
+ /// Return the lower value for this range.
///
const APInt &getLower() const { return Lower; }
- /// getUpper - Return the upper value for this range...
+ /// Return the upper value for this range.
///
const APInt &getUpper() const { return Upper; }
- /// getBitWidth - get the bit width of this ConstantRange
+ /// Get the bit width of this ConstantRange.
///
uint32_t getBitWidth() const { return Lower.getBitWidth(); }
- /// isFullSet - Return true if this set contains all of the elements possible
- /// for this data-type
+ /// Return true if this set contains all of the elements possible
+ /// for this data-type.
///
bool isFullSet() const;
- /// isEmptySet - Return true if this set contains no members.
+ /// Return true if this set contains no members.
///
bool isEmptySet() const;
- /// isWrappedSet - Return true if this set wraps around the top of the range,
- /// for example: [100, 8)
+ /// Return true if this set wraps around the top of the range.
+ /// For example: [100, 8).
///
bool isWrappedSet() const;
- /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of
- /// its bitwidth, for example: i8 [120, 140).
+ /// Return true if this set wraps around the INT_MIN of
+ /// its bitwidth. For example: i8 [120, 140).
///
bool isSignWrappedSet() const;
- /// contains - Return true if the specified value is in the set.
+ /// Return true if the specified value is in the set.
///
bool contains(const APInt &Val) const;
- /// contains - Return true if the other range is a subset of this one.
+ /// Return true if the other range is a subset of this one.
///
bool contains(const ConstantRange &CR) const;
- /// getSingleElement - If this set contains a single element, return it,
- /// otherwise return null.
+ /// If this set contains a single element, return it, otherwise return null.
///
const APInt *getSingleElement() const {
if (Upper == Lower + 1)
@@ -117,35 +116,31 @@ public:
return nullptr;
}
- /// isSingleElement - Return true if this set contains exactly one member.
+ /// Return true if this set contains exactly one member.
///
bool isSingleElement() const { return getSingleElement() != nullptr; }
- /// getSetSize - Return the number of elements in this set.
+ /// Return the number of elements in this set.
///
APInt getSetSize() const;
- /// getUnsignedMax - Return the largest unsigned value contained in the
- /// ConstantRange.
+ /// Return the largest unsigned value contained in the ConstantRange.
///
APInt getUnsignedMax() const;
- /// getUnsignedMin - Return the smallest unsigned value contained in the
- /// ConstantRange.
+ /// Return the smallest unsigned value contained in the ConstantRange.
///
APInt getUnsignedMin() const;
- /// getSignedMax - Return the largest signed value contained in the
- /// ConstantRange.
+ /// Return the largest signed value contained in the ConstantRange.
///
APInt getSignedMax() const;
- /// getSignedMin - Return the smallest signed value contained in the
- /// ConstantRange.
+ /// Return the smallest signed value contained in the ConstantRange.
///
APInt getSignedMin() const;
- /// operator== - Return true if this range is equal to another range.
+ /// Return true if this range is equal to another range.
///
bool operator==(const ConstantRange &CR) const {
return Lower == CR.Lower && Upper == CR.Upper;
@@ -154,15 +149,14 @@ public:
return !operator==(CR);
}
- /// subtract - Subtract the specified constant from the endpoints of this
- /// constant range.
+ /// Subtract the specified constant from the endpoints of this constant range.
ConstantRange subtract(const APInt &CI) const;
/// \brief Subtract the specified range from this range (aka relative
/// complement of the sets).
ConstantRange difference(const ConstantRange &CR) const;
- /// intersectWith - Return the range that results from the intersection of
+ /// Return the range that results from the intersection of
/// this range with another range. The resultant range is guaranteed to
/// include all elements contained in both input ranges, and to have the
/// smallest possible set size that does so. Because there may be two
@@ -171,7 +165,7 @@ public:
///
ConstantRange intersectWith(const ConstantRange &CR) const;
- /// unionWith - Return the range that results from the union of this range
+ /// Return the range that results from the union of this range
/// with another range. The resultant range is guaranteed to include the
/// elements of both sets, but may contain more. For example, [3, 9) union
/// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included
@@ -179,85 +173,84 @@ public:
///
ConstantRange unionWith(const ConstantRange &CR) const;
- /// zeroExtend - Return a new range in the specified integer type, which must
+ /// Return a new range in the specified integer type, which must
/// be strictly larger than the current type. The returned range will
/// correspond to the possible range of values if the source range had been
/// zero extended to BitWidth.
ConstantRange zeroExtend(uint32_t BitWidth) const;
- /// signExtend - Return a new range in the specified integer type, which must
+ /// Return a new range in the specified integer type, which must
/// be strictly larger than the current type. The returned range will
/// correspond to the possible range of values if the source range had been
/// sign extended to BitWidth.
ConstantRange signExtend(uint32_t BitWidth) const;
- /// truncate - Return a new range in the specified integer type, which must be
+ /// Return a new range in the specified integer type, which must be
/// strictly smaller than the current type. The returned range will
/// correspond to the possible range of values if the source range had been
/// truncated to the specified type.
ConstantRange truncate(uint32_t BitWidth) const;
- /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The
+ /// Make this range have the bit width given by \p BitWidth. The
/// value is zero extended, truncated, or left alone to make it that width.
ConstantRange zextOrTrunc(uint32_t BitWidth) const;
- /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The
+ /// Make this range have the bit width given by \p BitWidth. The
/// value is sign extended, truncated, or left alone to make it that width.
ConstantRange sextOrTrunc(uint32_t BitWidth) const;
- /// add - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from an addition of a value in this range and a value in \p Other.
ConstantRange add(const ConstantRange &Other) const;
- /// sub - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a subtraction of a value in this range and a value in \p Other.
ConstantRange sub(const ConstantRange &Other) const;
- /// multiply - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a multiplication of a value in this range and a value in \p Other.
/// TODO: This isn't fully implemented yet.
ConstantRange multiply(const ConstantRange &Other) const;
- /// smax - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a signed maximum of a value in this range and a value in \p Other.
ConstantRange smax(const ConstantRange &Other) const;
- /// umax - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from an unsigned maximum of a value in this range and a value in \p Other.
ConstantRange umax(const ConstantRange &Other) const;
- /// udiv - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from an unsigned division of a value in this range and a value in
/// \p Other.
ConstantRange udiv(const ConstantRange &Other) const;
- /// binaryAnd - return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a binary-and of a value in this range by a value in \p Other.
ConstantRange binaryAnd(const ConstantRange &Other) const;
- /// binaryOr - return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a binary-or of a value in this range by a value in \p Other.
ConstantRange binaryOr(const ConstantRange &Other) const;
- /// shl - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a left shift of a value in this range by a value in \p Other.
/// TODO: This isn't fully implemented yet.
ConstantRange shl(const ConstantRange &Other) const;
- /// lshr - Return a new range representing the possible values resulting
- /// from a logical right shift of a value in this range and a value in
- /// \p Other.
+ /// Return a new range representing the possible values resulting from a
+ /// logical right shift of a value in this range and a value in \p Other.
ConstantRange lshr(const ConstantRange &Other) const;
- /// inverse - Return a new range that is the logical not of the current set.
+ /// Return a new range that is the logical not of the current set.
///
ConstantRange inverse() const;
- /// print - Print out the bounds to a stream...
+ /// Print out the bounds to a stream.
///
void print(raw_ostream &OS) const;
- /// dump - Allow printing from a debugger easily...
+ /// Allow printing from a debugger easily.
///
void dump() const;
};
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index 0e72f040d3e0..1b0e1b7e7b77 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -37,12 +37,8 @@ class PointerType;
class VectorType;
class SequentialType;
-template<class ConstantClass, class TypeClass, class ValType>
-struct ConstantCreator;
-template<class ConstantClass, class TypeClass>
-struct ConstantArrayCreator;
-template<class ConstantClass, class TypeClass>
-struct ConvertConstantType;
+struct ConstantExprKeyType;
+template <class ConstantClass> struct ConstantAggrKeyType;
//===----------------------------------------------------------------------===//
/// This is the shared class of boolean and integer constants. This class
@@ -268,6 +264,9 @@ public:
/// isNegative - Return true if the sign bit is set.
bool isNegative() const { return Val.isNegative(); }
+ /// isInfinity - Return true if the value is infinity
+ bool isInfinity() const { return Val.isInfinity(); }
+
/// isNaN - Return true if the value is a NaN.
bool isNaN() const { return Val.isNaN(); }
@@ -338,7 +337,7 @@ public:
/// ConstantArray - Constant Array Declarations
///
class ConstantArray : public Constant {
- friend struct ConstantArrayCreator<ConstantArray, ArrayType>;
+ friend struct ConstantAggrKeyType<ConstantArray>;
ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION;
protected:
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
@@ -346,6 +345,10 @@ public:
// ConstantArray accessors
static Constant *get(ArrayType *T, ArrayRef<Constant*> V);
+private:
+ static Constant *getImpl(ArrayType *T, ArrayRef<Constant *> V);
+
+public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
@@ -376,14 +379,14 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant)
// ConstantStruct - Constant Struct Declarations
//
class ConstantStruct : public Constant {
- friend struct ConstantArrayCreator<ConstantStruct, StructType>;
+ friend struct ConstantAggrKeyType<ConstantStruct>;
ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION;
protected:
ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
public:
// ConstantStruct accessors
static Constant *get(StructType *T, ArrayRef<Constant*> V);
- static Constant *get(StructType *T, ...) END_WITH_NULL;
+ static Constant *get(StructType *T, ...) LLVM_END_WITH_NULL;
/// getAnon - Return an anonymous struct that has the specified
/// elements. If the struct is possibly empty, then you must specify a
@@ -435,7 +438,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant)
/// ConstantVector - Constant Vector Declarations
///
class ConstantVector : public Constant {
- friend struct ConstantArrayCreator<ConstantVector, VectorType>;
+ friend struct ConstantAggrKeyType<ConstantVector>;
ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION;
protected:
ConstantVector(VectorType *T, ArrayRef<Constant *> Val);
@@ -443,6 +446,10 @@ public:
// ConstantVector accessors
static Constant *get(ArrayRef<Constant*> V);
+private:
+ static Constant *getImpl(ArrayRef<Constant *> V);
+
+public:
/// getSplat - Return a ConstantVector with the specified constant in each
/// element.
static Constant *getSplat(unsigned NumElts, Constant *Elt);
@@ -794,9 +801,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value)
/// constant expressions. The Opcode field for the ConstantExpr class is
/// maintained in the Value::SubclassData field.
class ConstantExpr : public Constant {
- friend struct ConstantCreator<ConstantExpr,Type,
- std::pair<unsigned, std::vector<Constant*> > >;
- friend struct ConvertConstantType<ConstantExpr, Type>;
+ friend struct ConstantExprKeyType;
protected:
ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps)
@@ -856,19 +861,25 @@ public:
bool HasNUW = false, bool HasNSW = false);
static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false);
static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false);
- static Constant *getTrunc (Constant *C, Type *Ty);
- static Constant *getSExt (Constant *C, Type *Ty);
- static Constant *getZExt (Constant *C, Type *Ty);
- static Constant *getFPTrunc (Constant *C, Type *Ty);
- static Constant *getFPExtend(Constant *C, Type *Ty);
- static Constant *getUIToFP (Constant *C, Type *Ty);
- static Constant *getSIToFP (Constant *C, Type *Ty);
- static Constant *getFPToUI (Constant *C, Type *Ty);
- static Constant *getFPToSI (Constant *C, Type *Ty);
- static Constant *getPtrToInt(Constant *C, Type *Ty);
- static Constant *getIntToPtr(Constant *C, Type *Ty);
- static Constant *getBitCast (Constant *C, Type *Ty);
- static Constant *getAddrSpaceCast(Constant *C, Type *Ty);
+ static Constant *getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getSExt(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getZExt(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getFPTrunc(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getFPExtend(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getUIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getSIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getFPToUI(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getFPToSI(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getPtrToInt(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getIntToPtr(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getBitCast(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getAddrSpaceCast(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); }
static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); }
@@ -923,13 +934,14 @@ public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
- // @brief Convenience function for getting one of the casting operations
- // using a CastOps opcode.
- static Constant *getCast(
- unsigned ops, ///< The opcode for the conversion
- Constant *C, ///< The constant to be converted
- Type *Ty ///< The type to which the constant is converted
- );
+ /// \brief Convenience function for getting a Cast operation.
+ ///
+ /// \param ops The opcode for the conversion
+ /// \param C The constant to be converted
+ /// \param Ty The type to which the constant is converted
+ /// \param OnlyIfReduced see \a getWithOperands() docs.
+ static Constant *getCast(unsigned ops, Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
// @brief Create a ZExt or BitCast cast constant expression
static Constant *getZExtOrBitCast(
@@ -995,44 +1007,53 @@ public:
/// Select constant expr
///
- static Constant *getSelect(Constant *C, Constant *V1, Constant *V2);
+ /// \param OnlyIfReducedTy see \a getWithOperands() docs.
+ static Constant *getSelect(Constant *C, Constant *V1, Constant *V2,
+ Type *OnlyIfReducedTy = nullptr);
/// get - Return a binary or shift operator constant expression,
/// folding if possible.
///
+ /// \param OnlyIfReducedTy see \a getWithOperands() docs.
static Constant *get(unsigned Opcode, Constant *C1, Constant *C2,
- unsigned Flags = 0);
+ unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr);
- /// @brief Return an ICmp or FCmp comparison operator constant expression.
- static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2);
+ /// \brief 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,
+ bool OnlyIfReduced = false);
/// get* - Return some common constants without having to
/// specify the full Instruction::OPCODE identifier.
///
- static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS);
- static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS);
+ static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS,
+ bool OnlyIfReduced = false);
+ static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS,
+ bool OnlyIfReduced = false);
/// Getelementptr form. Value* is only accepted for convenience;
/// all elements must be Constant's.
///
- static Constant *getGetElementPtr(Constant *C,
- ArrayRef<Constant *> IdxList,
- bool InBounds = false) {
- return getGetElementPtr(C, makeArrayRef((Value * const *)IdxList.data(),
- IdxList.size()),
- InBounds);
- }
- static Constant *getGetElementPtr(Constant *C,
- Constant *Idx,
- bool InBounds = false) {
+ /// \param OnlyIfReducedTy see \a getWithOperands() docs.
+ static Constant *getGetElementPtr(Constant *C, ArrayRef<Constant *> IdxList,
+ bool InBounds = false,
+ Type *OnlyIfReducedTy = nullptr) {
+ return getGetElementPtr(
+ C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()),
+ InBounds, OnlyIfReducedTy);
+ }
+ static Constant *getGetElementPtr(Constant *C, Constant *Idx,
+ bool InBounds = false,
+ Type *OnlyIfReducedTy = nullptr) {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
- return getGetElementPtr(C, cast<Value>(Idx), InBounds);
+ return getGetElementPtr(C, cast<Value>(Idx), InBounds, OnlyIfReducedTy);
}
- static Constant *getGetElementPtr(Constant *C,
- ArrayRef<Value *> IdxList,
- bool InBounds = false);
+ static Constant *getGetElementPtr(Constant *C, ArrayRef<Value *> IdxList,
+ bool InBounds = false,
+ Type *OnlyIfReducedTy = nullptr);
/// Create an "inbounds" getelementptr. See the documentation for the
/// "inbounds" flag in LangRef.html for details.
@@ -1052,12 +1073,17 @@ public:
return getGetElementPtr(C, IdxList, true);
}
- static Constant *getExtractElement(Constant *Vec, Constant *Idx);
- static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx);
- static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask);
- static Constant *getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs);
+ static Constant *getExtractElement(Constant *Vec, Constant *Idx,
+ Type *OnlyIfReducedTy = nullptr);
+ static Constant *getInsertElement(Constant *Vec, Constant *Elt, Constant *Idx,
+ Type *OnlyIfReducedTy = nullptr);
+ static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask,
+ Type *OnlyIfReducedTy = nullptr);
+ static Constant *getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs,
+ Type *OnlyIfReducedTy = nullptr);
static Constant *getInsertValue(Constant *Agg, Constant *Val,
- ArrayRef<unsigned> Idxs);
+ ArrayRef<unsigned> Idxs,
+ Type *OnlyIfReducedTy = nullptr);
/// getOpcode - Return the opcode at the root of this constant expression
unsigned getOpcode() const { return getSubclassDataFromValue(); }
@@ -1084,11 +1110,17 @@ public:
return getWithOperands(Ops, getType());
}
- /// getWithOperands - This returns the current constant expression with the
- /// operands replaced with the specified values and with the specified result
- /// type. The specified array must have the same number of operands as our
- /// current one.
- Constant *getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const;
+ /// \brief Get the current expression with the operands replaced.
+ ///
+ /// Return the current constant expression with the operands replaced with \c
+ /// Ops and the type with \c Ty. The new operands must have the same number
+ /// as the current ones.
+ ///
+ /// If \c OnlyIfReduced is \c true, nullptr will be returned unless something
+ /// gets constant-folded, the type changes, or the expression is otherwise
+ /// canonicalized. This parameter should almost always be \c false.
+ Constant *getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
+ bool OnlyIfReduced = false) const;
/// getAsInstruction - Returns an Instruction which implements the same operation
/// as this ConstantExpr. The instruction is not linked to any basic block.
diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h
index 267350409604..ae1ac650a9ec 100644
--- a/include/llvm/IR/DIBuilder.h
+++ b/include/llvm/IR/DIBuilder.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/DataTypes.h"
@@ -27,6 +28,7 @@ namespace llvm {
class Function;
class Module;
class Value;
+ class Constant;
class LLVMContext;
class MDNode;
class StringRef;
@@ -38,7 +40,6 @@ namespace llvm {
class DIFile;
class DIEnumerator;
class DIType;
- class DIArray;
class DIGlobalVariable;
class DIImportedEntity;
class DINameSpace;
@@ -53,7 +54,6 @@ namespace llvm {
class DIObjCProperty;
class DIBuilder {
- private:
Module &M;
LLVMContext &VMContext;
@@ -66,27 +66,34 @@ namespace llvm {
Function *DeclareFn; // llvm.dbg.declare
Function *ValueFn; // llvm.dbg.value
- SmallVector<Value *, 4> AllEnumTypes;
- /// Use TrackingVH to collect RetainTypes, since they can be updated
- /// later on.
- SmallVector<TrackingVH<MDNode>, 4> AllRetainTypes;
- SmallVector<Value *, 4> AllSubprograms;
- SmallVector<Value *, 4> AllGVs;
- SmallVector<TrackingVH<MDNode>, 4> AllImportedModules;
+ SmallVector<Metadata *, 4> AllEnumTypes;
+ /// Track the RetainTypes, since they can be updated later on.
+ SmallVector<TrackingMDNodeRef, 4> AllRetainTypes;
+ SmallVector<Metadata *, 4> AllSubprograms;
+ SmallVector<Metadata *, 4> AllGVs;
+ SmallVector<TrackingMDNodeRef, 4> AllImportedModules;
- // Private use for multiple types of template parameters.
- DITemplateValueParameter
- createTemplateValueParameter(unsigned Tag, DIDescriptor Scope,
- StringRef Name, DIType Ty, Value *Val,
- MDNode *File = nullptr, unsigned LineNo = 0,
- unsigned ColumnNo = 0);
+ /// \brief Track nodes that may be unresolved.
+ SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
+ bool AllowUnresolvedNodes;
+
+ /// Each subprogram's preserved local variables.
+ DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> PreservedVariables;
DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION;
void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION;
- public:
- explicit DIBuilder(Module &M);
- enum ComplexAddrKind { OpPlus=1, OpDeref };
+ /// \brief Create a temporary.
+ ///
+ /// Create an \a MDNodeFwdDecl and track it in \a UnresolvedNodes.
+ void trackIfUnresolved(MDNode *N);
+
+ public:
+ /// \brief Construct a builder for a module.
+ ///
+ /// If \c AllowUnresolved, collect unresolved nodes attached to the module
+ /// in order to resolve cycles during \a finalize().
+ explicit DIBuilder(Module &M, bool AllowUnresolved = true);
enum DebugEmissionKind { FullDebug=1, LineTablesOnly };
/// finalize - Construct any deferred debug info descriptors.
@@ -165,8 +172,12 @@ namespace llvm {
/// \brief Create debugging information entry for a pointer to member.
/// @param PointeeTy Type pointed to by this pointer.
+ /// @param SizeInBits Size.
+ /// @param AlignInBits Alignment. (optional)
/// @param Class Type for which this pointer points to members of.
- DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class);
+ DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits = 0);
/// createReferenceType - Create debugging information entry for a c++
/// style reference or rvalue reference type.
@@ -218,36 +229,10 @@ namespace llvm {
/// @param Ty Type of the static member.
/// @param Flags Flags to encode member attribute, e.g. private.
/// @param Val Const initializer of the member.
- DIDerivedType
- createStaticMemberType(DIDescriptor Scope, StringRef Name,
- DIFile File, unsigned LineNo, DIType Ty,
- unsigned Flags, llvm::Value *Val);
-
- /// createObjCIVar - Create debugging information entry for Objective-C
- /// instance variable.
- /// @param Name Member name.
- /// @param File File where this member is defined.
- /// @param LineNo Line number.
- /// @param SizeInBits Member size.
- /// @param AlignInBits Member alignment.
- /// @param OffsetInBits Member offset.
- /// @param Flags Flags to encode member attribute, e.g. private
- /// @param Ty Parent type.
- /// @param PropertyName Name of the Objective C property associated with
- /// this ivar.
- /// @param PropertyGetterName Name of the Objective C property getter
- /// selector.
- /// @param PropertySetterName Name of the Objective C property setter
- /// selector.
- /// @param PropertyAttributes Objective C property attributes.
- DIDerivedType createObjCIVar(StringRef Name, DIFile File,
- unsigned LineNo, uint64_t SizeInBits,
- uint64_t AlignInBits, uint64_t OffsetInBits,
- unsigned Flags, DIType Ty,
- StringRef PropertyName = StringRef(),
- StringRef PropertyGetterName = StringRef(),
- StringRef PropertySetterName = StringRef(),
- unsigned PropertyAttributes = 0);
+ DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name,
+ DIFile File, unsigned LineNo,
+ DIType Ty, unsigned Flags,
+ llvm::Constant *Val);
/// createObjCIVar - Create debugging information entry for Objective-C
/// instance variable.
@@ -366,8 +351,8 @@ namespace llvm {
/// @param LineNo Line number.
/// @param ColumnNo Column Number.
DITemplateValueParameter
- createTemplateValueParameter(DIDescriptor Scope, StringRef Name,
- DIType Ty, Value *Val, MDNode *File = nullptr,
+ createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
+ Constant *Val, MDNode *File = nullptr,
unsigned LineNo = 0, unsigned ColumnNo = 0);
/// \brief Create debugging information for a template template parameter.
@@ -435,8 +420,9 @@ namespace llvm {
/// includes return type at 0th index.
/// @param Flags E.g.: LValueReference.
/// These flags are used to emit dwarf attributes.
- DICompositeType createSubroutineType(DIFile File, DIArray ParameterTypes,
- unsigned Flags = 0);
+ DISubroutineType createSubroutineType(DIFile File,
+ DITypeArray ParameterTypes,
+ unsigned Flags = 0);
/// createArtificialType - Create a new DIType with "artificial" flag set.
DIType createArtificialType(DIType Ty);
@@ -463,44 +449,22 @@ namespace llvm {
/// through debug info anchors.
void retainType(DIType T);
- /// createUnspecifiedParameter - Create unspecified type descriptor
+ /// createUnspecifiedParameter - Create unspecified parameter type
/// for a subroutine type.
- DIDescriptor createUnspecifiedParameter();
+ DIBasicType createUnspecifiedParameter();
/// getOrCreateArray - Get a DIArray, create one if required.
- DIArray getOrCreateArray(ArrayRef<Value *> Elements);
+ DIArray getOrCreateArray(ArrayRef<Metadata *> Elements);
+
+ /// getOrCreateTypeArray - Get a DITypeArray, create one if required.
+ DITypeArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements);
/// getOrCreateSubrange - Create a descriptor for a value range. This
/// implicitly uniques the values returned.
DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count);
- /// createGlobalVariable - Create a new descriptor for the specified global.
- /// @param Name Name of the variable.
- /// @param File File where this variable is defined.
- /// @param LineNo Line number.
- /// @param Ty Variable Type.
- /// @param isLocalToUnit Boolean flag indicate whether this variable is
- /// externally visible or not.
- /// @param Val llvm::Value of the variable.
- DIGlobalVariable
- createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo,
- DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val);
- /// \brief Create a new descriptor for the specified global.
- /// @param Name Name of the variable.
- /// @param LinkageName Mangled variable name.
- /// @param File File where this variable is defined.
- /// @param LineNo Line number.
- /// @param Ty Variable Type.
- /// @param isLocalToUnit Boolean flag indicate whether this variable is
- /// externally visible or not.
- /// @param Val llvm::Value of the variable.
- DIGlobalVariable
- createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile File,
- unsigned LineNo, DITypeRef Ty, bool isLocalToUnit,
- llvm::Value *Val);
-
- /// createStaticVariable - Create a new descriptor for the specified
+ /// createGlobalVariable - Create a new descriptor for the specified
/// variable.
/// @param Context Variable scope.
/// @param Name Name of the variable.
@@ -512,12 +476,19 @@ namespace llvm {
/// externally visible or not.
/// @param Val llvm::Value of the variable.
/// @param Decl Reference to the corresponding declaration.
- DIGlobalVariable
- createStaticVariable(DIDescriptor Context, StringRef Name,
- StringRef LinkageName, DIFile File, unsigned LineNo,
- DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val,
- MDNode *Decl = nullptr);
-
+ DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name,
+ StringRef LinkageName, DIFile File,
+ unsigned LineNo, DITypeRef Ty,
+ bool isLocalToUnit,
+ llvm::Constant *Val,
+ MDNode *Decl = nullptr);
+
+ /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable
+ /// except that the resulting DbgNode is temporary and meant to be RAUWed.
+ DIGlobalVariable createTempGlobalVariableFwdDecl(
+ DIDescriptor Context, StringRef Name, StringRef LinkageName,
+ DIFile File, unsigned LineNo, DITypeRef Ty, bool isLocalToUnit,
+ llvm::Constant *Val, MDNode *Decl = nullptr);
/// createLocalVariable - Create a new descriptor for the specified
/// local variable.
@@ -540,23 +511,18 @@ namespace llvm {
unsigned Flags = 0,
unsigned ArgNo = 0);
-
- /// createComplexVariable - Create a new descriptor for the specified
+ /// createExpression - Create a new descriptor for the specified
/// variable which has a complex address expression for its address.
- /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or
- /// DW_TAG_arg_variable.
- /// @param Scope Variable scope.
- /// @param Name Variable name.
- /// @param F File where this variable is defined.
- /// @param LineNo Line number.
- /// @param Ty Variable Type
/// @param Addr An array of complex address operations.
- /// @param ArgNo If this variable is an argument then this argument's
- /// number. 1 indicates 1st argument.
- DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope,
- StringRef Name, DIFile F, unsigned LineNo,
- DITypeRef Ty, ArrayRef<Value *> Addr,
- unsigned ArgNo = 0);
+ DIExpression createExpression(ArrayRef<int64_t> Addr = None);
+
+ /// createPieceExpression - Create a descriptor to describe one part
+ /// of aggregate variable that is fragmented across multiple Values.
+ ///
+ /// @param OffsetInBytes Offset of the piece in bytes.
+ /// @param SizeInBytes Size of the piece in bytes.
+ DIExpression createPieceExpression(unsigned OffsetInBytes,
+ unsigned SizeInBytes);
/// createFunction - Create a new descriptor for the specified subprogram.
/// See comments in DISubprogram for descriptions of these fields.
@@ -586,6 +552,21 @@ namespace llvm {
MDNode *TParam = nullptr,
MDNode *Decl = nullptr);
+ /// createTempFunctionFwdDecl - Identical to createFunction,
+ /// except that the resulting DbgNode is meant to be RAUWed.
+ DISubprogram createTempFunctionFwdDecl(DIDescriptor Scope, StringRef Name,
+ StringRef LinkageName,
+ DIFile File, unsigned LineNo,
+ DICompositeType Ty, bool isLocalToUnit,
+ bool isDefinition,
+ unsigned ScopeLine,
+ unsigned Flags = 0,
+ bool isOptimized = false,
+ Function *Fn = nullptr,
+ MDNode *TParam = nullptr,
+ MDNode *Decl = nullptr);
+
+
/// FIXME: this is added for dragonegg. Once we update dragonegg
/// to call resolve function, this will be removed.
DISubprogram createFunction(DIScopeRef Scope, StringRef Name,
@@ -646,8 +627,9 @@ namespace llvm {
/// lexical block as it crosses a file.
/// @param Scope Lexical block.
/// @param File Source file.
- DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope,
- DIFile File);
+ /// @param Discriminator DWARF path discriminator value.
+ DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File,
+ unsigned Discriminator = 0);
/// createLexicalBlock - This creates a descriptor for a lexical block
/// with the specified parent context.
@@ -655,10 +637,8 @@ namespace llvm {
/// @param File Source file.
/// @param Line Line number.
/// @param Col Column number.
- /// @param Discriminator DWARF path discriminator value.
DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File,
- unsigned Line, unsigned Col,
- unsigned Discriminator);
+ unsigned Line, unsigned Col);
/// \brief Create a descriptor for an imported module.
/// @param Context The scope this module is imported into
@@ -679,7 +659,7 @@ namespace llvm {
/// @param Decl The declaration (or definition) of a function, type, or
/// variable
/// @param Line Line number
- DIImportedEntity createImportedDeclaration(DIScope Context, DIScope Decl,
+ DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl,
unsigned Line,
StringRef Name = StringRef());
DIImportedEntity createImportedDeclaration(DIScope Context,
@@ -690,36 +670,52 @@ namespace llvm {
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
/// @param Storage llvm::Value of the variable
/// @param VarInfo Variable's debug info descriptor.
+ /// @param Expr A complex location expression.
/// @param InsertAtEnd Location for the new intrinsic.
Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
- BasicBlock *InsertAtEnd);
+ DIExpression Expr, BasicBlock *InsertAtEnd);
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
/// @param Storage llvm::Value of the variable
/// @param VarInfo Variable's debug info descriptor.
+ /// @param Expr A complex location expression.
/// @param InsertBefore Location for the new intrinsic.
Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
- Instruction *InsertBefore);
-
+ DIExpression Expr, Instruction *InsertBefore);
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
/// @param Val llvm::Value of the variable
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
+ /// @param Expr A complex location expression.
/// @param InsertAtEnd Location for the new intrinsic.
Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
- DIVariable VarInfo,
+ DIVariable VarInfo, DIExpression Expr,
BasicBlock *InsertAtEnd);
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
/// @param Val llvm::Value of the variable
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
+ /// @param Expr A complex location expression.
/// @param InsertBefore Location for the new intrinsic.
Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
- DIVariable VarInfo,
+ DIVariable VarInfo, DIExpression Expr,
Instruction *InsertBefore);
+ /// \brief Replace the vtable holder in the given composite type.
+ ///
+ /// If this creates a self reference, it may orphan some unresolved cycles
+ /// in the operands of \c T, so \a DIBuilder needs to track that.
+ void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder);
+
+ /// \brief Replace arrays on a composite type.
+ ///
+ /// If \c T is resolved, but the arrays aren't -- which can happen if \c T
+ /// has a self-reference -- \a DIBuilder needs to track the array to
+ /// resolve cycles.
+ void replaceArrays(DICompositeType &T, DIArray Elements,
+ DIArray TParems = DIArray());
};
} // end namespace llvm
diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h
index 877029f92f0b..a9e75955ce74 100644
--- a/include/llvm/IR/DataLayout.h
+++ b/include/llvm/IR/DataLayout.h
@@ -27,7 +27,8 @@
#include "llvm/Pass.h"
#include "llvm/Support/DataTypes.h"
-// this needs to be outside of the namespace, to avoid conflict with llvm-c decl
+// This needs to be outside of the namespace, to avoid conflict with llvm-c
+// decl.
typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
namespace llvm {
@@ -45,79 +46,71 @@ class ArrayRef;
/// Enum used to categorize the alignment types stored by LayoutAlignElem
enum AlignTypeEnum {
- INVALID_ALIGN = 0, ///< An invalid alignment
- INTEGER_ALIGN = 'i', ///< Integer type alignment
- VECTOR_ALIGN = 'v', ///< Vector type alignment
- FLOAT_ALIGN = 'f', ///< Floating point type alignment
- AGGREGATE_ALIGN = 'a' ///< Aggregate alignment
+ INVALID_ALIGN = 0,
+ INTEGER_ALIGN = 'i',
+ VECTOR_ALIGN = 'v',
+ FLOAT_ALIGN = 'f',
+ AGGREGATE_ALIGN = 'a'
};
-/// Layout alignment element.
+/// \brief Layout alignment element.
///
/// Stores the alignment data associated with a given alignment type (integer,
/// vector, float) and type bit width.
///
-/// @note The unusual order of elements in the structure attempts to reduce
+/// \note The unusual order of elements in the structure attempts to reduce
/// padding and make the structure slightly more cache friendly.
struct LayoutAlignElem {
- unsigned AlignType : 8; ///< Alignment type (AlignTypeEnum)
- unsigned TypeBitWidth : 24; ///< Type bit width
- unsigned ABIAlign : 16; ///< ABI alignment for this type/bitw
- unsigned PrefAlign : 16; ///< Pref. alignment for this type/bitw
+ /// \brief Alignment type from \c AlignTypeEnum
+ unsigned AlignType : 8;
+ unsigned TypeBitWidth : 24;
+ unsigned ABIAlign : 16;
+ unsigned PrefAlign : 16;
- /// Initializer
static LayoutAlignElem get(AlignTypeEnum align_type, unsigned abi_align,
unsigned pref_align, uint32_t bit_width);
- /// Equality predicate
bool operator==(const LayoutAlignElem &rhs) const;
};
-/// Layout pointer alignment element.
+/// \brief Layout pointer alignment element.
///
/// Stores the alignment data associated with a given pointer and address space.
///
-/// @note The unusual order of elements in the structure attempts to reduce
+/// \note The unusual order of elements in the structure attempts to reduce
/// padding and make the structure slightly more cache friendly.
struct PointerAlignElem {
- unsigned ABIAlign; ///< ABI alignment for this type/bitw
- unsigned PrefAlign; ///< Pref. alignment for this type/bitw
- uint32_t TypeByteWidth; ///< Type byte width
- uint32_t AddressSpace; ///< Address space for the pointer type
+ unsigned ABIAlign;
+ unsigned PrefAlign;
+ uint32_t TypeByteWidth;
+ uint32_t AddressSpace;
/// Initializer
static PointerAlignElem get(uint32_t AddressSpace, unsigned ABIAlign,
- unsigned PrefAlign, uint32_t TypeByteWidth);
- /// Equality predicate
+ unsigned PrefAlign, uint32_t TypeByteWidth);
bool operator==(const PointerAlignElem &rhs) const;
};
-/// This class holds a parsed version of the target data layout string in a
-/// module and provides methods for querying it. The target data layout string
-/// is specified *by the target* - a frontend generating LLVM IR is required to
-/// generate the right target data for the target being codegen'd to.
+/// \brief 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
+/// generating LLVM IR is required to generate the right target data for the
+/// target being codegen'd to.
class DataLayout {
private:
- bool LittleEndian; ///< Defaults to false
- unsigned StackNaturalAlign; ///< Stack natural alignment
-
- enum ManglingModeT {
- MM_None,
- MM_ELF,
- MM_MachO,
- MM_WINCOFF,
- MM_Mips
- };
+ /// Defaults to false.
+ bool BigEndian;
+
+ unsigned StackNaturalAlign;
+
+ enum ManglingModeT { MM_None, MM_ELF, MM_MachO, MM_WINCOFF, MM_Mips };
ManglingModeT ManglingMode;
- SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers.
+ SmallVector<unsigned char, 8> LegalIntWidths;
- /// Alignments - Where the primitive type alignment data is stored.
- ///
- /// @sa reset().
- /// @note Could support multiple size pointer alignments, e.g., 32-bit
- /// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now,
- /// we don't.
+ /// \brief Primitive type alignment data.
SmallVector<LayoutAlignElem, 16> Alignments;
+
typedef SmallVector<PointerAlignElem, 8> PointersTy;
PointersTy Pointers;
@@ -128,31 +121,28 @@ private:
PointersTy::iterator findPointerLowerBound(uint32_t AddressSpace);
- /// InvalidAlignmentElem - This member is a signal that a requested alignment
- /// type and bit width were not found in the SmallVector.
+ /// This member is a signal that a requested alignment type and bit width were
+ /// not found in the SmallVector.
static const LayoutAlignElem InvalidAlignmentElem;
- /// InvalidPointerElem - This member is a signal that a requested pointer
- /// type and bit width were not found in the DenseSet.
+ /// This member is a signal that a requested pointer type and bit width were
+ /// not found in the DenseSet.
static const PointerAlignElem InvalidPointerElem;
// The StructType -> StructLayout map.
mutable void *LayoutMap;
- //! Set/initialize target alignments
void setAlignment(AlignTypeEnum align_type, unsigned abi_align,
unsigned pref_align, uint32_t bit_width);
unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width,
bool ABIAlign, Type *Ty) const;
-
- //! Set/initialize pointer alignments
void setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
unsigned PrefAlign, uint32_t TypeByteWidth);
- //! Internal helper method that returns requested alignment for type.
+ /// Internal helper method that returns requested alignment for type.
unsigned getAlignment(Type *Ty, bool abi_or_pref) const;
- /// Valid alignment predicate.
+ /// \brief Valid alignment predicate.
///
/// Predicate that tests a LayoutAlignElem reference returned by get() against
/// InvalidAlignmentElem.
@@ -160,10 +150,10 @@ private:
return &align != &InvalidAlignmentElem;
}
- /// Valid pointer predicate.
+ /// \brief Valid pointer predicate.
///
- /// Predicate that tests a PointerAlignElem reference returned by get() against
- /// InvalidPointerElem.
+ /// Predicate that tests a PointerAlignElem reference returned by get()
+ /// against \c InvalidPointerElem.
bool validPointer(const PointerAlignElem &align) const {
return &align != &InvalidPointerElem;
}
@@ -184,11 +174,13 @@ public:
/// Initialize target data from properties stored in the module.
explicit DataLayout(const Module *M);
+ void init(const Module *M);
+
DataLayout(const DataLayout &DL) : LayoutMap(nullptr) { *this = DL; }
DataLayout &operator=(const DataLayout &DL) {
clear();
- LittleEndian = DL.isLittleEndian();
+ BigEndian = DL.isBigEndian();
StackNaturalAlign = DL.StackNaturalAlign;
ManglingMode = DL.ManglingMode;
LegalIntWidths = DL.LegalIntWidths;
@@ -200,27 +192,28 @@ public:
bool operator==(const DataLayout &Other) const;
bool operator!=(const DataLayout &Other) const { return !(*this == Other); }
- ~DataLayout(); // Not virtual, do not subclass this class
+ ~DataLayout(); // Not virtual, do not subclass this class
/// Parse a data layout string (with fallback to default values).
void reset(StringRef LayoutDescription);
/// Layout endianness...
- bool isLittleEndian() const { return LittleEndian; }
- bool isBigEndian() const { return !LittleEndian; }
+ bool isLittleEndian() const { return !BigEndian; }
+ bool isBigEndian() const { return BigEndian; }
- /// getStringRepresentation - Return the string representation of the
- /// DataLayout. This representation is in the same format accepted by the
- /// string constructor above.
+ /// \brief Returns the string representation of the DataLayout.
+ ///
+ /// This representation is in the same format accepted by the string
+ /// constructor above.
std::string getStringRepresentation() const;
- /// isLegalInteger - This function returns true if the specified type is
- /// known to be a native integer type supported by the CPU. For example,
- /// i64 is not native on most 32-bit CPUs and i37 is not native on any known
- /// one. This returns false if the integer width is not legal.
+ /// \brief Returns true if the specified type is known to be a native integer
+ /// type supported by the CPU.
///
- /// The width is specified in bits.
+ /// For example, i64 is not native on most 32-bit CPUs and i37 is not native
+ /// on any known one. This returns false if the integer width is not legal.
///
+ /// The width is specified in bits.
bool isLegalInteger(unsigned Width) const {
for (unsigned LegalIntWidth : LegalIntWidths)
if (LegalIntWidth == Width)
@@ -228,22 +221,20 @@ public:
return false;
}
- bool isIllegalInteger(unsigned Width) const {
- return !isLegalInteger(Width);
- }
+ bool isIllegalInteger(unsigned Width) const { return !isLegalInteger(Width); }
/// Returns true if the given alignment exceeds the natural stack alignment.
bool exceedsNaturalStackAlignment(unsigned Align) const {
return (StackNaturalAlign != 0) && (Align > StackNaturalAlign);
}
+ unsigned getStackAlignment() const { return StackNaturalAlign; }
+
bool hasMicrosoftFastStdCallMangling() const {
return ManglingMode == MM_WINCOFF;
}
- bool hasLinkerPrivateGlobalPrefix() const {
- return ManglingMode == MM_MachO;
- }
+ bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; }
const char *getLinkerPrivateGlobalPrefix() const {
if (ManglingMode == MM_MachO)
@@ -281,10 +272,11 @@ public:
static const char *getManglingComponent(const Triple &T);
- /// fitsInLegalInteger - This function 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 i27 fits in a legal
- /// integer type but i45 does not.
+ /// \brief 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
+ /// i27 fits in a legal integer type but i45 does not.
bool fitsInLegalInteger(unsigned Width) const {
for (unsigned LegalIntWidth : LegalIntWidths)
if (Width <= LegalIntWidth)
@@ -342,118 +334,116 @@ public:
/// [*] The alloc size depends on the alignment, and thus on the target.
/// These values are for x86-32 linux.
- /// getTypeSizeInBits - Return the number of bits necessary to hold the
- /// specified type. For example, returns 36 for i36 and 80 for x86_fp80.
- /// The type passed must have a size (Type::isSized() must return true).
+ /// \brief 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;
- /// getTypeStoreSize - Return the maximum number of bytes that may be
- /// overwritten by storing the specified type. For example, returns 5
- /// for i36 and 10 for x86_fp80.
+ /// \brief 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.
uint64_t getTypeStoreSize(Type *Ty) const {
- return (getTypeSizeInBits(Ty)+7)/8;
+ return (getTypeSizeInBits(Ty) + 7) / 8;
}
- /// getTypeStoreSizeInBits - Return the maximum number of bits that may be
- /// overwritten by storing the specified type; always a multiple of 8. For
- /// example, returns 40 for i36 and 80 for x86_fp80.
+ /// \brief 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.
uint64_t getTypeStoreSizeInBits(Type *Ty) const {
- return 8*getTypeStoreSize(Ty);
+ return 8 * getTypeStoreSize(Ty);
}
- /// getTypeAllocSize - Return the offset in bytes between successive objects
- /// of the specified type, including alignment padding. This is the amount
- /// that alloca reserves for this type. For example, returns 12 or 16 for
- /// x86_fp80, depending on alignment.
+ /// \brief 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,
+ /// returns 12 or 16 for x86_fp80, depending on alignment.
uint64_t getTypeAllocSize(Type *Ty) const {
// Round up to the next alignment boundary.
- return RoundUpAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty));
+ return RoundUpToAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty));
}
- /// getTypeAllocSizeInBits - Return the offset in bits between successive
- /// objects of the specified type, including alignment padding; always a
- /// multiple of 8. This is the amount that alloca reserves for this type.
- /// For example, returns 96 or 128 for x86_fp80, depending on alignment.
+ /// \brief 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,
+ /// returns 96 or 128 for x86_fp80, depending on alignment.
uint64_t getTypeAllocSizeInBits(Type *Ty) const {
- return 8*getTypeAllocSize(Ty);
+ return 8 * getTypeAllocSize(Ty);
}
- /// getABITypeAlignment - Return the minimum ABI-required alignment for the
- /// specified type.
+ /// \brief Returns the minimum ABI-required alignment for the specified type.
unsigned getABITypeAlignment(Type *Ty) const;
- /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for
- /// an integer type of the specified bitwidth.
+ /// \brief Returns the minimum ABI-required alignment for an integer type of
+ /// the specified bitwidth.
unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const;
- /// getPrefTypeAlignment - Return the preferred stack/global alignment for
- /// the specified type. This is always at least as good as the ABI alignment.
+ /// \brief 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;
- /// getPreferredTypeAlignmentShift - Return the preferred alignment for the
- /// specified type, returned as log2 of the value (a shift amount).
+ /// \brief Returns the preferred alignment for the specified type, returned as
+ /// log2 of the value (a shift amount).
unsigned getPreferredTypeAlignmentShift(Type *Ty) const;
- /// getIntPtrType - Return an integer type with size at least as big as that
- /// of a pointer in the given address space.
+ /// \brief 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;
- /// getIntPtrType - Return 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.
+ /// \brief 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;
- /// getSmallestLegalIntType - Return the smallest integer type with size at
- /// least as big as Width bits.
+ /// \brief Returns the smallest integer type with size at least as big as
+ /// Width bits.
Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const;
- /// getLargestLegalIntType - Return the largest legal integer type, or null if
- /// none are set.
+ /// \brief Returns the largest legal integer type, or null if none are set.
Type *getLargestLegalIntType(LLVMContext &C) const {
unsigned LargestSize = getLargestLegalIntTypeSize();
return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize);
}
- /// getLargestLegalIntTypeSize - Return the size of largest legal integer
- /// type size, or 0 if none are set.
+ /// \brief Returns the size of largest legal integer type size, or 0 if none
+ /// are set.
unsigned getLargestLegalIntTypeSize() const;
- /// getIndexedOffset - return the offset from the beginning of the type for
- /// the specified indices. This is used to implement getelementptr.
+ /// \brief Returns the offset from the beginning of the type for the specified
+ /// indices.
+ ///
+ /// This is used to implement getelementptr.
uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const;
- /// getStructLayout - Return a StructLayout object, indicating the alignment
- /// of the struct, its size, and the offsets of its fields. Note that this
- /// information is lazily cached.
+ /// \brief 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;
- /// getPreferredAlignment - Return the preferred alignment of the specified
- /// global. This includes an explicitly requested alignment (if the global
- /// has one).
+ /// \brief 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;
- /// getPreferredAlignmentLog - Return the preferred alignment of the
- /// specified global, returned in log form. This includes an explicitly
- /// requested alignment (if the global has one).
+ /// \brief Returns the preferred alignment of the specified global, returned
+ /// in log form.
+ ///
+ /// This includes an explicitly requested alignment (if the global has one).
unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const;
-
- /// RoundUpAlignment - Round the specified value up to the next alignment
- /// boundary specified by Alignment. For example, 7 rounded up to an
- /// alignment boundary of 4 is 8. 8 rounded up to the alignment boundary of 4
- /// is 8 because it is already aligned.
- template <typename UIntTy>
- static UIntTy RoundUpAlignment(UIntTy Val, unsigned Alignment) {
- assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!");
- return (Val + (Alignment-1)) & ~UIntTy(Alignment-1);
- }
};
inline DataLayout *unwrap(LLVMTargetDataRef P) {
- return reinterpret_cast<DataLayout*>(P);
+ return reinterpret_cast<DataLayout *>(P);
}
inline LLVMTargetDataRef wrap(const DataLayout *P) {
- return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout*>(P));
+ return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout *>(P));
}
class DataLayoutPass : public ImmutablePass {
@@ -466,40 +456,28 @@ public:
const DataLayout &getDataLayout() const { return DL; }
- // For use with the C API. C++ code should always use the constructor that
- // takes a module.
- explicit DataLayoutPass(const DataLayout &DL);
-
- explicit DataLayoutPass(const Module *M);
-
static char ID; // Pass identification, replacement for typeid
+
+ bool doFinalization(Module &M) override;
+ bool doInitialization(Module &M) override;
};
-/// StructLayout - used to lazily calculate structure layout information for a
-/// target machine, based on the DataLayout structure.
-///
+/// Used to lazily calculate structure layout information for a target machine,
+/// based on the DataLayout structure.
class StructLayout {
uint64_t StructSize;
unsigned StructAlignment;
unsigned NumElements;
- uint64_t MemberOffsets[1]; // variable sized array!
+ uint64_t MemberOffsets[1]; // variable sized array!
public:
+ uint64_t getSizeInBytes() const { return StructSize; }
- uint64_t getSizeInBytes() const {
- return StructSize;
- }
+ uint64_t getSizeInBits() const { return 8 * StructSize; }
- uint64_t getSizeInBits() const {
- return 8*StructSize;
- }
+ unsigned getAlignment() const { return StructAlignment; }
- unsigned getAlignment() const {
- return StructAlignment;
- }
-
- /// getElementContainingOffset - Given a valid byte offset into the structure,
- /// return the structure index that contains it.
- ///
+ /// \brief Given a valid byte offset into the structure, returns the structure
+ /// index that contains it.
unsigned getElementContainingOffset(uint64_t Offset) const;
uint64_t getElementOffset(unsigned Idx) const {
@@ -508,15 +486,14 @@ public:
}
uint64_t getElementOffsetInBits(unsigned Idx) const {
- return getElementOffset(Idx)*8;
+ return getElementOffset(Idx) * 8;
}
private:
- friend class DataLayout; // Only DataLayout can create this class
+ friend class DataLayout; // Only DataLayout can create this class
StructLayout(StructType *ST, const DataLayout &DL);
};
-
// The implementation of this method is provided inline as it is particularly
// well suited to constant folding when called on a specific Type subclass.
inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {
@@ -546,7 +523,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {
case Type::PPC_FP128TyID:
case Type::FP128TyID:
return 128;
- // In memory objects this is always aligned to a higher boundary, but
+ // In memory objects this is always aligned to a higher boundary, but
// only 80 bits contain information.
case Type::X86_FP80TyID:
return 80;
diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h
index 088eb9f01049..5c85d6d52824 100644
--- a/include/llvm/IR/DebugInfo.h
+++ b/include/llvm/IR/DebugInfo.h
@@ -18,13 +18,15 @@
#define LLVM_IR_DEBUGINFO_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <iterator>
namespace llvm {
class BasicBlock;
@@ -37,6 +39,7 @@ class Value;
class DbgDeclareInst;
class DbgValueInst;
class Instruction;
+class Metadata;
class MDNode;
class MDString;
class NamedMDNode;
@@ -52,21 +55,78 @@ class DIType;
class DIScope;
class DIObjCProperty;
-/// Maps from type identifier to the actual MDNode.
+/// \brief Maps from type identifier to the actual MDNode.
typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap;
-/// DIDescriptor - A thin wraper around MDNode to access encoded debug info.
-/// This should not be stored in a container, because the underlying MDNode
-/// may change in certain situations.
+class DIHeaderFieldIterator
+ : public std::iterator<std::input_iterator_tag, StringRef, std::ptrdiff_t,
+ const StringRef *, StringRef> {
+ StringRef Header;
+ StringRef Current;
+
+public:
+ DIHeaderFieldIterator() {}
+ DIHeaderFieldIterator(StringRef Header)
+ : Header(Header), Current(Header.slice(0, Header.find('\0'))) {}
+ StringRef operator*() const { return Current; }
+ const StringRef * operator->() const { return &Current; }
+ DIHeaderFieldIterator &operator++() {
+ increment();
+ return *this;
+ }
+ DIHeaderFieldIterator operator++(int) {
+ DIHeaderFieldIterator X(*this);
+ increment();
+ return X;
+ }
+ bool operator==(const DIHeaderFieldIterator &X) const {
+ return Current.data() == X.Current.data();
+ }
+ bool operator!=(const DIHeaderFieldIterator &X) const {
+ return !(*this == X);
+ }
+
+ StringRef getHeader() const { return Header; }
+ StringRef getCurrent() const { return Current; }
+ StringRef getPrefix() const {
+ if (Current.begin() == Header.begin())
+ return StringRef();
+ return Header.slice(0, Current.begin() - Header.begin() - 1);
+ }
+ StringRef getSuffix() const {
+ if (Current.end() == Header.end())
+ return StringRef();
+ return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos);
+ }
+
+private:
+ void increment() {
+ assert(Current.data() != nullptr && "Cannot increment past the end");
+ StringRef Suffix = getSuffix();
+ Current = Suffix.slice(0, Suffix.find('\0'));
+ }
+};
+
+/// \brief A thin wraper around MDNode to access encoded debug info.
+///
+/// This should not be stored in a container, because the underlying MDNode may
+/// change in certain situations.
class DIDescriptor {
// Befriends DIRef so DIRef can befriend the protected member
// function: getFieldAs<DIRef>.
template <typename T> friend class DIRef;
public:
+ /// \brief Accessibility flags.
+ ///
+ /// The three accessibility flags are mutually exclusive and rolled together
+ /// in the first two bits.
enum {
- FlagPrivate = 1 << 0,
- FlagProtected = 1 << 1,
+ FlagAccessibility = 1 << 0 | 1 << 1,
+ FlagPrivate = 1,
+ FlagProtected = 2,
+ FlagPublic = 3,
+
FlagFwdDecl = 1 << 2,
FlagAppleBlock = 1 << 3,
FlagBlockByrefStruct = 1 << 4,
@@ -108,8 +168,9 @@ public:
bool Verify() const;
- operator MDNode *() const { return const_cast<MDNode *>(DbgNode); }
- MDNode *operator->() const { return const_cast<MDNode *>(DbgNode); }
+ MDNode *get() const { return const_cast<MDNode *>(DbgNode); }
+ operator MDNode *() const { return get(); }
+ MDNode *operator->() const { return get(); }
// An explicit operator bool so that we can do testing of DI values
// easily.
@@ -121,12 +182,36 @@ public:
bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; }
bool operator!=(DIDescriptor Other) const { return !operator==(Other); }
- uint16_t getTag() const {
- return getUnsignedField(0) & ~LLVMDebugVersionMask;
+ StringRef getHeader() const {
+ return getStringField(0);
+ }
+
+ size_t getNumHeaderFields() const {
+ return std::distance(DIHeaderFieldIterator(getHeader()),
+ DIHeaderFieldIterator());
}
+ StringRef getHeaderField(unsigned Index) const {
+ // Since callers expect an empty string for out-of-range accesses, we can't
+ // use std::advance() here.
+ for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index)
+ if (!Index)
+ return *I;
+ return StringRef();
+ }
+
+ template <class T> T getHeaderFieldAs(unsigned Index) const {
+ T Int;
+ if (getHeaderField(Index).getAsInteger(0, Int))
+ return 0;
+ return Int;
+ }
+
+ uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); }
+
bool isDerivedType() const;
bool isCompositeType() const;
+ bool isSubroutineType() const;
bool isBasicType() const;
bool isVariable() const;
bool isSubprogram() const;
@@ -140,20 +225,21 @@ public:
bool isSubrange() const;
bool isEnumerator() const;
bool isType() const;
- bool isUnspecifiedParameter() const;
bool isTemplateTypeParameter() const;
bool isTemplateValueParameter() const;
bool isObjCProperty() const;
bool isImportedEntity() const;
+ bool isExpression() const;
- /// print - print descriptor.
void print(raw_ostream &OS) const;
-
- /// dump - print descriptor to dbgs() with a newline.
void dump() const;
+
+ /// \brief Replace all uses of debug info referenced by this descriptor.
+ void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D);
+ void replaceAllUsesWith(MDNode *D);
};
-/// DISubrange - This is used to represent ranges, for array bounds.
+/// \brief This is used to represent ranges, for array bounds.
class DISubrange : public DIDescriptor {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -161,23 +247,27 @@ class DISubrange : public DIDescriptor {
public:
explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {}
- int64_t getLo() const { return getInt64Field(1); }
- int64_t getCount() const { return getInt64Field(2); }
+ int64_t getLo() const { return getHeaderFieldAs<int64_t>(1); }
+ int64_t getCount() const { return getHeaderFieldAs<int64_t>(2); }
bool Verify() const;
};
-/// DIArray - This descriptor holds an array of descriptors.
-class DIArray : public DIDescriptor {
+/// \brief This descriptor holds an array of nodes with type T.
+template <typename T> class DITypedArray : public DIDescriptor {
public:
- explicit DIArray(const MDNode *N = nullptr) : DIDescriptor(N) {}
-
- unsigned getNumElements() const;
- DIDescriptor getElement(unsigned Idx) const {
- return getDescriptorField(Idx);
+ explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {}
+ unsigned getNumElements() const {
+ return DbgNode ? DbgNode->getNumOperands() : 0;
+ }
+ T getElement(unsigned Idx) const {
+ return getFieldAs<T>(Idx);
}
};
-/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}').
+typedef DITypedArray<DIDescriptor> DIArray;
+
+/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}').
+///
/// FIXME: it seems strange that this doesn't have either a reference to the
/// type/precision or a file/line pair for location info.
class DIEnumerator : public DIDescriptor {
@@ -187,16 +277,17 @@ class DIEnumerator : public DIDescriptor {
public:
explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {}
- StringRef getName() const { return getStringField(1); }
- int64_t getEnumValue() const { return getInt64Field(2); }
+ StringRef getName() const { return getHeaderField(1); }
+ int64_t getEnumValue() const { return getHeaderFieldAs<int64_t>(2); }
bool Verify() const;
};
template <typename T> class DIRef;
typedef DIRef<DIScope> DIScopeRef;
typedef DIRef<DIType> DITypeRef;
+typedef DITypedArray<DITypeRef> DITypeArray;
-/// DIScope - A base class for various scopes.
+/// \brief A base class for various scopes.
///
/// Although, implementation-wise, DIScope is the parent class of most
/// other DIxxx classes, including DIType and its descendants, most of
@@ -212,21 +303,28 @@ protected:
public:
explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {}
- /// Gets the parent scope for this scope node or returns a
- /// default constructed scope.
+ /// \brief Get the parent scope.
+ ///
+ /// Gets the parent scope for this scope node or returns a default
+ /// constructed scope.
DIScopeRef getContext() const;
+ /// \brief Get the scope name.
+ ///
/// If the scope node has a name, return that, else return an empty string.
StringRef getName() const;
StringRef getFilename() const;
StringRef getDirectory() const;
- /// Generate a reference to this DIScope. Uses the type identifier instead
- /// of the actual MDNode if possible, to help type uniquing.
+ /// \brief Generate a reference to this DIScope.
+ ///
+ /// Uses the type identifier instead of the actual MDNode if possible, to
+ /// help type uniquing.
DIScopeRef getRef() const;
};
-/// Represents reference to a DIDescriptor, abstracts over direct and
-/// identifier-based metadata references.
+/// \brief Represents reference to a DIDescriptor.
+///
+/// Abstracts over direct and identifier-based metadata references.
template <typename T> class DIRef {
template <typename DescTy>
friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const;
@@ -234,15 +332,16 @@ template <typename T> class DIRef {
friend DIScopeRef DIScope::getRef() const;
friend class DIType;
- /// Val can be either a MDNode or a MDString, in the latter,
- /// MDString specifies the type identifier.
- const Value *Val;
- explicit DIRef(const Value *V);
+ /// \brief Val can be either a MDNode or a MDString.
+ ///
+ /// In the latter, MDString specifies the type identifier.
+ const Metadata *Val;
+ explicit DIRef(const Metadata *V);
public:
T resolve(const DITypeIdentifierMap &Map) const;
StringRef getName() const;
- operator Value *() const { return const_cast<Value *>(Val); }
+ operator Metadata *() const { return const_cast<Metadata *>(Val); }
};
template <typename T>
@@ -273,17 +372,18 @@ template <typename T> StringRef DIRef<T>::getName() const {
return MS->getString();
}
-/// Specialize getFieldAs to handle fields that are references to DIScopes.
+/// \brief Handle fields that are references to DIScopes.
template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
-/// Specialize DIRef constructor for DIScopeRef.
-template <> DIRef<DIScope>::DIRef(const Value *V);
+/// \brief Specialize DIRef constructor for DIScopeRef.
+template <> DIRef<DIScope>::DIRef(const Metadata *V);
-/// Specialize getFieldAs to handle fields that are references to DITypes.
+/// \brief Handle fields that are references to DITypes.
template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
-/// Specialize DIRef constructor for DITypeRef.
-template <> DIRef<DIType>::DIRef(const Value *V);
+/// \brief Specialize DIRef constructor for DITypeRef.
+template <> DIRef<DIType>::DIRef(const Metadata *V);
-/// DIType - This is a wrapper for a type.
+/// \briefThis is a wrapper for a type.
+///
/// FIXME: Types should be factored much better so that CV qualifiers and
/// others do not require a huge and empty descriptor full of zeros.
class DIType : public DIScope {
@@ -299,22 +399,35 @@ public:
return DITypeRef(&*getRef());
}
- /// Verify - Verify that a type descriptor is well formed.
bool Verify() const;
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
- StringRef getName() const { return getStringField(3); }
- unsigned getLineNumber() const { return getUnsignedField(4); }
- uint64_t getSizeInBits() const { return getUInt64Field(5); }
- uint64_t getAlignInBits() const { return getUInt64Field(6); }
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const {
+ return getHeaderFieldAs<unsigned>(2);
+ }
+ uint64_t getSizeInBits() const {
+ return getHeaderFieldAs<unsigned>(3);
+ }
+ uint64_t getAlignInBits() const {
+ return getHeaderFieldAs<unsigned>(4);
+ }
// FIXME: Offset is only used for DW_TAG_member nodes. Making every type
// carry this is just plain insane.
- uint64_t getOffsetInBits() const { return getUInt64Field(7); }
- unsigned getFlags() const { return getUnsignedField(8); }
- bool isPrivate() const { return (getFlags() & FlagPrivate) != 0; }
- bool isProtected() const { return (getFlags() & FlagProtected) != 0; }
+ uint64_t getOffsetInBits() const {
+ return getHeaderFieldAs<unsigned>(5);
+ }
+ unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); }
+ bool isPrivate() const {
+ return (getFlags() & FlagAccessibility) == FlagPrivate;
+ }
+ bool isProtected() const {
+ return (getFlags() & FlagAccessibility) == FlagProtected;
+ }
+ bool isPublic() const {
+ return (getFlags() & FlagAccessibility) == FlagPublic;
+ }
bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; }
- // isAppleBlock - Return true if this is the Apple Blocks extension.
bool isAppleBlockExtension() const {
return (getFlags() & FlagAppleBlock) != 0;
}
@@ -336,27 +449,22 @@ public:
return (getFlags() & FlagRValueReference) != 0;
}
bool isValid() const { return DbgNode && isType(); }
-
- /// replaceAllUsesWith - Replace all uses of debug info referenced by
- /// this descriptor.
- void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D);
- void replaceAllUsesWith(MDNode *D);
};
-/// DIBasicType - A basic type, like 'int' or 'float'.
+/// \brief A basic type, like 'int' or 'float'.
class DIBasicType : public DIType {
public:
explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {}
- unsigned getEncoding() const { return getUnsignedField(9); }
+ unsigned getEncoding() const { return getHeaderFieldAs<unsigned>(7); }
- /// Verify - Verify that a basic type descriptor is well formed.
bool Verify() const;
};
-/// DIDerivedType - A simple derived type, like a const qualified type,
-/// a typedef, a pointer or reference, et cetera. Or, a data member of
-/// a class/struct/union.
+/// \brief A simple derived type
+///
+/// Like a const qualified type, a typedef, a pointer or reference, et cetera.
+/// Or, a data member of a class/struct/union.
class DIDerivedType : public DIType {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -364,62 +472,96 @@ class DIDerivedType : public DIType {
public:
explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {}
- DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(9); }
+ DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(3); }
- /// getObjCProperty - Return property node, if this ivar is
- /// associated with one.
+ /// \brief Return property node, if this ivar is associated with one.
MDNode *getObjCProperty() const;
DITypeRef getClassType() const {
assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
- return getFieldAs<DITypeRef>(10);
+ return getFieldAs<DITypeRef>(4);
}
Constant *getConstant() const {
assert((getTag() == dwarf::DW_TAG_member) && isStaticMember());
- return getConstantField(10);
+ return getConstantField(4);
}
- /// Verify - Verify that a derived type descriptor is well formed.
bool Verify() const;
};
-/// DICompositeType - This descriptor holds a type that can refer to multiple
-/// other types, like a function or struct.
+/// \brief Types that refer to multiple other types.
+///
+/// This descriptor holds a type that can refer to multiple other types, like a
+/// function or struct.
+///
/// DICompositeType is derived from DIDerivedType because some
/// composite types (such as enums) can be derived from basic types
// FIXME: Make this derive from DIType directly & just store the
// base type in a single DIType field.
class DICompositeType : public DIDerivedType {
+ friend class DIBuilder;
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
+ /// \brief Set the array of member DITypes.
+ void setArraysHelper(MDNode *Elements, MDNode *TParams);
+
public:
explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {}
- DIArray getTypeArray() const { return getFieldAs<DIArray>(10); }
- void setTypeArray(DIArray Elements, DIArray TParams = DIArray());
- unsigned getRunTimeLang() const { return getUnsignedField(11); }
- DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); }
+ DIArray getElements() const {
+ assert(!isSubroutineType() && "no elements for DISubroutineType");
+ return getFieldAs<DIArray>(4);
+ }
+
+private:
+ template <typename T>
+ void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) {
+ assert((!TParams || DbgNode->getNumOperands() == 8) &&
+ "If you're setting the template parameters this should include a slot "
+ "for that!");
+ setArraysHelper(Elements, TParams);
+ }
+
+public:
+ unsigned getRunTimeLang() const {
+ return getHeaderFieldAs<unsigned>(7);
+ }
+ DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); }
+
+private:
+ /// \brief Set the containing type.
void setContainingType(DICompositeType ContainingType);
- DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); }
+
+public:
+ DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); }
MDString *getIdentifier() const;
- /// Verify - Verify that a composite type descriptor is well formed.
bool Verify() const;
};
-/// DIFile - This is a wrapper for a file.
+class DISubroutineType : public DICompositeType {
+public:
+ explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {}
+ DITypedArray<DITypeRef> getTypeArray() const {
+ return getFieldAs<DITypedArray<DITypeRef>>(4);
+ }
+};
+
+/// \brief This is a wrapper for a file.
class DIFile : public DIScope {
friend class DIDescriptor;
public:
explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {}
+
+ /// \brief Retrieve the MDNode for the directory/file pair.
MDNode *getFileNode() const;
bool Verify() const;
};
-/// DICompileUnit - A wrapper for a compile unit.
+/// \brief A wrapper for a compile unit.
class DICompileUnit : public DIScope {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -428,13 +570,13 @@ public:
explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {}
dwarf::SourceLanguage getLanguage() const {
- return static_cast<dwarf::SourceLanguage>(getUnsignedField(2));
+ return static_cast<dwarf::SourceLanguage>(getHeaderFieldAs<unsigned>(1));
}
- StringRef getProducer() const { return getStringField(3); }
+ StringRef getProducer() const { return getHeaderField(2); }
- bool isOptimized() const { return getUnsignedField(4) != 0; }
- StringRef getFlags() const { return getStringField(5); }
- unsigned getRunTimeVersion() const { return getUnsignedField(6); }
+ bool isOptimized() const { return getHeaderFieldAs<bool>(3) != 0; }
+ StringRef getFlags() const { return getHeaderField(4); }
+ unsigned getRunTimeVersion() const { return getHeaderFieldAs<unsigned>(5); }
DIArray getEnumTypes() const;
DIArray getRetainedTypes() const;
@@ -442,14 +584,16 @@ public:
DIArray getGlobalVariables() const;
DIArray getImportedEntities() const;
- StringRef getSplitDebugFilename() const { return getStringField(12); }
- unsigned getEmissionKind() const { return getUnsignedField(13); }
+ void replaceSubprograms(DIArray Subprograms);
+ void replaceGlobalVariables(DIArray GlobalVariables);
+
+ StringRef getSplitDebugFilename() const { return getHeaderField(6); }
+ unsigned getEmissionKind() const { return getHeaderFieldAs<unsigned>(7); }
- /// Verify - Verify that a compile unit is well formed.
bool Verify() const;
};
-/// DISubprogram - This is a wrapper for a subprogram (e.g. a function).
+/// \brief This is a wrapper for a subprogram (e.g. a function).
class DISubprogram : public DIScope {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -457,93 +601,95 @@ class DISubprogram : public DIScope {
public:
explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {}
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
- StringRef getName() const { return getStringField(3); }
- StringRef getDisplayName() const { return getStringField(4); }
- StringRef getLinkageName() const { return getStringField(5); }
- unsigned getLineNumber() const { return getUnsignedField(6); }
- DICompositeType getType() const { return getFieldAs<DICompositeType>(7); }
-
- /// isLocalToUnit - Return true if this subprogram is local to the current
- /// compile unit, like 'static' in C.
- unsigned isLocalToUnit() const { return getUnsignedField(8); }
- unsigned isDefinition() const { return getUnsignedField(9); }
+ StringRef getName() const { return getHeaderField(1); }
+ StringRef getDisplayName() const { return getHeaderField(2); }
+ StringRef getLinkageName() const { return getHeaderField(3); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); }
- unsigned getVirtuality() const { return getUnsignedField(10); }
- unsigned getVirtualIndex() const { return getUnsignedField(11); }
+ /// \brief Check if this is local (like 'static' in C).
+ unsigned isLocalToUnit() const { return getHeaderFieldAs<unsigned>(5); }
+ unsigned isDefinition() const { return getHeaderFieldAs<unsigned>(6); }
- DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); }
+ unsigned getVirtuality() const { return getHeaderFieldAs<unsigned>(7); }
+ unsigned getVirtualIndex() const { return getHeaderFieldAs<unsigned>(8); }
- unsigned getFlags() const { return getUnsignedField(13); }
+ unsigned getFlags() const { return getHeaderFieldAs<unsigned>(9); }
- unsigned isArtificial() const {
- return (getUnsignedField(13) & FlagArtificial) != 0;
- }
- /// isPrivate - Return true if this subprogram has "private"
- /// access specifier.
- bool isPrivate() const { return (getUnsignedField(13) & FlagPrivate) != 0; }
- /// isProtected - Return true if this subprogram has "protected"
- /// access specifier.
- bool isProtected() const {
- return (getUnsignedField(13) & FlagProtected) != 0;
- }
- /// isExplicit - Return true if this subprogram is marked as explicit.
- bool isExplicit() const { return (getUnsignedField(13) & FlagExplicit) != 0; }
- /// isPrototyped - Return true if this subprogram is prototyped.
- bool isPrototyped() const {
- return (getUnsignedField(13) & FlagPrototyped) != 0;
- }
+ unsigned isOptimized() const { return getHeaderFieldAs<bool>(10); }
- /// Return true if this subprogram is a C++11 reference-qualified
- /// non-static member function (void foo() &).
- unsigned isLValueReference() const {
- return (getUnsignedField(13) & FlagLValueReference) != 0;
- }
+ /// \brief Get the beginning of the scope of the function (not the name).
+ unsigned getScopeLineNumber() const { return getHeaderFieldAs<unsigned>(11); }
- /// Return true if this subprogram is a C++11
- /// rvalue-reference-qualified non-static member function
- /// (void foo() &&).
- unsigned isRValueReference() const {
- return (getUnsignedField(13) & FlagRValueReference) != 0;
- }
+ DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
+ DISubroutineType getType() const { return getFieldAs<DISubroutineType>(3); }
- unsigned isOptimized() const;
+ DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(4); }
- /// Verify - Verify that a subprogram descriptor is well formed.
bool Verify() const;
- /// describes - Return true if this subprogram provides debugging
- /// information for the function F.
+ /// \brief Check if this provides debugging information for the function F.
bool describes(const Function *F);
- Function *getFunction() const { return getFunctionField(15); }
- void replaceFunction(Function *F) { replaceFunctionField(15, F); }
- DIArray getTemplateParams() const { return getFieldAs<DIArray>(16); }
+ Function *getFunction() const { return getFunctionField(5); }
+ void replaceFunction(Function *F) { replaceFunctionField(5, F); }
+ DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); }
DISubprogram getFunctionDeclaration() const {
- return getFieldAs<DISubprogram>(17);
+ return getFieldAs<DISubprogram>(7);
}
MDNode *getVariablesNodes() const;
DIArray getVariables() const;
- /// getScopeLineNumber - Get the beginning of the scope of the
- /// function, not necessarily where the name of the program
- /// starts.
- unsigned getScopeLineNumber() const { return getUnsignedField(19); }
+ unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; }
+ /// \brief Check for the "private" access specifier.
+ bool isPrivate() const {
+ return (getFlags() & FlagAccessibility) == FlagPrivate;
+ }
+ /// \brief Check for the "protected" access specifier.
+ bool isProtected() const {
+ return (getFlags() & FlagAccessibility) == FlagProtected;
+ }
+ /// \brief Check for the "public" access specifier.
+ bool isPublic() const {
+ return (getFlags() & FlagAccessibility) == FlagPublic;
+ }
+ /// \brief Check for "explicit".
+ bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; }
+ /// \brief Check if this is prototyped.
+ bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; }
+
+ /// \brief Check if this is reference-qualified.
+ ///
+ /// Return true if this subprogram is a C++11 reference-qualified non-static
+ /// member function (void foo() &).
+ unsigned isLValueReference() const {
+ return (getFlags() & FlagLValueReference) != 0;
+ }
+
+ /// \brief Check if this is rvalue-reference-qualified.
+ ///
+ /// Return true if this subprogram is a C++11 rvalue-reference-qualified
+ /// non-static member function (void foo() &&).
+ unsigned isRValueReference() const {
+ return (getFlags() & FlagRValueReference) != 0;
+ }
+
};
-/// DILexicalBlock - This is a wrapper for a lexical block.
+/// \brief This is a wrapper for a lexical block.
class DILexicalBlock : public DIScope {
public:
explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(2); }
- unsigned getLineNumber() const { return getUnsignedField(3); }
- unsigned getColumnNumber() const { return getUnsignedField(4); }
- unsigned getDiscriminator() const { return getUnsignedField(5); }
+ unsigned getLineNumber() const {
+ return getHeaderFieldAs<unsigned>(1);
+ }
+ unsigned getColumnNumber() const {
+ return getHeaderFieldAs<unsigned>(2);
+ }
bool Verify() const;
};
-/// DILexicalBlockFile - This is a wrapper for a lexical block with
-/// a filename change.
+/// \brief This is a wrapper for a lexical block with a filename change.
class DILexicalBlockFile : public DIScope {
public:
explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {}
@@ -555,68 +701,63 @@ public:
unsigned getLineNumber() const { return getScope().getLineNumber(); }
unsigned getColumnNumber() const { return getScope().getColumnNumber(); }
DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); }
+ unsigned getDiscriminator() const { return getHeaderFieldAs<unsigned>(1); }
bool Verify() const;
};
-/// DINameSpace - A wrapper for a C++ style name space.
+/// \brief A wrapper for a C++ style name space.
class DINameSpace : public DIScope {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
public:
explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {}
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
DIScope getContext() const { return getFieldAs<DIScope>(2); }
- StringRef getName() const { return getStringField(3); }
- unsigned getLineNumber() const { return getUnsignedField(4); }
- bool Verify() const;
-};
-
-/// DIUnspecifiedParameter - This is a wrapper for unspecified parameters.
-class DIUnspecifiedParameter : public DIDescriptor {
-public:
- explicit DIUnspecifiedParameter(const MDNode *N = nullptr)
- : DIDescriptor(N) {}
bool Verify() const;
};
-/// DITemplateTypeParameter - This is a wrapper for template type parameter.
+/// \brief This is a wrapper for template type parameter.
class DITemplateTypeParameter : public DIDescriptor {
public:
explicit DITemplateTypeParameter(const MDNode *N = nullptr)
: DIDescriptor(N) {}
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
+ unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); }
+
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
- StringRef getName() const { return getStringField(2); }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
- StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); }
+ DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
+ StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); }
StringRef getDirectory() const {
- return getFieldAs<DIFile>(4).getDirectory();
+ return getFieldAs<DIFile>(3).getDirectory();
}
- unsigned getLineNumber() const { return getUnsignedField(5); }
- unsigned getColumnNumber() const { return getUnsignedField(6); }
bool Verify() const;
};
-/// DITemplateValueParameter - This is a wrapper for template value parameter.
+/// \brief This is a wrapper for template value parameter.
class DITemplateValueParameter : public DIDescriptor {
public:
explicit DITemplateValueParameter(const MDNode *N = nullptr)
: DIDescriptor(N) {}
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
+ unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); }
+
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
- StringRef getName() const { return getStringField(2); }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
- Value *getValue() const;
- StringRef getFilename() const { return getFieldAs<DIFile>(5).getFilename(); }
+ DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
+ Metadata *getValue() const;
+ StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); }
StringRef getDirectory() const {
- return getFieldAs<DIFile>(5).getDirectory();
+ return getFieldAs<DIFile>(4).getDirectory();
}
- unsigned getLineNumber() const { return getUnsignedField(6); }
- unsigned getColumnNumber() const { return getUnsignedField(7); }
bool Verify() const;
};
-/// DIGlobalVariable - This is a wrapper for a global variable.
+/// \brief This is a wrapper for a global variable.
class DIGlobalVariable : public DIDescriptor {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -624,32 +765,30 @@ class DIGlobalVariable : public DIDescriptor {
public:
explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {}
- DIScope getContext() const { return getFieldAs<DIScope>(2); }
- StringRef getName() const { return getStringField(3); }
- StringRef getDisplayName() const { return getStringField(4); }
- StringRef getLinkageName() const { return getStringField(5); }
- StringRef getFilename() const { return getFieldAs<DIFile>(6).getFilename(); }
+ StringRef getName() const { return getHeaderField(1); }
+ StringRef getDisplayName() const { return getHeaderField(2); }
+ StringRef getLinkageName() const { return getHeaderField(3); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); }
+ unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); }
+ unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); }
+
+ DIScope getContext() const { return getFieldAs<DIScope>(1); }
+ StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); }
StringRef getDirectory() const {
- return getFieldAs<DIFile>(6).getDirectory();
+ return getFieldAs<DIFile>(2).getDirectory();
}
+ DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
- unsigned getLineNumber() const { return getUnsignedField(7); }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(8); }
- unsigned isLocalToUnit() const { return getUnsignedField(9); }
- unsigned isDefinition() const { return getUnsignedField(10); }
-
- GlobalVariable *getGlobal() const { return getGlobalVariableField(11); }
- Constant *getConstant() const { return getConstantField(11); }
+ GlobalVariable *getGlobal() const { return getGlobalVariableField(4); }
+ Constant *getConstant() const { return getConstantField(4); }
DIDerivedType getStaticDataMemberDeclaration() const {
- return getFieldAs<DIDerivedType>(12);
+ return getFieldAs<DIDerivedType>(5);
}
- /// Verify - Verify that a global variable descriptor is well formed.
bool Verify() const;
};
-/// DIVariable - This is a wrapper for a variable (e.g. parameter, local,
-/// global etc).
+/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc).
class DIVariable : public DIDescriptor {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -657,73 +796,107 @@ class DIVariable : public DIDescriptor {
public:
explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {}
- DIScope getContext() const { return getFieldAs<DIScope>(1); }
- StringRef getName() const { return getStringField(2); }
- DIFile getFile() const { return getFieldAs<DIFile>(3); }
- unsigned getLineNumber() const { return (getUnsignedField(4) << 8) >> 8; }
- unsigned getArgNumber() const {
- unsigned L = getUnsignedField(4);
- return L >> 24;
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const {
+ // FIXME: Line number and arg number shouldn't be merged together like this.
+ return (getHeaderFieldAs<unsigned>(2) << 8) >> 8;
}
- DITypeRef getType() const { return getFieldAs<DITypeRef>(5); }
+ unsigned getArgNumber() const { return getHeaderFieldAs<unsigned>(2) >> 24; }
+
+ DIScope getContext() const { return getFieldAs<DIScope>(1); }
+ DIFile getFile() const { return getFieldAs<DIFile>(2); }
+ DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
- /// isArtificial - Return true if this variable is marked as "artificial".
+ /// \brief Return true if this variable is marked as "artificial".
bool isArtificial() const {
- return (getUnsignedField(6) & FlagArtificial) != 0;
+ return (getHeaderFieldAs<unsigned>(3) & FlagArtificial) != 0;
}
bool isObjectPointer() const {
- return (getUnsignedField(6) & FlagObjectPointer) != 0;
+ return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0;
}
/// \brief Return true if this variable is represented as a pointer.
bool isIndirect() const {
- return (getUnsignedField(6) & FlagIndirectVariable) != 0;
+ return (getHeaderFieldAs<unsigned>(3) & FlagIndirectVariable) != 0;
}
- /// getInlinedAt - If this variable is inlined then return inline location.
+ /// \brief If this variable is inlined then return inline location.
MDNode *getInlinedAt() const;
- /// Verify - Verify that a variable descriptor is well formed.
bool Verify() const;
- /// HasComplexAddr - Return true if the variable has a complex address.
- bool hasComplexAddress() const { return getNumAddrElements() > 0; }
-
- /// \brief Return the size of this variable's complex address or
- /// zero if there is none.
- unsigned getNumAddrElements() const {
- if (DbgNode->getNumOperands() < 9)
- return 0;
- return getDescriptorField(8)->getNumOperands();
- }
-
- /// \brief return the Idx'th complex address element.
- uint64_t getAddrElement(unsigned Idx) const;
-
- /// isBlockByrefVariable - Return true if the variable was declared as
- /// a "__block" variable (Apple Blocks).
+ /// \brief Check if this is a "__block" variable (Apple Blocks).
bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const {
return (getType().resolve(Map)).isBlockByrefStruct();
}
- /// isInlinedFnArgument - Return true if this variable provides debugging
- /// information for an inlined function arguments.
+ /// \brief Check if this is an inlined function argument.
bool isInlinedFnArgument(const Function *CurFn);
+ /// \brief Return the size reported by the variable's type.
+ unsigned getSizeInBits(const DITypeIdentifierMap &Map);
+
void printExtendedName(raw_ostream &OS) const;
};
-/// DILocation - This object holds location information. This object
-/// is not associated with any DWARF tag.
+/// \brief A complex location expression.
+class DIExpression : public DIDescriptor {
+ friend class DIDescriptor;
+ void printInternal(raw_ostream &OS) const;
+
+public:
+ explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {}
+
+ bool Verify() const;
+
+ /// \brief Return the number of elements in the complex expression.
+ unsigned getNumElements() const {
+ if (!DbgNode)
+ return 0;
+ unsigned N = getNumHeaderFields();
+ assert(N > 0 && "missing tag");
+ return N - 1;
+ }
+
+ /// \brief return the Idx'th complex address element.
+ uint64_t getElement(unsigned Idx) const;
+
+ /// \brief Return whether this is a piece of an aggregate variable.
+ bool isVariablePiece() const;
+ /// \brief Return the offset of this piece in bytes.
+ uint64_t getPieceOffset() const;
+ /// \brief Return the size of this piece in bytes.
+ uint64_t getPieceSize() const;
+};
+
+/// \brief This object holds location information.
+///
+/// This object is not associated with any DWARF tag.
class DILocation : public DIDescriptor {
public:
explicit DILocation(const MDNode *N) : DIDescriptor(N) {}
- unsigned getLineNumber() const { return getUnsignedField(0); }
- unsigned getColumnNumber() const { return getUnsignedField(1); }
- DIScope getScope() const { return getFieldAs<DIScope>(2); }
- DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); }
+ unsigned getLineNumber() const {
+ if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode))
+ return L->getLine();
+ return 0;
+ }
+ unsigned getColumnNumber() const {
+ if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode))
+ return L->getColumn();
+ return 0;
+ }
+ DIScope getScope() const {
+ if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode))
+ return DIScope(dyn_cast_or_null<MDNode>(L->getScope()));
+ return DIScope(nullptr);
+ }
+ DILocation getOrigLocation() const {
+ if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode))
+ return DILocation(dyn_cast_or_null<MDNode>(L->getInlinedAt()));
+ return DILocation(nullptr);
+ }
StringRef getFilename() const { return getScope().getFilename(); }
StringRef getDirectory() const { return getScope().getDirectory(); }
bool Verify() const;
@@ -731,23 +904,30 @@ public:
return (getLineNumber() == Other.getLineNumber() &&
getFilename() == Other.getFilename());
}
- /// getDiscriminator - DWARF discriminators are used to distinguish
- /// identical file locations for instructions that are on different
- /// basic blocks. If two instructions are inside the same lexical block
- /// and are in different basic blocks, we create a new lexical block
- /// with identical location as the original but with a different
- /// discriminator value (lib/Transforms/Util/AddDiscriminators.cpp
- /// for details).
+ /// \brief Get the DWAF discriminator.
+ ///
+ /// DWARF discriminators are used to distinguish identical file locations for
+ /// instructions that are on different basic blocks. If two instructions are
+ /// inside the same lexical block and are in different basic blocks, we
+ /// create a new lexical block with identical location as the original but
+ /// with a different discriminator value
+ /// (lib/Transforms/Util/AddDiscriminators.cpp for details).
unsigned getDiscriminator() const {
// Since discriminators are associated with lexical blocks, make
// sure this location is a lexical block before retrieving its
// value.
- return getScope().isLexicalBlock()
- ? getFieldAs<DILexicalBlock>(2).getDiscriminator()
+ return getScope().isLexicalBlockFile()
+ ? DILexicalBlockFile(
+ cast<MDNode>(cast<MDLocation>(DbgNode)->getScope()))
+ .getDiscriminator()
: 0;
}
+
+ /// \brief Generate a new discriminator value for this location.
unsigned computeNewDiscriminator(LLVMContext &Ctx);
- DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlock NewScope);
+
+ /// \brief Return a copy of this location with a different scope.
+ DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope);
};
class DIObjCProperty : public DIDescriptor {
@@ -757,36 +937,38 @@ class DIObjCProperty : public DIDescriptor {
public:
explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {}
- StringRef getObjCPropertyName() const { return getStringField(1); }
- DIFile getFile() const { return getFieldAs<DIFile>(2); }
- unsigned getLineNumber() const { return getUnsignedField(3); }
+ StringRef getObjCPropertyName() const { return getHeaderField(1); }
+ DIFile getFile() const { return getFieldAs<DIFile>(1); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
- StringRef getObjCPropertyGetterName() const { return getStringField(4); }
- StringRef getObjCPropertySetterName() const { return getStringField(5); }
+ StringRef getObjCPropertyGetterName() const { return getHeaderField(3); }
+ StringRef getObjCPropertySetterName() const { return getHeaderField(4); }
+ unsigned getAttributes() const { return getHeaderFieldAs<unsigned>(5); }
bool isReadOnlyObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0;
}
bool isReadWriteObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0;
}
bool isAssignObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0;
}
bool isRetainObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0;
}
bool isCopyObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0;
}
bool isNonAtomicObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0;
}
- /// Objective-C doesn't have an ODR, so there is no benefit in storing
+ /// \brief Get the type.
+ ///
+ /// \note Objective-C doesn't have an ODR, so there is no benefit in storing
/// the type as a DITypeRef here.
- DIType getType() const { return getFieldAs<DIType>(7); }
+ DIType getType() const { return getFieldAs<DIType>(2); }
- /// Verify - Verify that a derived type descriptor is well formed.
bool Verify() const;
};
@@ -799,47 +981,47 @@ public:
explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); }
- unsigned getLineNumber() const { return getUnsignedField(3); }
- StringRef getName() const { return getStringField(4); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); }
+ StringRef getName() const { return getHeaderField(2); }
bool Verify() const;
};
-/// getDISubprogram - Find subprogram that is enclosing this scope.
+/// \brief Find subprogram that is enclosing this scope.
DISubprogram getDISubprogram(const MDNode *Scope);
-/// getDICompositeType - Find underlying composite type.
-DICompositeType getDICompositeType(DIType T);
-
-/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable
-/// to hold function specific information.
-NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP);
+/// \brief Find debug info for a given function.
+/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty
+/// DISubprogram.
+DISubprogram getDISubprogram(const Function *F);
-/// getFnSpecificMDNode - Return a NameMDNode, if available, that is
-/// suitable to hold function specific information.
-NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP);
+/// \brief Find underlying composite type.
+DICompositeType getDICompositeType(DIType T);
-/// createInlinedVariable - Create a new inlined variable based on current
-/// variable.
+/// \brief Create a new inlined variable based on current variable.
+///
/// @param DV Current Variable.
/// @param InlinedScope Location at current variable is inlined.
DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope,
LLVMContext &VMContext);
-/// cleanseInlinedVariable - Remove inlined scope from the variable.
+/// \brief Remove inlined scope from the variable.
DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext);
-/// Construct DITypeIdentifierMap by going through retained types of each CU.
+/// \brief Generate map by visiting all retained types.
DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes);
-/// Strip debug info in the module if it exists.
+/// \brief Strip debug info in the module if it exists.
+///
/// To do this, we remove all calls to the debugger intrinsics and any named
/// metadata for debugging. We also remove debug locations for instructions.
/// Return true if module is modified.
bool StripDebugInfo(Module &M);
-/// Return Debug Info Metadata Version by checking module flags.
+/// \brief Return Debug Info Metadata Version by checking module flags.
unsigned getDebugMetadataVersionFromModule(const Module &M);
+/// \brief 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
/// processDeclare, processValue and processLocation to handle DbgDeclareInst,
@@ -850,44 +1032,29 @@ class DebugInfoFinder {
public:
DebugInfoFinder() : TypeMapInitialized(false) {}
- /// processModule - Process entire module and collect debug info
- /// anchors.
+ /// \brief Process entire module and collect debug info anchors.
void processModule(const Module &M);
- /// processDeclare - Process DbgDeclareInst.
+ /// \brief Process DbgDeclareInst.
void processDeclare(const Module &M, const DbgDeclareInst *DDI);
- /// Process DbgValueInst.
+ /// \brief Process DbgValueInst.
void processValue(const Module &M, const DbgValueInst *DVI);
- /// processLocation - Process DILocation.
+ /// \brief Process DILocation.
void processLocation(const Module &M, DILocation Loc);
- /// Clear all lists.
+ /// \brief Clear all lists.
void reset();
private:
- /// Initialize TypeIdentifierMap.
void InitializeTypeMap(const Module &M);
- /// processType - Process DIType.
void processType(DIType DT);
-
- /// processSubprogram - Process DISubprogram.
void processSubprogram(DISubprogram SP);
-
void processScope(DIScope Scope);
-
- /// addCompileUnit - Add compile unit into CUs.
bool addCompileUnit(DICompileUnit CU);
-
- /// addGlobalVariable - Add global variable into GVs.
bool addGlobalVariable(DIGlobalVariable DIG);
-
- // addSubprogram - Add subprogram into SPs.
bool addSubprogram(DISubprogram SP);
-
- /// addType - Add type into Tys.
bool addType(DIType DT);
-
bool addScope(DIScope Scope);
public:
@@ -924,14 +1091,15 @@ public:
unsigned scope_count() const { return Scopes.size(); }
private:
- SmallVector<DICompileUnit, 8> CUs; // Compile Units
- SmallVector<DISubprogram, 8> SPs; // Subprograms
- SmallVector<DIGlobalVariable, 8> GVs; // Global Variables;
- SmallVector<DIType, 8> TYs; // Types
- SmallVector<DIScope, 8> Scopes; // Scopes
+ SmallVector<DICompileUnit, 8> CUs;
+ SmallVector<DISubprogram, 8> SPs;
+ SmallVector<DIGlobalVariable, 8> GVs;
+ SmallVector<DIType, 8> TYs;
+ SmallVector<DIScope, 8> Scopes;
SmallPtrSet<MDNode *, 64> NodesSeen;
DITypeIdentifierMap TypeIdentifierMap;
- /// Specify if TypeIdentifierMap is initialized.
+
+ /// \brief Specify if TypeIdentifierMap is initialized.
bool TypeMapInitialized;
};
diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h
index 3d969a8b7532..86e64417099d 100644
--- a/include/llvm/IR/DebugLoc.h
+++ b/include/llvm/IR/DebugLoc.h
@@ -15,51 +15,41 @@
#ifndef LLVM_IR_DEBUGLOC_H
#define LLVM_IR_DEBUGLOC_H
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
- template <typename T> struct DenseMapInfo;
- class MDNode;
+
class LLVMContext;
class raw_ostream;
+ class MDNode;
/// DebugLoc - Debug location id. This is carried by Instruction, SDNode,
/// and MachineInstr to compactly encode file/line/scope information for an
/// operation.
class DebugLoc {
- friend struct DenseMapInfo<DebugLoc>;
-
- /// getEmptyKey() - A private constructor that returns an unknown that is
- /// not equal to the tombstone key or DebugLoc().
- static DebugLoc getEmptyKey() {
- DebugLoc DL;
- DL.LineCol = 1;
- return DL;
- }
+ TrackingMDNodeRef Loc;
- /// getTombstoneKey() - A private constructor that returns an unknown that
- /// is not equal to the empty key or DebugLoc().
- static DebugLoc getTombstoneKey() {
- DebugLoc DL;
- DL.LineCol = 2;
- return DL;
+ public:
+ DebugLoc() {}
+ DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {}
+ DebugLoc(const DebugLoc &X) : Loc(X.Loc) {}
+ DebugLoc &operator=(DebugLoc &&X) {
+ Loc = std::move(X.Loc);
+ return *this;
+ }
+ DebugLoc &operator=(const DebugLoc &X) {
+ Loc = X.Loc;
+ return *this;
}
- /// LineCol - This 32-bit value encodes the line and column number for the
- /// location, encoded as 24-bits for line and 8 bits for col. A value of 0
- /// for either means unknown.
- uint32_t LineCol;
-
- /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information,
- /// decoded by LLVMContext. 0 is unknown.
- int ScopeIdx;
- public:
- DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown.
+ /// \brief Check whether this has a trivial destructor.
+ bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); }
/// get - Get a new DebugLoc that corresponds to the specified line/col
/// scope/inline location.
- static DebugLoc get(unsigned Line, unsigned Col,
- MDNode *Scope, MDNode *InlinedAt = nullptr);
+ static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope,
+ MDNode *InlinedAt = nullptr);
/// getFromDILocation - Translate the DILocation quad into a DebugLoc.
static DebugLoc getFromDILocation(MDNode *N);
@@ -68,56 +58,54 @@ namespace llvm {
static DebugLoc getFromDILexicalBlock(MDNode *N);
/// isUnknown - Return true if this is an unknown location.
- bool isUnknown() const { return ScopeIdx == 0; }
+ bool isUnknown() const { return !Loc; }
- unsigned getLine() const {
- return (LineCol << 8) >> 8; // Mask out column.
- }
-
- unsigned getCol() const {
- return LineCol >> 24;
- }
+ unsigned getLine() const;
+ unsigned getCol() const;
/// getScope - This returns the scope pointer for this DebugLoc, or null if
/// invalid.
- MDNode *getScope(const LLVMContext &Ctx) const;
+ MDNode *getScope() const;
+ MDNode *getScope(const LLVMContext &) const { return getScope(); }
/// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or
/// null if invalid or not present.
- MDNode *getInlinedAt(const LLVMContext &Ctx) const;
+ MDNode *getInlinedAt() const;
+ MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); }
/// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values.
+ void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const;
void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
- const LLVMContext &Ctx) const;
+ const LLVMContext &) const {
+ return getScopeAndInlinedAt(Scope, IA);
+ }
/// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid.
- MDNode *getScopeNode(const LLVMContext &Ctx) const;
+ MDNode *getScopeNode() const;
+ MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); }
// getFnDebugLoc - Walk up the scope chain of given debug loc and find line
// number info for the function.
- DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const;
+ DebugLoc getFnDebugLoc() const;
+ DebugLoc getFnDebugLoc(const LLVMContext &) const {
+ return getFnDebugLoc();
+ }
/// getAsMDNode - This method converts the compressed DebugLoc node into a
/// DILocation compatible MDNode.
- MDNode *getAsMDNode(const LLVMContext &Ctx) const;
+ MDNode *getAsMDNode() const;
+ MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); }
- bool operator==(const DebugLoc &DL) const {
- return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx;
- }
+ bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; }
bool operator!=(const DebugLoc &DL) const { return !(*this == DL); }
- void dump(const LLVMContext &Ctx) const;
+ void dump() const;
+ void dump(const LLVMContext &) const { dump(); }
/// \brief prints source location /path/to/file.exe:line:col @[inlined at]
- void print(const LLVMContext &Ctx, raw_ostream &OS) const;
+ void print(raw_ostream &OS) const;
+ void print(const LLVMContext &, raw_ostream &OS) const { print(OS); }
};
- template <>
- struct DenseMapInfo<DebugLoc> {
- static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); }
- static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); }
- static unsigned getHashValue(const DebugLoc &Key);
- static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; }
- };
} // end namespace llvm
#endif /* LLVM_SUPPORT_DEBUGLOC_H */
diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h
index ff150872a4e1..182015c98aa2 100644
--- a/include/llvm/IR/DerivedTypes.h
+++ b/include/llvm/IR/DerivedTypes.h
@@ -123,6 +123,9 @@ public:
typedef Type::subtype_iterator param_iterator;
param_iterator param_begin() const { return ContainedTys + 1; }
param_iterator param_end() const { return &ContainedTys[NumContainedTys]; }
+ ArrayRef<Type *> params() const {
+ return makeArrayRef(param_begin(), param_end());
+ }
/// Parameter type accessors.
Type *getParamType(unsigned i) const { return ContainedTys[i+1]; }
@@ -204,9 +207,6 @@ class StructType : public CompositeType {
///
void *SymbolTableEntry;
public:
- ~StructType() {
- delete [] ContainedTys; // Delete the body.
- }
/// StructType::create - This creates an identified struct.
static StructType *create(LLVMContext &Context, StringRef Name);
@@ -221,7 +221,7 @@ public:
StringRef Name,
bool isPacked = false);
static StructType *create(LLVMContext &Context, ArrayRef<Type*> Elements);
- static StructType *create(StringRef Name, Type *elt1, ...) END_WITH_NULL;
+ static StructType *create(StringRef Name, Type *elt1, ...) LLVM_END_WITH_NULL;
/// StructType::get - This static method is the primary way to create a
/// literal StructType.
@@ -236,7 +236,7 @@ public:
/// structure types by specifying the elements as arguments. Note that this
/// method always returns a non-packed struct, and requires at least one
/// element type.
- static StructType *get(Type *elt1, ...) END_WITH_NULL;
+ static StructType *get(Type *elt1, ...) LLVM_END_WITH_NULL;
bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; }
@@ -249,7 +249,7 @@ public:
bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; }
/// isSized - Return true if this is a sized type.
- bool isSized(SmallPtrSet<const Type*, 4> *Visited = nullptr) const;
+ bool isSized(SmallPtrSetImpl<const Type*> *Visited = nullptr) const;
/// hasName - Return true if this is a named struct that has a non-empty name.
bool hasName() const { return SymbolTableEntry != nullptr; }
@@ -266,7 +266,7 @@ public:
/// setBody - Specify a body for an opaque identified type.
void setBody(ArrayRef<Type*> Elements, bool isPacked = false);
- void setBody(Type *elt1, ...) END_WITH_NULL;
+ void setBody(Type *elt1, ...) LLVM_END_WITH_NULL;
/// isValidElementType - Return true if the specified type is valid as a
/// element type.
@@ -277,6 +277,9 @@ public:
typedef Type::subtype_iterator element_iterator;
element_iterator element_begin() const { return ContainedTys; }
element_iterator element_end() const { return &ContainedTys[NumContainedTys];}
+ ArrayRef<Type *> const elements() const {
+ return makeArrayRef(element_begin(), element_end());
+ }
/// isLayoutIdentical - Return true if this is layout identical to the
/// specified struct.
diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h
index 9c9f236180ce..c6a8854e0774 100644
--- a/include/llvm/IR/DiagnosticInfo.h
+++ b/include/llvm/IR/DiagnosticInfo.h
@@ -12,12 +12,13 @@
// Diagnostics reporting is still done as part of the LLVMContext.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H
-#define LLVM_SUPPORT_DIAGNOSTICINFO_H
+#ifndef LLVM_IR_DIAGNOSTICINFO_H
+#define LLVM_IR_DIAGNOSTICINFO_H
#include "llvm-c/Core.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
namespace llvm {
@@ -44,8 +45,10 @@ enum DiagnosticSeverity {
/// \brief Defines the different supported kind of a diagnostic.
/// This enum should be extended with a new ID for each added concrete subclass.
enum DiagnosticKind {
+ DK_Bitcode,
DK_InlineAsm,
DK_StackSize,
+ DK_Linker,
DK_DebugMetadataVersion,
DK_SampleProfile,
DK_OptimizationRemark,
@@ -95,6 +98,8 @@ public:
virtual void print(DiagnosticPrinter &DP) const = 0;
};
+typedef std::function<void(const DiagnosticInfo &)> DiagnosticHandlerFunction;
+
/// Diagnostic information for inline asm reporting.
/// This is basically a message and an optional location.
class DiagnosticInfoInlineAsm : public DiagnosticInfo {
@@ -324,7 +329,7 @@ public:
}
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- virtual bool isEnabled() const override;
+ bool isEnabled() const override;
};
/// Diagnostic information for missed-optimization remarks.
@@ -350,7 +355,7 @@ public:
}
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- virtual bool isEnabled() const override;
+ bool isEnabled() const override;
};
/// Diagnostic information for optimization analysis remarks.
@@ -377,7 +382,7 @@ public:
}
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- virtual bool isEnabled() const override;
+ bool isEnabled() const override;
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
@@ -432,7 +437,7 @@ public:
}
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- virtual bool isEnabled() const override;
+ bool isEnabled() const override;
};
/// Emit a warning when loop vectorization is specified but fails. \p Fn is the
diff --git a/include/llvm/IR/DiagnosticPrinter.h b/include/llvm/IR/DiagnosticPrinter.h
index 411c781e01c5..db5779a8a8a5 100644
--- a/include/llvm/IR/DiagnosticPrinter.h
+++ b/include/llvm/IR/DiagnosticPrinter.h
@@ -13,8 +13,8 @@
// on their needs.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_DIAGNOSTICPRINTER_H
-#define LLVM_SUPPORT_DIAGNOSTICPRINTER_H
+#ifndef LLVM_IR_DIAGNOSTICPRINTER_H
+#define LLVM_IR_DIAGNOSTICPRINTER_H
#include <string>
diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h
index e2d1ccc8a3ca..c1f208e3d72f 100644
--- a/include/llvm/IR/Dominators.h
+++ b/include/llvm/IR/Dominators.h
@@ -31,6 +31,11 @@
namespace llvm {
+// FIXME: Replace this brittle forward declaration with the include of the new
+// PassManager.h when doing so doesn't break the PassManagerBuilder.
+template <typename IRUnitT> class AnalysisManager;
+class PreservedAnalyses;
+
EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>);
EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>);
@@ -69,6 +74,13 @@ public:
DominatorTree() : DominatorTreeBase<BasicBlock>(false) {}
+ DominatorTree(DominatorTree &&Arg)
+ : Base(std::move(static_cast<Base &>(Arg))) {}
+ DominatorTree &operator=(DominatorTree &&RHS) {
+ Base::operator=(std::move(static_cast<Base &>(RHS)));
+ return *this;
+ }
+
/// \brief Returns *false* if the other dominator tree matches this dominator
/// tree.
inline bool compare(const DominatorTree &Other) const {
@@ -155,6 +167,43 @@ template <> struct GraphTraits<DominatorTree*>
};
/// \brief Analysis pass which computes a \c DominatorTree.
+class DominatorTreeAnalysis {
+public:
+ /// \brief Provide the result typedef for this analysis pass.
+ typedef DominatorTree Result;
+
+ /// \brief Opaque, unique identifier for this analysis pass.
+ static void *ID() { return (void *)&PassID; }
+
+ /// \brief Run the analysis pass over a function and produce a dominator tree.
+ DominatorTree run(Function &F);
+
+ /// \brief Provide access to a name for this pass for debugging purposes.
+ static StringRef name() { return "DominatorTreeAnalysis"; }
+
+private:
+ static char PassID;
+};
+
+/// \brief Printer pass for the \c DominatorTree.
+class DominatorTreePrinterPass {
+ raw_ostream &OS;
+
+public:
+ explicit DominatorTreePrinterPass(raw_ostream &OS);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+
+ static StringRef name() { return "DominatorTreePrinterPass"; }
+};
+
+/// \brief Verifier pass for the \c DominatorTree.
+struct DominatorTreeVerifierPass {
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+
+ static StringRef name() { return "DominatorTreeVerifierPass"; }
+};
+
+/// \brief Legacy analysis pass which computes a \c DominatorTree.
class DominatorTreeWrapperPass : public FunctionPass {
DominatorTree DT;
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index ad4b1395f0cb..51403281e964 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -87,11 +87,14 @@ private:
ValueSymbolTable *SymTab; ///< Symbol table of args/instructions
AttributeSet AttributeSets; ///< Parameter attributes
- // HasLazyArguments is stored in Value::SubclassData.
- /*bool HasLazyArguments;*/
-
- // The Calling Convention is stored in Value::SubclassData.
- /*CallingConv::ID CallingConvention;*/
+ /*
+ * Value::SubclassData
+ *
+ * bit 0 : HasLazyArguments
+ * bit 1 : HasPrefixData
+ * bit 2 : HasPrologueData
+ * bit 3-6: CallingConvention
+ */
friend class SymbolTableListTraits<Function, Module>;
@@ -102,7 +105,7 @@ private:
/// needs it. The hasLazyArguments predicate returns true if the arg list
/// hasn't been set up yet.
bool hasLazyArguments() const {
- return getSubclassDataFromValue() & 1;
+ return getSubclassDataFromValue() & (1<<0);
}
void CheckLazyArguments() const {
if (hasLazyArguments())
@@ -143,6 +146,9 @@ public:
/// arguments.
bool isVarArg() const;
+ bool isMaterializable() const;
+ void setIsMaterializable(bool V);
+
/// getIntrinsicID - This method returns the ID number of the specified
/// function, or Intrinsic::not_intrinsic if the function is not an
/// intrinsic, or if the pointer is null. This value is always defined to be
@@ -159,11 +165,11 @@ public:
/// calling convention of this function. The enum values for the known
/// calling conventions are defined in CallingConv.h.
CallingConv::ID getCallingConv() const {
- return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 2);
+ return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 3);
}
void setCallingConv(CallingConv::ID CC) {
- setValueSubclassData((getSubclassDataFromValue() & 3) |
- (static_cast<unsigned>(CC) << 2));
+ setValueSubclassData((getSubclassDataFromValue() & 7) |
+ (static_cast<unsigned>(CC) << 3));
}
/// @brief Return the attribute list for this Function.
@@ -445,12 +451,19 @@ public:
bool arg_empty() const;
bool hasPrefixData() const {
- return getSubclassDataFromValue() & 2;
+ return getSubclassDataFromValue() & (1<<1);
}
Constant *getPrefixData() const;
void setPrefixData(Constant *PrefixData);
+ bool hasPrologueData() const {
+ return getSubclassDataFromValue() & (1<<2);
+ }
+
+ Constant *getPrologueData() const;
+ void setPrologueData(Constant *PrologueData);
+
/// viewCFG - This function is meant for use from the debugger. You can just
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
/// program, displaying the CFG of the current function with the code for each
diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h
index a1216a174282..6f57dc2a98a6 100644
--- a/include/llvm/IR/GVMaterializer.h
+++ b/include/llvm/IR/GVMaterializer.h
@@ -19,11 +19,13 @@
#define LLVM_IR_GVMATERIALIZER_H
#include <system_error>
+#include <vector>
namespace llvm {
class Function;
class GlobalValue;
class Module;
+class StructType;
class GVMaterializer {
protected:
@@ -32,17 +34,13 @@ protected:
public:
virtual ~GVMaterializer();
- /// True if GV can be materialized from whatever backing store this
- /// GVMaterializer uses and has not been materialized yet.
- virtual bool isMaterializable(const GlobalValue *GV) const = 0;
-
/// True if GV has been materialized and can be dematerialized back to
/// whatever backing store this GVMaterializer uses.
virtual bool isDematerializable(const GlobalValue *GV) const = 0;
/// Make sure the given GlobalValue is fully read.
///
- virtual std::error_code Materialize(GlobalValue *GV) = 0;
+ virtual std::error_code materialize(GlobalValue *GV) = 0;
/// If the given GlobalValue is read in, and if the GVMaterializer supports
/// it, release the memory for the GV, and set it up to be materialized
@@ -55,7 +53,7 @@ public:
///
virtual std::error_code MaterializeModule(Module *M) = 0;
- virtual void releaseBuffer() = 0;
+ virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0;
};
} // End llvm namespace
diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h
index 2e042f489749..546fea2dfa9b 100644
--- a/include/llvm/IR/GlobalObject.h
+++ b/include/llvm/IR/GlobalObject.h
@@ -1,4 +1,4 @@
-//===-- llvm/GlobalObject.h - Class to represent a global object *- C++ -*-===//
+//===-- llvm/GlobalObject.h - Class to represent global objects -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -35,12 +35,24 @@ protected:
std::string Section; // Section to emit this into, empty means default
Comdat *ObjComdat;
+ static const unsigned AlignmentBits = 5;
+ static const unsigned GlobalObjectSubClassDataBits =
+ GlobalValueSubClassDataBits - AlignmentBits;
+
+private:
+ static const unsigned AlignmentMask = (1 << AlignmentBits) - 1;
+
public:
unsigned getAlignment() const {
- return (1u << getGlobalValueSubClassData()) >> 1;
+ unsigned Data = getGlobalValueSubClassData();
+ unsigned AlignmentData = Data & AlignmentMask;
+ return (1u << AlignmentData) >> 1;
}
void setAlignment(unsigned Align);
+ unsigned getGlobalObjectSubClassData() const;
+ void setGlobalObjectSubClassData(unsigned Val);
+
bool hasSection() const { return !StringRef(getSection()).empty(); }
const char *getSection() const { return Section.c_str(); }
void setSection(StringRef S);
diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h
index 68e410ba4b8b..d0f7e9a11790 100644
--- a/include/llvm/IR/GlobalValue.h
+++ b/include/llvm/IR/GlobalValue.h
@@ -20,6 +20,7 @@
#include "llvm/IR/Constant.h"
#include "llvm/IR/DerivedTypes.h"
+#include <system_error>
namespace llvm {
@@ -84,6 +85,7 @@ private:
// (19 + 3 + 2 + 1 + 2 + 5) == 32.
unsigned SubClassData : 19;
protected:
+ static const unsigned GlobalValueSubClassDataBits = 19;
unsigned getGlobalValueSubClassData() const {
return SubClassData;
}
@@ -246,6 +248,7 @@ public:
bool hasLinkOnceLinkage() const {
return isLinkOnceLinkage(Linkage);
}
+ bool hasLinkOnceODRLinkage() const { return isLinkOnceODRLinkage(Linkage); }
bool hasWeakLinkage() const {
return isWeakLinkage(Linkage);
}
@@ -309,7 +312,7 @@ public:
/// Make sure this GlobalValue is fully read. If the module is corrupt, this
/// returns true and fills in the optional string with information about the
/// problem. If successful, this returns false.
- bool Materialize(std::string *ErrInfo = nullptr);
+ std::error_code materialize();
/// If this GlobalValue is read in, and if the GVMaterializer supports it,
/// release the memory for the function, and set it up to be materialized
@@ -325,6 +328,13 @@ public:
/// the current translation unit.
bool isDeclaration() const;
+ bool isDeclarationForLinker() const {
+ if (hasAvailableExternallyLinkage())
+ return true;
+
+ return isDeclaration();
+ }
+
/// This method unlinks 'this' from the containing module, but does not delete
/// it.
virtual void removeFromParent() = 0;
diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index aed2463d42d8..e5f62fb9625e 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -28,7 +28,7 @@
#include "llvm/Support/CBindingWrapping.h"
namespace llvm {
- class MDNode;
+class MDNode;
/// \brief This provides the default implementation of the IRBuilder
/// 'InsertHelper' method that is called whenever an instruction is created by
@@ -364,43 +364,60 @@ public:
/// \brief Create and insert a memset to the specified pointer and the
/// specified value.
///
- /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
- /// specified, it will be added to the instruction.
+ /// 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 *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr) {
- return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
+ return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile,
+ TBAATag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief 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.
+ /// 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,
bool isVolatile = false, MDNode *TBAATag = nullptr,
- MDNode *TBAAStructTag = nullptr) {
+ MDNode *TBAAStructTag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag,
- TBAAStructTag);
+ TBAAStructTag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
bool isVolatile = false, MDNode *TBAATag = nullptr,
- MDNode *TBAAStructTag = nullptr);
+ MDNode *TBAAStructTag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief 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.
+ /// 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) {
- return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
+ return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile,
+ TBAATag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief Create a lifetime.start intrinsic.
///
@@ -412,7 +429,46 @@ public:
/// If the pointer isn't i8* it will be converted.
CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr);
+ /// \brief Create a call to Masked Load intrinsic
+ CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask,
+ Value *PassThru = 0, const Twine &Name = "");
+
+ /// \brief Create a call to Masked Store intrinsic
+ CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align,
+ Value *Mask);
+
+ /// \brief Create an assume intrinsic call that allows the optimizer to
+ /// assume that the provided condition will be true.
+ CallInst *CreateAssumption(Value *Cond);
+
+ /// \brief Create a call to the experimental.gc.statepoint intrinsic to
+ /// start a new statepoint sequence.
+ CallInst *CreateGCStatepoint(Value *ActualCallee,
+ ArrayRef<Value*> CallArgs,
+ ArrayRef<Value*> DeoptArgs,
+ ArrayRef<Value*> GCArgs,
+ const Twine &Name = "");
+
+ /// \brief Create a call to the experimental.gc.result intrinsic to extract
+ /// the result from a call wrapped in a statepoint.
+ CallInst *CreateGCResult(Instruction *Statepoint,
+ Type *ResultType,
+ const Twine &Name = "");
+
+ /// \brief Create a call to the experimental.gc.relocate intrinsics to
+ /// project the relocated value of one pointer from the statepoint.
+ CallInst *CreateGCRelocate(Instruction *Statepoint,
+ int BaseOffset,
+ int DerivedOffset,
+ Type *ResultType,
+ const Twine &Name = "");
+
private:
+ /// \brief Create a call to a masked intrinsic with given Id.
+ /// Masked intrinsic has only one overloaded type - data type.
+ CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef<Value *> Ops,
+ Type *DataTy, const Twine &Name = "");
+
Value *getCastedInt8PtrValue(Value *Ptr);
};
@@ -429,7 +485,7 @@ private:
/// The first template argument handles whether or not to preserve names in the
/// final instruction output. This defaults to on. The second template argument
/// specifies a class to use for creating constants. This defaults to creating
-/// minimally folded constants. The fourth template argument allows clients to
+/// minimally folded constants. The third template argument allows clients to
/// specify custom insertion hooks that are called on every newly created
/// insertion.
template<bool preserveNames = true, typename T = ConstantFolder,
@@ -570,8 +626,7 @@ public:
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
BasicBlock *UnwindDest, const Twine &Name = "") {
- return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest,
- ArrayRef<Value *>()),
+ return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, None),
Name);
}
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
@@ -1226,6 +1281,18 @@ public:
return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name);
return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name);
}
+
+ Value *CreateBitOrPointerCast(Value *V, Type *DestTy,
+ const Twine &Name = "") {
+ if (V->getType() == DestTy)
+ return V;
+ if (V->getType()->isPointerTy() && DestTy->isIntegerTy())
+ return CreatePtrToInt(V, DestTy, Name);
+ if (V->getType()->isIntegerTy() && DestTy->isPointerTy())
+ return CreateIntToPtr(V, DestTy, Name);
+
+ return CreateBitCast(V, DestTy, Name);
+ }
private:
// \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
// compile time error, instead of converting the string to bool for the
@@ -1508,6 +1575,44 @@ public:
}
return V;
}
+
+ /// \brief 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
+ /// must be subtracted from the provided pointer to get the pointer with the
+ /// specified alignment.
+ CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
+ unsigned Alignment,
+ Value *OffsetValue = nullptr) {
+ assert(isa<PointerType>(PtrValue->getType()) &&
+ "trying to create an alignment assumption on a non-pointer?");
+
+ PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
+ Type *IntPtrTy = getIntPtrTy(&DL, PtrTy->getAddressSpace());
+ Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint");
+
+ Value *Mask = ConstantInt::get(IntPtrTy,
+ Alignment > 0 ? Alignment - 1 : 0);
+ if (OffsetValue) {
+ bool IsOffsetZero = false;
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(OffsetValue))
+ IsOffsetZero = CI->isZero();
+
+ if (!IsOffsetZero) {
+ if (OffsetValue->getType() != IntPtrTy)
+ OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true,
+ "offsetcast");
+ PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr");
+ }
+ }
+
+ Value *Zero = ConstantInt::get(IntPtrTy, 0);
+ Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr");
+ Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond");
+
+ return CreateAssumption(InvCond);
+ }
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h
index 2f78c83165eb..7f2027b6e297 100644
--- a/include/llvm/IR/IRPrintingPasses.h
+++ b/include/llvm/IR/IRPrintingPasses.h
@@ -16,8 +16,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_IR_PRINTING_PASSES_H
-#define LLVM_IR_IR_PRINTING_PASSES_H
+#ifndef LLVM_IR_IRPRINTINGPASSES_H
+#define LLVM_IR_IRPRINTINGPASSES_H
#include "llvm/ADT/StringRef.h"
#include <string>
@@ -58,7 +58,7 @@ public:
PrintModulePass();
PrintModulePass(raw_ostream &OS, const std::string &Banner = "");
- PreservedAnalyses run(Module *M);
+ PreservedAnalyses run(Module &M);
static StringRef name() { return "PrintModulePass"; }
};
@@ -75,7 +75,7 @@ public:
PrintFunctionPass();
PrintFunctionPass(raw_ostream &OS, const std::string &Banner = "");
- PreservedAnalyses run(Function *F);
+ PreservedAnalyses run(Function &F);
static StringRef name() { return "PrintFunctionPass"; }
};
diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h
index ac190892bab0..b2d79d0f0bfc 100644
--- a/include/llvm/IR/InlineAsm.h
+++ b/include/llvm/IR/InlineAsm.h
@@ -25,12 +25,9 @@ namespace llvm {
class PointerType;
class FunctionType;
class Module;
+
struct InlineAsmKeyType;
-template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
- bool HasLargeKey>
-class ConstantUniqueMap;
-template<class ConstantClass, class TypeClass, class ValType>
-struct ConstantCreator;
+template <class ConstantClass> class ConstantUniqueMap;
class InlineAsm : public Value {
public:
@@ -40,9 +37,8 @@ public:
};
private:
- friend struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType>;
- friend class ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&,
- PointerType, InlineAsm, false>;
+ friend struct InlineAsmKeyType;
+ friend class ConstantUniqueMap<InlineAsm>;
InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION;
void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION;
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index 981aad852b29..030f5d690a0c 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -29,8 +29,8 @@ class LLVMContext;
// TerminatorInst Class
//===----------------------------------------------------------------------===//
-/// TerminatorInst - Subclasses of this class are all able to terminate a basic
-/// block. Thus, these are all the flow control type of operations.
+/// Subclasses of this class are all able to terminate a basic
+/// block. Thus, these are all the flow control type of operations.
///
class TerminatorInst : public Instruction {
protected:
@@ -51,23 +51,19 @@ protected:
virtual BasicBlock *getSuccessorV(unsigned idx) const = 0;
virtual unsigned getNumSuccessorsV() const = 0;
virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0;
- TerminatorInst *clone_impl() const override = 0;
public:
- /// getNumSuccessors - Return the number of successors that this terminator
- /// has.
+ /// Return the number of successors that this terminator has.
unsigned getNumSuccessors() const {
return getNumSuccessorsV();
}
- /// getSuccessor - Return the specified successor.
- ///
+ /// Return the specified successor.
BasicBlock *getSuccessor(unsigned idx) const {
return getSuccessorV(idx);
}
- /// setSuccessor - Update the specified successor to point at the provided
- /// block.
+ /// Update the specified successor to point at the provided block.
void setSuccessor(unsigned idx, BasicBlock *B) {
setSuccessorV(idx, B);
}
@@ -153,7 +149,7 @@ public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- /// Create() - Construct a binary instruction, given the opcode and the two
+ /// Construct a binary instruction, given the opcode and the two
/// operands. Optionally (if InstBefore is specified) insert the instruction
/// into a BasicBlock right before the specified instruction. The specified
/// Instruction is allowed to be a dereferenced end iterator.
@@ -162,14 +158,14 @@ public:
const Twine &Name = Twine(),
Instruction *InsertBefore = nullptr);
- /// Create() - Construct a binary instruction, given the opcode and the two
+ /// Construct a binary instruction, given the opcode and the two
/// operands. Also automatically insert this instruction to the end of the
/// BasicBlock specified.
///
static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2,
const Twine &Name, BasicBlock *InsertAtEnd);
- /// Create* - These methods just forward to Create, and are useful when you
+ /// These methods just forward to Create, and are useful when you
/// statically know what type of instruction you're going to create. These
/// helpers just save some typing.
#define HANDLE_BINARY_INST(N, OPC, CLASS) \
@@ -281,8 +277,7 @@ public:
/// Helper functions to construct and inspect unary operations (NEG and NOT)
/// via binary operators SUB and XOR:
///
- /// CreateNeg, CreateNot - Create the NEG and NOT
- /// instructions out of SUB and XOR instructions.
+ /// Create the NEG and NOT instructions out of SUB and XOR instructions.
///
static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "",
Instruction *InsertBefore = nullptr);
@@ -305,16 +300,14 @@ public:
static BinaryOperator *CreateNot(Value *Op, const Twine &Name,
BasicBlock *InsertAtEnd);
- /// isNeg, isFNeg, isNot - Check if the given Value is a
- /// NEG, FNeg, or NOT instruction.
+ /// Check if the given Value is a NEG, FNeg, or NOT instruction.
///
static bool isNeg(const Value *V);
static bool isFNeg(const Value *V, bool IgnoreZeroSign=false);
static bool isNot(const Value *V);
- /// getNegArgument, getNotArgument - Helper functions to extract the
- /// unary argument of a NEG, FNEG or NOT operation implemented via
- /// Sub, FSub, or Xor.
+ /// Helper functions to extract the unary argument of a NEG, FNEG or NOT
+ /// operation implemented via Sub, FSub, or Xor.
///
static const Value *getNegArgument(const Value *BinOp);
static Value *getNegArgument( Value *BinOp);
@@ -327,37 +320,42 @@ public:
return static_cast<BinaryOps>(Instruction::getOpcode());
}
- /// swapOperands - Exchange the two operands to this instruction.
+ /// Exchange the two operands to this instruction.
/// This instruction is safe to use on any binary instruction and
/// does not modify the semantics of the instruction. If the instruction
/// cannot be reversed (ie, it's a Div), then return true.
///
bool swapOperands();
- /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction,
- /// which must be an operator which supports this flag. See LangRef.html
- /// for the meaning of this flag.
+ /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
void setHasNoUnsignedWrap(bool b = true);
- /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction,
- /// which must be an operator which supports this flag. See LangRef.html
- /// for the meaning of this flag.
+ /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
void setHasNoSignedWrap(bool b = true);
- /// setIsExact - Set or clear the exact flag on this instruction,
- /// which must be an operator which supports this flag. See LangRef.html
- /// for the meaning of this flag.
+ /// Set or clear the exact flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
void setIsExact(bool b = true);
- /// hasNoUnsignedWrap - Determine whether the no unsigned wrap flag is set.
+ /// Determine whether the no unsigned wrap flag is set.
bool hasNoUnsignedWrap() const;
- /// hasNoSignedWrap - Determine whether the no signed wrap flag is set.
+ /// Determine whether the no signed wrap flag is set.
bool hasNoSignedWrap() const;
- /// isExact - Determine whether the exact flag is set.
+ /// Determine whether the exact flag is set.
bool isExact() const;
+ /// Convenience method to copy supported wrapping, exact, and fast-math flags
+ /// from V to this instruction.
+ void copyIRFlags(const Value *V);
+
+ /// Logical 'and' of any supported wrapping, exact, and fast-math flags of
+ /// V and this instruction.
+ void andIRFlags(const Value *V);
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->isBinaryOp();
@@ -378,7 +376,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value)
// CastInst Class
//===----------------------------------------------------------------------===//
-/// CastInst - This is the base class for all instructions that perform data
+/// This is the base class for all instructions that perform data
/// casts. It is simply provided so that instruction category testing
/// can be performed with code like:
///
@@ -491,6 +489,19 @@ public:
Instruction *InsertBefore = 0 ///< Place to insert the instruction
);
+ /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction.
+ ///
+ /// If the value is a pointer type and the destination an integer type,
+ /// creates a PtrToInt cast. If the value is an integer type and the
+ /// destination a pointer type, creates an IntToPtr cast. Otherwise, creates
+ /// a bitcast.
+ static CastInst *CreateBitOrPointerCast(
+ Value *S, ///< The pointer value to be casted (operand 0)
+ Type *Ty, ///< The type to which cast should be made
+ const Twine &Name = "", ///< Name for the instruction
+ Instruction *InsertBefore = 0 ///< Place to insert the instruction
+ );
+
/// @brief Create a ZExt, BitCast, or Trunc for int -> int casts.
static CastInst *CreateIntegerCast(
Value *S, ///< The pointer value to be casted (operand 0)
@@ -553,6 +564,17 @@ public:
Type *DestTy ///< The Type to which the value should be cast.
);
+ /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these
+ /// types is valid and a no-op.
+ ///
+ /// This ensures that any pointer<->integer cast has enough bits in the
+ /// integer and any other cast is a bitcast.
+ static bool isBitOrNoopPointerCastable(
+ Type *SrcTy, ///< The Type from which the value should be cast.
+ Type *DestTy, ///< The Type to which the value should be cast.
+ const DataLayout *Layout = 0 ///< Optional DataLayout.
+ );
+
/// Returns the opcode necessary to cast Val into Ty using usual casting
/// rules.
/// @brief Infer the opcode for cast operand and type
diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h
index bac6a95b1b71..ba7791c99b6a 100644
--- a/include/llvm/IR/Instruction.h
+++ b/include/llvm/IR/Instruction.h
@@ -25,6 +25,7 @@ namespace llvm {
class FastMathFlags;
class LLVMContext;
class MDNode;
+struct AAMDNodes;
template<typename ValueSubClass, typename ItemParentClass>
class SymbolTableListTraits;
@@ -155,19 +156,25 @@ public:
/// getAllMetadata - Get all metadata attached to this Instruction. The first
/// element of each pair returned is the KindID, the second element is the
/// metadata value. This list is returned sorted by the KindID.
- void getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode*> > &MDs)const{
+ void
+ getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
if (hasMetadata())
getAllMetadataImpl(MDs);
}
/// getAllMetadataOtherThanDebugLoc - This does the same thing as
/// getAllMetadata, except that it filters out the debug location.
- void getAllMetadataOtherThanDebugLoc(SmallVectorImpl<std::pair<unsigned,
- MDNode*> > &MDs) const {
+ void getAllMetadataOtherThanDebugLoc(
+ SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
if (hasMetadataOtherThanDebugLoc())
getAllMetadataOtherThanDebugLocImpl(MDs);
}
+ /// getAAMetadata - Fills the AAMDNodes structure with AA metadata from
+ /// this instruction. When Merge is true, the existing AA metadata is
+ /// merged with that from this instruction providing the most-general result.
+ void getAAMetadata(AAMDNodes &N, bool Merge = false) const;
+
/// setMetadata - Set the metadata of the specified kind to the specified
/// node. This updates/replaces metadata if already present, or removes it if
/// Node is null.
@@ -179,7 +186,7 @@ public:
/// convenience method for passes to do so.
void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
void dropUnknownMetadata() {
- return dropUnknownMetadata(ArrayRef<unsigned>());
+ return dropUnknownMetadata(None);
}
void dropUnknownMetadata(unsigned ID1) {
return dropUnknownMetadata(makeArrayRef(ID1));
@@ -189,6 +196,10 @@ public:
return dropUnknownMetadata(IDs);
}
+ /// setAAMetadata - Sets the metadata on this instruction from the
+ /// AAMDNodes structure.
+ void setAAMetadata(const AAMDNodes &N);
+
/// setDebugLoc - Set the debug location information for this instruction.
void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; }
@@ -220,11 +231,16 @@ public:
/// this flag.
void setHasAllowReciprocal(bool B);
- /// Convenience function for setting all the fast-math flags on this
+ /// Convenience function for setting multiple fast-math flags on this
/// instruction, which must be an operator which supports these flags. See
- /// LangRef.html for the meaning of these flats.
+ /// LangRef.html for the meaning of these flags.
void setFastMathFlags(FastMathFlags FMF);
+ /// Convenience function for transferring all fast-math flag values to this
+ /// instruction, which must be an operator which supports these flags. See
+ /// LangRef.html for the meaning of these flags.
+ void copyFastMathFlags(FastMathFlags FMF);
+
/// Determine whether the unsafe-algebra flag is set.
bool hasUnsafeAlgebra() const;
@@ -242,7 +258,7 @@ public:
/// Convenience function for getting all the fast-math flags, which must be an
/// operator which supports these flags. See LangRef.html for the meaning of
- /// these flats.
+ /// these flags.
FastMathFlags getFastMathFlags() const;
/// Copy I's fast-math flags
@@ -258,9 +274,10 @@ private:
// These are all implemented in Metadata.cpp.
MDNode *getMetadataImpl(unsigned KindID) const;
MDNode *getMetadataImpl(StringRef Kind) const;
- void getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,MDNode*> > &)const;
- void getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl<std::pair<unsigned,
- MDNode*> > &) const;
+ void
+ getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
+ void getAllMetadataOtherThanDebugLocImpl(
+ SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
void clearMetadataHashEntries();
public:
//===--------------------------------------------------------------------===//
@@ -323,6 +340,11 @@ public:
return mayReadFromMemory() || mayWriteToMemory();
}
+ /// isAtomic - Return true if this instruction has an
+ /// AtomicOrdering of unordered or higher.
+ ///
+ bool isAtomic() const;
+
/// mayThrow - Return true if this instruction may throw an exception.
///
bool mayThrow() const;
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index 308467f7aa17..045e51eb1baa 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -17,8 +17,8 @@
#define LLVM_IR_INSTRUCTIONS_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DerivedTypes.h"
@@ -50,6 +50,22 @@ enum SynchronizationScope {
CrossThread = 1
};
+/// Returns true if the ordering is at least as strong as acquire
+/// (i.e. acquire, acq_rel or seq_cst)
+inline bool isAtLeastAcquire(AtomicOrdering Ord) {
+ return (Ord == Acquire ||
+ Ord == AcquireRelease ||
+ Ord == SequentiallyConsistent);
+}
+
+/// Returns true if the ordering is at least as strong as release
+/// (i.e. release, acq_rel or seq_cst)
+inline bool isAtLeastRelease(AtomicOrdering Ord) {
+return (Ord == Release ||
+ Ord == AcquireRelease ||
+ Ord == SequentiallyConsistent);
+}
+
//===----------------------------------------------------------------------===//
// AllocaInst Class
//===----------------------------------------------------------------------===//
@@ -119,7 +135,7 @@ public:
return getSubclassDataFromInstruction() & 32;
}
- /// \brief Specify whether this alloca is used to represent a the arguments to
+ /// \brief Specify whether this alloca is used to represent the arguments to
/// a call.
void setUsedWithInAlloca(bool V) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~32) |
@@ -225,7 +241,6 @@ public:
(xthread << 6));
}
- bool isAtomic() const { return getOrdering() != NotAtomic; }
void setAtomic(AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread) {
setOrdering(Ordering);
@@ -345,7 +360,6 @@ public:
(xthread << 6));
}
- bool isAtomic() const { return getOrdering() != NotAtomic; }
void setAtomic(AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread) {
setOrdering(Ordering);
@@ -637,7 +651,7 @@ public:
Sub,
/// *p = old & v
And,
- /// *p = ~old & v
+ /// *p = ~(old & v)
Nand,
/// *p = old | v
Or,
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index e053f7867c53..c227ea080167 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -28,6 +28,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Metadata.h"
namespace llvm {
/// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic
@@ -81,7 +82,14 @@ namespace llvm {
class DbgDeclareInst : public DbgInfoIntrinsic {
public:
Value *getAddress() const;
- MDNode *getVariable() const { return cast<MDNode>(getArgOperand(1)); }
+ MDNode *getVariable() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(1))->getMetadata());
+ }
+ MDNode *getExpression() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const IntrinsicInst *I) {
@@ -102,7 +110,14 @@ namespace llvm {
return cast<ConstantInt>(
const_cast<Value*>(getArgOperand(1)))->getZExtValue();
}
- MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); }
+ MDNode *getVariable() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ }
+ MDNode *getExpression() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(3))->getMetadata());
+ }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const IntrinsicInst *I) {
@@ -320,6 +335,33 @@ namespace llvm {
Value *getSrc() const { return const_cast<Value*>(getArgOperand(1)); }
};
+ /// This represents the llvm.instrprof_increment intrinsic.
+ class InstrProfIncrementInst : public IntrinsicInst {
+ public:
+ static inline bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::instrprof_increment;
+ }
+ static inline bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+
+ GlobalVariable *getName() const {
+ return cast<GlobalVariable>(
+ const_cast<Value *>(getArgOperand(0))->stripPointerCasts());
+ }
+
+ ConstantInt *getHash() const {
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1)));
+ }
+
+ ConstantInt *getNumCounters() const {
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
+ }
+
+ ConstantInt *getIndex() const {
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
+ }
+ };
}
#endif
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h
index b0d746bd4127..56d1e4af26aa 100644
--- a/include/llvm/IR/Intrinsics.h
+++ b/include/llvm/IR/Intrinsics.h
@@ -28,10 +28,9 @@ class LLVMContext;
class Module;
class AttributeSet;
-/// Intrinsic Namespace - This namespace contains an enum with a value for
-/// every intrinsic/builtin function known by LLVM. These enum values are
-/// returned by Function::getIntrinsicID().
-///
+/// This namespace contains an enum with a value for every intrinsic/builtin
+/// function known by LLVM. The enum values are returned by
+/// Function::getIntrinsicID().
namespace Intrinsic {
enum ID {
not_intrinsic = 0, // Must be zero
@@ -43,25 +42,21 @@ namespace Intrinsic {
, num_intrinsics
};
- /// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as
- /// "llvm.ppc.altivec.lvx".
+ /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
std::string getName(ID id, ArrayRef<Type*> Tys = None);
- /// Intrinsic::getType(ID) - Return the function type for an intrinsic.
- ///
+ /// Return the function type for an intrinsic.
FunctionType *getType(LLVMContext &Context, ID id,
ArrayRef<Type*> Tys = None);
- /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be
- /// overloaded.
+ /// Returns true if the intrinsic can be overloaded.
bool isOverloaded(ID id);
- /// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic.
- ///
+ /// Return the attributes for an intrinsic.
AttributeSet getAttributes(LLVMContext &C, ID id);
- /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function
- /// declaration for an intrinsic, and return it.
+ /// Create or insert an LLVM Function declaration for an intrinsic, and return
+ /// it.
///
/// The Tys parameter is for intrinsics with overloaded types (e.g., those
/// using iAny, fAny, vAny, or iPTRAny). For a declaration of an overloaded
@@ -75,14 +70,14 @@ namespace Intrinsic {
/// Map a MS builtin name to an intrinsic ID.
ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName);
- /// IITDescriptor - This is a type descriptor which explains the type
- /// requirements of an intrinsic. This is returned by
- /// getIntrinsicInfoTableEntries.
+ /// This is a type descriptor which explains the type requirements of an
+ /// intrinsic. This is returned by getIntrinsicInfoTableEntries.
struct IITDescriptor {
enum IITDescriptorKind {
Void, VarArg, MMX, Metadata, Half, Float, Double,
Integer, Vector, Pointer, Struct,
- Argument, ExtendArgument, TruncArgument, HalfVecArgument
+ Argument, ExtendArgument, TruncArgument, HalfVecArgument,
+ SameVecWidthArgument, PtrToArgument
} Kind;
union {
@@ -102,13 +97,15 @@ namespace Intrinsic {
};
unsigned getArgumentNumber() const {
assert(Kind == Argument || Kind == ExtendArgument ||
- Kind == TruncArgument || Kind == HalfVecArgument);
+ Kind == TruncArgument || Kind == HalfVecArgument ||
+ Kind == SameVecWidthArgument || Kind == PtrToArgument);
return Argument_Info >> 2;
}
ArgKind getArgumentKind() const {
assert(Kind == Argument || Kind == ExtendArgument ||
- Kind == TruncArgument || Kind == HalfVecArgument);
- return (ArgKind)(Argument_Info&3);
+ Kind == TruncArgument || Kind == HalfVecArgument ||
+ Kind == SameVecWidthArgument || Kind == PtrToArgument);
+ return (ArgKind)(Argument_Info & 3);
}
static IITDescriptor get(IITDescriptorKind K, unsigned Field) {
@@ -117,9 +114,8 @@ namespace Intrinsic {
}
};
- /// getIntrinsicInfoTableEntries - Return the IIT table descriptor for the
- /// specified intrinsic into an array of IITDescriptors.
- ///
+ /// Return the IIT table descriptor for the specified intrinsic into an array
+ /// of IITDescriptors.
void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
} // End Intrinsic namespace
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index 0b8f64fc7984..a1188bccdc25 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -112,6 +112,11 @@ class LLVMMatchType<int num>
// the intrinsic is overloaded, so the matched type should be declared as iAny.
class LLVMExtendedType<int num> : LLVMMatchType<num>;
class LLVMTruncatedType<int num> : LLVMMatchType<num>;
+class LLVMVectorSameWidth<int num, LLVMType elty>
+ : LLVMMatchType<num> {
+ ValueType ElTy = elty.VT;
+}
+class LLVMPointerTo<int num> : LLVMMatchType<num>;
// Match the type of another intrinsic parameter that is expected to be a
// vector type, but change the element count to be half as many
@@ -254,6 +259,10 @@ def int_gcwrite : Intrinsic<[],
//
def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
+def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>;
+def int_framerecover : Intrinsic<[llvm_ptr_ty],
+ [llvm_ptr_ty, llvm_ptr_ty],
+ [IntrNoMem]>;
def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty],
[IntrNoMem], "llvm.read_register">;
def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty],
@@ -277,12 +286,22 @@ def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>;
def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>;
+// The assume intrinsic is marked as arbitrarily writing so that proper
+// control dependencies will be maintained.
+def int_assume : Intrinsic<[], [llvm_i1_ty], []>;
+
// Stack Protector Intrinsic - The stackprotector intrinsic writes the stack
// guard to the correct place on the stack frame.
def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>;
def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty],
[IntrReadWriteArgMem]>;
+// A counter increment for instrumentation based profiling.
+def int_instrprof_increment : Intrinsic<[],
+ [llvm_ptr_ty, llvm_i64_ty,
+ llvm_i32_ty, llvm_i32_ty],
+ []>;
+
//===------------------- Standard C Library Intrinsics --------------------===//
//
@@ -324,6 +343,8 @@ let Properties = [IntrNoMem] in {
def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
+ def int_minnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>;
+ def int_maxnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_copysign : Intrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
@@ -369,9 +390,12 @@ let Properties = [IntrNoMem] in {
// places.
let Properties = [IntrNoMem] in {
def int_dbg_declare : Intrinsic<[],
- [llvm_metadata_ty, llvm_metadata_ty]>;
+ [llvm_metadata_ty,
+ llvm_metadata_ty,
+ llvm_metadata_ty]>;
def int_dbg_value : Intrinsic<[],
[llvm_metadata_ty, llvm_i64_ty,
+ llvm_metadata_ty,
llvm_metadata_ty]>;
}
@@ -476,11 +500,29 @@ def int_experimental_stackmap : Intrinsic<[],
def int_experimental_patchpoint_void : Intrinsic<[],
[llvm_i64_ty, llvm_i32_ty,
llvm_ptr_ty, llvm_i32_ty,
- llvm_vararg_ty]>;
+ llvm_vararg_ty],
+ [Throws]>;
def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty],
[llvm_i64_ty, llvm_i32_ty,
llvm_ptr_ty, llvm_i32_ty,
- llvm_vararg_ty]>;
+ llvm_vararg_ty],
+ [Throws]>;
+
+
+//===------------------------ Garbage Collection Intrinsics ---------------===//
+// These are documented in docs/Statepoint.rst
+
+def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty],
+ [llvm_anyptr_ty, llvm_i32_ty,
+ llvm_i32_ty, llvm_vararg_ty]>;
+
+def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>;
+def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty],
+ [llvm_i32_ty]>;
+def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>;
+
+def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>;
//===-------------------------- Other Intrinsics --------------------------===//
//
@@ -528,6 +570,17 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty],
def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
[], "llvm.clear_cache">;
+//===-------------------------- Masked Intrinsics -------------------------===//
+//
+def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>,
+ llvm_i32_ty,
+ LLVMVectorSameWidth<0, llvm_i1_ty>],
+ [IntrReadWriteArgMem]>;
+
+def int_masked_load : Intrinsic<[llvm_anyvector_ty],
+ [LLVMPointerTo<0>, llvm_i32_ty,
+ LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>],
+ [IntrReadArgMem]>;
//===----------------------------------------------------------------------===//
// Target-specific intrinsics
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td
index a02d7072d720..ce758e257312 100644
--- a/include/llvm/IR/IntrinsicsARM.td
+++ b/include/llvm/IR/IntrinsicsARM.td
@@ -20,8 +20,13 @@ let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.".
def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">,
Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
+// A space-consuming intrinsic primarily for testing ARMConstantIslands. The
+// first argument is the number of bytes this "instruction" takes up, the second
+// and return value are essentially chains, used to force ordering during ISel.
+def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
+
//===----------------------------------------------------------------------===//
-// Saturating Arithmentic
+// Saturating Arithmetic
def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
@@ -132,6 +137,7 @@ def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
// HINT
def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>;
+def int_arm_dbg : Intrinsic<[], [llvm_i32_ty]>;
//===----------------------------------------------------------------------===//
// RBIT
@@ -340,10 +346,6 @@ def int_arm_neon_vqneg : Neon_1Arg_Intrinsic;
// Vector Count Leading Sign/Zero Bits.
def int_arm_neon_vcls : Neon_1Arg_Intrinsic;
-def int_arm_neon_vclz : Neon_1Arg_Intrinsic;
-
-// Vector Count One Bits.
-def int_arm_neon_vcnt : Neon_1Arg_Intrinsic;
// Vector Reciprocal Estimate.
def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic;
diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td
index cd512841a1af..9deed414b50a 100644
--- a/include/llvm/IR/IntrinsicsNVVM.td
+++ b/include/llvm/IR/IntrinsicsNVVM.td
@@ -797,24 +797,30 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
// Generated within nvvm. Use for ldu on sm_20 or later
def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldu.global.i">;
def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldu.global.f">;
def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldu.global.p">;
// Generated within nvvm. Use for ldg on sm_35 or later
def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldg.global.i">;
def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldg.global.f">;
def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldg.global.p">;
// Use for generic pointers
diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td
index 49ddfb8b613b..5cdabdeadaea 100644
--- a/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/include/llvm/IR/IntrinsicsPowerPC.td
@@ -28,8 +28,10 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>;
def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>;
- // sync instruction
+ // sync instruction (i.e. sync 0, a.k.a hwsync)
def int_ppc_sync : Intrinsic<[], [], []>;
+ // lwsync is sync 1
+ def int_ppc_lwsync : Intrinsic<[], [], []>;
// Intrinsics used to generate ctr-based loops. These should only be
// generated by the PowerPC backend!
@@ -45,6 +47,13 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
list<IntrinsicProperty> properties>
: GCCBuiltin<!strconcat("__builtin_altivec_", GCCIntSuffix)>,
Intrinsic<ret_types, param_types, properties>;
+
+ /// PowerPC_VSX_Intrinsic - Base class for all VSX intrinsics.
+ class PowerPC_VSX_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types,
+ list<LLVMType> param_types,
+ list<IntrinsicProperty> properties>
+ : GCCBuiltin<!strconcat("__builtin_vsx_", GCCIntSuffix)>,
+ Intrinsic<ret_types, param_types, properties>;
}
//===----------------------------------------------------------------------===//
@@ -87,6 +96,32 @@ class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix>
//===----------------------------------------------------------------------===//
+// PowerPC VSX Intrinsic Class Definitions.
+//
+
+/// PowerPC_VSX_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2f64
+/// vectors and returns one. These intrinsics have no side effects.
+class PowerPC_VSX_Vec_DDD_Intrinsic<string GCCIntSuffix>
+ : PowerPC_VSX_Intrinsic<GCCIntSuffix,
+ [llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty],
+ [IntrNoMem]>;
+
+/// PowerPC_VSX_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32
+/// vectors and returns one. These intrinsics have no side effects.
+class PowerPC_VSX_Vec_FFF_Intrinsic<string GCCIntSuffix>
+ : PowerPC_VSX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty],
+ [IntrNoMem]>;
+
+/// PowerPC_VSX_Sca_DDD_Intrinsic - A PowerPC intrinsic that takes two f64
+/// scalars and returns one. These intrinsics have no side effects.
+class PowerPC_VSX_Sca_DDD_Intrinsic<string GCCIntSuffix>
+ : PowerPC_VSX_Intrinsic<GCCIntSuffix,
+ [llvm_double_ty], [llvm_double_ty, llvm_double_ty],
+ [IntrNoMem]>;
+
+
+//===----------------------------------------------------------------------===//
// PowerPC Altivec Intrinsic Definitions.
let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
@@ -474,3 +509,36 @@ def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">;
def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">;
def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">;
def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">;
+
+
+//===----------------------------------------------------------------------===//
+// PowerPC VSX Intrinsic Definitions.
+
+let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
+
+// Vector load.
+def int_ppc_vsx_lxvw4x :
+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+def int_ppc_vsx_lxvd2x :
+ Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+
+// Vector store.
+def int_ppc_vsx_stxvw4x :
+ Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>;
+def int_ppc_vsx_stxvd2x :
+ Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>;
+
+// Vector and scalar maximum.
+def int_ppc_vsx_xvmaxdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmaxdp">;
+def int_ppc_vsx_xvmaxsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvmaxsp">;
+def int_ppc_vsx_xsmaxdp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmaxdp">;
+
+// Vector and scalar minimum.
+def int_ppc_vsx_xvmindp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmindp">;
+def int_ppc_vsx_xvminsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvminsp">;
+def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">;
+
+// Vector divide.
+def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">;
+def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">;
+}
diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td
index ba69eaae089f..505566738221 100644
--- a/include/llvm/IR/IntrinsicsR600.td
+++ b/include/llvm/IR/IntrinsicsR600.td
@@ -33,10 +33,14 @@ defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz <
"__builtin_r600_read_tgid">;
defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz <
"__builtin_r600_read_tidig">;
-
} // End TargetPrefix = "r600"
let TargetPrefix = "AMDGPU" in {
+
+class AMDGPUReadPreloadRegisterIntrinsic<string name>
+ : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
+ GCCBuiltin<name>;
+
def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">,
// 1st parameter: Numerator
// 2nd parameter: Denominator
@@ -48,7 +52,7 @@ def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">,
def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">,
Intrinsic<[llvm_anyfloat_ty],
- [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty],
[IntrNoMem]>;
def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">,
@@ -69,4 +73,13 @@ def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">,
def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">,
Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">,
+ Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>;
+
+def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">,
+ Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>;
+
+def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic <
+ "__builtin_amdgpu_read_workdim">;
+
} // End TargetPrefix = "AMDGPU"
diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td
index 5de950813cd4..81c729065505 100644
--- a/include/llvm/IR/IntrinsicsX86.td
+++ b/include/llvm/IR/IntrinsicsX86.td
@@ -886,7 +886,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector insert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty],
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
}
@@ -896,13 +896,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty],
[IntrNoMem]>;
def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty],
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty],
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty],
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty],
@@ -915,17 +915,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector dot product
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_i32_ty],
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem, Commutative]>;
def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty],
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem, Commutative]>;
}
// Vector sum of absolute differences
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i32_ty],
+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i8_ty],
[IntrNoMem, Commutative]>;
}
@@ -1171,10 +1171,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
- llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
- llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>;
@@ -1187,7 +1187,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_dp_ps_256 : GCCBuiltin<"__builtin_ia32_dpps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
- llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Vector compare
@@ -1389,6 +1389,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
GCCBuiltin<"__builtin_ia32_storeupd512_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_store_ss :
+ GCCBuiltin<"__builtin_ia32_storess_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty],
+ [IntrReadWriteArgMem]>;
}
//===----------------------------------------------------------------------===//
@@ -1580,6 +1584,44 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi512">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi512">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi512">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrai_d : GCCBuiltin<"__builtin_ia32_psradi512">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrai_q : GCCBuiltin<"__builtin_ia32_psraqi512">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_psll_d : GCCBuiltin<"__builtin_ia32_pslld512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psll_q : GCCBuiltin<"__builtin_ia32_psllq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrl_d : GCCBuiltin<"__builtin_ia32_psrld512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psra_d : GCCBuiltin<"__builtin_ia32_psrad512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psra_q : GCCBuiltin<"__builtin_ia32_psraq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Pack ops.
@@ -1706,13 +1748,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v32i8_ty], [IntrNoMem]>;
def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx2_pblendd_128 : GCCBuiltin<"__builtin_ia32_pblendd128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ llvm_i8_ty], [IntrNoMem]>;
}
// Vector load with broadcast
@@ -1787,6 +1829,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_vinserti128 : GCCBuiltin<"__builtin_ia32_insert128i256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_vextractf32x4_512 :
+ GCCBuiltin<"__builtin_ia32_extractf32x4_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v16f32_ty, llvm_i8_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vextracti32x4_512 :
+ GCCBuiltin<"__builtin_ia32_extracti32x4_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v16i32_ty, llvm_i8_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vextractf64x4_512 :
+ GCCBuiltin<"__builtin_ia32_extractf64x4_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v8f64_ty, llvm_i8_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vextracti64x4_512 :
+ GCCBuiltin<"__builtin_ia32_extracti64x4_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i64_ty, llvm_i8_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Conditional load ops
@@ -1871,6 +1930,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty],
[IntrNoMem]>;
+
+ def int_x86_avx512_mask_psllv_d : GCCBuiltin<"__builtin_ia32_psllv16si_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psllv_q : GCCBuiltin<"__builtin_ia32_psllv8di_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psrav_d : GCCBuiltin<"__builtin_ia32_psrav16si_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psrav_q : GCCBuiltin<"__builtin_ia32_psrav8di_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv16si_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv8di_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
}
// Gather ops
@@ -1951,11 +2035,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v32i8_ty], [IntrNoMem]>;
def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
- llvm_i32_ty], [IntrNoMem, Commutative]>;
+ llvm_i8_ty], [IntrNoMem, Commutative]>;
def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">,
Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
- def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
//===----------------------------------------------------------------------===//
@@ -1986,13 +2068,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512">,
+ def int_x86_fma_mask_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512">,
+ def int_x86_fma_mask_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">,
Intrinsic<[llvm_v4f32_ty],
@@ -2018,13 +2122,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512">,
+ def int_x86_fma_mask_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512">,
+ def int_x86_fma_mask_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">,
Intrinsic<[llvm_v4f32_ty],
@@ -2050,13 +2176,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512">,
+ def int_x86_fma_mask_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_fma_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512">,
+ def int_x86_fma_mask_vfnmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">,
Intrinsic<[llvm_v4f32_ty],
@@ -2082,13 +2230,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512">,
+ def int_x86_fma_mask_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_fma_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512">,
+ def int_x86_fma_mask_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">,
Intrinsic<[llvm_v4f32_ty],
@@ -2108,13 +2278,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512">,
+ def int_x86_fma_mask_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmaddsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmaddsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512">,
+ def int_x86_fma_mask_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmaddsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmaddsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">,
Intrinsic<[llvm_v4f32_ty],
@@ -2134,13 +2326,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512">,
+ def int_x86_fma_mask_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsubadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512">,
+ def int_x86_fma_mask_vfmsubadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsubadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
}
@@ -2749,6 +2963,30 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
}
//===----------------------------------------------------------------------===//
+// ADX
+
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_addcarryx_u32: GCCBuiltin<"__builtin_ia32_addcarryx_u32">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_addcarryx_u64: GCCBuiltin<"__builtin_ia32_addcarryx_u64">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_addcarry_u32: GCCBuiltin<"__builtin_ia32_addcarry_u32">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_addcarry_u64: GCCBuiltin<"__builtin_ia32_addcarry_u64">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_subborrow_u32: GCCBuiltin<"__builtin_ia32_subborrow_u32">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_subborrow_u64: GCCBuiltin<"__builtin_ia32_subborrow_u64">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+}
+
+//===----------------------------------------------------------------------===//
// RTM intrinsics. Transactional Memory support.
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
@@ -2955,10 +3193,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty],
[IntrNoMem]>;
- def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512">,
- Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], [IntrNoMem]>;
- def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512">,
- Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], [IntrNoMem]>;
+ def int_x86_avx512_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_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_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
@@ -2993,6 +3233,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_rcp28_pd : GCCBuiltin<"__builtin_ia32_rcp28pd_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_exp2_ps : GCCBuiltin<"__builtin_ia32_exp2ps_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_exp2_pd : GCCBuiltin<"__builtin_ia32_exp2pd_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+
def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty],
@@ -3167,10 +3414,26 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16f32_ty],
[llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
[IntrNoMem]>;
+ def int_x86_avx512_mask_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendmps_256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_ps_128 : GCCBuiltin<"__builtin_ia32_blendmps_128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrNoMem]>;
+ def int_x86_avx512_mask_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendmpd_256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_pd_128 : GCCBuiltin<"__builtin_ia32_blendmpd_128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">,
Intrinsic<[llvm_v16i32_ty],
@@ -3180,8 +3443,428 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
+ def int_x86_avx512_mask_blend_d_256 : GCCBuiltin<"__builtin_ia32_blendmd_256_mask">,
+ Intrinsic<[llvm_v8i32_ty],
+ [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_q_256 : GCCBuiltin<"__builtin_ia32_blendmq_256_mask">,
+ Intrinsic<[llvm_v4i64_ty],
+ [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_d_128 : GCCBuiltin<"__builtin_ia32_blendmd_128_mask">,
+ Intrinsic<[llvm_v4i32_ty],
+ [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_q_128 : GCCBuiltin<"__builtin_ia32_blendmq_128_mask">,
+ Intrinsic<[llvm_v2i64_ty],
+ [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_blend_w_512 : GCCBuiltin<"__builtin_ia32_blendmw_512_mask">,
+ Intrinsic<[llvm_v32i16_ty],
+ [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_w_256 : GCCBuiltin<"__builtin_ia32_blendmw_256_mask">,
+ Intrinsic<[llvm_v16i16_ty],
+ [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_w_128 : GCCBuiltin<"__builtin_ia32_blendmw_128_mask">,
+ Intrinsic<[llvm_v8i16_ty],
+ [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_b_512 : GCCBuiltin<"__builtin_ia32_blendmb_512_mask">,
+ Intrinsic<[llvm_v64i8_ty],
+ [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_b_256 : GCCBuiltin<"__builtin_ia32_blendmb_256_mask">,
+ Intrinsic<[llvm_v32i8_ty],
+ [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_b_128 : GCCBuiltin<"__builtin_ia32_blendmb_128_mask">,
+ Intrinsic<[llvm_v16i8_ty],
+ [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+
+}
+
+let TargetPrefix = "x86" in {
+ def int_x86_avx512_mask_valign_q_512 : GCCBuiltin<"__builtin_ia32_alignq512_mask">,
+ Intrinsic<[llvm_v8i64_ty],
+ [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_valign_d_512 : GCCBuiltin<"__builtin_ia32_alignd512_mask">,
+ Intrinsic<[llvm_v16i32_ty],
+ [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
}
+// Compares
+let TargetPrefix = "x86" in {
+ // 512-bit
+ def int_x86_avx512_mask_pcmpeq_b_512 : GCCBuiltin<"__builtin_ia32_pcmpeqb512_mask">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_w_512 : GCCBuiltin<"__builtin_ia32_pcmpeqw512_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pcmpgt_b_512: GCCBuiltin<"__builtin_ia32_pcmpgtb512_mask">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_w_512: GCCBuiltin<"__builtin_ia32_pcmpgtw512_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_d_512: GCCBuiltin<"__builtin_ia32_pcmpgtd512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_q_512: GCCBuiltin<"__builtin_ia32_pcmpgtq512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty,
+ llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem ]>;
+ def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty,
+ llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ // 256-bit
+ def int_x86_avx512_mask_pcmpeq_b_256 : GCCBuiltin<"__builtin_ia32_pcmpeqb256_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_w_256 : GCCBuiltin<"__builtin_ia32_pcmpeqw256_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_d_256 : GCCBuiltin<"__builtin_ia32_pcmpeqd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_q_256 : GCCBuiltin<"__builtin_ia32_pcmpeqq256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pcmpgt_b_256: GCCBuiltin<"__builtin_ia32_pcmpgtb256_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_w_256: GCCBuiltin<"__builtin_ia32_pcmpgtw256_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_d_256: GCCBuiltin<"__builtin_ia32_pcmpgtd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_q_256: GCCBuiltin<"__builtin_ia32_pcmpgtq256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ // 128-bit
+ def int_x86_avx512_mask_pcmpeq_b_128 : GCCBuiltin<"__builtin_ia32_pcmpeqb128_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_w_128 : GCCBuiltin<"__builtin_ia32_pcmpeqw128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_d_128 : GCCBuiltin<"__builtin_ia32_pcmpeqd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_q_128 : GCCBuiltin<"__builtin_ia32_pcmpeqq128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pcmpgt_b_128: GCCBuiltin<"__builtin_ia32_pcmpgtb128_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_w_128: GCCBuiltin<"__builtin_ia32_pcmpgtw128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_d_128: GCCBuiltin<"__builtin_ia32_pcmpgtd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_q_128: GCCBuiltin<"__builtin_ia32_pcmpgtq128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+}
+
+// Compress, Expand
+let TargetPrefix = "x86" in {
+ def int_x86_avx512_mask_compress_ps_512 :
+ GCCBuiltin<"__builtin_ia32_compresssf512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_pd_512 :
+ GCCBuiltin<"__builtin_ia32_compressdf512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_ps_256 :
+ GCCBuiltin<"__builtin_ia32_compresssf256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_pd_256 :
+ GCCBuiltin<"__builtin_ia32_compressdf256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_ps_128 :
+ GCCBuiltin<"__builtin_ia32_compresssf128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_pd_128 :
+ GCCBuiltin<"__builtin_ia32_compressdf128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_compress_store_ps_512 :
+ GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty,
+ llvm_i16_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_pd_512 :
+ GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_ps_256 :
+ GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_pd_256 :
+ GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_ps_128 :
+ GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_pd_128 :
+ GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+
+ def int_x86_avx512_mask_compress_d_512 :
+ GCCBuiltin<"__builtin_ia32_compresssi512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_q_512 :
+ GCCBuiltin<"__builtin_ia32_compressdi512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_d_256 :
+ GCCBuiltin<"__builtin_ia32_compresssi256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_q_256 :
+ GCCBuiltin<"__builtin_ia32_compressdi256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_d_128 :
+ GCCBuiltin<"__builtin_ia32_compresssi128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_q_128 :
+ GCCBuiltin<"__builtin_ia32_compressdi128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_compress_store_d_512 :
+ GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty,
+ llvm_i16_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_q_512 :
+ GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_d_256 :
+ GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_q_256 :
+ GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_d_128 :
+ GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_q_128 :
+ GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+
+// expand
+ def int_x86_avx512_mask_expand_ps_512 :
+ GCCBuiltin<"__builtin_ia32_expandsf512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_pd_512 :
+ GCCBuiltin<"__builtin_ia32_expanddf512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_ps_256 :
+ GCCBuiltin<"__builtin_ia32_expandsf256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_pd_256 :
+ GCCBuiltin<"__builtin_ia32_expanddf256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_ps_128 :
+ GCCBuiltin<"__builtin_ia32_expandsf128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_pd_128 :
+ GCCBuiltin<"__builtin_ia32_expanddf128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_expand_load_ps_512 :
+ GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty,
+ llvm_i16_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_pd_512 :
+ GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_ps_256 :
+ GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_pd_256 :
+ GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_ps_128 :
+ GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_pd_128 :
+ GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+
+ def int_x86_avx512_mask_expand_d_512 :
+ GCCBuiltin<"__builtin_ia32_expandsi512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_q_512 :
+ GCCBuiltin<"__builtin_ia32_expanddi512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_d_256 :
+ GCCBuiltin<"__builtin_ia32_expandsi256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_q_256 :
+ GCCBuiltin<"__builtin_ia32_expanddi256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_d_128 :
+ GCCBuiltin<"__builtin_ia32_expandsi128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_q_128 :
+ GCCBuiltin<"__builtin_ia32_expanddi128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_expand_load_d_512 :
+ GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty,
+ llvm_i16_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_q_512 :
+ GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_d_256 :
+ GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_q_256 :
+ GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_d_128 :
+ GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_q_128 :
+ GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+
+}
// Misc.
let TargetPrefix = "x86" in {
def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">,
@@ -3190,13 +3873,6 @@ let TargetPrefix = "x86" in {
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_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
llvm_v16i32_ty, llvm_i16_ty],
@@ -3205,6 +3881,8 @@ let TargetPrefix = "x86" in {
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
+ def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h
index 4d940d599b9a..2f18782a0730 100644
--- a/include/llvm/IR/LLVMContext.h
+++ b/include/llvm/IR/LLVMContext.h
@@ -18,6 +18,7 @@
#include "llvm-c/Core.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Options.h"
namespace llvm {
@@ -52,7 +53,12 @@ public:
MD_fpmath = 3, // "fpmath"
MD_range = 4, // "range"
MD_tbaa_struct = 5, // "tbaa.struct"
- MD_invariant_load = 6 // "invariant.load"
+ MD_invariant_load = 6, // "invariant.load"
+ MD_alias_scope = 7, // "alias.scope"
+ MD_noalias = 8, // "noalias",
+ MD_nontemporal = 9, // "nontemporal"
+ MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access"
+ MD_nonnull = 11 // "nonnull"
};
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
@@ -97,12 +103,14 @@ public:
/// setDiagnosticHandler - This method sets a handler that is invoked
/// when the backend needs to report anything to the user. The first
/// argument is a function pointer and the second is a context pointer that
- /// gets passed into the DiagHandler.
+ /// gets passed into the DiagHandler. The third argument should be set to
+ /// true if the handler only expects enabled diagnostics.
///
/// LLVMContext doesn't take ownership or interpret either of these
/// pointers.
void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler,
- void *DiagContext = nullptr);
+ void *DiagContext = nullptr,
+ bool RespectFilters = false);
/// getDiagnosticHandler - Return the diagnostic handler set by
/// setDiagnosticHandler.
@@ -112,14 +120,16 @@ public:
/// setDiagnosticContext.
void *getDiagnosticContext() const;
- /// diagnose - Report a message to the currently installed diagnostic handler.
+ /// \brief Report a message to the currently installed diagnostic handler.
+ ///
/// This function returns, in particular in the case of error reporting
- /// (DI.Severity == RS_Error), so the caller should leave the compilation
+ /// (DI.Severity == \a DS_Error), so the caller should leave the compilation
/// process in a self-consistent state, even though the generated code
/// need not be correct.
- /// The diagnostic message will be implicitly prefixed with a severity
- /// keyword according to \p DI.getSeverity(), i.e., "error: "
- /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note.
+ ///
+ /// The diagnostic message will be implicitly prefixed with a severity keyword
+ /// according to \p DI.getSeverity(), i.e., "error: " for \a DS_Error,
+ /// "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.
@@ -157,6 +167,14 @@ public:
void emitError(const Instruction *I, const Twine &ErrorStr);
void emitError(const Twine &ErrorStr);
+ /// \brief 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)>
+ ValT getOption() const {
+ return OptionRegistry::instance().template get<ValT, Base, Mem>();
+ }
+
private:
LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
diff --git a/include/llvm/IR/LeakDetector.h b/include/llvm/IR/LeakDetector.h
deleted file mode 100644
index cb18df875867..000000000000
--- a/include/llvm/IR/LeakDetector.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a class that can be used to provide very simple memory leak
-// checks for an API. Basically LLVM uses this to make sure that Instructions,
-// for example, are deleted when they are supposed to be, and not leaked away.
-//
-// When compiling with NDEBUG (Release build), this class does nothing, thus
-// adding no checking overhead to release builds. Note that this class is
-// implemented in a very simple way, requiring completely manual manipulation
-// and checking for garbage, but this is intentional: users should not be using
-// this API, only other APIs should.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_IR_LEAKDETECTOR_H
-#define LLVM_IR_LEAKDETECTOR_H
-
-#include <string>
-
-namespace llvm {
-
-class LLVMContext;
-class Value;
-
-struct LeakDetector {
- /// addGarbageObject - Add a pointer to the internal set of "garbage" object
- /// pointers. This should be called when objects are created, or if they are
- /// taken out of an owning collection.
- ///
- static void addGarbageObject(void *Object) {
-#ifndef NDEBUG
- addGarbageObjectImpl(Object);
-#endif
- }
-
- /// removeGarbageObject - Remove a pointer from our internal representation of
- /// our "garbage" objects. This should be called when an object is added to
- /// an "owning" collection.
- ///
- static void removeGarbageObject(void *Object) {
-#ifndef NDEBUG
- removeGarbageObjectImpl(Object);
-#endif
- }
-
- /// checkForGarbage - Traverse the internal representation of garbage
- /// pointers. If there are any pointers that have been add'ed, but not
- /// remove'd, big obnoxious warnings about memory leaks are issued.
- ///
- /// The specified message will be printed indicating when the check was
- /// performed.
- ///
- static void checkForGarbage(LLVMContext &C, const std::string &Message) {
-#ifndef NDEBUG
- checkForGarbageImpl(C, Message);
-#endif
- }
-
- /// Overload the normal methods to work better with Value*'s because they are
- /// by far the most common in LLVM. This does not affect the actual
- /// functioning of this class, it just makes the warning messages nicer.
- ///
- static void addGarbageObject(const Value *Object) {
-#ifndef NDEBUG
- addGarbageObjectImpl(Object);
-#endif
- }
- static void removeGarbageObject(const Value *Object) {
-#ifndef NDEBUG
- removeGarbageObjectImpl(Object);
-#endif
- }
-
-private:
- // If we are debugging, the actual implementations will be called...
- static void addGarbageObjectImpl(const Value *Object);
- static void removeGarbageObjectImpl(const Value *Object);
- static void addGarbageObjectImpl(void *Object);
- static void removeGarbageObjectImpl(void *Object);
- static void checkForGarbageImpl(LLVMContext &C, const std::string &Message);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h
index c967a6bca8b2..6c04e9dc3d3f 100644
--- a/include/llvm/IR/LegacyPassManager.h
+++ b/include/llvm/IR/LegacyPassManager.h
@@ -37,9 +37,10 @@ class PassManagerBase {
public:
virtual ~PassManagerBase();
- /// add - Add a pass to the queue of passes to run. This passes ownership of
+ /// Add a pass to the queue of passes to run. This passes ownership of
/// the Pass to the PassManager. When the PassManager is destroyed, the pass
/// will be destroyed as well, so there is no need to delete the pass. This
+ /// may even destroy the pass right away if it is found to be redundant. This
/// implies that all passes MUST be allocated with 'new'.
virtual void add(Pass *P) = 0;
};
@@ -51,10 +52,6 @@ public:
PassManager();
~PassManager();
- /// add - Add a pass to the queue of passes to run. This passes ownership of
- /// the Pass to the PassManager. When the PassManager is destroyed, the pass
- /// will be destroyed as well, so there is no need to delete the pass. This
- /// implies that all passes MUST be allocated with 'new'.
void add(Pass *P) override;
/// run - Execute all of the passes scheduled for execution. Keep track of
@@ -75,11 +72,6 @@ public:
explicit FunctionPassManager(Module *M);
~FunctionPassManager();
- /// add - Add a pass to the queue of passes to run. This passes
- /// ownership of the Pass to the PassManager. When the
- /// PassManager_X is destroyed, the pass will be destroyed as well, so
- /// there is no need to delete the pass.
- /// This implies that all passes MUST be allocated with 'new'.
void add(Pass *P) override;
/// run - Execute all of the passes scheduled for execution. Keep
diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h
index f6065a4e21a6..ab500a1dd2a3 100644
--- a/include/llvm/IR/LegacyPassManagers.h
+++ b/include/llvm/IR/LegacyPassManagers.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PASSMANAGERS_H
-#define LLVM_PASSMANAGERS_H
+#ifndef LLVM_IR_LEGACYPASSMANAGERS_H
+#define LLVM_IR_LEGACYPASSMANAGERS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -61,7 +61,7 @@
//
// [o] class FunctionPassManager;
//
-// This is a external interface used by JIT to manage FunctionPasses. This
+// This is a external interface used to manage FunctionPasses. This
// interface relies on FunctionPassManagerImpl to do all the tasks.
//
// [o] class FunctionPassManagerImpl : public ModulePass, PMDataManager,
@@ -248,7 +248,7 @@ private:
DenseMap<Pass *, SmallPtrSet<Pass *, 8> > InversedLastUser;
/// Immutable passes are managed by top level manager.
- SmallVector<ImmutablePass *, 8> ImmutablePasses;
+ SmallVector<ImmutablePass *, 16> ImmutablePasses;
DenseMap<Pass *, AnalysisUsage *> AnUsageMap;
};
@@ -393,7 +393,7 @@ private:
// Collection of higher level analysis used by the pass managed by
// this manager.
- SmallVector<Pass *, 8> HigherLevelAnalysis;
+ SmallVector<Pass *, 16> HigherLevelAnalysis;
unsigned Depth;
};
diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h
index 37d263bf52a8..91a6685f6125 100644
--- a/include/llvm/IR/MDBuilder.h
+++ b/include/llvm/IR/MDBuilder.h
@@ -15,6 +15,7 @@
#ifndef LLVM_IR_MDBUILDER_H
#define LLVM_IR_MDBUILDER_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include <utility>
@@ -23,9 +24,10 @@ namespace llvm {
class APInt;
template <typename T> class ArrayRef;
class LLVMContext;
+class Constant;
+class ConstantAsMetadata;
class MDNode;
class MDString;
-class StringRef;
class MDBuilder {
LLVMContext &Context;
@@ -36,6 +38,9 @@ public:
/// \brief Return the given string as metadata.
MDString *createString(StringRef Str);
+ /// \brief Return the given constant as metadata.
+ ConstantAsMetadata *createConstant(Constant *C);
+
//===------------------------------------------------------------------===//
// FPMath metadata.
//===------------------------------------------------------------------===//
@@ -63,19 +68,54 @@ public:
MDNode *createRange(const APInt &Lo, const APInt &Hi);
//===------------------------------------------------------------------===//
- // TBAA metadata.
+ // AA metadata.
//===------------------------------------------------------------------===//
- /// \brief Return metadata appropriate for a TBAA root node. Each returned
+protected:
+ /// \brief 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
/// node is distinct from all other metadata and will never be identified
/// (uniqued) with anything else.
- MDNode *createAnonymousTBAARoot();
+ MDNode *createAnonymousTBAARoot() {
+ return createAnonymousAARoot();
+ }
+
+ /// \brief 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.
+ /// Each returned node is distinct from all other metadata and will never
+ /// be identified (uniqued) with anything else.
+ MDNode *createAnonymousAliasScope(MDNode *Domain,
+ StringRef Name = StringRef()) {
+ return createAnonymousAARoot(Name, Domain);
+ }
/// \brief 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
+ /// 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
+ /// 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,
/// parent in the TBAA tree, and value for 'pointsToConstantMemory'.
MDNode *createTBAANode(StringRef Name, MDNode *Parent,
diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h
index c1ba5858a612..1e6b5b1dca00 100644
--- a/include/llvm/IR/Mangler.h
+++ b/include/llvm/IR/Mangler.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TARGET_MANGLER_H
-#define LLVM_TARGET_MANGLER_H
+#ifndef LLVM_IR_MANGLER_H
+#define LLVM_IR_MANGLER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/raw_ostream.h"
@@ -66,4 +66,4 @@ public:
} // End llvm namespace
-#endif // LLVM_TARGET_MANGLER_H
+#endif
diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def
new file mode 100644
index 000000000000..2098bb57eb56
--- /dev/null
+++ b/include/llvm/IR/Metadata.def
@@ -0,0 +1,59 @@
+//===- llvm/Metadata.def - Metadata definitions -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Macros for running through all types of metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \
+ defined HANDLE_METADATA_BRANCH || defined HANDLE_UNIQUABLE_LEAF || \
+ defined HANDLE_UNIQUABLE_BRANCH)
+#error "Missing macro definition of HANDLE_METADATA*"
+#endif
+
+// Handler for all types of metadata.
+#ifndef HANDLE_METADATA
+#define HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for leaf nodes in the class hierarchy.
+#ifndef HANDLE_METADATA_LEAF
+#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for non-leaf nodes in the class hierarchy.
+#ifndef HANDLE_METADATA_BRANCH
+#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for leaf nodes under UniquableMDNode.
+#ifndef HANDLE_UNIQUABLE_LEAF
+#define HANDLE_UNIQUABLE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS)
+#endif
+
+// Handler for non-leaf nodes under UniquableMDNode.
+#ifndef HANDLE_UNIQUABLE_BRANCH
+#define HANDLE_UNIQUABLE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS)
+#endif
+
+HANDLE_METADATA_LEAF(MDString)
+HANDLE_METADATA_BRANCH(ValueAsMetadata)
+HANDLE_METADATA_LEAF(ConstantAsMetadata)
+HANDLE_METADATA_LEAF(LocalAsMetadata)
+HANDLE_METADATA_BRANCH(MDNode)
+HANDLE_METADATA_LEAF(MDNodeFwdDecl)
+HANDLE_UNIQUABLE_BRANCH(UniquableMDNode)
+HANDLE_UNIQUABLE_LEAF(MDTuple)
+HANDLE_UNIQUABLE_LEAF(MDLocation)
+
+#undef HANDLE_METADATA
+#undef HANDLE_METADATA_LEAF
+#undef HANDLE_METADATA_BRANCH
+#undef HANDLE_UNIQUABLE_LEAF
+#undef HANDLE_UNIQUABLE_BRANCH
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index 7a0ca887201b..3bf6d38d311d 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -17,10 +17,14 @@
#define LLVM_IR_METADATA_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/MetadataTracking.h"
#include "llvm/IR/Value.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <type_traits>
namespace llvm {
class LLVMContext;
@@ -30,169 +34,887 @@ template<typename ValueSubClass, typename ItemParentClass>
enum LLVMConstants : uint32_t {
- DEBUG_METADATA_VERSION = 1 // Current debug info version number.
+ DEBUG_METADATA_VERSION = 2 // Current debug info version number.
};
+/// \brief Root of the metadata hierarchy.
+///
+/// This is a root class for typeless data in the IR.
+class Metadata {
+ friend class ReplaceableMetadataImpl;
+
+ /// \brief RTTI.
+ const unsigned char SubclassID;
+
+protected:
+ /// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
+ bool IsDistinctInContext : 1;
+ // TODO: expose remaining bits to subclasses.
+
+ unsigned short SubclassData16;
+ unsigned SubclassData32;
+
+public:
+ enum MetadataKind {
+ MDTupleKind,
+ MDLocationKind,
+ MDNodeFwdDeclKind,
+ ConstantAsMetadataKind,
+ LocalAsMetadataKind,
+ MDStringKind
+ };
+
+protected:
+ Metadata(unsigned ID)
+ : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0),
+ SubclassData32(0) {}
+ ~Metadata() {}
+
+ /// \brief Store this in a big non-uniqued untyped bucket.
+ bool isStoredDistinctInContext() const { return IsDistinctInContext; }
+
+ /// \brief Default handling of a changed operand, which asserts.
+ ///
+ /// If subclasses pass themselves in as owners to a tracking node reference,
+ /// they must provide an implementation of this method.
+ void handleChangedOperand(void *, Metadata *) {
+ llvm_unreachable("Unimplemented in Metadata subclass");
+ }
+
+public:
+ unsigned getMetadataID() const { return SubclassID; }
+
+ /// \brief User-friendly dump.
+ void dump() const;
+ void print(raw_ostream &OS) const;
+ void printAsOperand(raw_ostream &OS, bool PrintType = true,
+ const Module *M = nullptr) const;
+};
+
+#define HANDLE_METADATA(CLASS) class CLASS;
+#include "llvm/IR/Metadata.def"
+
+inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) {
+ MD.print(OS);
+ return OS;
+}
+
+/// \brief Metadata wrapper in the Value hierarchy.
+///
+/// A member of the \a Value hierarchy to represent a reference to metadata.
+/// This allows, e.g., instrinsics to have metadata as operands.
+///
+/// Notably, this is the only thing in either hierarchy that is allowed to
+/// reference \a LocalAsMetadata.
+class MetadataAsValue : public Value {
+ friend class ReplaceableMetadataImpl;
+ friend class LLVMContextImpl;
+
+ Metadata *MD;
+
+ MetadataAsValue(Type *Ty, Metadata *MD);
+ ~MetadataAsValue();
+
+ /// \brief Drop use of metadata (during teardown).
+ void dropUse() { MD = nullptr; }
+
+public:
+ static MetadataAsValue *get(LLVMContext &Context, Metadata *MD);
+ static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD);
+ Metadata *getMetadata() const { return MD; }
+
+ static bool classof(const Value *V) {
+ return V->getValueID() == MetadataAsValueVal;
+ }
+
+private:
+ void handleChangedMetadata(Metadata *MD);
+ void track();
+ void untrack();
+};
+
+/// \brief Shared implementation of use-lists for replaceable metadata.
+///
+/// Most metadata cannot be RAUW'ed. This is a shared implementation of
+/// use-lists and associated API for the two that support it (\a ValueAsMetadata
+/// and \a TempMDNode).
+class ReplaceableMetadataImpl {
+ friend class MetadataTracking;
+
+public:
+ typedef MetadataTracking::OwnerTy OwnerTy;
+
+private:
+ uint64_t NextIndex;
+ SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
+
+public:
+ ReplaceableMetadataImpl() : NextIndex(0) {}
+ ~ReplaceableMetadataImpl() {
+ assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
+ }
+
+ /// \brief Replace all uses of this with MD.
+ ///
+ /// Replace all uses of this with \c MD, which is allowed to be null.
+ void replaceAllUsesWith(Metadata *MD);
+
+ /// \brief Resolve all uses of this.
+ ///
+ /// Resolve all uses of this, turning off RAUW permanently. If \c
+ /// ResolveUsers, call \a UniquableMDNode::resolve() on any users whose last
+ /// operand is resolved.
+ void resolveAllUses(bool ResolveUsers = true);
+
+private:
+ void addRef(void *Ref, OwnerTy Owner);
+ void dropRef(void *Ref);
+ void moveRef(void *Ref, void *New, const Metadata &MD);
+
+ static ReplaceableMetadataImpl *get(Metadata &MD);
+};
+
+/// \brief Value wrapper in the Metadata hierarchy.
+///
+/// This is a custom value handle that allows other metadata to refer to
+/// classes in the Value hierarchy.
+///
+/// Because of full uniquing support, each value is only wrapped by a single \a
+/// ValueAsMetadata object, so the lookup maps are far more efficient than
+/// those using ValueHandleBase.
+class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl {
+ friend class ReplaceableMetadataImpl;
+ friend class LLVMContextImpl;
+
+ Value *V;
+
+ /// \brief Drop users without RAUW (during teardown).
+ void dropUsers() {
+ ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false);
+ }
+
+protected:
+ ValueAsMetadata(unsigned ID, Value *V)
+ : Metadata(ID), V(V) {
+ assert(V && "Expected valid value");
+ }
+ ~ValueAsMetadata() {}
+
+public:
+ static ValueAsMetadata *get(Value *V);
+ static ConstantAsMetadata *getConstant(Value *C) {
+ return cast<ConstantAsMetadata>(get(C));
+ }
+ static LocalAsMetadata *getLocal(Value *Local) {
+ return cast<LocalAsMetadata>(get(Local));
+ }
+
+ static ValueAsMetadata *getIfExists(Value *V);
+ static ConstantAsMetadata *getConstantIfExists(Value *C) {
+ return cast_or_null<ConstantAsMetadata>(getIfExists(C));
+ }
+ static LocalAsMetadata *getLocalIfExists(Value *Local) {
+ return cast_or_null<LocalAsMetadata>(getIfExists(Local));
+ }
+
+ Value *getValue() const { return V; }
+ Type *getType() const { return V->getType(); }
+ LLVMContext &getContext() const { return V->getContext(); }
+
+ static void handleDeletion(Value *V);
+ static void handleRAUW(Value *From, Value *To);
+
+protected:
+ /// \brief Handle collisions after \a Value::replaceAllUsesWith().
+ ///
+ /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped
+ /// \a Value gets RAUW'ed and the target already exists, this is used to
+ /// merge the two metadata nodes.
+ void replaceAllUsesWith(Metadata *MD) {
+ ReplaceableMetadataImpl::replaceAllUsesWith(MD);
+ }
+
+public:
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == LocalAsMetadataKind ||
+ MD->getMetadataID() == ConstantAsMetadataKind;
+ }
+};
+
+class ConstantAsMetadata : public ValueAsMetadata {
+ friend class ValueAsMetadata;
+
+ ConstantAsMetadata(Constant *C)
+ : ValueAsMetadata(ConstantAsMetadataKind, C) {}
+
+public:
+ static ConstantAsMetadata *get(Constant *C) {
+ return ValueAsMetadata::getConstant(C);
+ }
+ static ConstantAsMetadata *getIfExists(Constant *C) {
+ return ValueAsMetadata::getConstantIfExists(C);
+ }
+
+ Constant *getValue() const {
+ return cast<Constant>(ValueAsMetadata::getValue());
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == ConstantAsMetadataKind;
+ }
+};
+
+class LocalAsMetadata : public ValueAsMetadata {
+ friend class ValueAsMetadata;
+
+ LocalAsMetadata(Value *Local)
+ : ValueAsMetadata(LocalAsMetadataKind, Local) {
+ assert(!isa<Constant>(Local) && "Expected local value");
+ }
+
+public:
+ static LocalAsMetadata *get(Value *Local) {
+ return ValueAsMetadata::getLocal(Local);
+ }
+ static LocalAsMetadata *getIfExists(Value *Local) {
+ return ValueAsMetadata::getLocalIfExists(Local);
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == LocalAsMetadataKind;
+ }
+};
+
+/// \brief Transitional API for extracting constants from Metadata.
+///
+/// This namespace contains transitional functions for metadata that points to
+/// \a Constants.
+///
+/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode
+/// operands could refer to any \a Value. There's was a lot of code like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *CI = dyn_cast<ConstantInt>(N->getOperand(2));
+/// \endcode
+///
+/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining
+/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three
+/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and
+/// cast in the \a Value hierarchy. Besides creating boiler-plate, this
+/// requires subtle control flow changes.
+///
+/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt,
+/// so that metadata can refer to numbers without traversing a bridge to the \a
+/// Value hierarchy. In this final state, the code above would look like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *MI = dyn_cast<MDInt>(N->getOperand(2));
+/// \endcode
+///
+/// The API in this namespace supports the transition. \a MDInt doesn't exist
+/// yet, and even once it does, changing each metadata schema to use it is its
+/// own mini-project. In the meantime this API prevents us from introducing
+/// complex and bug-prone control flow that will disappear in the end. In
+/// particular, the above code looks like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *CI = mdconst::dyn_extract<ConstantInt>(N->getOperand(2));
+/// \endcode
+///
+/// The full set of provided functions includes:
+///
+/// mdconst::hasa <=> isa
+/// mdconst::extract <=> cast
+/// mdconst::extract_or_null <=> cast_or_null
+/// mdconst::dyn_extract <=> dyn_cast
+/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null
+///
+/// The target of the cast must be a subclass of \a Constant.
+namespace mdconst {
+
+namespace detail {
+template <class T> T &make();
+template <class T, class Result> struct HasDereference {
+ typedef char Yes[1];
+ typedef char No[2];
+ template <size_t N> struct SFINAE {};
+
+ template <class U, class V>
+ static Yes &hasDereference(SFINAE<sizeof(static_cast<V>(*make<U>()))> * = 0);
+ template <class U, class V> static No &hasDereference(...);
+
+ static const bool value =
+ sizeof(hasDereference<T, Result>(nullptr)) == sizeof(Yes);
+};
+template <class V, class M> struct IsValidPointer {
+ static const bool value = std::is_base_of<Constant, V>::value &&
+ HasDereference<M, const Metadata &>::value;
+};
+template <class V, class M> struct IsValidReference {
+ static const bool value = std::is_base_of<Constant, V>::value &&
+ std::is_convertible<M, const Metadata &>::value;
+};
+} // end namespace detail
+
+/// \brief Check whether Metadata has a Value.
+///
+/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of
+/// type \c X.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, bool>::type
+hasa(Y &&MD) {
+ assert(MD && "Null pointer sent into hasa");
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+ return isa<X>(V->getValue());
+ return false;
+}
+template <class X, class Y>
+inline
+ typename std::enable_if<detail::IsValidReference<X, Y &>::value, bool>::type
+ hasa(Y &MD) {
+ return hasa(&MD);
+}
+
+/// \brief Extract a Value from Metadata.
+///
+/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract(Y &&MD) {
+ return cast<X>(cast<ConstantAsMetadata>(MD)->getValue());
+}
+template <class X, class Y>
+inline
+ typename std::enable_if<detail::IsValidReference<X, Y &>::value, X *>::type
+ extract(Y &MD) {
+ return extract(&MD);
+}
+
+/// \brief Extract a Value from Metadata, allowing null.
+///
+/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, allowing \c MD to be null.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract_or_null(Y &&MD) {
+ if (auto *V = cast_or_null<ConstantAsMetadata>(MD))
+ return cast<X>(V->getValue());
+ return nullptr;
+}
+
+/// \brief Extract a Value from Metadata, if any.
+///
+/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a
+/// Value it does contain is of the wrong subclass.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract(Y &&MD) {
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+ return dyn_cast<X>(V->getValue());
+ return nullptr;
+}
+
+/// \brief Extract a Value from Metadata, if any, allowing null.
+///
+/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a
+/// Value it does contain is of the wrong subclass, allowing \c MD to be null.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract_or_null(Y &&MD) {
+ if (auto *V = dyn_cast_or_null<ConstantAsMetadata>(MD))
+ return dyn_cast<X>(V->getValue());
+ return nullptr;
+}
+
+} // end namespace mdconst
+
//===----------------------------------------------------------------------===//
-/// MDString - a single uniqued string.
+/// \brief A single uniqued string.
+///
/// These are used to efficiently contain a byte sequence for metadata.
/// MDString is always unnamed.
-class MDString : public Value {
- virtual void anchor();
+class MDString : public Metadata {
+ friend class StringMapEntry<MDString>;
+
MDString(const MDString &) LLVM_DELETED_FUNCTION;
+ MDString &operator=(MDString &&) LLVM_DELETED_FUNCTION;
+ MDString &operator=(const MDString &) LLVM_DELETED_FUNCTION;
+
+ StringMapEntry<MDString> *Entry;
+ MDString() : Metadata(MDStringKind), Entry(nullptr) {}
+ MDString(MDString &&) : Metadata(MDStringKind) {}
- explicit MDString(LLVMContext &C);
public:
static MDString *get(LLVMContext &Context, StringRef Str);
static MDString *get(LLVMContext &Context, const char *Str) {
return get(Context, Str ? StringRef(Str) : StringRef());
}
- StringRef getString() const { return getName(); }
+ StringRef getString() const;
- unsigned getLength() const { return (unsigned)getName().size(); }
+ unsigned getLength() const { return (unsigned)getString().size(); }
typedef StringRef::iterator iterator;
- /// begin() - Pointer to the first byte of the string.
- iterator begin() const { return getName().begin(); }
+ /// \brief Pointer to the first byte of the string.
+ iterator begin() const { return getString().begin(); }
- /// end() - Pointer to one byte past the end of the string.
- iterator end() const { return getName().end(); }
+ /// \brief Pointer to one byte past the end of the string.
+ iterator end() const { return getString().end(); }
- /// Methods for support type inquiry through isa, cast, and dyn_cast:
- static bool classof(const Value *V) {
- return V->getValueID() == MDStringVal;
+ const unsigned char *bytes_begin() const { return getString().bytes_begin(); }
+ const unsigned char *bytes_end() const { return getString().bytes_end(); }
+
+ /// \brief Methods for support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDStringKind;
}
};
+/// \brief 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,
+ MDNode *N = nullptr)
+ : TBAA(T), Scope(S), NoAlias(N) {}
+
+ bool operator==(const AAMDNodes &A) const {
+ return TBAA == A.TBAA && Scope == A.Scope && NoAlias == A.NoAlias;
+ }
+
+ bool operator!=(const AAMDNodes &A) const { return !(*this == A); }
+
+ LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; }
+
+ /// \brief The tag for type-based alias analysis.
+ MDNode *TBAA;
-class MDNodeOperand;
+ /// \brief The tag for alias scope specification (used with noalias).
+ MDNode *Scope;
+
+ /// \brief The tag specifying the noalias scope.
+ MDNode *NoAlias;
+};
+
+// Specialize DenseMapInfo for AAMDNodes.
+template<>
+struct DenseMapInfo<AAMDNodes> {
+ static inline AAMDNodes getEmptyKey() {
+ return AAMDNodes(DenseMapInfo<MDNode *>::getEmptyKey(), 0, 0);
+ }
+ static inline AAMDNodes getTombstoneKey() {
+ return AAMDNodes(DenseMapInfo<MDNode *>::getTombstoneKey(), 0, 0);
+ }
+ static unsigned getHashValue(const AAMDNodes &Val) {
+ return DenseMapInfo<MDNode *>::getHashValue(Val.TBAA) ^
+ DenseMapInfo<MDNode *>::getHashValue(Val.Scope) ^
+ DenseMapInfo<MDNode *>::getHashValue(Val.NoAlias);
+ }
+ static bool isEqual(const AAMDNodes &LHS, const AAMDNodes &RHS) {
+ return LHS == RHS;
+ }
+};
+
+/// \brief Tracking metadata reference owned by Metadata.
+///
+/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance
+/// of \a Metadata, which has the option of registering itself for callbacks to
+/// re-unique itself.
+///
+/// In particular, this is used by \a MDNode.
+class MDOperand {
+ MDOperand(MDOperand &&) LLVM_DELETED_FUNCTION;
+ MDOperand(const MDOperand &) LLVM_DELETED_FUNCTION;
+ MDOperand &operator=(MDOperand &&) LLVM_DELETED_FUNCTION;
+ MDOperand &operator=(const MDOperand &) LLVM_DELETED_FUNCTION;
+
+ Metadata *MD;
+
+public:
+ MDOperand() : MD(nullptr) {}
+ ~MDOperand() { untrack(); }
+
+ Metadata *get() const { return MD; }
+ operator Metadata *() const { return get(); }
+ Metadata *operator->() const { return get(); }
+ Metadata &operator*() const { return *get(); }
+
+ void reset() {
+ untrack();
+ MD = nullptr;
+ }
+ void reset(Metadata *MD, Metadata *Owner) {
+ untrack();
+ this->MD = MD;
+ track(Owner);
+ }
+
+private:
+ void track(Metadata *Owner) {
+ if (MD) {
+ if (Owner)
+ MetadataTracking::track(this, *MD, *Owner);
+ else
+ MetadataTracking::track(MD);
+ }
+ }
+ void untrack() {
+ assert(static_cast<void *>(this) == &MD && "Expected same address");
+ if (MD)
+ MetadataTracking::untrack(MD);
+ }
+};
+
+template <> struct simplify_type<MDOperand> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const MDOperand> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); }
+};
//===----------------------------------------------------------------------===//
-/// MDNode - a tuple of other values.
-class MDNode : public Value, public FoldingSetNode {
+/// \brief Tuple of metadata.
+class MDNode : public Metadata {
MDNode(const MDNode &) LLVM_DELETED_FUNCTION;
void operator=(const MDNode &) LLVM_DELETED_FUNCTION;
- friend class MDNodeOperand;
- friend class LLVMContextImpl;
- friend struct FoldingSetTrait<MDNode>;
-
- /// Hash - If the MDNode is uniqued cache the hash to speed up lookup.
- unsigned Hash;
+ void *operator new(size_t) LLVM_DELETED_FUNCTION;
- /// NumOperands - This many 'MDNodeOperand' items are co-allocated onto the
- /// end of this MDNode.
+ LLVMContext &Context;
unsigned NumOperands;
- // Subclass data enums.
- enum {
- /// FunctionLocalBit - This bit is set if this MDNode is function local.
- /// This is true when it (potentially transitively) contains a reference to
- /// something in a function, like an argument, basicblock, or instruction.
- FunctionLocalBit = 1 << 0,
+protected:
+ unsigned MDNodeSubclassData;
- /// NotUniquedBit - This is set on MDNodes that are not uniqued because they
- /// have a null operand.
- NotUniquedBit = 1 << 1,
+ void *operator new(size_t Size, unsigned NumOps);
+ void operator delete(void *Mem);
- /// DestroyFlag - This bit is set by destroy() so the destructor can assert
- /// that the node isn't being destroyed with a plain 'delete'.
- DestroyFlag = 1 << 2
- };
+ /// \brief Required by std, but never called.
+ void operator delete(void *, unsigned) {
+ llvm_unreachable("Constructor throws?");
+ }
- // FunctionLocal enums.
- enum FunctionLocalness {
- FL_Unknown = -1,
- FL_No = 0,
- FL_Yes = 1
- };
+ /// \brief Required by std, but never called.
+ void operator delete(void *, unsigned, bool) {
+ llvm_unreachable("Constructor throws?");
+ }
- /// replaceOperand - Replace each instance of F from the operand list of this
- /// node with T.
- void replaceOperand(MDNodeOperand *Op, Value *NewVal);
- ~MDNode();
+ MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs);
+ ~MDNode() {}
- MDNode(LLVMContext &C, ArrayRef<Value*> Vals, bool isFunctionLocal);
+ void dropAllReferences();
+
+ MDOperand *mutable_begin() { return mutable_end() - NumOperands; }
+ MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); }
- static MDNode *getMDNode(LLVMContext &C, ArrayRef<Value*> Vals,
- FunctionLocalness FL, bool Insert = true);
public:
- // Constructors and destructors.
- static MDNode *get(LLVMContext &Context, ArrayRef<Value*> Vals);
- // getWhenValsUnresolved - Construct MDNode determining function-localness
- // from isFunctionLocal argument, not by analyzing Vals.
- static MDNode *getWhenValsUnresolved(LLVMContext &Context,
- ArrayRef<Value*> Vals,
- bool isFunctionLocal);
-
- static MDNode *getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals);
-
- /// getTemporary - Return a temporary MDNode, for use in constructing
- /// cyclic MDNode structures. A temporary MDNode is not uniqued,
- /// may be RAUW'd, and must be manually deleted with deleteTemporary.
- static MDNode *getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals);
-
- /// deleteTemporary - Deallocate a node created by getTemporary. The
- /// node must not have any users.
+ static inline MDNode *get(LLVMContext &Context, ArrayRef<Metadata *> MDs);
+ static inline MDNode *getIfExists(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+ static inline MDNode *getDistinct(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+
+ /// \brief Return a temporary MDNode
+ ///
+ /// For use in constructing cyclic MDNode structures. A temporary MDNode is
+ /// not uniqued, may be RAUW'd, and must be manually deleted with
+ /// deleteTemporary.
+ static MDNodeFwdDecl *getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+
+ /// \brief Deallocate a node created by getTemporary.
+ ///
+ /// The node must not have any users.
static void deleteTemporary(MDNode *N);
- /// replaceOperandWith - Replace a specific operand.
- void replaceOperandWith(unsigned i, Value *NewVal);
+ LLVMContext &getContext() const { return Context; }
- /// getOperand - Return specified operand.
- Value *getOperand(unsigned i) const LLVM_READONLY;
+ /// \brief Replace a specific operand.
+ void replaceOperandWith(unsigned I, Metadata *New);
- /// getNumOperands - Return number of MDNode operands.
- unsigned getNumOperands() const { return NumOperands; }
+ /// \brief Check if node is fully resolved.
+ bool isResolved() const;
- /// isFunctionLocal - Return whether MDNode is local to a function.
- bool isFunctionLocal() const {
- return (getSubclassDataFromValue() & FunctionLocalBit) != 0;
+ /// \brief Check if node is distinct.
+ ///
+ /// Distinct nodes are not uniqued, and will not be returned by \a
+ /// MDNode::get().
+ bool isDistinct() const {
+ return isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this);
}
- // getFunction - If this metadata is function-local and recursively has a
- // function-local operand, return the first such operand's parent function.
- // Otherwise, return null. getFunction() should not be used for performance-
- // critical code because it recursively visits all the MDNode's operands.
- const Function *getFunction() const;
+protected:
+ /// \brief Set an operand.
+ ///
+ /// Sets the operand directly, without worrying about uniquing.
+ void setOperand(unsigned I, Metadata *New);
- /// Profile - calculate a unique identifier for this MDNode to collapse
- /// duplicates
- void Profile(FoldingSetNodeID &ID) const;
+public:
+ typedef const MDOperand *op_iterator;
+ typedef iterator_range<op_iterator> op_range;
- /// Methods for support type inquiry through isa, cast, and dyn_cast:
- static bool classof(const Value *V) {
- return V->getValueID() == MDNodeVal;
+ op_iterator op_begin() const {
+ return const_cast<MDNode *>(this)->mutable_begin();
+ }
+ op_iterator op_end() const {
+ return const_cast<MDNode *>(this)->mutable_end();
+ }
+ op_range operands() const { return op_range(op_begin(), op_end()); }
+
+ const MDOperand &getOperand(unsigned I) const {
+ assert(I < NumOperands && "Out of range");
+ return op_begin()[I];
+ }
+
+ /// \brief Return number of MDNode operands.
+ unsigned getNumOperands() const { return NumOperands; }
+
+ /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDTupleKind ||
+ MD->getMetadataID() == MDLocationKind ||
+ MD->getMetadataID() == MDNodeFwdDeclKind;
}
- /// Check whether MDNode is a vtable access.
+ /// \brief Check whether MDNode is a vtable access.
bool isTBAAVtableAccess() const;
- /// Methods for metadata merging.
+ /// \brief 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);
+ static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B);
static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B);
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
+};
+
+/// \brief Uniquable metadata node.
+///
+/// A uniquable metadata node. This contains the basic functionality
+/// for implementing sub-types of \a MDNode that can be uniqued like
+/// constants.
+///
+/// There is limited support for RAUW at construction time. At
+/// construction time, if any operands are an instance of \a
+/// MDNodeFwdDecl (or another unresolved \a UniquableMDNode, which
+/// indicates an \a MDNodeFwdDecl in its path), the node itself will be
+/// unresolved. As soon as all operands become resolved, it will drop
+/// RAUW support permanently.
+///
+/// If an unresolved node is part of a cycle, \a resolveCycles() needs
+/// to be called on some member of the cycle when each \a MDNodeFwdDecl
+/// has been removed.
+class UniquableMDNode : public MDNode {
+ friend class ReplaceableMetadataImpl;
+ friend class MDNode;
+ friend class LLVMContextImpl;
+
+ /// \brief Support RAUW as long as one of its arguments is replaceable.
+ ///
+ /// FIXME: Save memory by storing this in a pointer union with the
+ /// LLVMContext, and adding an LLVMContext reference to RMI.
+ std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses;
+
+protected:
+ /// \brief Create a new node.
+ ///
+ /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW
+ /// will be dropped once all operands have been resolved (or if \a
+ /// resolveCycles() is called).
+ UniquableMDNode(LLVMContext &C, unsigned ID, ArrayRef<Metadata *> Vals,
+ bool AllowRAUW);
+ ~UniquableMDNode() {}
+
+ void storeDistinctInContext();
+
+public:
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDTupleKind ||
+ MD->getMetadataID() == MDLocationKind;
+ }
+
+ /// \brief Check whether any operands are forward declarations.
+ ///
+ /// Returns \c true as long as any operands (or their operands, etc.) are \a
+ /// MDNodeFwdDecl.
+ ///
+ /// As forward declarations are resolved, their containers should get
+ /// resolved automatically. However, if this (or one of its operands) is
+ /// involved in a cycle, \a resolveCycles() needs to be called explicitly.
+ bool isResolved() const { return !ReplaceableUses; }
+
+ /// \brief Resolve cycles.
+ ///
+ /// Once all forward declarations have been resolved, force cycles to be
+ /// resolved.
+ ///
+ /// \pre No operands (or operands' operands, etc.) are \a MDNodeFwdDecl.
+ void resolveCycles();
+
+private:
+ void handleChangedOperand(void *Ref, Metadata *New);
+
+ void resolve();
+ void resolveAfterOperandChange(Metadata *Old, Metadata *New);
+ void decrementUnresolvedOperandCount();
+
+ void deleteAsSubclass();
+ UniquableMDNode *uniquify();
+ void eraseFromStore();
+};
+
+/// \brief Tuple of metadata.
+///
+/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by
+/// default based on their operands.
+class MDTuple : public UniquableMDNode {
+ friend class LLVMContextImpl;
+ friend class UniquableMDNode;
+
+ MDTuple(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW)
+ : UniquableMDNode(C, MDTupleKind, Vals, AllowRAUW) {}
+ ~MDTuple() { dropAllReferences(); }
+
+ void setHash(unsigned Hash) { MDNodeSubclassData = Hash; }
+ void recalculateHash();
+
+ static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+ bool ShouldCreate);
+
+public:
+ /// \brief Get the hash, if any.
+ unsigned getHash() const { return MDNodeSubclassData; }
+
+ static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return getImpl(Context, MDs, /* ShouldCreate */ true);
+ }
+ static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return getImpl(Context, MDs, /* ShouldCreate */ false);
+ }
+
+ /// \brief Return a distinct node.
+ ///
+ /// Return a distinct node -- i.e., a node that is not uniqued.
+ static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs);
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDTupleKind;
+ }
+
+private:
+ MDTuple *uniquifyImpl();
+ void eraseFromStoreImpl();
+};
+
+MDNode *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return MDTuple::get(Context, MDs);
+}
+MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return MDTuple::getIfExists(Context, MDs);
+}
+MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return MDTuple::getDistinct(Context, MDs);
+}
+
+/// \brief Debug location.
+///
+/// A debug location in source code, used for debug info and otherwise.
+class MDLocation : public UniquableMDNode {
+ friend class LLVMContextImpl;
+ friend class UniquableMDNode;
+
+ MDLocation(LLVMContext &C, unsigned Line, unsigned Column,
+ ArrayRef<Metadata *> MDs, bool AllowRAUW);
+ ~MDLocation() { dropAllReferences(); }
+
+ static MDLocation *constructHelper(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool AllowRAUW);
+
+ static MDLocation *getImpl(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool ShouldCreate);
+
+ // Disallow replacing operands.
+ void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION;
+
+public:
+ static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column,
+ Metadata *Scope, Metadata *InlinedAt = nullptr) {
+ return getImpl(Context, Line, Column, Scope, InlinedAt,
+ /* ShouldCreate */ true);
+ }
+ static MDLocation *getIfExists(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt = nullptr) {
+ return getImpl(Context, Line, Column, Scope, InlinedAt,
+ /* ShouldCreate */ false);
+ }
+ static MDLocation *getDistinct(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt = nullptr);
+
+ unsigned getLine() const { return MDNodeSubclassData; }
+ unsigned getColumn() const { return SubclassData16; }
+ Metadata *getScope() const { return getOperand(0); }
+ Metadata *getInlinedAt() const {
+ if (getNumOperands() == 2)
+ return getOperand(1);
+ return nullptr;
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDLocationKind;
+ }
+
private:
- // destroy - Delete this node. Only when there are no uses.
- void destroy();
+ MDLocation *uniquifyImpl();
+ void eraseFromStoreImpl();
+};
+
+/// \brief Forward declaration of metadata.
+///
+/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a
+/// MDTuple, this class has full support for RAUW, is not owned, is not
+/// uniqued, and is suitable for forward references.
+class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl {
+ friend class Metadata;
+ friend class ReplaceableMetadataImpl;
+
+ MDNodeFwdDecl(LLVMContext &C, ArrayRef<Metadata *> Vals)
+ : MDNode(C, MDNodeFwdDeclKind, Vals) {}
+
+public:
+ ~MDNodeFwdDecl() { dropAllReferences(); }
+
+ // MSVC doesn't see the alternative: "using MDNode::operator delete".
+ void operator delete(void *Mem) { MDNode::operator delete(Mem); }
- bool isNotUniqued() const {
- return (getSubclassDataFromValue() & NotUniquedBit) != 0;
+ static MDNodeFwdDecl *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return new (MDs.size()) MDNodeFwdDecl(Context, MDs);
}
- void setIsNotUniqued();
- // Shadow Value::setValueSubclassData with a private forwarding method so that
- // any future subclasses cannot accidentally use it.
- void setValueSubclassData(unsigned short D) {
- Value::setValueSubclassData(D);
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDNodeFwdDeclKind;
}
+
+ using ReplaceableMetadataImpl::replaceAllUsesWith;
};
//===----------------------------------------------------------------------===//
-/// NamedMDNode - a tuple of MDNodes. Despite its name, a NamedMDNode isn't
-/// itself an MDNode. NamedMDNodes belong to modules, have names, and contain
-/// lists of MDNodes.
+/// \brief 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.
+///
+/// TODO: Inherit from Metadata.
class NamedMDNode : public ilist_node<NamedMDNode> {
friend class SymbolTableListTraits<NamedMDNode, Module>;
friend struct ilist_traits<NamedMDNode>;
@@ -202,7 +924,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> {
std::string Name;
Module *Parent;
- void *Operands; // SmallVector<TrackingVH<MDNode>, 4>
+ void *Operands; // SmallVector<TrackingMDRef, 4>
void setParent(Module *M) { Parent = M; }
@@ -245,46 +967,34 @@ class NamedMDNode : public ilist_node<NamedMDNode> {
};
public:
- /// eraseFromParent - Drop all references and remove the node from parent
- /// module.
+ /// \brief Drop all references and remove the node from parent module.
void eraseFromParent();
- /// dropAllReferences - Remove all uses and clear node vector.
+ /// \brief Remove all uses and clear node vector.
void dropAllReferences();
- /// ~NamedMDNode - Destroy NamedMDNode.
~NamedMDNode();
- /// getParent - Get the module that holds this named metadata collection.
+ /// \brief Get the module that holds this named metadata collection.
inline Module *getParent() { return Parent; }
inline const Module *getParent() const { return Parent; }
- /// getOperand - Return specified operand.
MDNode *getOperand(unsigned i) const;
-
- /// getNumOperands - Return the number of NamedMDNode operands.
unsigned getNumOperands() const;
-
- /// addOperand - Add metadata operand.
void addOperand(MDNode *M);
-
- /// getName - Return a constant reference to this named metadata's name.
+ void setOperand(unsigned I, MDNode *New);
StringRef getName() const;
-
- /// print - Implement operator<< on NamedMDNode.
void print(raw_ostream &ROS) const;
-
- /// dump() - Allow printing of NamedMDNodes from the debugger.
void dump() const;
// ---------------------------------------------------------------------------
// Operand Iterator interface...
//
- typedef op_iterator_impl<MDNode*, MDNode> op_iterator;
+ typedef op_iterator_impl<MDNode *, MDNode> op_iterator;
op_iterator op_begin() { return op_iterator(this, 0); }
op_iterator op_end() { return op_iterator(this, getNumOperands()); }
- typedef op_iterator_impl<const MDNode*, MDNode> const_op_iterator;
+ typedef op_iterator_impl<const MDNode *, MDNode> const_op_iterator;
const_op_iterator op_begin() const { return const_op_iterator(this, 0); }
const_op_iterator op_end() const { return const_op_iterator(this, getNumOperands()); }
diff --git a/include/llvm/IR/MetadataTracking.h b/include/llvm/IR/MetadataTracking.h
new file mode 100644
index 000000000000..541d9b3b1245
--- /dev/null
+++ b/include/llvm/IR/MetadataTracking.h
@@ -0,0 +1,99 @@
+//===- llvm/IR/MetadataTracking.h - Metadata tracking ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Low-level functions to enable tracking of metadata that could RAUW.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_METADATATRACKING_H
+#define LLVM_IR_METADATATRACKING_H
+
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/Casting.h"
+#include <type_traits>
+
+namespace llvm {
+
+class Metadata;
+class MetadataAsValue;
+
+/// \brief API for tracking metadata references through RAUW and deletion.
+///
+/// Shared API for updating \a Metadata pointers in subclasses that support
+/// RAUW.
+///
+/// This API is not meant to be used directly. See \a TrackingMDRef for a
+/// user-friendly tracking reference.
+class MetadataTracking {
+public:
+ /// \brief Track the reference to metadata.
+ ///
+ /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD
+ /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets
+ /// deleted, \c MD will be set to \c nullptr.
+ ///
+ /// If tracking isn't supported, \c *MD will not change.
+ ///
+ /// \return true iff tracking is supported by \c MD.
+ static bool track(Metadata *&MD) {
+ return track(&MD, *MD, static_cast<Metadata *>(nullptr));
+ }
+
+ /// \brief Track the reference to metadata for \a Metadata.
+ ///
+ /// As \a track(Metadata*&), but with support for calling back to \c Owner to
+ /// tell it that its operand changed. This could trigger \c Owner being
+ /// re-uniqued.
+ static bool track(void *Ref, Metadata &MD, Metadata &Owner) {
+ return track(Ref, MD, &Owner);
+ }
+
+ /// \brief Track the reference to metadata for \a MetadataAsValue.
+ ///
+ /// As \a track(Metadata*&), but with support for calling back to \c Owner to
+ /// tell it that its operand changed. This could trigger \c Owner being
+ /// re-uniqued.
+ static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) {
+ return track(Ref, MD, &Owner);
+ }
+
+ /// \brief Stop tracking a reference to metadata.
+ ///
+ /// Stops \c *MD from tracking \c MD.
+ static void untrack(Metadata *&MD) { untrack(&MD, *MD); }
+ static void untrack(void *Ref, Metadata &MD);
+
+ /// \brief Move tracking from one reference to another.
+ ///
+ /// Semantically equivalent to \c untrack(MD) followed by \c track(New),
+ /// except that ownership callbacks are maintained.
+ ///
+ /// Note: it is an error if \c *MD does not equal \c New.
+ ///
+ /// \return true iff tracking is supported by \c MD.
+ static bool retrack(Metadata *&MD, Metadata *&New) {
+ return retrack(&MD, *MD, &New);
+ }
+ static bool retrack(void *Ref, Metadata &MD, void *New);
+
+ /// \brief Check whether metadata is replaceable.
+ static bool isReplaceable(const Metadata &MD);
+
+ typedef PointerUnion<MetadataAsValue *, Metadata *> OwnerTy;
+
+private:
+ /// \brief Track a reference to metadata for an owner.
+ ///
+ /// Generalized version of tracking.
+ static bool track(void *Ref, Metadata &MD, OwnerTy Owner);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index 26f62db9db53..b24023b05e4f 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -23,6 +23,7 @@
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/DataTypes.h"
#include <system_error>
@@ -32,8 +33,6 @@ class GVMaterializer;
class LLVMContext;
class RandomNumberGenerator;
class StructType;
-template<typename T> struct DenseMapInfo;
-template<typename KeyT, typename ValueT, typename KeyInfoT> class DenseMap;
template<> struct ilist_traits<Function>
: public SymbolTableListTraits<Function, Module> {
@@ -137,6 +136,11 @@ public:
/// The Function constant iterator
typedef FunctionListType::const_iterator const_iterator;
+ /// The Function reverse iterator.
+ typedef FunctionListType::reverse_iterator reverse_iterator;
+ /// The Function constant reverse iterator.
+ typedef FunctionListType::const_reverse_iterator const_reverse_iterator;
+
/// The Global Alias iterators.
typedef AliasListType::iterator alias_iterator;
/// The Global Alias constant iterator
@@ -144,7 +148,7 @@ public:
/// The named metadata iterators.
typedef NamedMDListType::iterator named_metadata_iterator;
- /// The named metadata constant interators.
+ /// The named metadata constant iterators.
typedef NamedMDListType::const_iterator const_named_metadata_iterator;
/// This enumeration defines the supported behaviors of module flags.
@@ -177,15 +181,23 @@ public:
/// Appends the two values, which are required to be metadata
/// nodes. However, duplicate entries in the second list are dropped
/// during the append operation.
- AppendUnique = 6
+ AppendUnique = 6,
+
+ // Markers:
+ ModFlagBehaviorFirstVal = Error,
+ ModFlagBehaviorLastVal = AppendUnique
};
+ /// Checks if Metadata represents a valid ModFlagBehavior, and stores the
+ /// converted result in MFB.
+ static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB);
+
struct ModuleFlagEntry {
ModFlagBehavior Behavior;
MDString *Key;
- Value *Val;
- ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V)
- : Behavior(B), Key(K), Val(V) {}
+ Metadata *Val;
+ ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V)
+ : Behavior(B), Key(K), Val(V) {}
};
/// @}
@@ -205,9 +217,8 @@ private:
Materializer; ///< Used to materialize GlobalValues
std::string ModuleID; ///< Human readable identifier for the module
std::string TargetTriple; ///< Platform target triple Module compiled on
+ ///< Format: (arch)(sub)-(vendor)-(sys0-(abi)
void *NamedMDSymTab; ///< NamedMDNode names.
- // Allow lazy initialization in const method.
- mutable RandomNumberGenerator *RNG; ///< The random number generator for this module.
// We need to keep the string because the C API expects us to own the string
// representation.
@@ -237,6 +248,12 @@ public:
/// @returns the module identifier as a string
const std::string &getModuleIdentifier() const { return ModuleID; }
+ /// \brief Get a short "name" for the module.
+ ///
+ /// This is useful for debugging or logging. It is essentially a convenience
+ /// wrapper around getModuleIdentifier().
+ StringRef getName() const { return ModuleID; }
+
/// Get the data layout string for the module's target platform. This is
/// equivalent to getDataLayout()->getStringRepresentation().
const std::string &getDataLayoutStr() const { return DataLayoutStr; }
@@ -256,10 +273,16 @@ public:
/// @returns a string containing the module-scope inline assembly blocks.
const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; }
- /// Get the RandomNumberGenerator for this module. The RNG can be
- /// seeded via -rng-seed=<uint64> and is salted with the ModuleID.
- /// The returned RNG should not be shared across threads.
- RandomNumberGenerator &getRNG() const;
+ /// Get a RandomNumberGenerator salted for use with this module. The
+ /// RNG can be seeded via -rng-seed=<uint64> and is salted with the
+ /// ModuleID and the provided pass salt. The returned RNG should not
+ /// be shared across threads or passes.
+ ///
+ /// A unique RNG per pass ensures a reproducible random stream even
+ /// when other randomness consuming passes are added or removed. In
+ /// addition, the random stream will be reproducible across LLVM
+ /// versions when the pass does not change.
+ RandomNumberGenerator *createRNG(const Pass* P) const;
/// @}
/// @name Module Level Mutators
@@ -313,6 +336,8 @@ public:
/// name.
StructType *getTypeByName(StringRef Name) const;
+ std::vector<StructType *> getIdentifiedStructTypes() const;
+
/// @}
/// @name Function Accessors
/// @{
@@ -339,11 +364,11 @@ public:
/// function arguments, which makes it easier for clients to use.
Constant *getOrInsertFunction(StringRef Name,
AttributeSet AttributeList,
- Type *RetTy, ...) END_WITH_NULL;
+ Type *RetTy, ...) LLVM_END_WITH_NULL;
/// Same as above, but without the attributes.
Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...)
- END_WITH_NULL;
+ LLVM_END_WITH_NULL;
/// Look up the specified function in the module symbol table. If it does not
/// exist, return null.
@@ -357,8 +382,11 @@ public:
/// does not exist, return null. If AllowInternal is set to true, this
/// function will return types that have InternalLinkage. By default, these
/// types are not returned.
- const GlobalVariable *getGlobalVariable(StringRef Name,
- bool AllowInternal = false) const {
+ GlobalVariable *getGlobalVariable(StringRef Name) const {
+ return getGlobalVariable(Name, false);
+ }
+
+ GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const {
return const_cast<Module *>(this)->getGlobalVariable(Name, AllowInternal);
}
@@ -424,7 +452,7 @@ public:
/// Return the corresponding value if Key appears in module flags, otherwise
/// return null.
- Value *getModuleFlag(StringRef Key) const;
+ Metadata *getModuleFlag(StringRef Key) const;
/// Returns the NamedMDNode in the module that represents module-level flags.
/// This method returns null if there are no module-level flags.
@@ -437,7 +465,8 @@ public:
/// Add a module-level flag to the module-level flags metadata. It will create
/// the module-level flags named metadata if it doesn't already exist.
- void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val);
+ void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val);
+ void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val);
void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val);
void addModuleFlag(MDNode *Node);
@@ -456,9 +485,6 @@ public:
/// Retrieves the GVMaterializer, if any, for this Module.
GVMaterializer *getMaterializer() const { return Materializer.get(); }
- /// True if the definition of GV has yet to be materializedfrom the
- /// GVMaterializer.
- bool isMaterializable(const GlobalValue *GV) const;
/// Returns true if this GV was loaded from this Module's GVMaterializer and
/// the GVMaterializer knows how to dematerialize the GV.
bool isDematerializable(const GlobalValue *GV) const;
@@ -466,10 +492,10 @@ public:
/// Make sure the GlobalValue is fully read. If the module is corrupt, this
/// returns true and fills in the optional string with information about the
/// problem. If successful, this returns false.
- bool Materialize(GlobalValue *GV, std::string *ErrInfo = nullptr);
+ std::error_code materialize(GlobalValue *GV);
/// If the GlobalValue is read in, and if the GVMaterializer supports it,
/// release the memory for the function, and set it up to be materialized
- /// lazily. If !isDematerializable(), this method is a noop.
+ /// lazily. If !isDematerializable(), this method is a no-op.
void Dematerialize(GlobalValue *GV);
/// Make sure all GlobalValues in this Module are fully read.
@@ -478,7 +504,7 @@ public:
/// Make sure all GlobalValues in this Module are fully read and clear the
/// Materializer. If the module is corrupt, this DOES NOT clear the old
/// Materializer.
- std::error_code materializeAllPermanently(bool ReleaseBuffer = false);
+ std::error_code materializeAllPermanently();
/// @}
/// @name Direct access to the globals list, functions list, and symbol table
@@ -546,9 +572,20 @@ public:
const_iterator begin() const { return FunctionList.begin(); }
iterator end () { return FunctionList.end(); }
const_iterator end () const { return FunctionList.end(); }
+ reverse_iterator rbegin() { return FunctionList.rbegin(); }
+ const_reverse_iterator rbegin() const{ return FunctionList.rbegin(); }
+ reverse_iterator rend() { return FunctionList.rend(); }
+ const_reverse_iterator rend() const { return FunctionList.rend(); }
size_t size() const { return FunctionList.size(); }
bool empty() const { return FunctionList.empty(); }
+ iterator_range<iterator> functions() {
+ return iterator_range<iterator>(begin(), end());
+ }
+ iterator_range<const_iterator> functions() const {
+ return iterator_range<const_iterator>(begin(), end());
+ }
+
/// @}
/// @name Alias Iteration
/// @{
@@ -620,6 +657,15 @@ public:
unsigned getDwarfVersion() const;
/// @}
+/// @name Utility functions for querying and setting PIC level
+/// @{
+
+ /// \brief Returns the PIC level (small or large model)
+ PICLevel::Level getPICLevel() const;
+
+ /// \brief Set the PIC level (small or large model)
+ void setPICLevel(PICLevel::Level PL);
+/// @}
};
/// An raw_ostream inserter for modules.
diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h
index 888cabffe378..0933f2170236 100644
--- a/include/llvm/IR/Operator.h
+++ b/include/llvm/IR/Operator.h
@@ -28,9 +28,8 @@ class GetElementPtrInst;
class BinaryOperator;
class ConstantExpr;
-/// Operator - This is a utility class that provides an abstraction for the
-/// common functionality between Instructions and ConstantExprs.
-///
+/// This is a utility class that provides an abstraction for the common
+/// functionality between Instructions and ConstantExprs.
class Operator : public User {
private:
// The Operator class is intended to be used as a utility, and is never itself
@@ -46,17 +45,15 @@ protected:
~Operator();
public:
- /// getOpcode - Return the opcode for this Instruction or ConstantExpr.
- ///
+ /// Return the opcode for this Instruction or ConstantExpr.
unsigned getOpcode() const {
if (const Instruction *I = dyn_cast<Instruction>(this))
return I->getOpcode();
return cast<ConstantExpr>(this)->getOpcode();
}
- /// getOpcode - If V is an Instruction or ConstantExpr, return its
- /// opcode. Otherwise return UserOp1.
- ///
+ /// If V is an Instruction or ConstantExpr, return its opcode.
+ /// Otherwise return UserOp1.
static unsigned getOpcode(const Value *V) {
if (const Instruction *I = dyn_cast<Instruction>(V))
return I->getOpcode();
@@ -72,10 +69,9 @@ public:
}
};
-/// OverflowingBinaryOperator - Utility class for integer arithmetic operators
-/// which may exhibit overflow - Add, Sub, and Mul. It does not include SDiv,
-/// despite that operator having the potential for overflow.
-///
+/// Utility class for integer arithmetic operators which may exhibit overflow -
+/// Add, Sub, and Mul. It does not include SDiv, despite that operator having
+/// the potential for overflow.
class OverflowingBinaryOperator : public Operator {
public:
enum {
@@ -96,13 +92,13 @@ private:
}
public:
- /// hasNoUnsignedWrap - Test whether this operation is known to never
+ /// Test whether this operation is known to never
/// undergo unsigned overflow, aka the nuw property.
bool hasNoUnsignedWrap() const {
return SubclassOptionalData & NoUnsignedWrap;
}
- /// hasNoSignedWrap - Test whether this operation is known to never
+ /// Test whether this operation is known to never
/// undergo signed overflow, aka the nsw property.
bool hasNoSignedWrap() const {
return (SubclassOptionalData & NoSignedWrap) != 0;
@@ -126,8 +122,8 @@ public:
}
};
-/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as
-/// "exact", indicating that no bits are destroyed.
+/// A udiv or sdiv instruction, which can be marked as "exact",
+/// indicating that no bits are destroyed.
class PossiblyExactOperator : public Operator {
public:
enum {
@@ -142,8 +138,7 @@ private:
}
public:
- /// isExact - Test whether this division is known to be exact, with
- /// zero remainder.
+ /// Test whether this division is known to be exact, with zero remainder.
bool isExact() const {
return SubclassOptionalData & IsExact;
}
@@ -217,7 +212,7 @@ public:
};
-/// FPMathOperator - Utility class for floating point operations which can have
+/// Utility class for floating point operations which can have
/// information about relaxed accuracy requirements attached to them.
class FPMathOperator : public Operator {
private:
@@ -257,11 +252,18 @@ private:
(B * FastMathFlags::AllowReciprocal);
}
- /// Convenience function for setting all the fast-math flags
+ /// Convenience function for setting multiple fast-math flags.
+ /// FMF is a mask of the bits to set.
void setFastMathFlags(FastMathFlags FMF) {
SubclassOptionalData |= FMF.Flags;
}
+ /// Convenience function for copying all fast-math flags.
+ /// All values in FMF are transferred to this operator.
+ void copyFastMathFlags(FastMathFlags FMF) {
+ SubclassOptionalData = FMF.Flags;
+ }
+
public:
/// Test whether this operation is permitted to be
/// algebraically transformed, aka the 'A' fast-math property.
@@ -312,8 +314,7 @@ public:
};
-/// ConcreteOperator - A helper template for defining operators for individual
-/// opcodes.
+/// A helper template for defining operators for individual opcodes.
template<typename SuperClass, unsigned Opc>
class ConcreteOperator : public SuperClass {
public:
@@ -357,6 +358,8 @@ class LShrOperator
};
+class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {};
+
class GEPOperator
: public ConcreteOperator<Operator, Instruction::GetElementPtr> {
@@ -372,8 +375,7 @@ class GEPOperator
}
public:
- /// isInBounds - Test whether this is an inbounds GEP, as defined
- /// by LangRef.html.
+ /// Test whether this is an inbounds GEP, as defined by LangRef.html.
bool isInBounds() const {
return SubclassOptionalData & IsInBounds;
}
@@ -393,16 +395,14 @@ public:
return 0U; // get index for modifying correct operand
}
- /// getPointerOperandType - Method to return the pointer operand as a
- /// PointerType.
+ /// Method to return the pointer operand as a PointerType.
Type *getPointerOperandType() const {
return getPointerOperand()->getType();
}
- /// getPointerAddressSpace - Method to return the address space of the
- /// pointer operand.
+ /// Method to return the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
- return cast<PointerType>(getPointerOperandType())->getAddressSpace();
+ return getPointerOperandType()->getPointerAddressSpace();
}
unsigned getNumIndices() const { // Note: always non-negative
@@ -413,8 +413,8 @@ public:
return getNumOperands() > 1;
}
- /// hasAllZeroIndices - Return true if all of the indices of this GEP are
- /// zeros. If so, the result pointer and the first operand have the same
+ /// Return true if all of the indices of this GEP are zeros.
+ /// If so, the result pointer and the first operand have the same
/// value, just potentially different types.
bool hasAllZeroIndices() const {
for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
@@ -426,8 +426,8 @@ public:
return true;
}
- /// hasAllConstantIndices - Return true if all of the indices of this GEP are
- /// constant integers. If so, the result pointer and the first operand have
+ /// Return true if all of the indices of this GEP are constant integers.
+ /// If so, the result pointer and the first operand have
/// a constant offset between them.
bool hasAllConstantIndices() const {
for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
@@ -493,14 +493,12 @@ public:
return 0U; // get index for modifying correct operand
}
- /// getPointerOperandType - Method to return the pointer operand as a
- /// PointerType.
+ /// Method to return the pointer operand as a PointerType.
Type *getPointerOperandType() const {
return getPointerOperand()->getType();
}
- /// getPointerAddressSpace - Method to return the address space of the
- /// pointer operand.
+ /// Method to return the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return cast<PointerType>(getPointerOperandType())->getAddressSpace();
}
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index cc2a80b9ff7d..262576849264 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -35,14 +35,17 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_PASS_MANAGER_H
-#define LLVM_IR_PASS_MANAGER_H
+#ifndef LLVM_IR_PASSMANAGER_H
+#define LLVM_IR_PASSMANAGER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManagerInternal.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/type_traits.h"
#include <list>
#include <memory>
@@ -91,9 +94,12 @@ public:
}
/// \brief Mark a particular pass as preserved, adding it to the set.
- template <typename PassT> void preserve() {
+ template <typename PassT> void preserve() { preserve(PassT::ID()); }
+
+ /// \brief Mark an abstract PassID as preserved, adding it to the set.
+ void preserve(void *PassID) {
if (!areAllPreserved())
- PreservedPassIDs.insert(PassT::ID());
+ PreservedPassIDs.insert(PassID);
}
/// \brief Intersect this set with another in place.
@@ -107,11 +113,9 @@ public:
PreservedPassIDs = Arg.PreservedPassIDs;
return;
}
- for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(),
- E = PreservedPassIDs.end();
- I != E; ++I)
- if (!Arg.PreservedPassIDs.count(*I))
- PreservedPassIDs.erase(*I);
+ for (void *P : PreservedPassIDs)
+ if (!Arg.PreservedPassIDs.count(P))
+ PreservedPassIDs.erase(P);
}
/// \brief Intersect this set with a temporary other set in place.
@@ -125,11 +129,9 @@ public:
PreservedPassIDs = std::move(Arg.PreservedPassIDs);
return;
}
- for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(),
- E = PreservedPassIDs.end();
- I != E; ++I)
- if (!Arg.PreservedPassIDs.count(*I))
- PreservedPassIDs.erase(*I);
+ for (void *P : PreservedPassIDs)
+ if (!Arg.PreservedPassIDs.count(P))
+ PreservedPassIDs.erase(P);
}
/// \brief Query whether a pass is marked as preserved by this set.
@@ -144,408 +146,115 @@ public:
PreservedPassIDs.count(PassID);
}
+ /// \brief Test whether all passes are preserved.
+ ///
+ /// This is used primarily to optimize for the case of no changes which will
+ /// common in many scenarios.
+ bool areAllPreserved() const {
+ return PreservedPassIDs.count((void *)AllPassesID);
+ }
+
private:
// Note that this must not be -1 or -2 as those are already used by the
// SmallPtrSet.
static const uintptr_t AllPassesID = (intptr_t)(-3);
- bool areAllPreserved() const {
- return PreservedPassIDs.count((void *)AllPassesID);
- }
-
SmallPtrSet<void *, 2> PreservedPassIDs;
};
-/// \brief Implementation details of the pass manager interfaces.
-namespace detail {
-
-/// \brief Template for the abstract base class used to dispatch
-/// polymorphically over pass objects.
-template <typename IRUnitT, typename AnalysisManagerT> struct PassConcept {
- // Boiler plate necessary for the container of derived classes.
- virtual ~PassConcept() {}
-
- /// \brief The polymorphic API which runs the pass over a given IR entity.
- ///
- /// Note that actual pass object can omit the analysis manager argument if
- /// desired. Also that the analysis manager may be null if there is no
- /// analysis manager in the pass pipeline.
- virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0;
-
- /// \brief Polymorphic method to access the name of a pass.
- virtual StringRef name() = 0;
-};
-
-/// \brief SFINAE metafunction for computing whether \c PassT has a run method
-/// accepting an \c AnalysisManagerT.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- typename ResultT>
-class PassRunAcceptsAnalysisManager {
- typedef char SmallType;
- struct BigType {
- char a, b;
- };
-
- template <typename T, ResultT (T::*)(IRUnitT, AnalysisManagerT *)>
- struct Checker;
-
- template <typename T> static SmallType f(Checker<T, &T::run> *);
- template <typename T> static BigType f(...);
+// Forward declare the analysis manager template.
+template <typename IRUnitT> class AnalysisManager;
-public:
- enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
-};
-
-/// \brief A template wrapper used to implement the polymorphic API.
+/// \brief Manages a sequence of passes over units of IR.
///
-/// Can be instantiated for any object which provides a \c run method accepting
-/// an \c IRUnitT. It requires the pass to be a copyable object. When the
-/// \c run method also accepts an \c AnalysisManagerT*, we pass it along.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, AnalysisManagerT, PassT, PreservedAnalyses>::Value>
-struct PassModel;
-
-/// \brief Specialization of \c PassModel for passes that accept an analyis
-/// manager.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct PassModel<IRUnitT, AnalysisManagerT, PassT, true>
- : PassConcept<IRUnitT, AnalysisManagerT> {
- explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
- PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(PassModel &LHS, PassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- PassModel &operator=(PassModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override {
- return Pass.run(IR, AM);
- }
- StringRef name() override { return PassT::name(); }
- PassT Pass;
-};
-
-/// \brief Specialization of \c PassModel for passes that accept an analyis
-/// manager.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct PassModel<IRUnitT, AnalysisManagerT, PassT, false>
- : PassConcept<IRUnitT, AnalysisManagerT> {
- explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
- PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(PassModel &LHS, PassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- PassModel &operator=(PassModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override {
- return Pass.run(IR);
- }
- StringRef name() override { return PassT::name(); }
- PassT Pass;
-};
-
-/// \brief Abstract concept of an analysis result.
+/// A pass manager contains a sequence of passes to run over units of IR. It is
+/// itself a valid pass over that unit of IR, and when over some given IR will
+/// run each pass in sequence. This is the primary and most basic building
+/// block of a pass pipeline.
///
-/// This concept is parameterized over the IR unit that this result pertains
-/// to.
-template <typename IRUnitT> struct AnalysisResultConcept {
- virtual ~AnalysisResultConcept() {}
-
- /// \brief Method to try and mark a result as invalid.
- ///
- /// When the outer analysis manager detects a change in some underlying
- /// unit of the IR, it will call this method on all of the results cached.
- ///
- /// This method also receives a set of preserved analyses which can be used
- /// to avoid invalidation because the pass which changed the underlying IR
- /// took care to update or preserve the analysis result in some way.
- ///
- /// \returns true if the result is indeed invalid (the default).
- virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0;
-};
-
-/// \brief SFINAE metafunction for computing whether \c ResultT provides an
-/// \c invalidate member function.
-template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
- typedef char SmallType;
- struct BigType {
- char a, b;
- };
-
- template <typename T, bool (T::*)(IRUnitT, const PreservedAnalyses &)>
- struct Checker;
-
- template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
- template <typename T> static BigType f(...);
-
+/// If it is run with an \c AnalysisManager<IRUnitT> argument, it will propagate
+/// that analysis manager to each pass it runs, as well as calling the analysis
+/// manager's invalidation routine with the PreservedAnalyses of each pass it
+/// runs.
+template <typename IRUnitT> class PassManager {
public:
- enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
-};
-
-/// \brief Wrapper to model the analysis result concept.
-///
-/// By default, this will implement the invalidate method with a trivial
-/// implementation so that the actual analysis result doesn't need to provide
-/// an invalidation handler. It is only selected when the invalidation handler
-/// is not part of the ResultT's interface.
-template <typename IRUnitT, typename PassT, typename ResultT,
- bool HasInvalidateHandler =
- ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
-struct AnalysisResultModel;
-
-/// \brief Specialization of \c AnalysisResultModel which provides the default
-/// invalidate functionality.
-template <typename IRUnitT, typename PassT, typename ResultT>
-struct AnalysisResultModel<IRUnitT, PassT, ResultT, false>
- : AnalysisResultConcept<IRUnitT> {
- explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
- AnalysisResultModel(AnalysisResultModel &&Arg)
- : Result(std::move(Arg.Result)) {}
- friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
- using std::swap;
- swap(LHS.Result, RHS.Result);
- }
- AnalysisResultModel &operator=(AnalysisResultModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- /// \brief The model bases invalidation solely on being in the preserved set.
- //
- // FIXME: We should actually use two different concepts for analysis results
- // rather than two different models, and avoid the indirect function call for
- // ones that use the trivial behavior.
- bool invalidate(IRUnitT, const PreservedAnalyses &PA) override {
- return !PA.preserved(PassT::ID());
- }
-
- ResultT Result;
-};
-
-/// \brief Specialization of \c AnalysisResultModel which delegates invalidate
-/// handling to \c ResultT.
-template <typename IRUnitT, typename PassT, typename ResultT>
-struct AnalysisResultModel<IRUnitT, PassT, ResultT, true>
- : AnalysisResultConcept<IRUnitT> {
- explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
- AnalysisResultModel(AnalysisResultModel &&Arg)
- : Result(std::move(Arg.Result)) {}
- friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
- using std::swap;
- swap(LHS.Result, RHS.Result);
- }
- AnalysisResultModel &operator=(AnalysisResultModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- /// \brief The model delegates to the \c ResultT method.
- bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override {
- return Result.invalidate(IR, PA);
- }
-
- ResultT Result;
-};
-
-/// \brief Abstract concept of an analysis pass.
-///
-/// This concept is parameterized over the IR unit that it can run over and
-/// produce an analysis result.
-template <typename IRUnitT, typename AnalysisManagerT>
-struct AnalysisPassConcept {
- virtual ~AnalysisPassConcept() {}
-
- /// \brief Method to run this analysis over a unit of IR.
- /// \returns A unique_ptr to the analysis result object to be queried by
- /// users.
- virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT IR, AnalysisManagerT *AM) = 0;
-};
-
-/// \brief Wrapper to model the analysis pass concept.
-///
-/// Can wrap any type which implements a suitable \c run method. The method
-/// must accept the IRUnitT as an argument and produce an object which can be
-/// wrapped in a \c AnalysisResultModel.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, AnalysisManagerT, PassT, typename PassT::Result>::Value>
-struct AnalysisPassModel;
-
-/// \brief Specialization of \c AnalysisPassModel which passes an
-/// \c AnalysisManager to PassT's run method.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, true>
- : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
- explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ /// \brief Construct a pass manager.
+ ///
+ /// It can be passed a flag to get debug logging as the passes are run.
+ PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
- AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- AnalysisPassModel &operator=(AnalysisPassModel RHS) {
- swap(*this, RHS);
+ PassManager(PassManager &&Arg)
+ : Passes(std::move(Arg.Passes)),
+ DebugLogging(std::move(Arg.DebugLogging)) {}
+ PassManager &operator=(PassManager &&RHS) {
+ Passes = std::move(RHS.Passes);
+ DebugLogging = std::move(RHS.DebugLogging);
return *this;
}
- // FIXME: Replace PassT::Result with type traits when we use C++11.
- typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
- ResultModelT;
-
- /// \brief The model delegates to the \c PassT::run method.
- ///
- /// The return is wrapped in an \c AnalysisResultModel.
- std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT IR, AnalysisManagerT *AM) override {
- return make_unique<ResultModelT>(Pass.run(IR, AM));
- }
+ /// \brief Run all of the passes in this manager over the IR.
+ PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM = nullptr) {
+ PreservedAnalyses PA = PreservedAnalyses::all();
- PassT Pass;
-};
+ if (DebugLogging)
+ dbgs() << "Starting pass manager run.\n";
-/// \brief Specialization of \c AnalysisPassModel which does not pass an
-/// \c AnalysisManager to PassT's run method.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, false>
- : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
- explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
- AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- AnalysisPassModel &operator=(AnalysisPassModel RHS) {
- swap(*this, RHS);
- return *this;
- }
+ for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
+ if (DebugLogging)
+ dbgs() << "Running pass: " << Passes[Idx]->name() << "\n";
- // FIXME: Replace PassT::Result with type traits when we use C++11.
- typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
- ResultModelT;
+ PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM);
- /// \brief The model delegates to the \c PassT::run method.
- ///
- /// The return is wrapped in an \c AnalysisResultModel.
- std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT IR, AnalysisManagerT *) override {
- return make_unique<ResultModelT>(Pass.run(IR));
- }
+ // If we have an active analysis manager at this level we want to ensure
+ // we update it as each pass runs and potentially invalidates analyses.
+ // We also update the preserved set of analyses based on what analyses we
+ // have already handled the invalidation for here and don't need to
+ // invalidate when finished.
+ if (AM)
+ PassPA = AM->invalidate(IR, std::move(PassPA));
- PassT Pass;
-};
+ // Finally, we intersect the final preserved analyses to compute the
+ // aggregate preserved set for this pass manager.
+ PA.intersect(std::move(PassPA));
-} // End namespace detail
+ // FIXME: Historically, the pass managers all called the LLVM context's
+ // yield function here. We don't have a generic way to acquire the
+ // context and it isn't yet clear what the right pattern is for yielding
+ // in the new pass manager so it is currently omitted.
+ //IR.getContext().yield();
+ }
-class ModuleAnalysisManager;
+ if (DebugLogging)
+ dbgs() << "Finished pass manager run.\n";
-class ModulePassManager {
-public:
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- ModulePassManager() {}
- ModulePassManager(ModulePassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
- ModulePassManager &operator=(ModulePassManager &&RHS) {
- Passes = std::move(RHS.Passes);
- return *this;
+ return PA;
}
- /// \brief Run all of the module passes in this module pass manager over
- /// a module.
- ///
- /// This method should only be called for a single module as there is the
- /// expectation that the lifetime of a pass is bounded to that of a module.
- PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = nullptr);
-
- template <typename ModulePassT> void addPass(ModulePassT Pass) {
- Passes.emplace_back(new ModulePassModel<ModulePassT>(std::move(Pass)));
+ template <typename PassT> void addPass(PassT Pass) {
+ typedef detail::PassModel<IRUnitT, PassT> PassModelT;
+ Passes.emplace_back(new PassModelT(std::move(Pass)));
}
- static StringRef name() { return "ModulePassManager"; }
+ static StringRef name() { return "PassManager"; }
private:
- // Pull in the concept type and model template specialized for modules.
- typedef detail::PassConcept<Module *, ModuleAnalysisManager>
- ModulePassConcept;
- template <typename PassT>
- struct ModulePassModel
- : detail::PassModel<Module *, ModuleAnalysisManager, PassT> {
- ModulePassModel(PassT Pass)
- : detail::PassModel<Module *, ModuleAnalysisManager, PassT>(
- std::move(Pass)) {}
- };
+ typedef detail::PassConcept<IRUnitT> PassConceptT;
- ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION;
- ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION;
+ PassManager(const PassManager &) LLVM_DELETED_FUNCTION;
+ PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION;
- std::vector<std::unique_ptr<ModulePassConcept>> Passes;
-};
-
-class FunctionAnalysisManager;
+ std::vector<std::unique_ptr<PassConceptT>> Passes;
-class FunctionPassManager {
-public:
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- FunctionPassManager() {}
- FunctionPassManager(FunctionPassManager &&Arg)
- : Passes(std::move(Arg.Passes)) {}
- FunctionPassManager &operator=(FunctionPassManager &&RHS) {
- Passes = std::move(RHS.Passes);
- return *this;
- }
-
- template <typename FunctionPassT> void addPass(FunctionPassT Pass) {
- Passes.emplace_back(new FunctionPassModel<FunctionPassT>(std::move(Pass)));
- }
-
- PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = nullptr);
-
- static StringRef name() { return "FunctionPassManager"; }
-
-private:
- // Pull in the concept type and model template specialized for functions.
- typedef detail::PassConcept<Function *, FunctionAnalysisManager>
- FunctionPassConcept;
- template <typename PassT>
- struct FunctionPassModel
- : detail::PassModel<Function *, FunctionAnalysisManager, PassT> {
- FunctionPassModel(PassT Pass)
- : detail::PassModel<Function *, FunctionAnalysisManager, PassT>(
- std::move(Pass)) {}
- };
+ /// \brief Flag indicating whether we should do debug logging.
+ bool DebugLogging;
+};
- FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION;
- FunctionPassManager &
- operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION;
+/// \brief Convenience typedef for a pass manager over modules.
+typedef PassManager<Module> ModulePassManager;
- std::vector<std::unique_ptr<FunctionPassConcept>> Passes;
-};
+/// \brief Convenience typedef for a pass manager over functions.
+typedef PassManager<Function> FunctionPassManager;
namespace detail {
@@ -560,6 +269,12 @@ namespace detail {
/// - invalidateImpl
///
/// The details of the call pattern are within.
+///
+/// Note that there is also a generic analysis manager template which implements
+/// the above required functions along with common datastructures used for
+/// managing analyses. This base class is factored so that if you need to
+/// customize the handling of a specific IR unit, you can do so without
+/// replicating *all* of the boilerplate.
template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase {
DerivedT *derived_this() { return static_cast<DerivedT *>(this); }
const DerivedT *derived_this() const {
@@ -572,7 +287,7 @@ template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase {
protected:
typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT;
- typedef detail::AnalysisPassConcept<IRUnitT, DerivedT> PassConceptT;
+ typedef detail::AnalysisPassConcept<IRUnitT> PassConceptT;
// FIXME: Provide template aliases for the models when we're using C++11 in
// a mode supporting them.
@@ -592,7 +307,7 @@ public:
///
/// If there is not a valid cached result in the manager already, this will
/// re-run the analysis to produce a valid result.
- template <typename PassT> typename PassT::Result &getResult(IRUnitT IR) {
+ template <typename PassT> typename PassT::Result &getResult(IRUnitT &IR) {
assert(AnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being queried");
@@ -609,7 +324,7 @@ public:
///
/// \returns null if there is no cached result.
template <typename PassT>
- typename PassT::Result *getCachedResult(IRUnitT IR) const {
+ typename PassT::Result *getCachedResult(IRUnitT &IR) const {
assert(AnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being queried");
@@ -631,25 +346,28 @@ public:
template <typename PassT> void registerPass(PassT Pass) {
assert(!AnalysisPasses.count(PassT::ID()) &&
"Registered the same analysis pass twice!");
- typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT;
+ typedef detail::AnalysisPassModel<IRUnitT, PassT> PassModelT;
AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass)));
}
/// \brief Invalidate a specific analysis pass for an IR module.
///
/// Note that the analysis result can disregard invalidation.
- template <typename PassT> void invalidate(Module *M) {
+ template <typename PassT> void invalidate(IRUnitT &IR) {
assert(AnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being invalidated");
- derived_this()->invalidateImpl(PassT::ID(), M);
+ derived_this()->invalidateImpl(PassT::ID(), IR);
}
/// \brief Invalidate analyses cached for an IR unit.
///
/// Walk through all of the analyses pertaining to this unit of IR and
/// invalidate them unless they are preserved by the PreservedAnalyses set.
- void invalidate(IRUnitT IR, const PreservedAnalyses &PA) {
- derived_this()->invalidateImpl(IR, PA);
+ /// We accept the PreservedAnalyses set by value and update it with each
+ /// analyis pass which has been successfully invalidated and thus can be
+ /// preserved going forward. The updated set is returned.
+ PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) {
+ return derived_this()->invalidateImpl(IR, std::move(PA));
}
protected:
@@ -679,108 +397,153 @@ private:
} // End namespace detail
-/// \brief A module analysis pass manager with lazy running and caching of
+/// \brief A generic analysis pass manager with lazy running and caching of
/// results.
-class ModuleAnalysisManager
- : public detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> {
- friend class detail::AnalysisManagerBase<ModuleAnalysisManager, Module *>;
- typedef detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> BaseT;
- typedef BaseT::ResultConceptT ResultConceptT;
- typedef BaseT::PassConceptT PassConceptT;
-
-public:
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- ModuleAnalysisManager() {}
- ModuleAnalysisManager(ModuleAnalysisManager &&Arg)
- : BaseT(std::move(static_cast<BaseT &>(Arg))),
- ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {}
- ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) {
- BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
- ModuleAnalysisResults = std::move(RHS.ModuleAnalysisResults);
- return *this;
- }
-
-private:
- ModuleAnalysisManager(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION;
- ModuleAnalysisManager &
- operator=(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION;
-
- /// \brief Get a module pass result, running the pass if necessary.
- ResultConceptT &getResultImpl(void *PassID, Module *M);
-
- /// \brief Get a cached module pass result or return null.
- ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const;
-
- /// \brief Invalidate a module pass result.
- void invalidateImpl(void *PassID, Module *M);
-
- /// \brief Invalidate results across a module.
- void invalidateImpl(Module *M, const PreservedAnalyses &PA);
-
- /// \brief Map type from module analysis pass ID to pass result concept
- /// pointer.
- typedef DenseMap<void *,
- std::unique_ptr<detail::AnalysisResultConcept<Module *>>>
- ModuleAnalysisResultMapT;
-
- /// \brief Cache of computed module analysis results for this module.
- ModuleAnalysisResultMapT ModuleAnalysisResults;
-};
-
-/// \brief A function analysis manager to coordinate and cache analyses run over
-/// a module.
-class FunctionAnalysisManager
- : public detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> {
- friend class detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>;
- typedef detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>
- BaseT;
- typedef BaseT::ResultConceptT ResultConceptT;
- typedef BaseT::PassConceptT PassConceptT;
+///
+/// This analysis manager can be used for any IR unit where the address of the
+/// IR unit sufficies as its identity. It manages the cache for a unit of IR via
+/// the address of each unit of IR cached.
+template <typename IRUnitT>
+class AnalysisManager
+ : public detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT> {
+ friend class detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT>;
+ typedef detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT> BaseT;
+ typedef typename BaseT::ResultConceptT ResultConceptT;
+ typedef typename BaseT::PassConceptT PassConceptT;
public:
// Most public APIs are inherited from the CRTP base class.
+ /// \brief Construct an empty analysis manager.
+ ///
+ /// A flag can be passed to indicate that the manager should perform debug
+ /// logging.
+ AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}
+
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- FunctionAnalysisManager() {}
- FunctionAnalysisManager(FunctionAnalysisManager &&Arg)
+ AnalysisManager(AnalysisManager &&Arg)
: BaseT(std::move(static_cast<BaseT &>(Arg))),
- FunctionAnalysisResults(std::move(Arg.FunctionAnalysisResults)) {}
- FunctionAnalysisManager &operator=(FunctionAnalysisManager &&RHS) {
+ AnalysisResults(std::move(Arg.AnalysisResults)),
+ DebugLogging(std::move(Arg.DebugLogging)) {}
+ AnalysisManager &operator=(AnalysisManager &&RHS) {
BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
- FunctionAnalysisResults = std::move(RHS.FunctionAnalysisResults);
+ AnalysisResults = std::move(RHS.AnalysisResults);
+ DebugLogging = std::move(RHS.DebugLogging);
return *this;
}
/// \brief Returns true if the analysis manager has an empty results cache.
- bool empty() const;
+ bool empty() const {
+ assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&
+ "The storage and index of analysis results disagree on how many "
+ "there are!");
+ return AnalysisResults.empty();
+ }
- /// \brief Clear the function analysis result cache.
+ /// \brief Clear the analysis result cache.
///
- /// This routine allows cleaning up when the set of functions itself has
+ /// This routine allows cleaning up when the set of IR units itself has
/// potentially changed, and thus we can't even look up a a result and
- /// invalidate it directly. Notably, this does *not* call invalidate
- /// functions as there is nothing to be done for them.
- void clear();
+ /// invalidate it directly. Notably, this does *not* call invalidate functions
+ /// as there is nothing to be done for them.
+ void clear() {
+ AnalysisResults.clear();
+ AnalysisResultLists.clear();
+ }
private:
- FunctionAnalysisManager(const FunctionAnalysisManager &)
- LLVM_DELETED_FUNCTION;
- FunctionAnalysisManager &
- operator=(const FunctionAnalysisManager &) LLVM_DELETED_FUNCTION;
+ AnalysisManager(const AnalysisManager &) LLVM_DELETED_FUNCTION;
+ AnalysisManager &operator=(const AnalysisManager &) LLVM_DELETED_FUNCTION;
+
+ /// \brief Get an analysis result, running the pass if necessary.
+ ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) {
+ typename AnalysisResultMapT::iterator RI;
+ bool Inserted;
+ std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair(
+ std::make_pair(PassID, &IR), typename AnalysisResultListT::iterator()));
+
+ // If we don't have a cached result for this function, look up the pass and
+ // run it to produce a result, which we then add to the cache.
+ if (Inserted) {
+ auto &P = this->lookupPass(PassID);
+ if (DebugLogging)
+ dbgs() << "Running analysis: " << P.name() << "\n";
+ AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
+ ResultList.emplace_back(PassID, P.run(IR, this));
+ RI->second = std::prev(ResultList.end());
+ }
- /// \brief Get a function pass result, running the pass if necessary.
- ResultConceptT &getResultImpl(void *PassID, Function *F);
+ return *RI->second->second;
+ }
- /// \brief Get a cached function pass result or return null.
- ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const;
+ /// \brief Get a cached analysis result or return null.
+ ResultConceptT *getCachedResultImpl(void *PassID, IRUnitT &IR) const {
+ typename AnalysisResultMapT::const_iterator RI =
+ AnalysisResults.find(std::make_pair(PassID, &IR));
+ return RI == AnalysisResults.end() ? nullptr : &*RI->second->second;
+ }
/// \brief Invalidate a function pass result.
- void invalidateImpl(void *PassID, Function *F);
+ void invalidateImpl(void *PassID, IRUnitT &IR) {
+ typename AnalysisResultMapT::iterator RI =
+ AnalysisResults.find(std::make_pair(PassID, &IR));
+ if (RI == AnalysisResults.end())
+ return;
+
+ if (DebugLogging)
+ dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name()
+ << "\n";
+ AnalysisResultLists[&IR].erase(RI->second);
+ AnalysisResults.erase(RI);
+ }
/// \brief Invalidate the results for a function..
- void invalidateImpl(Function *F, const PreservedAnalyses &PA);
+ PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) {
+ // Short circuit for a common case of all analyses being preserved.
+ if (PA.areAllPreserved())
+ return std::move(PA);
+
+ if (DebugLogging)
+ dbgs() << "Invalidating all non-preserved analyses for: "
+ << IR.getName() << "\n";
+
+ // Clear all the invalidated results associated specifically with this
+ // function.
+ SmallVector<void *, 8> InvalidatedPassIDs;
+ AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];
+ for (typename AnalysisResultListT::iterator I = ResultsList.begin(),
+ E = ResultsList.end();
+ I != E;) {
+ void *PassID = I->first;
+
+ // Pass the invalidation down to the pass itself to see if it thinks it is
+ // necessary. The analysis pass can return false if no action on the part
+ // of the analysis manager is required for this invalidation event.
+ if (I->second->invalidate(IR, PA)) {
+ if (DebugLogging)
+ dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name()
+ << "\n";
+
+ InvalidatedPassIDs.push_back(I->first);
+ I = ResultsList.erase(I);
+ } else {
+ ++I;
+ }
+
+ // After handling each pass, we mark it as preserved. Once we've
+ // invalidated any stale results, the rest of the system is allowed to
+ // start preserving this analysis again.
+ PA.preserve(PassID);
+ }
+ while (!InvalidatedPassIDs.empty())
+ AnalysisResults.erase(
+ std::make_pair(InvalidatedPassIDs.pop_back_val(), &IR));
+ if (ResultsList.empty())
+ AnalysisResultLists.erase(&IR);
+
+ return std::move(PA);
+ }
/// \brief List of function analysis pass IDs and associated concept pointers.
///
@@ -788,30 +551,37 @@ private:
/// erases. Provides both the pass ID and concept pointer such that it is
/// half of a bijection and provides storage for the actual result concept.
typedef std::list<std::pair<
- void *, std::unique_ptr<detail::AnalysisResultConcept<Function *>>>>
- FunctionAnalysisResultListT;
+ void *, std::unique_ptr<detail::AnalysisResultConcept<IRUnitT>>>>
+ AnalysisResultListT;
/// \brief Map type from function pointer to our custom list type.
- typedef DenseMap<Function *, FunctionAnalysisResultListT>
- FunctionAnalysisResultListMapT;
+ typedef DenseMap<IRUnitT *, AnalysisResultListT> AnalysisResultListMapT;
/// \brief Map from function to a list of function analysis results.
///
/// Provides linear time removal of all analysis results for a function and
/// the ultimate storage for a particular cached analysis result.
- FunctionAnalysisResultListMapT FunctionAnalysisResultLists;
+ AnalysisResultListMapT AnalysisResultLists;
/// \brief Map type from a pair of analysis ID and function pointer to an
/// iterator into a particular result list.
- typedef DenseMap<std::pair<void *, Function *>,
- FunctionAnalysisResultListT::iterator>
- FunctionAnalysisResultMapT;
+ typedef DenseMap<std::pair<void *, IRUnitT *>,
+ typename AnalysisResultListT::iterator> AnalysisResultMapT;
/// \brief Map from an analysis ID and function to a particular cached
/// analysis result.
- FunctionAnalysisResultMapT FunctionAnalysisResults;
+ AnalysisResultMapT AnalysisResults;
+
+ /// \brief A flag indicating whether debug logging is enabled.
+ bool DebugLogging;
};
+/// \brief Convenience typedef for the Module analysis manager.
+typedef AnalysisManager<Module> ModuleAnalysisManager;
+
+/// \brief Convenience typedef for the Function analysis manager.
+typedef AnalysisManager<Function> FunctionAnalysisManager;
+
/// \brief A module analysis which acts as a proxy for a function analysis
/// manager.
///
@@ -826,6 +596,8 @@ public:
static void *ID() { return (void *)&PassID; }
+ static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; }
+
explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM)
: FAM(&FAM) {}
// We have to explicitly define all the special member functions because MSVC
@@ -850,7 +622,7 @@ public:
/// In debug builds, it will also assert that the analysis manager is empty
/// as no queries should arrive at the function analysis manager prior to
/// this analysis being requested.
- Result run(Module *M);
+ Result run(Module &M);
private:
static char PassID;
@@ -888,7 +660,7 @@ public:
/// Regardless of whether this analysis is marked as preserved, all of the
/// analyses in the \c FunctionAnalysisManager are potentially invalidated
/// based on the set of preserved analyses.
- bool invalidate(Module *M, const PreservedAnalyses &PA);
+ bool invalidate(Module &M, const PreservedAnalyses &PA);
private:
FunctionAnalysisManager *FAM;
@@ -924,7 +696,7 @@ public:
const ModuleAnalysisManager &getManager() const { return *MAM; }
/// \brief Handle invalidation by ignoring it, this pass is immutable.
- bool invalidate(Function *) { return false; }
+ bool invalidate(Function &) { return false; }
private:
const ModuleAnalysisManager *MAM;
@@ -932,6 +704,8 @@ public:
static void *ID() { return (void *)&PassID; }
+ static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; }
+
ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM)
: MAM(&MAM) {}
// We have to explicitly define all the special member functions because MSVC
@@ -950,7 +724,7 @@ public:
/// \brief Run the analysis pass and create our proxy result object.
/// Nothing to see here, it just forwards the \c MAM reference into the
/// result.
- Result run(Function *) { return Result(*MAM); }
+ Result run(Function &) { return Result(*MAM); }
private:
static char PassID;
@@ -966,6 +740,20 @@ private:
/// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function
/// pass over the module to enable a \c FunctionAnalysisManager to be used
/// within this run safely.
+///
+/// Function passes run within this adaptor can rely on having exclusive access
+/// to the function they are run over. They should not read or modify any other
+/// functions! Other threads or systems may be manipulating other functions in
+/// the module, and so their state should never be relied on.
+/// FIXME: Make the above true for all of LLVM's actual passes, some still
+/// violate this principle.
+///
+/// Function passes can also read the module containing the function, but they
+/// should not modify that module outside of the use lists of various globals.
+/// For example, a function pass is not permitted to add functions to the
+/// module.
+/// FIXME: Make the above true for all of LLVM's actual passes, some still
+/// violate this principle.
template <typename FunctionPassT> class ModuleToFunctionPassAdaptor {
public:
explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass)
@@ -976,7 +764,8 @@ public:
: Pass(Arg.Pass) {}
ModuleToFunctionPassAdaptor(ModuleToFunctionPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
- friend void swap(ModuleToFunctionPassAdaptor &LHS, ModuleToFunctionPassAdaptor &RHS) {
+ friend void swap(ModuleToFunctionPassAdaptor &LHS,
+ ModuleToFunctionPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
}
@@ -986,21 +775,23 @@ public:
}
/// \brief Runs the function pass across every function in the module.
- PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
FunctionAnalysisManager *FAM = nullptr;
if (AM)
// Setup the function analysis manager from its proxy.
FAM = &AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
PreservedAnalyses PA = PreservedAnalyses::all();
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
- PreservedAnalyses PassPA = Pass.run(I, FAM);
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ PreservedAnalyses PassPA = Pass.run(*I, FAM);
// We know that the function pass couldn't have invalidated any other
// function's analyses (that's the contract of a function pass), so
- // directly handle the function analysis manager's invalidation here.
+ // directly handle the function analysis manager's invalidation here and
+ // update our preserved set to reflect that these have already been
+ // handled.
if (FAM)
- FAM->invalidate(I, PassPA);
+ PassPA = FAM->invalidate(*I, std::move(PassPA));
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@@ -1029,6 +820,66 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
return std::move(ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
}
+/// \brief A template utility pass to force an analysis result to be available.
+///
+/// This is a no-op pass which simply forces a specific analysis pass's result
+/// to be available when it is run.
+template <typename AnalysisT> struct RequireAnalysisPass {
+ /// \brief Run this pass over some unit of IR.
+ ///
+ /// This pass can be run over any unit of IR and use any analysis manager
+ /// provided they satisfy the basic API requirements. When this pass is
+ /// created, these methods can be instantiated to satisfy whatever the
+ /// context requires.
+ template <typename IRUnitT>
+ PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) {
+ if (AM)
+ (void)AM->template getResult<AnalysisT>(Arg);
+
+ return PreservedAnalyses::all();
+ }
+
+ static StringRef name() { return "RequireAnalysisPass"; }
+};
+
+/// \brief A template utility pass to force an analysis result to be
+/// invalidated.
+///
+/// This is a no-op pass which simply forces a specific analysis result to be
+/// invalidated when it is run.
+template <typename AnalysisT> struct InvalidateAnalysisPass {
+ /// \brief Run this pass over some unit of IR.
+ ///
+ /// This pass can be run over any unit of IR and use any analysis manager
+ /// provided they satisfy the basic API requirements. When this pass is
+ /// created, these methods can be instantiated to satisfy whatever the
+ /// context requires.
+ template <typename IRUnitT>
+ PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) {
+ if (AM)
+ // We have to directly invalidate the analysis result as we can't
+ // enumerate all other analyses and use the preserved set to control it.
+ (void)AM->template invalidate<AnalysisT>(Arg);
+
+ return PreservedAnalyses::all();
+ }
+
+ static StringRef name() { return "InvalidateAnalysisPass"; }
+};
+
+/// \brief A utility pass that does nothing but preserves no analyses.
+///
+/// As a consequence fo not preserving any analyses, this pass will force all
+/// analysis passes to be re-run to produce fresh results if any are needed.
+struct InvalidateAllAnalysesPass {
+ /// \brief Run this pass over some unit of IR.
+ template <typename IRUnitT> PreservedAnalyses run(IRUnitT &Arg) {
+ return PreservedAnalyses::none();
+ }
+
+ static StringRef name() { return "InvalidateAllAnalysesPass"; }
+};
+
}
#endif
diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h
new file mode 100644
index 000000000000..297f5f4e07f4
--- /dev/null
+++ b/include/llvm/IR/PassManagerInternal.h
@@ -0,0 +1,349 @@
+//===- PassManager internal APIs and implementation details -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This header provides internal APIs and implementation details used by the
+/// pass management interfaces exposed in PassManager.h. To understand more
+/// context of why these particular interfaces are needed, see that header
+/// file. None of these APIs should be used elsewhere.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_PASSMANAGERINTERNAL_H
+#define LLVM_IR_PASSMANAGERINTERNAL_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+template <typename IRUnitT> class AnalysisManager;
+class PreservedAnalyses;
+
+/// \brief Implementation details of the pass manager interfaces.
+namespace detail {
+
+/// \brief Template for the abstract base class used to dispatch
+/// polymorphically over pass objects.
+template <typename IRUnitT> struct PassConcept {
+ // Boiler plate necessary for the container of derived classes.
+ virtual ~PassConcept() {}
+
+ /// \brief The polymorphic API which runs the pass over a given IR entity.
+ ///
+ /// Note that actual pass object can omit the analysis manager argument if
+ /// desired. Also that the analysis manager may be null if there is no
+ /// analysis manager in the pass pipeline.
+ virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
+
+ /// \brief Polymorphic method to access the name of a pass.
+ virtual StringRef name() = 0;
+};
+
+/// \brief SFINAE metafunction for computing whether \c PassT has a run method
+/// accepting an \c AnalysisManager<IRUnitT>.
+template <typename IRUnitT, typename PassT, typename ResultT>
+class PassRunAcceptsAnalysisManager {
+ typedef char SmallType;
+ struct BigType {
+ char a, b;
+ };
+
+ template <typename T, ResultT (T::*)(IRUnitT &, AnalysisManager<IRUnitT> *)>
+ struct Checker;
+
+ template <typename T> static SmallType f(Checker<T, &T::run> *);
+ template <typename T> static BigType f(...);
+
+public:
+ enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
+};
+
+/// \brief A template wrapper used to implement the polymorphic API.
+///
+/// Can be instantiated for any object which provides a \c run method accepting
+/// an \c IRUnitT. It requires the pass to be a copyable object. When the
+/// \c run method also accepts an \c AnalysisManager<IRUnitT>*, we pass it
+/// along.
+template <typename IRUnitT, typename PassT,
+ typename PreservedAnalysesT = PreservedAnalyses,
+ bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
+ IRUnitT, PassT, PreservedAnalysesT>::Value>
+struct PassModel;
+
+/// \brief Specialization of \c PassModel for passes that accept an analyis
+/// manager.
+template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
+struct PassModel<IRUnitT, PassT, PreservedAnalysesT, true>
+ : PassConcept<IRUnitT> {
+ explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
+ PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+ friend void swap(PassModel &LHS, PassModel &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ PassModel &operator=(PassModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ return Pass.run(IR, AM);
+ }
+ StringRef name() override { return PassT::name(); }
+ PassT Pass;
+};
+
+/// \brief Specialization of \c PassModel for passes that accept an analyis
+/// manager.
+template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
+struct PassModel<IRUnitT, PassT, PreservedAnalysesT, false>
+ : PassConcept<IRUnitT> {
+ explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
+ PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+ friend void swap(PassModel &LHS, PassModel &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ PassModel &operator=(PassModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ return Pass.run(IR);
+ }
+ StringRef name() override { return PassT::name(); }
+ PassT Pass;
+};
+
+/// \brief Abstract concept of an analysis result.
+///
+/// This concept is parameterized over the IR unit that this result pertains
+/// to.
+template <typename IRUnitT> struct AnalysisResultConcept {
+ virtual ~AnalysisResultConcept() {}
+
+ /// \brief Method to try and mark a result as invalid.
+ ///
+ /// When the outer analysis manager detects a change in some underlying
+ /// unit of the IR, it will call this method on all of the results cached.
+ ///
+ /// This method also receives a set of preserved analyses which can be used
+ /// to avoid invalidation because the pass which changed the underlying IR
+ /// took care to update or preserve the analysis result in some way.
+ ///
+ /// \returns true if the result is indeed invalid (the default).
+ virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0;
+};
+
+/// \brief SFINAE metafunction for computing whether \c ResultT provides an
+/// \c invalidate member function.
+template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
+ typedef char SmallType;
+ struct BigType {
+ char a, b;
+ };
+
+ template <typename T, bool (T::*)(IRUnitT &, const PreservedAnalyses &)>
+ struct Checker;
+
+ template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
+ template <typename T> static BigType f(...);
+
+public:
+ enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
+};
+
+/// \brief Wrapper to model the analysis result concept.
+///
+/// By default, this will implement the invalidate method with a trivial
+/// implementation so that the actual analysis result doesn't need to provide
+/// an invalidation handler. It is only selected when the invalidation handler
+/// is not part of the ResultT's interface.
+template <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT = PreservedAnalyses,
+ bool HasInvalidateHandler =
+ ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
+struct AnalysisResultModel;
+
+/// \brief Specialization of \c AnalysisResultModel which provides the default
+/// invalidate functionality.
+template <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, false>
+ : AnalysisResultConcept<IRUnitT> {
+ explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
+ AnalysisResultModel(AnalysisResultModel &&Arg)
+ : Result(std::move(Arg.Result)) {}
+ friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
+ using std::swap;
+ swap(LHS.Result, RHS.Result);
+ }
+ AnalysisResultModel &operator=(AnalysisResultModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ /// \brief The model bases invalidation solely on being in the preserved set.
+ //
+ // FIXME: We should actually use two different concepts for analysis results
+ // rather than two different models, and avoid the indirect function call for
+ // ones that use the trivial behavior.
+ bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override {
+ return !PA.preserved(PassT::ID());
+ }
+
+ ResultT Result;
+};
+
+/// \brief Specialization of \c AnalysisResultModel which delegates invalidate
+/// handling to \c ResultT.
+template <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, true>
+ : AnalysisResultConcept<IRUnitT> {
+ explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
+ AnalysisResultModel(AnalysisResultModel &&Arg)
+ : Result(std::move(Arg.Result)) {}
+ friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
+ using std::swap;
+ swap(LHS.Result, RHS.Result);
+ }
+ AnalysisResultModel &operator=(AnalysisResultModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ /// \brief The model delegates to the \c ResultT method.
+ bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override {
+ return Result.invalidate(IR, PA);
+ }
+
+ ResultT Result;
+};
+
+/// \brief Abstract concept of an analysis pass.
+///
+/// This concept is parameterized over the IR unit that it can run over and
+/// produce an analysis result.
+template <typename IRUnitT> struct AnalysisPassConcept {
+ virtual ~AnalysisPassConcept() {}
+
+ /// \brief Method to run this analysis over a unit of IR.
+ /// \returns A unique_ptr to the analysis result object to be queried by
+ /// users.
+ virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
+
+ /// \brief Polymorphic method to access the name of a pass.
+ virtual StringRef name() = 0;
+};
+
+/// \brief Wrapper to model the analysis pass concept.
+///
+/// Can wrap any type which implements a suitable \c run method. The method
+/// must accept the IRUnitT as an argument and produce an object which can be
+/// wrapped in a \c AnalysisResultModel.
+template <typename IRUnitT, typename PassT,
+ bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
+ IRUnitT, PassT, typename PassT::Result>::Value>
+struct AnalysisPassModel;
+
+/// \brief Specialization of \c AnalysisPassModel which passes an
+/// \c AnalysisManager to PassT's run method.
+template <typename IRUnitT, typename PassT>
+struct AnalysisPassModel<IRUnitT, PassT, true> : AnalysisPassConcept<IRUnitT> {
+ explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
+ AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+ friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ AnalysisPassModel &operator=(AnalysisPassModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ // FIXME: Replace PassT::Result with type traits when we use C++11.
+ typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
+ ResultModelT;
+
+ /// \brief The model delegates to the \c PassT::run method.
+ ///
+ /// The return is wrapped in an \c AnalysisResultModel.
+ std::unique_ptr<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ return make_unique<ResultModelT>(Pass.run(IR, AM));
+ }
+
+ /// \brief The model delegates to a static \c PassT::name method.
+ ///
+ /// The returned string ref must point to constant immutable data!
+ StringRef name() override { return PassT::name(); }
+
+ PassT Pass;
+};
+
+/// \brief Specialization of \c AnalysisPassModel which does not pass an
+/// \c AnalysisManager to PassT's run method.
+template <typename IRUnitT, typename PassT>
+struct AnalysisPassModel<IRUnitT, PassT, false> : AnalysisPassConcept<IRUnitT> {
+ explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
+ AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+ friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ AnalysisPassModel &operator=(AnalysisPassModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ // FIXME: Replace PassT::Result with type traits when we use C++11.
+ typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
+ ResultModelT;
+
+ /// \brief The model delegates to the \c PassT::run method.
+ ///
+ /// The return is wrapped in an \c AnalysisResultModel.
+ std::unique_ptr<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *) override {
+ return make_unique<ResultModelT>(Pass.run(IR));
+ }
+
+ /// \brief The model delegates to a static \c PassT::name method.
+ ///
+ /// The returned string ref must point to constant immutable data!
+ StringRef name() override { return PassT::name(); }
+
+ PassT Pass;
+};
+
+} // End namespace detail
+}
+
+#endif
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index 2efb29489473..f94e10576893 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -32,61 +32,64 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Operator.h"
namespace llvm {
namespace PatternMatch {
-template<typename Val, typename Pattern>
-bool match(Val *V, const Pattern &P) {
- return const_cast<Pattern&>(P).match(V);
+template <typename Val, typename Pattern> bool match(Val *V, const Pattern &P) {
+ return const_cast<Pattern &>(P).match(V);
}
-
-template<typename SubPattern_t>
-struct OneUse_match {
+template <typename SubPattern_t> struct OneUse_match {
SubPattern_t SubPattern;
OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
return V->hasOneUse() && SubPattern.match(V);
}
};
-template<typename T>
-inline OneUse_match<T> m_OneUse(const T &SubPattern) { return SubPattern; }
-
+template <typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) {
+ return SubPattern;
+}
-template<typename Class>
-struct class_match {
- template<typename ITy>
- bool match(ITy *V) { return isa<Class>(V); }
+template <typename Class> struct class_match {
+ template <typename ITy> bool match(ITy *V) { return isa<Class>(V); }
};
-/// m_Value() - Match an arbitrary value and ignore it.
+/// \brief Match an arbitrary value and ignore it.
inline class_match<Value> m_Value() { return class_match<Value>(); }
-/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it.
+
+/// \brief Match an arbitrary binary operation and ignore it.
+inline class_match<BinaryOperator> m_BinOp() {
+ return class_match<BinaryOperator>();
+}
+
+/// \brief Matches any compare instruction and ignore it.
+inline class_match<CmpInst> m_Cmp() { return class_match<CmpInst>(); }
+
+/// \brief Match an arbitrary ConstantInt and ignore it.
inline class_match<ConstantInt> m_ConstantInt() {
return class_match<ConstantInt>();
}
-/// m_Undef() - Match an arbitrary undef constant.
+
+/// \brief Match an arbitrary undef constant.
inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
+/// \brief Match an arbitrary Constant and ignore it.
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
/// Matching combinators
-template<typename LTy, typename RTy>
-struct match_combine_or {
+template <typename LTy, typename RTy> struct match_combine_or {
LTy L;
RTy R;
- match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { }
+ match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {}
- template<typename ITy>
- bool match(ITy *V) {
+ template <typename ITy> bool match(ITy *V) {
if (L.match(V))
return true;
if (R.match(V))
@@ -95,15 +98,13 @@ struct match_combine_or {
}
};
-template<typename LTy, typename RTy>
-struct match_combine_and {
+template <typename LTy, typename RTy> struct match_combine_and {
LTy L;
RTy R;
- match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { }
+ match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {}
- template<typename ITy>
- bool match(ITy *V) {
+ template <typename ITy> bool match(ITy *V) {
if (L.match(V))
if (R.match(V))
return true;
@@ -112,46 +113,44 @@ struct match_combine_and {
};
/// Combine two pattern matchers matching L || R
-template<typename LTy, typename RTy>
+template <typename LTy, typename RTy>
inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) {
return match_combine_or<LTy, RTy>(L, R);
}
/// Combine two pattern matchers matching L && R
-template<typename LTy, typename RTy>
+template <typename LTy, typename RTy>
inline match_combine_and<LTy, RTy> m_CombineAnd(const LTy &L, const RTy &R) {
return match_combine_and<LTy, RTy>(L, R);
}
struct match_zero {
- template<typename ITy>
- bool match(ITy *V) {
- if (const Constant *C = dyn_cast<Constant>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *C = dyn_cast<Constant>(V))
return C->isNullValue();
return false;
}
};
-/// m_Zero() - Match an arbitrary zero/null constant. This includes
+/// \brief Match an arbitrary zero/null constant. This includes
/// zero_initializer for vectors and ConstantPointerNull for pointers.
inline match_zero m_Zero() { return match_zero(); }
struct match_neg_zero {
- template<typename ITy>
- bool match(ITy *V) {
- if (const Constant *C = dyn_cast<Constant>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *C = dyn_cast<Constant>(V))
return C->isNegativeZeroValue();
return false;
}
};
-/// m_NegZero() - Match an arbitrary zero/null constant. This includes
+/// \brief Match an arbitrary zero/null constant. This includes
/// zero_initializer for vectors and ConstantPointerNull for pointers. For
/// floating point constants, this will match negative zero but not positive
/// zero
inline match_neg_zero m_NegZero() { return match_neg_zero(); }
-/// m_AnyZero() - Match an arbitrary zero/null constant. This includes
+/// \brief - Match an arbitrary zero/null constant. This includes
/// zero_initializer for vectors and ConstantPointerNull for pointers. For
/// floating point constants, this will match negative zero and positive zero
inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() {
@@ -161,16 +160,14 @@ inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() {
struct apint_match {
const APInt *&Res;
apint_match(const APInt *&R) : Res(R) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ template <typename ITy> bool match(ITy *V) {
+ if (auto *CI = dyn_cast<ConstantInt>(V)) {
Res = &CI->getValue();
return true;
}
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(C->getSplatValue())) {
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) {
Res = &CI->getValue();
return true;
}
@@ -178,16 +175,13 @@ struct apint_match {
}
};
-/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the
+/// \brief Match a ConstantInt or splatted ConstantVector, binding the
/// specified pointer to the contained APInt.
inline apint_match m_APInt(const APInt *&Res) { return Res; }
-
-template<int64_t Val>
-struct constantint_match {
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+template <int64_t Val> struct constantint_match {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V)) {
const APInt &CIV = CI->getValue();
if (Val >= 0)
return CIV == static_cast<uint64_t>(Val);
@@ -200,45 +194,39 @@ struct constantint_match {
}
};
-/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value.
-template<int64_t Val>
-inline constantint_match<Val> m_ConstantInt() {
+/// \brief Match a ConstantInt with a specific value.
+template <int64_t Val> inline constantint_match<Val> m_ConstantInt() {
return constantint_match<Val>();
}
-/// cst_pred_ty - This helper class is used to match scalar and vector constants
-/// that satisfy a specified predicate.
-template<typename Predicate>
-struct cst_pred_ty : public Predicate {
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
+/// \brief This helper class is used to match scalar and vector constants that
+/// satisfy a specified predicate.
+template <typename Predicate> struct cst_pred_ty : public Predicate {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V))
return this->isValue(CI->getValue());
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (const ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (const auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
return this->isValue(CI->getValue());
return false;
}
};
-/// api_pred_ty - This helper class is used to match scalar and vector constants
-/// that satisfy a specified predicate, and bind them to an APInt.
-template<typename Predicate>
-struct api_pred_ty : public Predicate {
+/// \brief This helper class is used to match scalar and vector constants that
+/// satisfy a specified predicate, and bind them to an APInt.
+template <typename Predicate> struct api_pred_ty : public Predicate {
const APInt *&Res;
api_pred_ty(const APInt *&R) : Res(R) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V))
if (this->isValue(CI->getValue())) {
Res = &CI->getValue();
return true;
}
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
if (this->isValue(CI->getValue())) {
Res = &CI->getValue();
return true;
@@ -248,12 +236,11 @@ struct api_pred_ty : public Predicate {
}
};
-
struct is_one {
bool isValue(const APInt &C) { return C == 1; }
};
-/// m_One() - Match an integer 1 or a vector with all elements equal to 1.
+/// \brief Match an integer 1 or a vector with all elements equal to 1.
inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); }
inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; }
@@ -261,34 +248,43 @@ struct is_all_ones {
bool isValue(const APInt &C) { return C.isAllOnesValue(); }
};
-/// m_AllOnes() - Match an integer or vector with all bits set to true.
-inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();}
+/// \brief Match an integer or vector with all bits set to true.
+inline cst_pred_ty<is_all_ones> m_AllOnes() {
+ return cst_pred_ty<is_all_ones>();
+}
inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; }
struct is_sign_bit {
bool isValue(const APInt &C) { return C.isSignBit(); }
};
-/// m_SignBit() - Match an integer or vector with only the sign bit(s) set.
-inline cst_pred_ty<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();}
+/// \brief Match an integer or vector with only the sign bit(s) set.
+inline cst_pred_ty<is_sign_bit> m_SignBit() {
+ return cst_pred_ty<is_sign_bit>();
+}
inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; }
struct is_power2 {
bool isValue(const APInt &C) { return C.isPowerOf2(); }
};
-/// m_Power2() - Match an integer or vector power of 2.
+/// \brief Match an integer or vector power of 2.
inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); }
inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; }
-template<typename Class>
-struct bind_ty {
+struct is_maxsignedvalue {
+ bool isValue(const APInt &C) { return C.isMaxSignedValue(); }
+};
+
+inline cst_pred_ty<is_maxsignedvalue> m_MaxSignedValue() { return cst_pred_ty<is_maxsignedvalue>(); }
+inline api_pred_ty<is_maxsignedvalue> m_MaxSignedValue(const APInt *&V) { return V; }
+
+template <typename Class> struct bind_ty {
Class *&VR;
bind_ty(Class *&V) : VR(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (Class *CV = dyn_cast<Class>(V)) {
+ template <typename ITy> bool match(ITy *V) {
+ if (auto *CV = dyn_cast<Class>(V)) {
VR = CV;
return true;
}
@@ -296,64 +292,62 @@ struct bind_ty {
}
};
-/// m_Value - Match a value, capturing it if we match.
+/// \brief Match a value, capturing it if we match.
inline bind_ty<Value> m_Value(Value *&V) { return V; }
-/// m_ConstantInt - Match a ConstantInt, capturing the value if we match.
+/// \brief Match a binary operator, capturing it if we match.
+inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; }
+
+/// \brief Match a ConstantInt, capturing the value if we match.
inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; }
-/// m_Constant - Match a Constant, capturing the value if we match.
+/// \brief Match a Constant, capturing the value if we match.
inline bind_ty<Constant> m_Constant(Constant *&C) { return C; }
-/// m_ConstantFP - Match a ConstantFP, capturing the value if we match.
+/// \brief Match a ConstantFP, capturing the value if we match.
inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; }
-/// specificval_ty - Match a specified Value*.
+/// \brief Match a specified Value*.
struct specificval_ty {
const Value *Val;
specificval_ty(const Value *V) : Val(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- return V == Val;
- }
+ template <typename ITy> bool match(ITy *V) { return V == Val; }
};
-/// m_Specific - Match if we have a specific specified value.
+/// \brief Match if we have a specific specified value.
inline specificval_ty m_Specific(const Value *V) { return V; }
-/// Match a specified floating point value or vector of all elements of that
-/// value.
+/// \brief Match a specified floating point value or vector of all elements of
+/// that value.
struct specific_fpval {
double Val;
specific_fpval(double V) : Val(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CFP = dyn_cast<ConstantFP>(V))
return CFP->isExactlyValue(Val);
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue()))
return CFP->isExactlyValue(Val);
return false;
}
};
-/// Match a specific floating point value or vector with all elements equal to
-/// the value.
+/// \brief Match a specific floating point value or vector with all elements
+/// equal to the value.
inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); }
-/// Match a float 1.0 or vector with all elements equal to 1.0.
+/// \brief Match a float 1.0 or vector with all elements equal to 1.0.
inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); }
struct bind_const_intval_ty {
uint64_t &VR;
bind_const_intval_ty(uint64_t &V) : VR(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (ConstantInt *CV = dyn_cast<ConstantInt>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CV = dyn_cast<ConstantInt>(V))
if (CV->getBitWidth() <= 64) {
VR = CV->getZExtValue();
return true;
@@ -362,152 +356,196 @@ struct bind_const_intval_ty {
}
};
-/// m_ConstantInt - Match a ConstantInt and bind to its value. This does not
-/// match ConstantInts wider than 64-bits.
+/// \brief Match a specified integer value or vector of all elements of that
+// value.
+struct specific_intval {
+ uint64_t Val;
+ specific_intval(uint64_t V) : Val(V) {}
+
+ template <typename ITy> bool match(ITy *V) {
+ const auto *CI = dyn_cast<ConstantInt>(V);
+ if (!CI && V->getType()->isVectorTy())
+ if (const auto *C = dyn_cast<Constant>(V))
+ CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue());
+
+ if (CI && CI->getBitWidth() <= 64)
+ return CI->getZExtValue() == Val;
+
+ return false;
+ }
+};
+
+/// \brief Match a specific integer value or vector with all elements equal to
+/// the value.
+inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); }
+
+/// \brief Match a ConstantInt and bind to its value. This does not match
+/// ConstantInts wider than 64-bits.
inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; }
//===----------------------------------------------------------------------===//
+// Matcher for any binary operator.
+//
+template <typename LHS_t, typename RHS_t> struct AnyBinaryOp_match {
+ LHS_t L;
+ RHS_t R;
+
+ AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
+
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *I = dyn_cast<BinaryOperator>(V))
+ return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
+ return false;
+ }
+};
+
+template <typename LHS, typename RHS>
+inline AnyBinaryOp_match<LHS, RHS> m_BinOp(const LHS &L, const RHS &R) {
+ return AnyBinaryOp_match<LHS, RHS>(L, R);
+}
+
+//===----------------------------------------------------------------------===//
// Matchers for specific binary operators.
//
-template<typename LHS_t, typename RHS_t, unsigned Opcode>
+template <typename LHS_t, typename RHS_t, unsigned Opcode>
struct BinaryOp_match {
LHS_t L;
RHS_t R;
BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opcode) {
- BinaryOperator *I = cast<BinaryOperator>(V);
+ auto *I = cast<BinaryOperator>(V);
return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
}
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ if (auto *CE = dyn_cast<ConstantExpr>(V))
return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) &&
R.match(CE->getOperand(1));
return false;
}
};
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Add>
-m_Add(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FAdd>
-m_FAdd(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Sub>
-m_Sub(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FSub>
-m_FSub(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Mul>
-m_Mul(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FMul>
-m_FMul(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::UDiv>
-m_UDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::SDiv>
-m_SDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FDiv>
-m_FDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::URem>
-m_URem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::SRem>
-m_SRem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FRem>
-m_FRem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::And>
-m_And(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::And>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Or>
-m_Or(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Xor>
-m_Xor(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Shl>
-m_Shl(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::LShr>
-m_LShr(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::AShr>
-m_AShr(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R);
}
-template<typename LHS_t, typename RHS_t, unsigned Opcode, unsigned WrapFlags = 0>
+template <typename LHS_t, typename RHS_t, unsigned Opcode,
+ unsigned WrapFlags = 0>
struct OverflowingBinaryOp_match {
LHS_t L;
RHS_t R;
- OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
+ OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS)
+ : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (OverflowingBinaryOperator *Op = dyn_cast<OverflowingBinaryOperator>(V)) {
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *Op = dyn_cast<OverflowingBinaryOperator>(V)) {
if (Op->getOpcode() != Opcode)
return false;
if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap &&
@@ -591,43 +629,42 @@ m_NUWShl(const LHS &L, const RHS &R) {
//===----------------------------------------------------------------------===//
// Class that matches two different binary ops.
//
-template<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2>
+template <typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2>
struct BinOp2_match {
LHS_t L;
RHS_t R;
BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opc1 ||
V->getValueID() == Value::InstructionVal + Opc2) {
- BinaryOperator *I = cast<BinaryOperator>(V);
+ auto *I = cast<BinaryOperator>(V);
return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
}
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ if (auto *CE = dyn_cast<ConstantExpr>(V))
return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) &&
L.match(CE->getOperand(0)) && R.match(CE->getOperand(1));
return false;
}
};
-/// m_Shr - Matches LShr or AShr.
-template<typename LHS, typename RHS>
+/// \brief Matches LShr or AShr.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>
m_Shr(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R);
}
-/// m_LogicalShift - Matches LShr or Shl.
-template<typename LHS, typename RHS>
+/// \brief Matches LShr or Shl.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>
m_LogicalShift(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R);
}
-/// m_IDiv - Matches UDiv and SDiv.
-template<typename LHS, typename RHS>
+/// \brief Matches UDiv and SDiv.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>
m_IDiv(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R);
@@ -636,38 +673,36 @@ m_IDiv(const LHS &L, const RHS &R) {
//===----------------------------------------------------------------------===//
// Class that matches exact binary ops.
//
-template<typename SubPattern_t>
-struct Exact_match {
+template <typename SubPattern_t> struct Exact_match {
SubPattern_t SubPattern;
Exact_match(const SubPattern_t &SP) : SubPattern(SP) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (PossiblyExactOperator *PEO = dyn_cast<PossiblyExactOperator>(V))
return PEO->isExact() && SubPattern.match(V);
return false;
}
};
-template<typename T>
-inline Exact_match<T> m_Exact(const T &SubPattern) { return SubPattern; }
+template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
+ return SubPattern;
+}
//===----------------------------------------------------------------------===//
// Matchers for CmpInst classes
//
-template<typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
+template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
struct CmpClass_match {
PredicateTy &Predicate;
LHS_t L;
RHS_t R;
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
- : Predicate(Pred), L(LHS), R(RHS) {}
+ : Predicate(Pred), L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (Class *I = dyn_cast<Class>(V))
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
Predicate = I->getPredicate();
@@ -677,123 +712,114 @@ struct CmpClass_match {
}
};
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
+inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
+m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R);
+}
+
+template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS,
- ICmpInst, ICmpInst::Predicate>(Pred, L, R);
+ return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R);
}
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS,
- FCmpInst, FCmpInst::Predicate>(Pred, L, R);
+ return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
}
//===----------------------------------------------------------------------===//
// Matchers for SelectInst classes
//
-template<typename Cond_t, typename LHS_t, typename RHS_t>
+template <typename Cond_t, typename LHS_t, typename RHS_t>
struct SelectClass_match {
Cond_t C;
LHS_t L;
RHS_t R;
- SelectClass_match(const Cond_t &Cond, const LHS_t &LHS,
- const RHS_t &RHS)
- : C(Cond), L(LHS), R(RHS) {}
+ SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, const RHS_t &RHS)
+ : C(Cond), L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (SelectInst *I = dyn_cast<SelectInst>(V))
- return C.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)) &&
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *I = dyn_cast<SelectInst>(V))
+ return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) &&
R.match(I->getOperand(2));
return false;
}
};
-template<typename Cond, typename LHS, typename RHS>
-inline SelectClass_match<Cond, LHS, RHS>
-m_Select(const Cond &C, const LHS &L, const RHS &R) {
+template <typename Cond, typename LHS, typename RHS>
+inline SelectClass_match<Cond, LHS, RHS> m_Select(const Cond &C, const LHS &L,
+ const RHS &R) {
return SelectClass_match<Cond, LHS, RHS>(C, L, R);
}
-/// m_SelectCst - This matches a select of two constants, e.g.:
-/// m_SelectCst<-1, 0>(m_Value(V))
-template<int64_t L, int64_t R, typename Cond>
-inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> >
+/// \brief This matches a select of two constants, e.g.:
+/// m_SelectCst<-1, 0>(m_Value(V))
+template <int64_t L, int64_t R, typename Cond>
+inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R>>
m_SelectCst(const Cond &C) {
return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>());
}
-
//===----------------------------------------------------------------------===//
// Matchers for CastInst classes
//
-template<typename Op_t, unsigned Opcode>
-struct CastClass_match {
+template <typename Op_t, unsigned Opcode> struct CastClass_match {
Op_t Op;
CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
return O->getOpcode() == Opcode && Op.match(O->getOperand(0));
return false;
}
};
-/// m_BitCast
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::BitCast>
-m_BitCast(const OpTy &Op) {
+/// \brief Matches BitCast.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::BitCast> m_BitCast(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::BitCast>(Op);
}
-/// m_PtrToInt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::PtrToInt>
-m_PtrToInt(const OpTy &Op) {
+/// \brief Matches PtrToInt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::PtrToInt> m_PtrToInt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::PtrToInt>(Op);
}
-/// m_Trunc
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::Trunc>
-m_Trunc(const OpTy &Op) {
+/// \brief Matches Trunc.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::Trunc> m_Trunc(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::Trunc>(Op);
}
-/// m_SExt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::SExt>
-m_SExt(const OpTy &Op) {
+/// \brief Matches SExt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::SExt> m_SExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SExt>(Op);
}
-/// m_ZExt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::ZExt>
-m_ZExt(const OpTy &Op) {
+/// \brief Matches ZExt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::ZExt>(Op);
}
-/// m_UIToFP
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::UIToFP>
-m_UIToFP(const OpTy &Op) {
+/// \brief Matches UIToFP.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::UIToFP>(Op);
}
-/// m_SIToFP
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::SIToFP>
-m_SIToFP(const OpTy &Op) {
+/// \brief Matches SIToFP.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::SIToFP> m_SIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SIToFP>(Op);
}
@@ -801,46 +827,41 @@ m_SIToFP(const OpTy &Op) {
// Matchers for unary operators
//
-template<typename LHS_t>
-struct not_match {
+template <typename LHS_t> struct not_match {
LHS_t L;
not_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
if (O->getOpcode() == Instruction::Xor)
return matchIfNot(O->getOperand(0), O->getOperand(1));
return false;
}
+
private:
bool matchIfNot(Value *LHS, Value *RHS) {
return (isa<ConstantInt>(RHS) || isa<ConstantDataVector>(RHS) ||
// FIXME: Remove CV.
isa<ConstantVector>(RHS)) &&
- cast<Constant>(RHS)->isAllOnesValue() &&
- L.match(LHS);
+ cast<Constant>(RHS)->isAllOnesValue() && L.match(LHS);
}
};
-template<typename LHS>
-inline not_match<LHS> m_Not(const LHS &L) { return L; }
+template <typename LHS> inline not_match<LHS> m_Not(const LHS &L) { return L; }
-
-template<typename LHS_t>
-struct neg_match {
+template <typename LHS_t> struct neg_match {
LHS_t L;
neg_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
if (O->getOpcode() == Instruction::Sub)
return matchIfNeg(O->getOperand(0), O->getOperand(1));
return false;
}
+
private:
bool matchIfNeg(Value *LHS, Value *RHS) {
return ((isa<ConstantInt>(LHS) && cast<ConstantInt>(LHS)->isZero()) ||
@@ -849,36 +870,33 @@ private:
}
};
-/// m_Neg - Match an integer negate.
-template<typename LHS>
-inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
-
+/// \brief Match an integer negate.
+template <typename LHS> inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
-template<typename LHS_t>
-struct fneg_match {
+template <typename LHS_t> struct fneg_match {
LHS_t L;
fneg_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
if (O->getOpcode() == Instruction::FSub)
return matchIfFNeg(O->getOperand(0), O->getOperand(1));
return false;
}
+
private:
bool matchIfFNeg(Value *LHS, Value *RHS) {
- if (ConstantFP *C = dyn_cast<ConstantFP>(LHS))
+ if (const auto *C = dyn_cast<ConstantFP>(LHS))
return C->isNegativeZeroValue() && L.match(RHS);
return false;
}
};
-/// m_FNeg - Match a floating point negate.
-template<typename LHS>
-inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
-
+/// \brief Match a floating point negate.
+template <typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) {
+ return L;
+}
//===----------------------------------------------------------------------===//
// Matchers for control flow.
@@ -886,13 +904,10 @@ inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
struct br_match {
BasicBlock *&Succ;
- br_match(BasicBlock *&Succ)
- : Succ(Succ) {
- }
+ br_match(BasicBlock *&Succ) : Succ(Succ) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (BranchInst *BI = dyn_cast<BranchInst>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *BI = dyn_cast<BranchInst>(V))
if (BI->isUnconditional()) {
Succ = BI->getSuccessor(0);
return true;
@@ -903,17 +918,14 @@ struct br_match {
inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); }
-template<typename Cond_t>
-struct brc_match {
+template <typename Cond_t> struct brc_match {
Cond_t Cond;
BasicBlock *&T, *&F;
brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f)
- : Cond(C), T(t), F(f) {
- }
+ : Cond(C), T(t), F(f) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (BranchInst *BI = dyn_cast<BranchInst>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *BI = dyn_cast<BranchInst>(V))
if (BI->isConditional() && Cond.match(BI->getCondition())) {
T = BI->getSuccessor(0);
F = BI->getSuccessor(1);
@@ -923,31 +935,28 @@ struct brc_match {
}
};
-template<typename Cond_t>
+template <typename Cond_t>
inline brc_match<Cond_t> m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) {
return brc_match<Cond_t>(C, T, F);
}
-
//===----------------------------------------------------------------------===//
// Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y).
//
-template<typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t>
+template <typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t>
struct MaxMin_match {
LHS_t L;
RHS_t R;
- MaxMin_match(const LHS_t &LHS, const RHS_t &RHS)
- : L(LHS), R(RHS) {}
+ MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
// Look for "(x pred y) ? x : y" or "(x pred y) ? y : x".
- SelectInst *SI = dyn_cast<SelectInst>(V);
+ auto *SI = dyn_cast<SelectInst>(V);
if (!SI)
return false;
- CmpInst_t *Cmp = dyn_cast<CmpInst_t>(SI->getCondition());
+ auto *Cmp = dyn_cast<CmpInst_t>(SI->getCondition());
if (!Cmp)
return false;
// At this point we have a select conditioned on a comparison. Check that
@@ -959,8 +968,8 @@ struct MaxMin_match {
if ((TrueVal != LHS || FalseVal != RHS) &&
(TrueVal != RHS || FalseVal != LHS))
return false;
- typename CmpInst_t::Predicate Pred = LHS == TrueVal ?
- Cmp->getPredicate() : Cmp->getSwappedPredicate();
+ typename CmpInst_t::Predicate Pred =
+ LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate();
// Does "(x pred y) ? x : y" represent the desired max/min operation?
if (!Pred_t::match(Pred))
return false;
@@ -969,83 +978,83 @@ struct MaxMin_match {
}
};
-/// smax_pred_ty - Helper class for identifying signed max predicates.
+/// \brief Helper class for identifying signed max predicates.
struct smax_pred_ty {
static bool match(ICmpInst::Predicate Pred) {
return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE;
}
};
-/// smin_pred_ty - Helper class for identifying signed min predicates.
+/// \brief Helper class for identifying signed min predicates.
struct smin_pred_ty {
static bool match(ICmpInst::Predicate Pred) {
return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE;
}
};
-/// umax_pred_ty - Helper class for identifying unsigned max predicates.
+/// \brief Helper class for identifying unsigned max predicates.
struct umax_pred_ty {
static bool match(ICmpInst::Predicate Pred) {
return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE;
}
};
-/// umin_pred_ty - Helper class for identifying unsigned min predicates.
+/// \brief Helper class for identifying unsigned min predicates.
struct umin_pred_ty {
static bool match(ICmpInst::Predicate Pred) {
return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE;
}
};
-/// ofmax_pred_ty - Helper class for identifying ordered max predicates.
+/// \brief Helper class for identifying ordered max predicates.
struct ofmax_pred_ty {
static bool match(FCmpInst::Predicate Pred) {
return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE;
}
};
-/// ofmin_pred_ty - Helper class for identifying ordered min predicates.
+/// \brief Helper class for identifying ordered min predicates.
struct ofmin_pred_ty {
static bool match(FCmpInst::Predicate Pred) {
return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE;
}
};
-/// ufmax_pred_ty - Helper class for identifying unordered max predicates.
+/// \brief Helper class for identifying unordered max predicates.
struct ufmax_pred_ty {
static bool match(FCmpInst::Predicate Pred) {
return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE;
}
};
-/// ufmin_pred_ty - Helper class for identifying unordered min predicates.
+/// \brief Helper class for identifying unordered min predicates.
struct ufmin_pred_ty {
static bool match(FCmpInst::Predicate Pred) {
return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE;
}
};
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>
-m_SMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty> m_SMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>
-m_SMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty> m_SMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>
-m_UMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty> m_UMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>
-m_UMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> m_UMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>(L, R);
}
@@ -1058,9 +1067,9 @@ m_UMin(const LHS &L, const RHS &R) {
///
/// max(L, R) iff L and R are not NaN
/// m_OrdFMax(L, R) = R iff L or R are NaN
-template<typename LHS, typename RHS>
-inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>
-m_OrdFMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> m_OrdFMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>(L, R);
}
@@ -1073,9 +1082,9 @@ m_OrdFMax(const LHS &L, const RHS &R) {
///
/// max(L, R) iff L and R are not NaN
/// m_OrdFMin(L, R) = R iff L or R are NaN
-template<typename LHS, typename RHS>
-inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>
-m_OrdFMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>(L, R);
}
@@ -1088,7 +1097,7 @@ m_OrdFMin(const LHS &L, const RHS &R) {
///
/// max(L, R) iff L and R are not NaN
/// m_UnordFMin(L, R) = L iff L or R are NaN
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>
m_UnordFMax(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R);
@@ -1103,40 +1112,39 @@ m_UnordFMax(const LHS &L, const RHS &R) {
///
/// max(L, R) iff L and R are not NaN
/// m_UnordFMin(L, R) = L iff L or R are NaN
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>
m_UnordFMin(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R);
}
-template<typename Opnd_t>
-struct Argument_match {
+template <typename Opnd_t> struct Argument_match {
unsigned OpI;
Opnd_t Val;
- Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { }
+ Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
CallSite CS(V);
return CS.isCall() && Val.match(CS.getArgument(OpI));
}
};
-/// Match an argument
-template<unsigned OpI, typename Opnd_t>
+/// \brief Match an argument.
+template <unsigned OpI, typename Opnd_t>
inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) {
return Argument_match<Opnd_t>(OpI, Op);
}
-/// Intrinsic matchers.
+/// \brief Intrinsic matchers.
struct IntrinsicID_match {
unsigned ID;
- IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { }
+ IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- IntrinsicInst *II = dyn_cast<IntrinsicInst>(V);
- return II && II->getIntrinsicID() == ID;
+ template <typename OpTy> bool match(OpTy *V) {
+ if (const auto *CI = dyn_cast<CallInst>(V))
+ if (const auto *F = CI->getCalledFunction())
+ return F->getIntrinsicID() == ID;
+ return false;
}
};
@@ -1147,64 +1155,74 @@ struct IntrinsicID_match {
template <typename T0 = void, typename T1 = void, typename T2 = void,
typename T3 = void, typename T4 = void, typename T5 = void,
typename T6 = void, typename T7 = void, typename T8 = void,
- typename T9 = void, typename T10 = void> struct m_Intrinsic_Ty;
-template <typename T0>
-struct m_Intrinsic_Ty<T0> {
- typedef match_combine_and<IntrinsicID_match, Argument_match<T0> > Ty;
+ typename T9 = void, typename T10 = void>
+struct m_Intrinsic_Ty;
+template <typename T0> struct m_Intrinsic_Ty<T0> {
+ typedef match_combine_and<IntrinsicID_match, Argument_match<T0>> Ty;
};
-template <typename T0, typename T1>
-struct m_Intrinsic_Ty<T0, T1> {
- typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty,
- Argument_match<T1> > Ty;
+template <typename T0, typename T1> struct m_Intrinsic_Ty<T0, T1> {
+ typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty, Argument_match<T1>>
+ Ty;
};
template <typename T0, typename T1, typename T2>
struct m_Intrinsic_Ty<T0, T1, T2> {
typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1>::Ty,
- Argument_match<T2> > Ty;
+ Argument_match<T2>> Ty;
};
template <typename T0, typename T1, typename T2, typename T3>
struct m_Intrinsic_Ty<T0, T1, T2, T3> {
typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1, T2>::Ty,
- Argument_match<T3> > Ty;
+ Argument_match<T3>> Ty;
};
-/// Match intrinsic calls like this:
-/// m_Intrinsic<Intrinsic::fabs>(m_Value(X))
-template <Intrinsic::ID IntrID>
-inline IntrinsicID_match
-m_Intrinsic() { return IntrinsicID_match(IntrID); }
+/// \brief Match intrinsic calls like this:
+/// m_Intrinsic<Intrinsic::fabs>(m_Value(X))
+template <Intrinsic::ID IntrID> inline IntrinsicID_match m_Intrinsic() {
+ return IntrinsicID_match(IntrID);
+}
-template<Intrinsic::ID IntrID, typename T0>
-inline typename m_Intrinsic_Ty<T0>::Ty
-m_Intrinsic(const T0 &Op0) {
+template <Intrinsic::ID IntrID, typename T0>
+inline typename m_Intrinsic_Ty<T0>::Ty m_Intrinsic(const T0 &Op0) {
return m_CombineAnd(m_Intrinsic<IntrID>(), m_Argument<0>(Op0));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1>
-inline typename m_Intrinsic_Ty<T0, T1>::Ty
-m_Intrinsic(const T0 &Op0, const T1 &Op1) {
+template <Intrinsic::ID IntrID, typename T0, typename T1>
+inline typename m_Intrinsic_Ty<T0, T1>::Ty m_Intrinsic(const T0 &Op0,
+ const T1 &Op1) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0), m_Argument<1>(Op1));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2>
+template <Intrinsic::ID IntrID, typename T0, typename T1, typename T2>
inline typename m_Intrinsic_Ty<T0, T1, T2>::Ty
m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1), m_Argument<2>(Op2));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2, typename T3>
+template <Intrinsic::ID IntrID, typename T0, typename T1, typename T2,
+ typename T3>
inline typename m_Intrinsic_Ty<T0, T1, T2, T3>::Ty
m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1, Op2), m_Argument<3>(Op3));
}
-// Helper intrinsic matching specializations
-template<typename Opnd0>
-inline typename m_Intrinsic_Ty<Opnd0>::Ty
-m_BSwap(const Opnd0 &Op0) {
+// Helper intrinsic matching specializations.
+template <typename Opnd0>
+inline typename m_Intrinsic_Ty<Opnd0>::Ty m_BSwap(const Opnd0 &Op0) {
return m_Intrinsic<Intrinsic::bswap>(Op0);
}
+template <typename Opnd0, typename Opnd1>
+inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMin(const Opnd0 &Op0,
+ const Opnd1 &Op1) {
+ return m_Intrinsic<Intrinsic::minnum>(Op0, Op1);
+}
+
+template <typename Opnd0, typename Opnd1>
+inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMax(const Opnd0 &Op0,
+ const Opnd1 &Op1) {
+ return m_Intrinsic<Intrinsic::maxnum>(Op0, Op1);
+}
+
} // end namespace PatternMatch
} // end namespace llvm
diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h
index 02bc583a255a..5e1be37805ff 100644
--- a/include/llvm/IR/PredIteratorCache.h
+++ b/include/llvm/IR/PredIteratorCache.h
@@ -11,14 +11,14 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_IR_PREDITERATORCACHE_H
+#define LLVM_IR_PREDITERATORCACHE_H
+
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/CFG.h"
#include "llvm/Support/Allocator.h"
-#ifndef LLVM_IR_PREDITERATORCACHE_H
-#define LLVM_IR_PREDITERATORCACHE_H
-
namespace llvm {
/// PredIteratorCache - This class is an extremely trivial cache for
diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h
new file mode 100644
index 000000000000..e3c4243e9d81
--- /dev/null
+++ b/include/llvm/IR/Statepoint.h
@@ -0,0 +1,215 @@
+//===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains utility functions and a wrapper class analogous to
+// CallSite for accessing the fields of gc.statepoint, gc.relocate, and
+// gc.result intrinsics
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_IR_STATEPOINT_H
+#define __LLVM_IR_STATEPOINT_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+bool isStatepoint(const ImmutableCallSite &CS);
+bool isStatepoint(const Instruction *inst);
+bool isStatepoint(const Instruction &inst);
+
+bool isGCRelocate(const Instruction *inst);
+bool isGCRelocate(const ImmutableCallSite &CS);
+
+bool isGCResult(const Instruction *inst);
+bool isGCResult(const ImmutableCallSite &CS);
+
+/// Analogous to CallSiteBase, this provides most of the actual
+/// functionality for Statepoint and ImmutableStatepoint. It is
+/// templatized to allow easily specializing of const and non-const
+/// concrete subtypes. This is structured analogous to CallSite
+/// rather than the IntrinsicInst.h helpers since we want to support
+/// invokable statepoints in the near future.
+/// TODO: This does not currently allow the if(Statepoint S = ...)
+/// idiom used with CallSites. Consider refactoring to support.
+template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
+class StatepointBase {
+ CallSiteTy StatepointCS;
+ void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t s) LLVM_DELETED_FUNCTION;
+
+ protected:
+ explicit StatepointBase(InstructionTy *I) : StatepointCS(I) {
+ assert(isStatepoint(I));
+ }
+ explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) {
+ assert(isStatepoint(CS));
+ }
+
+ public:
+ typedef typename CallSiteTy::arg_iterator arg_iterator;
+
+ /// Return the underlying CallSite.
+ CallSiteTy getCallSite() {
+ return StatepointCS;
+ }
+
+ /// Return the value actually being called or invoked.
+ ValueTy *actualCallee() {
+ return StatepointCS.getArgument(0);
+ }
+ /// Number of arguments to be passed to the actual callee.
+ int numCallArgs() {
+ return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
+ }
+ /// Number of additional arguments excluding those intended
+ /// for garbage collection.
+ int numTotalVMSArgs() {
+ return cast<ConstantInt>(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue();
+ }
+
+ typename CallSiteTy::arg_iterator call_args_begin() {
+ // 3 = callTarget, #callArgs, flag
+ int Offset = 3;
+ assert(Offset <= (int)StatepointCS.arg_size());
+ return StatepointCS.arg_begin() + Offset;
+ }
+ typename CallSiteTy::arg_iterator call_args_end() {
+ int Offset = 3 + numCallArgs();
+ assert(Offset <= (int)StatepointCS.arg_size());
+ return StatepointCS.arg_begin() + Offset;
+ }
+
+ /// range adapter for call arguments
+ iterator_range<arg_iterator> call_args() {
+ return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
+ }
+
+ typename CallSiteTy::arg_iterator vm_state_begin() {
+ return call_args_end();
+ }
+ typename CallSiteTy::arg_iterator vm_state_end() {
+ int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs();
+ assert(Offset <= (int)StatepointCS.arg_size());
+ return StatepointCS.arg_begin() + Offset;
+ }
+
+ /// range adapter for vm state arguments
+ iterator_range<arg_iterator> vm_state_args() {
+ return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end());
+ }
+
+ typename CallSiteTy::arg_iterator first_vm_state_stack_begin() {
+ // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci,
+ // 1st_#stack, 1st_#local, 1st_#monitor
+ return vm_state_begin() + 6;
+ }
+
+ typename CallSiteTy::arg_iterator gc_args_begin() {
+ return vm_state_end();
+ }
+ typename CallSiteTy::arg_iterator gc_args_end() {
+ return StatepointCS.arg_end();
+ }
+
+ /// range adapter for gc arguments
+ iterator_range<arg_iterator> gc_args() {
+ return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
+ }
+
+
+#ifndef NDEBUG
+ /// Asserts if this statepoint is malformed. Common cases for failure
+ /// include incorrect length prefixes for variable length sections or
+ /// illegal values for parameters.
+ void verify() {
+ assert(numCallArgs() >= 0 &&
+ "number of arguments to actually callee can't be negative");
+
+ // The internal asserts in the iterator accessors do the rest.
+ (void)call_args_begin();
+ (void)call_args_end();
+ (void)vm_state_begin();
+ (void)vm_state_end();
+ (void)gc_args_begin();
+ (void)gc_args_end();
+ }
+#endif
+};
+
+/// A specialization of it's base class for read only access
+/// to a gc.statepoint.
+class ImmutableStatepoint
+ : public StatepointBase<const Instruction, const Value,
+ ImmutableCallSite> {
+ typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
+ Base;
+
+public:
+ explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
+ explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
+};
+
+/// A specialization of it's base class for read-write access
+/// to a gc.statepoint.
+class Statepoint : public StatepointBase<Instruction, Value, CallSite> {
+ typedef StatepointBase<Instruction, Value, CallSite> Base;
+
+public:
+ explicit Statepoint(Instruction *I) : Base(I) {}
+ explicit Statepoint(CallSite CS) : Base(CS) {}
+};
+
+/// Wraps a call to a gc.relocate and provides access to it's operands.
+/// TODO: This should likely be refactored to resememble the wrappers in
+/// InstrinsicInst.h.
+class GCRelocateOperands {
+ ImmutableCallSite RelocateCS;
+
+ public:
+ GCRelocateOperands(const User* U) : RelocateCS(U) {
+ assert(isGCRelocate(U));
+ }
+ GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
+ assert(isGCRelocate(inst));
+ }
+ GCRelocateOperands(CallSite CS) : RelocateCS(CS) {
+ assert(isGCRelocate(CS));
+ }
+
+ /// The statepoint with which this gc.relocate is associated.
+ const Instruction *statepoint() {
+ return cast<Instruction>(RelocateCS.getArgument(0));
+ }
+ /// The index into the associate statepoint's argument list
+ /// which contains the base pointer of the pointer whose
+ /// relocation this gc.relocate describes.
+ int basePtrIndex() {
+ return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue();
+ }
+ /// The index into the associate statepoint's argument list which
+ /// contains the pointer whose relocation this gc.relocate describes.
+ int derivedPtrIndex() {
+ return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
+ }
+ Value *basePtr() {
+ ImmutableCallSite CS(statepoint());
+ return *(CS.arg_begin() + basePtrIndex());
+ }
+ Value *derivedPtr() {
+ ImmutableCallSite CS(statepoint());
+ return *(CS.arg_begin() + derivedPtrIndex());
+ }
+};
+}
+#endif
diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h
new file mode 100644
index 000000000000..e24112154e16
--- /dev/null
+++ b/include/llvm/IR/TrackingMDRef.h
@@ -0,0 +1,170 @@
+//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// References to metadata that track RAUW.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_TRACKINGMDREF_H
+#define LLVM_IR_TRACKINGMDREF_H
+
+#include "llvm/IR/MetadataTracking.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+
+class Metadata;
+class MDNode;
+class ValueAsMetadata;
+
+/// \brief Tracking metadata reference.
+///
+/// This class behaves like \a TrackingVH, but for metadata.
+class TrackingMDRef {
+ Metadata *MD;
+
+public:
+ TrackingMDRef() : MD(nullptr) {}
+ explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
+
+ TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
+ TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
+ TrackingMDRef &operator=(TrackingMDRef &&X) {
+ if (&X == this)
+ return *this;
+
+ untrack();
+ MD = X.MD;
+ retrack(X);
+ return *this;
+ }
+ TrackingMDRef &operator=(const TrackingMDRef &X) {
+ if (&X == this)
+ return *this;
+
+ untrack();
+ MD = X.MD;
+ track();
+ return *this;
+ }
+ ~TrackingMDRef() { untrack(); }
+
+ Metadata *get() const { return MD; }
+ operator Metadata *() const { return get(); }
+ Metadata *operator->() const { return get(); }
+ Metadata &operator*() const { return *get(); }
+
+ void reset() {
+ untrack();
+ MD = nullptr;
+ }
+ void reset(Metadata *MD) {
+ untrack();
+ this->MD = MD;
+ track();
+ }
+
+ /// \brief Check whether this has a trivial destructor.
+ ///
+ /// If \c MD isn't replaceable, the destructor will be a no-op.
+ bool hasTrivialDestructor() const {
+ return !MD || !MetadataTracking::isReplaceable(*MD);
+ }
+
+ bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
+ bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
+
+private:
+ void track() {
+ if (MD)
+ MetadataTracking::track(MD);
+ }
+ void untrack() {
+ if (MD)
+ MetadataTracking::untrack(MD);
+ }
+ void retrack(TrackingMDRef &X) {
+ assert(MD == X.MD && "Expected values to match");
+ if (X.MD) {
+ MetadataTracking::retrack(X.MD, MD);
+ X.MD = nullptr;
+ }
+ }
+};
+
+/// \brief Typed tracking ref.
+///
+/// Track refererences of a particular type. It's useful to use this for \a
+/// MDNode and \a ValueAsMetadata.
+template <class T> class TypedTrackingMDRef {
+ TrackingMDRef Ref;
+
+public:
+ TypedTrackingMDRef() {}
+ explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
+
+ TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
+ TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
+ TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
+ Ref = std::move(X.Ref);
+ return *this;
+ }
+ TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
+ Ref = X.Ref;
+ return *this;
+ }
+
+ T *get() const { return (T *)Ref.get(); }
+ operator T *() const { return get(); }
+ T *operator->() const { return get(); }
+ T &operator*() const { return *get(); }
+
+ bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
+ bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
+
+ void reset() { Ref.reset(); }
+ void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
+
+ /// \brief Check whether this has a trivial destructor.
+ bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
+};
+
+typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
+typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
+
+// Expose the underlying metadata to casting.
+template <> struct simplify_type<TrackingMDRef> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const TrackingMDRef> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
+ return MD.get();
+ }
+};
+
+template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
+ typedef T *SimpleType;
+ static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
+ return MD.get();
+ }
+};
+
+template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
+ typedef T *SimpleType;
+ static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
+ return MD.get();
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h
index 7955587e3c76..c2073c7750b2 100644
--- a/include/llvm/IR/Type.h
+++ b/include/llvm/IR/Type.h
@@ -265,7 +265,7 @@ public:
/// get the actual size for a particular target, it is reasonable to use the
/// DataLayout subsystem to do this.
///
- bool isSized(SmallPtrSet<const Type*, 4> *Visited = nullptr) const {
+ bool isSized(SmallPtrSetImpl<const Type*> *Visited = nullptr) const {
// If it's a primitive, it is always sized.
if (getTypeID() == IntegerTyID || isFloatingPointTy() ||
getTypeID() == PointerTyID ||
@@ -313,6 +313,9 @@ public:
typedef Type * const *subtype_iterator;
subtype_iterator subtype_begin() const { return ContainedTys; }
subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];}
+ ArrayRef<Type*> subtypes() const {
+ return makeArrayRef(subtype_begin(), subtype_end());
+ }
typedef std::reverse_iterator<subtype_iterator> subtype_reverse_iterator;
subtype_reverse_iterator subtype_rbegin() const {
@@ -323,7 +326,7 @@ public:
}
/// getContainedType - This method is used to implement the type iterator
- /// (defined a the end of the file). For derived types, this returns the
+ /// (defined at the end of the file). For derived types, this returns the
/// types 'contained' in the derived type.
///
Type *getContainedType(unsigned i) const {
@@ -419,7 +422,7 @@ private:
/// isSizedDerivedType - Derived types like structures and arrays are sized
/// iff all of the members of the type are sized as well. Since asking for
/// their size is relatively uncommon, move this operation out of line.
- bool isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited = nullptr) const;
+ bool isSizedDerivedType(SmallPtrSetImpl<const Type*> *Visited = nullptr) const;
};
// Printing of types.
diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h
index cea66a4ab069..73a63ad0349e 100644
--- a/include/llvm/IR/TypeFinder.h
+++ b/include/llvm/IR/TypeFinder.h
@@ -31,6 +31,7 @@ class TypeFinder {
// To avoid walking constant expressions multiple times and other IR
// objects, we keep several helper maps.
DenseSet<const Value*> VisitedConstants;
+ DenseSet<const MDNode *> VisitedMetadata;
DenseSet<Type*> VisitedTypes;
std::vector<StructType*> StructTypes;
diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h
new file mode 100644
index 000000000000..5df459b1bd30
--- /dev/null
+++ b/include/llvm/IR/UseListOrder.h
@@ -0,0 +1,62 @@
+//===- llvm/IR/UseListOrder.h - LLVM Use List Order -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file has structures and command-line options for preserving use-list
+// order.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_USELISTORDER_H
+#define LLVM_IR_USELISTORDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include <vector>
+
+namespace llvm {
+
+class Module;
+class Function;
+class Value;
+
+/// \brief Structure to hold a use-list order.
+struct UseListOrder {
+ const Value *V;
+ const Function *F;
+ std::vector<unsigned> Shuffle;
+
+ UseListOrder(const Value *V, const Function *F, size_t ShuffleSize)
+ : V(V), F(F), Shuffle(ShuffleSize) {}
+
+ UseListOrder() : V(0), F(0) {}
+ UseListOrder(UseListOrder &&X)
+ : V(X.V), F(X.F), Shuffle(std::move(X.Shuffle)) {}
+ UseListOrder &operator=(UseListOrder &&X) {
+ V = X.V;
+ F = X.F;
+ Shuffle = std::move(X.Shuffle);
+ return *this;
+ }
+
+private:
+ UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION;
+ UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION;
+};
+
+typedef std::vector<UseListOrder> UseListOrderStack;
+
+/// \brief Whether to preserve use-list ordering.
+bool shouldPreserveBitcodeUseListOrder();
+bool shouldPreserveAssemblyUseListOrder();
+void setPreserveBitcodeUseListOrder(bool ShouldPreserve);
+void setPreserveAssemblyUseListOrder(bool ShouldPreserve);
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h
index 848adae9ceca..f578227d6cae 100644
--- a/include/llvm/IR/User.h
+++ b/include/llvm/IR/User.h
@@ -26,9 +26,9 @@
namespace llvm {
-/// OperandTraits - Compile-time customization of
-/// operand-related allocators and accessors
-/// for use of the User class
+/// \brief Compile-time customization of User operands.
+///
+/// Customizes operand-related allocators and accessors.
template <class>
struct OperandTraits;
@@ -39,11 +39,8 @@ class User : public Value {
friend struct HungoffOperandTraits;
virtual void anchor();
protected:
- /// NumOperands - The number of values used by this User.
+ /// \brief This is a pointer to the array of Uses for this User.
///
- unsigned NumOperands;
-
- /// OperandList - This is a pointer to the array of Uses for this User.
/// For nodes of fixed arity (e.g. a binary operator) this array will live
/// prefixed to some derived class instance. For nodes of resizable variable
/// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically
@@ -52,7 +49,9 @@ protected:
void *operator new(size_t s, unsigned Us);
User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps)
- : Value(ty, vty), NumOperands(NumOps), OperandList(OpList) {}
+ : Value(ty, vty), OperandList(OpList) {
+ NumOperands = NumOps;
+ }
Use *allocHungoffUses(unsigned) const;
void dropHungoffUses() {
Use::zap(OperandList, OperandList + NumOperands, true);
@@ -64,13 +63,13 @@ public:
~User() {
Use::zap(OperandList, OperandList + NumOperands);
}
- /// operator delete - free memory allocated for User and Use objects
+ /// \brief Free memory allocated for User and Use objects.
void operator delete(void *Usr);
- /// placement delete - required by std, but never called.
+ /// \brief Placement delete - required by std, but never called.
void operator delete(void*, unsigned) {
llvm_unreachable("Constructor throws?");
}
- /// placement delete - required by std, but never called.
+ /// \brief Placement delete - required by std, but never called.
void operator delete(void*, unsigned, bool) {
llvm_unreachable("Constructor throws?");
}
@@ -128,8 +127,7 @@ public:
return const_op_range(op_begin(), op_end());
}
- /// Convenience iterator for directly iterating over the Values in the
- /// OperandList
+ /// \brief 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 *,
@@ -150,22 +148,23 @@ public:
return iterator_range<value_op_iterator>(value_op_begin(), value_op_end());
}
- // dropAllReferences() - This function is in charge of "letting go" of all
- // objects that this User refers to. This allows one to
- // 'delete' a whole class at a time, even though there may be circular
- // references... First all references are dropped, and all use counts go to
- // zero. Then everything is deleted for real. Note that no operations are
- // valid on an object that has "dropped all references", except operator
- // delete.
- //
+ /// \brief 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
+ /// though there may be circular references... First all references are
+ /// dropped, and all use counts go to zero. Then everything is deleted for
+ /// real. Note that no operations are valid on an object that has "dropped
+ /// all references", except operator delete.
void dropAllReferences() {
for (Use &U : operands())
U.set(nullptr);
}
- /// replaceUsesOfWith - Replaces all references to the "From" definition with
- /// references to the "To" definition.
+ /// \brief Replace uses of one Value with another.
///
+ /// Replaces all references to the "From" definition with references to the
+ /// "To" definition.
void replaceUsesOfWith(Value *From, Value *To);
// Methods for support type inquiry through isa, cast, and dyn_cast:
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index b5bbc96eac2a..705fc0f52d58 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -37,7 +37,6 @@ class GlobalVariable;
class InlineAsm;
class Instruction;
class LLVMContext;
-class MDNode;
class Module;
class StringRef;
class Twine;
@@ -53,6 +52,8 @@ typedef StringMapEntry<Value*> ValueName;
// Value Class
//===----------------------------------------------------------------------===//
+/// \brief 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
/// the super class of other important classes such as Instruction and Function.
@@ -64,31 +65,45 @@ typedef StringMapEntry<Value*> ValueName;
/// using this Value. A Value can also have an arbitrary number of ValueHandle
/// objects that watch it and listen to RAUW and Destroy events. See
/// llvm/IR/ValueHandle.h for details.
-///
-/// @brief LLVM Value Representation
class Value {
Type *VTy;
Use *UseList;
- friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name.
+ friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD.
friend class ValueHandleBase;
- ValueName *Name;
+ PointerIntPair<ValueName *, 1> NameAndIsUsedByMD;
const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast)
unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this?
protected:
- /// SubclassOptionalData - This member is similar to SubclassData, however it
- /// is for holding information which may be used to aid optimization, but
- /// which may be cleared to zero without affecting conservative
- /// interpretation.
+ /// \brief 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
+ /// cleared to zero without affecting conservative interpretation.
unsigned char SubclassOptionalData : 7;
private:
- /// SubclassData - This member is defined by this class, but is not used for
- /// anything. Subclasses can use it to hold whatever state they find useful.
- /// This field is initialized to zero by the ctor.
+ /// \brief 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
+ /// field is initialized to zero by the ctor.
unsigned short SubclassData;
+protected:
+ /// \brief 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
+ /// any.
+ ///
+ /// This is stored here to save space in User on 64-bit hosts. Since most
+ /// instances of Value have operands, 32-bit hosts aren't significantly
+ /// affected.
+ unsigned NumOperands;
+
+private:
template <typename UseT> // UseT == 'Use' or 'const Use'
class use_iterator_impl
: public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> {
@@ -175,6 +190,7 @@ private:
Use &getUse() const { return *UI; }
/// \brief Return the operand # of this use in its User.
+ ///
/// FIXME: Replace all callers with a direct call to Use::getOperandNo.
unsigned getOperandNo() const { return UI->getOperandNo(); }
};
@@ -187,15 +203,14 @@ protected:
public:
virtual ~Value();
- /// dump - Support for debugging, callable in GDB: V->dump()
- //
+ /// \brief Support for debugging, callable in GDB: V->dump()
void dump() const;
- /// print - Implement operator<< on Value.
- ///
+ /// \brief Implement operator<< on Value.
void print(raw_ostream &O) const;
/// \brief 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
/// even constanst get pretty-printed; for example, the type of a null
@@ -203,40 +218,56 @@ public:
void printAsOperand(raw_ostream &O, bool PrintType = true,
const Module *M = nullptr) const;
- /// All values are typed, get the type of this value.
- ///
+ /// \brief All values are typed, get the type of this value.
Type *getType() const { return VTy; }
- /// All values hold a context through their type.
+ /// \brief All values hold a context through their type.
LLVMContext &getContext() const;
- // All values can potentially be named.
- bool hasName() const { return Name != nullptr && SubclassID != MDStringVal; }
- ValueName *getValueName() const { return Name; }
- void setValueName(ValueName *VN) { Name = VN; }
+ // \brief All values can potentially be named.
+ bool hasName() const { return getValueName() != nullptr; }
+ ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); }
+ void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); }
- /// getName() - Return a constant reference to the value's name. This is cheap
- /// and guaranteed to return the same reference as long as the value is not
- /// modified.
+private:
+ void destroyValueName();
+
+public:
+ /// \brief Return a constant reference to the value's name.
+ ///
+ /// This is cheap and guaranteed to return the same reference as long as the
+ /// value is not modified.
StringRef getName() const;
- /// setName() - Change the name of the value, choosing a new unique name if
- /// the provided name is taken.
+ /// \brief 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);
- /// takeName - transfer the name from V to this value, setting V's name to
- /// empty. It is an error to call V->takeName(V).
+ /// \brief 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);
- /// replaceAllUsesWith - Go through the uses list for this definition and make
- /// each use point to "V" instead of "this". After this completes, 'this's
- /// use list is guaranteed to be empty.
+ /// \brief 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);
+ /// replaceUsesOutsideBlock - Go through the uses list for this definition and
+ /// make each use point to "V" instead of "this" when the use is outside the
+ /// block. 'This's use list is expected to have at least one element.
+ /// Unlike replaceAllUsesWith this function does not support basic block
+ /// values or constant users.
+ void replaceUsesOutsideBlock(Value *V, BasicBlock *BB);
+
//----------------------------------------------------------------------
// Methods for handling the chain of uses of this Value.
//
@@ -255,6 +286,8 @@ public:
return iterator_range<const_use_iterator>(use_begin(), use_end());
}
+ bool user_empty() const { return UseList == nullptr; }
+
typedef user_iterator_impl<User> user_iterator;
typedef user_iterator_impl<const User> const_user_iterator;
user_iterator user_begin() { return user_iterator(UseList); }
@@ -270,36 +303,38 @@ public:
return iterator_range<const_user_iterator>(user_begin(), user_end());
}
- /// hasOneUse - Return true if there is exactly one user of this value. This
- /// is specialized because it is a common request and does not require
- /// traversing the whole use list.
+ /// \brief Return true if there is exactly one user of this value.
///
+ /// This is specialized because it is a common request and does not require
+ /// traversing the whole use list.
bool hasOneUse() const {
const_use_iterator I = use_begin(), E = use_end();
if (I == E) return false;
return ++I == E;
}
- /// hasNUses - Return true if this Value has exactly N users.
- ///
+ /// \brief Return true if this Value has exactly N users.
bool hasNUses(unsigned N) const;
- /// hasNUsesOrMore - Return true if this value has N users or more. This is
- /// logically equivalent to getNumUses() >= N.
+ /// \brief 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.
bool isUsedInBasicBlock(const BasicBlock *BB) const;
- /// getNumUses - This method computes the number of uses of this Value. This
- /// is a linear time operation. Use hasOneUse, hasNUses, or hasNUsesOrMore
- /// to check for specific values.
+ /// \brief 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;
- /// addUse - This method should only be used by the Use class.
- ///
+ /// \brief This method should only be used by the Use class.
void addUse(Use &U) { U.addToList(&UseList); }
+ /// \brief 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
/// Value classes SubclassID field. They are used for concrete type
@@ -322,8 +357,7 @@ public:
ConstantStructVal, // This is an instance of ConstantStruct
ConstantVectorVal, // This is an instance of ConstantVector
ConstantPointerNullVal, // This is an instance of ConstantPointerNull
- MDNodeVal, // This is an instance of MDNode
- MDStringVal, // This is an instance of MDString
+ MetadataAsValueVal, // This is an instance of MetadataAsValue
InlineAsmVal, // This is an instance of InlineAsm
InstructionVal, // This is an instance of Instruction
// Enum values starting at InstructionVal are used for Instructions;
@@ -334,11 +368,12 @@ public:
ConstantLastVal = ConstantPointerNullVal
};
- /// getValueID - Return an ID for the concrete type of this object. This is
- /// used to implement the classof checks. This should not be used for any
- /// other purpose, as the values may change as LLVM evolves. Also, note that
- /// for instructions, the Instruction's opcode is added to InstructionVal. So
- /// this means three things:
+ /// \brief Return an ID for the concrete type of this object.
+ ///
+ /// This is used to implement the classof checks. This should not be used
+ /// for any other purpose, as the values may change as LLVM evolves. Also,
+ /// note that for instructions, the Instruction's opcode is added to
+ /// InstructionVal. So this means three things:
/// # there is no value with code InstructionVal (no opcode==0).
/// # there are more possible values for the value type than in ValueTy enum.
/// # the InstructionVal enumerator must be the highest valued enumerator in
@@ -347,64 +382,62 @@ public:
return SubclassID;
}
- /// getRawSubclassOptionalData - Return the raw optional flags value
- /// contained in this value. This should only be used when testing two
- /// Values for equivalence.
+ /// \brief Return the raw optional flags value contained in this value.
+ ///
+ /// This should only be used when testing two Values for equivalence.
unsigned getRawSubclassOptionalData() const {
return SubclassOptionalData;
}
- /// clearSubclassOptionalData - Clear the optional flags contained in
- /// this value.
+ /// \brief Clear the optional flags contained in this value.
void clearSubclassOptionalData() {
SubclassOptionalData = 0;
}
- /// hasSameSubclassOptionalData - Test whether the optional flags contained
- /// in this value are equal to the optional flags in the given value.
+ /// \brief Check the optional flags for equality.
bool hasSameSubclassOptionalData(const Value *V) const {
return SubclassOptionalData == V->SubclassOptionalData;
}
- /// intersectOptionalDataWith - Clear any optional flags in this value
- /// that are not also set in the given value.
+ /// \brief Clear any optional flags not set in the given Value.
void intersectOptionalDataWith(const Value *V) {
SubclassOptionalData &= V->SubclassOptionalData;
}
- /// hasValueHandle - Return true if there is a value handle associated with
- /// this value.
+ /// \brief Return true if there is a value handle associated with this value.
bool hasValueHandle() const { return HasValueHandle; }
- /// \brief Strips off any unneeded pointer casts, all-zero GEPs and aliases
- /// from the specified value, returning the original uncasted value.
+ /// \brief Return true if there is metadata referencing this value.
+ bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); }
+
+ /// \brief Strip off pointer casts, all-zero GEPs, and aliases.
///
- /// If this is called on a non-pointer value, it returns 'this'.
+ /// Returns the original uncasted value. If this is called on a non-pointer
+ /// value, it returns 'this'.
Value *stripPointerCasts();
const Value *stripPointerCasts() const {
return const_cast<Value*>(this)->stripPointerCasts();
}
- /// \brief Strips off any unneeded pointer casts and all-zero GEPs from the
- /// specified value, returning the original uncasted value.
+ /// \brief Strip off pointer casts and all-zero GEPs.
///
- /// If this is called on a non-pointer value, it returns 'this'.
+ /// Returns the original uncasted value. If this is called on a non-pointer
+ /// value, it returns 'this'.
Value *stripPointerCastsNoFollowAliases();
const Value *stripPointerCastsNoFollowAliases() const {
return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases();
}
- /// \brief Strips off unneeded pointer casts and all-constant GEPs from the
- /// specified value, returning the original pointer value.
+ /// \brief Strip off pointer casts and all-constant inbounds GEPs.
///
- /// If this is called on a non-pointer value, it returns 'this'.
+ /// Returns the original pointer value. If this is called on a non-pointer
+ /// value, it returns 'this'.
Value *stripInBoundsConstantOffsets();
const Value *stripInBoundsConstantOffsets() const {
return const_cast<Value*>(this)->stripInBoundsConstantOffsets();
}
- /// \brief Strips like \c stripInBoundsConstantOffsets but also accumulates
- /// the constant offset stripped.
+ /// \brief 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
@@ -419,23 +452,27 @@ public:
->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
}
- /// \brief Strips off unneeded pointer casts and any in-bounds offsets from
- /// the specified value, returning the original pointer value.
+ /// \brief Strip off pointer casts and inbounds GEPs.
///
- /// If this is called on a non-pointer value, it returns 'this'.
+ /// Returns the original pointer value. If this is called on a non-pointer
+ /// value, it returns 'this'.
Value *stripInBoundsOffsets();
const Value *stripInBoundsOffsets() const {
return const_cast<Value*>(this)->stripInBoundsOffsets();
}
- /// isDereferenceablePointer - Test if this value is always a pointer to
- /// allocated and suitably aligned memory for a simple load or store.
+ /// \brief Check if this is always a dereferenceable pointer.
+ ///
+ /// Test if this value is always a pointer to allocated and suitably aligned
+ /// memory for a simple load or store.
bool isDereferenceablePointer(const DataLayout *DL = nullptr) const;
- /// DoPHITranslation - If this value is a PHI node with CurBB as its parent,
- /// return the value in the PHI node corresponding to PredBB. If not, return
- /// ourself. This is useful if you want to know the value something has in a
- /// predecessor block.
+ /// \brief 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
+ /// useful if you want to know the value something has in a predecessor
+ /// block.
Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB);
const Value *DoPHITranslation(const BasicBlock *CurBB,
@@ -443,11 +480,14 @@ public:
return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB);
}
- /// MaximumAlignment - This is the greatest alignment value supported by
- /// load, store, and alloca instructions, and global values.
+ /// \brief The maximum alignment for instructions.
+ ///
+ /// This is the greatest alignment value supported by load, store, and alloca
+ /// instructions, and global values.
static const unsigned MaximumAlignment = 1u << 29;
- /// mutateType - Mutate the type of this Value to be of the specified type.
+ /// \brief 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
/// recreate IR objects with the right types instead of mutating them in
@@ -456,6 +496,37 @@ public:
VTy = Ty;
}
+ /// \brief 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.
+ void reverseUseList();
+
+private:
+ /// \brief 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.
+ ///
+ /// \return the first element in the list.
+ ///
+ /// \note Completely ignores \a Use::Prev (doesn't read, doesn't update).
+ template <class Compare>
+ static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) {
+ Use *Merged;
+ mergeUseListsImpl(L, R, &Merged, Cmp);
+ return Merged;
+ }
+
+ /// \brief Tail-recursive helper for \a mergeUseLists().
+ ///
+ /// \param[out] Next the first element in the list.
+ template <class Compare>
+ static void mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp);
+
protected:
unsigned short getSubclassDataFromValue() const { return SubclassData; }
void setValueSubclassData(unsigned short D) { SubclassData = D; }
@@ -472,6 +543,91 @@ void Use::set(Value *V) {
if (V) V->addUse(*this);
}
+template <class Compare> void Value::sortUseList(Compare Cmp) {
+ if (!UseList || !UseList->Next)
+ // No need to sort 0 or 1 uses.
+ return;
+
+ // Note: this function completely ignores Prev pointers until the end when
+ // they're fixed en masse.
+
+ // Create a binomial vector of sorted lists, visiting uses one at a time and
+ // merging lists as necessary.
+ const unsigned MaxSlots = 32;
+ Use *Slots[MaxSlots];
+
+ // Collect the first use, turning it into a single-item list.
+ Use *Next = UseList->Next;
+ UseList->Next = nullptr;
+ unsigned NumSlots = 1;
+ Slots[0] = UseList;
+
+ // Collect all but the last use.
+ while (Next->Next) {
+ Use *Current = Next;
+ Next = Current->Next;
+
+ // Turn Current into a single-item list.
+ Current->Next = nullptr;
+
+ // Save Current in the first available slot, merging on collisions.
+ unsigned I;
+ for (I = 0; I < NumSlots; ++I) {
+ if (!Slots[I])
+ break;
+
+ // Merge two lists, doubling the size of Current and emptying slot I.
+ //
+ // Since the uses in Slots[I] originally preceded those in Current, send
+ // Slots[I] in as the left parameter to maintain a stable sort.
+ Current = mergeUseLists(Slots[I], Current, Cmp);
+ Slots[I] = nullptr;
+ }
+ // Check if this is a new slot.
+ if (I == NumSlots) {
+ ++NumSlots;
+ assert(NumSlots <= MaxSlots && "Use list bigger than 2^32");
+ }
+
+ // Found an open slot.
+ Slots[I] = Current;
+ }
+
+ // Merge all the lists together.
+ assert(Next && "Expected one more Use");
+ assert(!Next->Next && "Expected only one Use");
+ UseList = Next;
+ for (unsigned I = 0; I < NumSlots; ++I)
+ if (Slots[I])
+ // Since the uses in Slots[I] originally preceded those in UseList, send
+ // Slots[I] in as the left parameter to maintain a stable sort.
+ UseList = mergeUseLists(Slots[I], UseList, Cmp);
+
+ // Fix the Prev pointers.
+ for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) {
+ I->setPrev(Prev);
+ Prev = &I->Next;
+ }
+}
+
+template <class Compare>
+void Value::mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp) {
+ if (!L) {
+ *Next = R;
+ return;
+ }
+ if (!R) {
+ *Next = L;
+ return;
+ }
+ if (Cmp(*R, *L)) {
+ *Next = R;
+ mergeUseListsImpl(L, R->Next, &R->Next, Cmp);
+ return;
+ }
+ *Next = L;
+ mergeUseListsImpl(L->Next, R, &L->Next, Cmp);
+}
// isa - Provide some specializations of isa so that we don't have to include
// the subtype header files to test to see if the value is a subclass...
@@ -537,12 +693,6 @@ template <> struct isa_impl<GlobalObject, Value> {
}
};
-template <> struct isa_impl<MDNode, Value> {
- static inline bool doit(const Value &Val) {
- return Val.getValueID() == Value::MDNodeVal;
- }
-};
-
// Value* is only 4-byte aligned.
template<>
class PointerLikeTypeTraits<Value*> {
diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h
index aa29b2ed6906..8fc7fdb03950 100644
--- a/include/llvm/IR/ValueHandle.h
+++ b/include/llvm/IR/ValueHandle.h
@@ -33,15 +33,16 @@ public:
enum { NumLowBitsAvailable = 2 };
};
-/// ValueHandleBase - This is the common base class of value handles.
+/// \brief This is the common base class of value handles.
+///
/// ValueHandle's are smart pointers to Value's that have special behavior when
/// the value is deleted or ReplaceAllUsesWith'd. See the specific handles
/// below for details.
-///
class ValueHandleBase {
friend class Value;
protected:
- /// HandleBaseKind - This indicates what sub class the handle actually is.
+ /// \brief This indicates what sub class the handle actually is.
+ ///
/// This is to avoid having a vtable for the light-weight handle pointers. The
/// fully general Callback version does have a vtable.
enum HandleBaseKind {
@@ -55,55 +56,48 @@ private:
PointerIntPair<ValueHandleBase**, 2, HandleBaseKind> PrevPair;
ValueHandleBase *Next;
- // A subclass may want to store some information along with the value
- // pointer. Allow them to do this by making the value pointer a pointer-int
- // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this
- // access.
- PointerIntPair<Value*, 2> VP;
+ Value* V;
ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION;
public:
explicit ValueHandleBase(HandleBaseKind Kind)
- : PrevPair(nullptr, Kind), Next(nullptr), VP(nullptr, 0) {}
+ : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {}
ValueHandleBase(HandleBaseKind Kind, Value *V)
- : PrevPair(nullptr, Kind), Next(nullptr), VP(V, 0) {
- if (isValid(VP.getPointer()))
+ : PrevPair(nullptr, Kind), Next(nullptr), V(V) {
+ if (isValid(V))
AddToUseList();
}
ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS)
- : PrevPair(nullptr, Kind), Next(nullptr), VP(RHS.VP) {
- if (isValid(VP.getPointer()))
+ : PrevPair(nullptr, Kind), Next(nullptr), V(RHS.V) {
+ if (isValid(V))
AddToExistingUseList(RHS.getPrevPtr());
}
~ValueHandleBase() {
- if (isValid(VP.getPointer()))
+ if (isValid(V))
RemoveFromUseList();
}
Value *operator=(Value *RHS) {
- if (VP.getPointer() == RHS) return RHS;
- if (isValid(VP.getPointer())) RemoveFromUseList();
- VP.setPointer(RHS);
- if (isValid(VP.getPointer())) AddToUseList();
+ if (V == RHS) return RHS;
+ if (isValid(V)) RemoveFromUseList();
+ V = RHS;
+ if (isValid(V)) AddToUseList();
return RHS;
}
Value *operator=(const ValueHandleBase &RHS) {
- if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer();
- if (isValid(VP.getPointer())) RemoveFromUseList();
- VP.setPointer(RHS.VP.getPointer());
- if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr());
- return VP.getPointer();
+ if (V == RHS.V) return RHS.V;
+ if (isValid(V)) RemoveFromUseList();
+ V = RHS.V;
+ if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr());
+ return V;
}
- Value *operator->() const { return getValPtr(); }
- Value &operator*() const { return *getValPtr(); }
+ Value *operator->() const { return V; }
+ Value &operator*() const { return *V; }
protected:
- Value *getValPtr() const { return VP.getPointer(); }
-
- void setValPtrInt(unsigned K) { VP.setInt(K); }
- unsigned getValPtrInt() const { return VP.getInt(); }
+ Value *getValPtr() const { return V; }
static bool isValid(Value *V) {
return V &&
@@ -122,26 +116,28 @@ private:
HandleBaseKind getKind() const { return PrevPair.getInt(); }
void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); }
- /// AddToExistingUseList - Add this ValueHandle to the use list for VP, where
+ /// \brief Add this ValueHandle to the use list for V.
+ ///
/// List is the address of either the head of the list or a Next node within
/// the existing use list.
void AddToExistingUseList(ValueHandleBase **List);
- /// AddToExistingUseListAfter - Add this ValueHandle to the use list after
- /// Node.
+ /// \brief Add this ValueHandle to the use list after Node.
void AddToExistingUseListAfter(ValueHandleBase *Node);
- /// AddToUseList - Add this ValueHandle to the use list for VP.
+ /// \brief Add this ValueHandle to the use list for V.
void AddToUseList();
- /// RemoveFromUseList - Remove this ValueHandle from its current use list.
+ /// \brief Remove this ValueHandle from its current use list.
void RemoveFromUseList();
};
-/// WeakVH - This is a value handle that tries hard to point to a Value, even
-/// across RAUW operations, but will null itself out if the value is destroyed.
-/// this is useful for advisory sorts of information, but should not be used as
-/// the key of a map (since the map would have to rearrange itself when the
-/// pointer changes).
+/// \brief 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
+/// is useful for advisory sorts of information, but should not be used as the
+/// key of a map (since the map would have to rearrange itself when the pointer
+/// changes).
class WeakVH : public ValueHandleBase {
public:
WeakVH() : ValueHandleBase(Weak) {}
@@ -170,14 +166,16 @@ template<> struct simplify_type<WeakVH> {
}
};
-/// AssertingVH - This is a Value Handle that points to a value and asserts out
-/// if the value is destroyed while the handle is still live. This is very
-/// useful for catching dangling pointer bugs and other things which can be
-/// non-obvious. One particularly useful place to use this is as the Key of a
-/// map. Dangling pointer bugs often lead to really subtle bugs that only occur
-/// if another object happens to get allocated to the same address as the old
-/// one. Using an AssertingVH ensures that an assert is triggered as soon as
-/// the bad delete occurs.
+/// \brief 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
+/// catching dangling pointer bugs and other things which can be non-obvious.
+/// One particularly useful place to use this is as the Key of a map. Dangling
+/// pointer bugs often lead to really subtle bugs that only occur if another
+/// object happens to get allocated to the same address as the old one. Using
+/// an AssertingVH ensures that an assert is triggered as soon as the bad
+/// delete occurs.
///
/// Note that an AssertingVH handle does *not* follow values across RAUW
/// operations. This means that RAUW's need to explicitly update the
@@ -189,25 +187,23 @@ class AssertingVH
: public ValueHandleBase
#endif
{
+ friend struct DenseMapInfo<AssertingVH<ValueTy> >;
#ifndef NDEBUG
- ValueTy *getValPtr() const {
- return static_cast<ValueTy*>(ValueHandleBase::getValPtr());
- }
- void setValPtr(ValueTy *P) {
- ValueHandleBase::operator=(GetAsValue(P));
- }
+ Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); }
+ void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); }
#else
- ValueTy *ThePtr;
- ValueTy *getValPtr() const { return ThePtr; }
- void setValPtr(ValueTy *P) { ThePtr = P; }
+ Value *ThePtr;
+ Value *getRawValPtr() const { return ThePtr; }
+ void setRawValPtr(Value *P) { ThePtr = P; }
#endif
-
- // Convert a ValueTy*, which may be const, to the type the base
- // class expects.
+ // Convert a ValueTy*, which may be const, to the raw Value*.
static Value *GetAsValue(Value *V) { return V; }
static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); }
+ ValueTy *getValPtr() const { return static_cast<ValueTy *>(getRawValPtr()); }
+ void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); }
+
public:
#ifndef NDEBUG
AssertingVH() : ValueHandleBase(Assert) {}
@@ -215,7 +211,7 @@ public:
AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {}
#else
AssertingVH() : ThePtr(nullptr) {}
- AssertingVH(ValueTy *P) : ThePtr(P) {}
+ AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {}
#endif
operator ValueTy*() const {
@@ -238,21 +234,25 @@ public:
// Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap.
template<typename T>
struct DenseMapInfo<AssertingVH<T> > {
- typedef DenseMapInfo<T*> PointerInfo;
static inline AssertingVH<T> getEmptyKey() {
- return AssertingVH<T>(PointerInfo::getEmptyKey());
+ AssertingVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey());
+ return Res;
}
- static inline T* getTombstoneKey() {
- return AssertingVH<T>(PointerInfo::getTombstoneKey());
+ static inline AssertingVH<T> getTombstoneKey() {
+ AssertingVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey());
+ return Res;
}
static unsigned getHashValue(const AssertingVH<T> &Val) {
- return PointerInfo::getHashValue(Val);
+ return DenseMapInfo<Value *>::getHashValue(Val.getRawValPtr());
}
static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) {
- return LHS == RHS;
+ return DenseMapInfo<Value *>::isEqual(LHS.getRawValPtr(),
+ RHS.getRawValPtr());
}
};
-
+
template <typename T>
struct isPodLike<AssertingVH<T> > {
#ifdef NDEBUG
@@ -263,8 +263,7 @@ struct isPodLike<AssertingVH<T> > {
};
-/// TrackingVH - This is a value handle that tracks a Value (or Value subclass),
-/// even across RAUW operations.
+/// \brief 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,
@@ -332,12 +331,14 @@ public:
ValueTy &operator*() const { return *getValPtr(); }
};
-/// CallbackVH - This is a value handle that allows subclasses to define
-/// callbacks that run when the underlying Value has RAUW called on it or is
-/// destroyed. This class can be used as the key of a map, as long as the user
-/// takes it out of the map before calling setValPtr() (since the map has to
-/// rearrange itself when the pointer changes). Unlike ValueHandleBase, this
-/// class has a vtable and a virtual destructor.
+/// \brief 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
+/// class can be used as the key of a map, as long as the user takes it out of
+/// the map before calling setValPtr() (since the map has to rearrange itself
+/// when the pointer changes). Unlike ValueHandleBase, this class has a vtable
+/// and a virtual destructor.
class CallbackVH : public ValueHandleBase {
virtual void anchor();
protected:
@@ -358,16 +359,20 @@ public:
return getValPtr();
}
- /// Called when this->getValPtr() is destroyed, inside ~Value(), so you may
- /// call any non-virtual Value method on getValPtr(), but no subclass methods.
- /// If WeakVH were implemented as a CallbackVH, it would use this method to
- /// call setValPtr(NULL). AssertingVH would use this method to cause an
- /// assertion failure.
+ /// \brief 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
+ /// methods. If WeakVH were implemented as a CallbackVH, it would use this
+ /// method to call setValPtr(NULL). AssertingVH would use this method to
+ /// cause an assertion failure.
///
/// All implementations must remove the reference from this object to the
/// Value that's being destroyed.
virtual void deleted() { setValPtr(nullptr); }
+ /// \brief Callback for Value RAUW.
+ ///
/// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called,
/// _before_ any of the uses have actually been replaced. If WeakVH were
/// implemented as a CallbackVH, it would use this method to call
diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h
index 43a79c7db2b9..f2ea405f1428 100644
--- a/include/llvm/IR/ValueMap.h
+++ b/include/llvm/IR/ValueMap.h
@@ -27,10 +27,13 @@
#define LLVM_IR_VALUEMAP_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Mutex.h"
+#include "llvm/Support/UniqueLock.h"
#include "llvm/Support/type_traits.h"
#include <iterator>
+#include <memory>
namespace llvm {
@@ -78,8 +81,10 @@ class ValueMap {
friend class ValueMapCallbackVH<KeyT, ValueT, Config>;
typedef ValueMapCallbackVH<KeyT, ValueT, Config> ValueMapCVH;
typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH> > MapT;
+ typedef DenseMap<const Metadata *, TrackingMDRef> MDMapT;
typedef typename Config::ExtraData ExtraData;
MapT Map;
+ std::unique_ptr<MDMapT> MDMap;
ExtraData Data;
ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION;
ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION;
@@ -90,12 +95,19 @@ public:
typedef unsigned size_type;
explicit ValueMap(unsigned NumInitBuckets = 64)
- : Map(NumInitBuckets), Data() {}
+ : Map(NumInitBuckets), Data() {}
explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64)
- : Map(NumInitBuckets), Data(Data) {}
+ : Map(NumInitBuckets), Data(Data) {}
~ValueMap() {}
+ bool hasMD() const { return MDMap; }
+ MDMapT &MD() {
+ if (!MDMap)
+ MDMap.reset(new MDMapT);
+ return *MDMap;
+ }
+
typedef ValueMapIterator<MapT, KeyT> iterator;
typedef ValueMapConstIterator<MapT, KeyT> const_iterator;
inline iterator begin() { return iterator(Map.begin()); }
@@ -109,9 +121,12 @@ public:
/// Grow the map so that it has at least Size buckets. Does not shrink
void resize(size_t Size) { Map.resize(Size); }
- void clear() { Map.clear(); }
+ void clear() {
+ Map.clear();
+ MDMap.reset();
+ }
- /// Return 1 if the specified key is in the map, 0 otherwise.
+ /// Return 1 if the specified key is in the map, 0 otherwise.
size_type count(const KeyT &Val) const {
return Map.find_as(Val) == Map.end() ? 0 : 1;
}
@@ -209,6 +224,9 @@ class ValueMapCallbackVH : public CallbackVH {
: CallbackVH(const_cast<Value*>(static_cast<const Value*>(Key))),
Map(Map) {}
+ // Private constructor used to create empty/tombstone DenseMap keys.
+ ValueMapCallbackVH(Value *V) : CallbackVH(V), Map(nullptr) {}
+
public:
KeyT Unwrap() const { return cast_or_null<KeySansPointerT>(getValPtr()); }
@@ -216,12 +234,11 @@ public:
// Make a copy that won't get changed even when *this is destroyed.
ValueMapCallbackVH Copy(*this);
typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data);
+ unique_lock<typename Config::mutex_type> Guard;
if (M)
- M->acquire();
+ Guard = unique_lock<typename Config::mutex_type>(*M);
Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this.
Copy.Map->Map.erase(Copy); // Definitely destroys *this.
- if (M)
- M->release();
}
void allUsesReplacedWith(Value *new_key) override {
assert(isa<KeySansPointerT>(new_key) &&
@@ -229,8 +246,9 @@ public:
// Make a copy that won't get changed even when *this is destroyed.
ValueMapCallbackVH Copy(*this);
typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data);
+ unique_lock<typename Config::mutex_type> Guard;
if (M)
- M->acquire();
+ Guard = unique_lock<typename Config::mutex_type>(*M);
KeyT typed_new_key = cast<KeySansPointerT>(new_key);
// Can destroy *this:
@@ -245,27 +263,24 @@ public:
Copy.Map->insert(std::make_pair(typed_new_key, Target));
}
}
- if (M)
- M->release();
}
};
template<typename KeyT, typename ValueT, typename Config>
struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config> > {
typedef ValueMapCallbackVH<KeyT, ValueT, Config> VH;
- typedef DenseMapInfo<KeyT> PointerInfo;
static inline VH getEmptyKey() {
- return VH(PointerInfo::getEmptyKey(), nullptr);
+ return VH(DenseMapInfo<Value *>::getEmptyKey());
}
static inline VH getTombstoneKey() {
- return VH(PointerInfo::getTombstoneKey(), nullptr);
+ return VH(DenseMapInfo<Value *>::getTombstoneKey());
}
static unsigned getHashValue(const VH &Val) {
- return PointerInfo::getHashValue(Val.Unwrap());
+ return DenseMapInfo<KeyT>::getHashValue(Val.Unwrap());
}
static unsigned getHashValue(const KeyT &Val) {
- return PointerInfo::getHashValue(Val);
+ return DenseMapInfo<KeyT>::getHashValue(Val);
}
static bool isEqual(const VH &LHS, const VH &RHS) {
return LHS == RHS;
diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h
index 0272e206f37a..43bd123e7f44 100644
--- a/include/llvm/IR/Verifier.h
+++ b/include/llvm/IR/Verifier.h
@@ -77,8 +77,8 @@ class VerifierPass {
public:
explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {}
- PreservedAnalyses run(Module *M);
- PreservedAnalyses run(Function *F);
+ PreservedAnalyses run(Module &M);
+ PreservedAnalyses run(Function &F);
static StringRef name() { return "VerifierPass"; }
};
diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h
index 59ffc095f47f..2d9ace0b62a0 100644
--- a/include/llvm/IRReader/IRReader.h
+++ b/include/llvm/IRReader/IRReader.h
@@ -15,12 +15,12 @@
#ifndef LLVM_IRREADER_IRREADER_H
#define LLVM_IRREADER_IRREADER_H
+#include "llvm/Support/MemoryBuffer.h"
#include <string>
namespace llvm {
class Module;
-class MemoryBuffer;
class SMDiagnostic;
class LLVMContext;
@@ -28,20 +28,21 @@ class LLVMContext;
/// for it which does lazy deserialization of function bodies. Otherwise,
/// attempt to parse it as LLVM Assembly and return a fully populated
/// Module.
-Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err,
- LLVMContext &Context);
+std::unique_ptr<Module> getLazyIRFileModule(StringRef Filename,
+ SMDiagnostic &Err,
+ LLVMContext &Context);
/// If the given MemoryBuffer holds a bitcode image, return a Module
/// for it. Otherwise, attempt to parse it as LLVM Assembly and return
-/// a Module for it. This function *never* takes ownership of Buffer.
-Module *ParseIR(MemoryBuffer *Buffer, SMDiagnostic &Err, LLVMContext &Context);
+/// a Module for it.
+std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err,
+ LLVMContext &Context);
/// If the given file holds a bitcode image, return a Module for it.
/// Otherwise, attempt to parse it as LLVM Assembly and return a Module
/// for it.
-Module *ParseIRFile(const std::string &Filename, SMDiagnostic &Err,
- LLVMContext &Context);
-
+std::unique_ptr<Module> parseIRFile(StringRef Filename, SMDiagnostic &Err,
+ LLVMContext &Context);
}
#endif
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 02f4259a51ac..30280033ee20 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -71,8 +71,9 @@ void initializeAliasDebuggerPass(PassRegistry&);
void initializeAliasSetPrinterPass(PassRegistry&);
void initializeAlwaysInlinerPass(PassRegistry&);
void initializeArgPromotionPass(PassRegistry&);
-void initializeAtomicExpandLoadLinkedPass(PassRegistry&);
+void initializeAtomicExpandPass(PassRegistry&);
void initializeSampleProfileLoaderPass(PassRegistry&);
+void initializeAlignmentFromAssumptionsPass(PassRegistry&);
void initializeBarrierNoopPass(PassRegistry&);
void initializeBasicAliasAnalysisPass(PassRegistry&);
void initializeCallGraphWrapperPassPass(PassRegistry &);
@@ -89,6 +90,8 @@ void initializeCFGOnlyPrinterPass(PassRegistry&);
void initializeCFGOnlyViewerPass(PassRegistry&);
void initializeCFGPrinterPass(PassRegistry&);
void initializeCFGSimplifyPassPass(PassRegistry&);
+void initializeCFLAliasAnalysisPass(PassRegistry&);
+void initializeForwardControlFlowIntegrityPass(PassRegistry&);
void initializeFlattenCFGPassPass(PassRegistry&);
void initializeStructurizeCFGPass(PassRegistry&);
void initializeCFGViewerPass(PassRegistry&);
@@ -103,7 +106,6 @@ void initializeDAEPass(PassRegistry&);
void initializeDAHPass(PassRegistry&);
void initializeDCEPass(PassRegistry&);
void initializeDSEPass(PassRegistry&);
-void initializeDebugIRPass(PassRegistry&);
void initializeDebugInfoVerifierLegacyPassPass(PassRegistry &);
void initializeDeadInstEliminationPass(PassRegistry&);
void initializeDeadMachineInstructionElimPass(PassRegistry&);
@@ -119,15 +121,16 @@ void initializeEarlyIfConverterPass(PassRegistry&);
void initializeEdgeBundlesPass(PassRegistry&);
void initializeExpandPostRAPass(PassRegistry&);
void initializeGCOVProfilerPass(PassRegistry&);
+void initializeInstrProfilingPass(PassRegistry&);
void initializeAddressSanitizerPass(PassRegistry&);
void initializeAddressSanitizerModulePass(PassRegistry&);
void initializeMemorySanitizerPass(PassRegistry&);
void initializeThreadSanitizerPass(PassRegistry&);
+void initializeSanitizerCoverageModulePass(PassRegistry&);
void initializeDataFlowSanitizerPass(PassRegistry&);
void initializeScalarizerPass(PassRegistry&);
void initializeEarlyCSEPass(PassRegistry&);
void initializeExpandISelPseudosPass(PassRegistry&);
-void initializeFindUsedTypesPass(PassRegistry&);
void initializeFunctionAttrsPass(PassRegistry&);
void initializeGCMachineCodeAnalysisPass(PassRegistry&);
void initializeGCModuleInfoPass(PassRegistry&);
@@ -207,6 +210,7 @@ void initializeObjCARCAPElimPass(PassRegistry&);
void initializeObjCARCExpandPass(PassRegistry&);
void initializeObjCARCContractPass(PassRegistry&);
void initializeObjCARCOptPass(PassRegistry&);
+void initializePAEvalPass(PassRegistry &);
void initializeOptimizePHIsPass(PassRegistry&);
void initializePartiallyInlineLibCallsPass(PassRegistry&);
void initializePEIPass(PassRegistry&);
@@ -259,10 +263,13 @@ void initializeTailDuplicatePassPass(PassRegistry&);
void initializeTargetPassConfigPass(PassRegistry&);
void initializeDataLayoutPassPass(PassRegistry &);
void initializeTargetTransformInfoAnalysisGroup(PassRegistry&);
+void initializeFunctionTargetTransformInfoPass(PassRegistry &);
void initializeNoTTIPass(PassRegistry&);
void initializeTargetLibraryInfoPass(PassRegistry&);
+void initializeAssumptionCacheTrackerPass(PassRegistry &);
void initializeTwoAddressInstructionPassPass(PassRegistry&);
void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
+void initializeScopedNoAliasAAPass(PassRegistry&);
void initializeUnifyFunctionExitNodesPass(PassRegistry&);
void initializeUnreachableBlockElimPass(PassRegistry&);
void initializeUnreachableMachineBlockElimPass(PassRegistry&);
@@ -277,7 +284,9 @@ void initializeSLPVectorizerPass(PassRegistry&);
void initializeBBVectorizePass(PassRegistry&);
void initializeMachineFunctionPrinterPassPass(PassRegistry&);
void initializeStackMapLivenessPass(PassRegistry&);
+void initializeMachineCombinerPass(PassRegistry &);
void initializeLoadCombinePass(PassRegistry&);
+void initializeRewriteSymbolsPass(PassRegistry&);
}
#endif
diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h
index b19b2325f73b..0c9ce4a54f02 100644
--- a/include/llvm/LTO/LTOCodeGenerator.h
+++ b/include/llvm/LTO/LTOCodeGenerator.h
@@ -32,8 +32,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LTO_CODE_GENERATOR_H
-#define LTO_CODE_GENERATOR_H
+#ifndef LLVM_LTO_LTOCODEGENERATOR_H
+#define LLVM_LTO_LTOCODEGENERATOR_H
#include "llvm-c/lto.h"
#include "llvm/ADT/ArrayRef.h"
@@ -61,10 +61,11 @@ struct LTOCodeGenerator {
static const char *getVersionString();
LTOCodeGenerator();
+ LTOCodeGenerator(std::unique_ptr<LLVMContext> Context);
~LTOCodeGenerator();
// Merge given module, return true on success.
- bool addModule(struct LTOModule*, std::string &errMsg);
+ bool addModule(struct LTOModule *);
void setTargetOptions(TargetOptions options);
void setDebugInfo(lto_debug_model);
@@ -101,6 +102,7 @@ struct LTOCodeGenerator {
bool disableOpt,
bool disableInline,
bool disableGVNLoadPRE,
+ bool disableVectorization,
std::string &errMsg);
// As with compile_to_file(), this function compiles the merged module into
@@ -112,19 +114,23 @@ struct LTOCodeGenerator {
bool disableOpt,
bool disableInline,
bool disableGVNLoadPRE,
+ bool disableVectorization,
std::string &errMsg);
void setDiagnosticHandler(lto_diagnostic_handler_t, void *);
+ LLVMContext &getContext() { return Context; }
+
private:
void initializeLTOPasses();
bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline,
- bool disableGVNLoadPRE, std::string &errMsg);
+ bool disableGVNLoadPRE, bool disableVectorization,
+ std::string &errMsg);
void applyScopeRestrictions();
- void applyRestriction(GlobalValue &GV, const ArrayRef<StringRef> &Libcalls,
+ void applyRestriction(GlobalValue &GV, ArrayRef<StringRef> Libcalls,
std::vector<const char *> &MustPreserveList,
- SmallPtrSet<GlobalValue *, 8> &AsmUsed,
+ SmallPtrSetImpl<GlobalValue *> &AsmUsed,
Mangler &Mangler);
bool determineTarget(std::string &errMsg);
@@ -134,6 +140,8 @@ private:
typedef StringMap<uint8_t> StringSet;
+ void initialize();
+ std::unique_ptr<LLVMContext> OwnedContext;
LLVMContext &Context;
Linker IRLinker;
TargetMachine *TargetMach;
@@ -142,7 +150,7 @@ private:
lto_codegen_model CodeModel;
StringSet MustPreserveSymbols;
StringSet AsmUndefinedRefs;
- MemoryBuffer *NativeObjectFile;
+ std::unique_ptr<MemoryBuffer> NativeObjectFile;
std::vector<char *> CodegenOptions;
std::string MCpu;
std::string MAttr;
@@ -152,4 +160,4 @@ private:
void *DiagContext;
};
}
-#endif // LTO_CODE_GENERATOR_H
+#endif
diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/LTOModule.h
index c43846a64050..53c2b8e521be 100644
--- a/include/llvm/LTO/LTOModule.h
+++ b/include/llvm/LTO/LTOModule.h
@@ -11,11 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LTO_MODULE_H
-#define LTO_MODULE_H
+#ifndef LLVM_LTO_LTOMODULE_H
+#define LLVM_LTO_LTOMODULE_H
#include "llvm-c/lto.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
@@ -37,8 +38,6 @@ namespace llvm {
///
struct LTOModule {
private:
- typedef StringMap<uint8_t> StringSet;
-
struct NameAndAttributes {
const char *name;
uint32_t attributes;
@@ -46,21 +45,27 @@ private:
const GlobalValue *symbol;
};
+ std::unique_ptr<LLVMContext> OwnedContext;
+
std::unique_ptr<object::IRObjectFile> IRFile;
std::unique_ptr<TargetMachine> _target;
- StringSet _linkeropt_strings;
+ StringSet<> _linkeropt_strings;
std::vector<const char *> _deplibs;
std::vector<const char *> _linkeropts;
std::vector<NameAndAttributes> _symbols;
// _defines and _undefines only needed to disambiguate tentative definitions
- StringSet _defines;
+ StringSet<> _defines;
StringMap<NameAndAttributes> _undefines;
std::vector<const char*> _asm_undefines;
LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM);
+ LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM,
+ std::unique_ptr<LLVMContext> Context);
public:
+ ~LTOModule();
+
/// Returns 'true' if the file or memory contents is LLVM bitcode.
static bool isBitcodeFile(const void *mem, size_t length);
static bool isBitcodeFile(const char *path);
@@ -71,8 +76,8 @@ public:
StringRef triplePrefix);
/// Create a MemoryBuffer from a memory range with an optional name.
- static MemoryBuffer *makeBuffer(const void *mem, size_t length,
- StringRef name = "");
+ static std::unique_ptr<MemoryBuffer>
+ makeBuffer(const void *mem, size_t length, StringRef name = "");
/// Create an LTOModule. N.B. These methods take ownership of the buffer. The
/// caller must have initialized the Targets, the TargetMCs, the AsmPrinters,
@@ -95,6 +100,13 @@ public:
TargetOptions options, std::string &errMsg,
StringRef path = "");
+ static LTOModule *createInLocalContext(const void *mem, size_t length,
+ TargetOptions options,
+ std::string &errMsg, StringRef path);
+ static LTOModule *createInContext(const void *mem, size_t length,
+ TargetOptions options, std::string &errMsg,
+ StringRef path, LLVMContext *Context);
+
const Module &getModule() const {
return const_cast<LTOModule*>(this)->getModule();
}
@@ -202,10 +214,9 @@ private:
/// Get string that the data pointer points to.
bool objcClassNameFromExpression(const Constant *c, std::string &name);
- /// Create an LTOModule (private version). N.B. This method takes ownership of
- /// the buffer.
- static LTOModule *makeLTOModule(std::unique_ptr<MemoryBuffer> Buffer,
- TargetOptions options, std::string &errMsg);
+ /// Create an LTOModule (private version).
+ static LTOModule *makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
+ std::string &errMsg, LLVMContext *Context);
};
}
-#endif // LTO_MODULE_H
+#endif
diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h
index e06560ca0b64..2e8feab6d29d 100644
--- a/include/llvm/LinkAllPasses.h
+++ b/include/llvm/LinkAllPasses.h
@@ -18,7 +18,6 @@
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/CallPrinter.h"
#include "llvm/Analysis/DomPrinter.h"
-#include "llvm/Analysis/FindUsedTypes.h"
#include "llvm/Analysis/IntervalPartition.h"
#include "llvm/Analysis/Lint.h"
#include "llvm/Analysis/Passes.h"
@@ -33,6 +32,7 @@
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/SymbolRewriter.h"
#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
#include "llvm/Transforms/Vectorize.h"
#include <cstdlib>
@@ -52,15 +52,18 @@ namespace {
(void) llvm::createAliasAnalysisCounterPass();
(void) llvm::createAliasDebugger();
(void) llvm::createArgumentPromotionPass();
+ (void) llvm::createAlignmentFromAssumptionsPass();
(void) llvm::createBasicAliasAnalysisPass();
(void) llvm::createLibCallAliasAnalysisPass(nullptr);
(void) llvm::createScalarEvolutionAliasAnalysisPass();
(void) llvm::createTypeBasedAliasAnalysisPass();
+ (void) llvm::createScopedNoAliasAAPass();
(void) llvm::createBoundsCheckingPass();
(void) llvm::createBreakCriticalEdgesPass();
(void) llvm::createCallGraphPrinterPass();
(void) llvm::createCallGraphViewerPass();
(void) llvm::createCFGSimplificationPass();
+ (void) llvm::createCFLAliasAnalysisPass();
(void) llvm::createStructurizeCFGPass();
(void) llvm::createConstantMergePass();
(void) llvm::createConstantPropagationPass();
@@ -75,6 +78,7 @@ namespace {
(void) llvm::createDomOnlyViewerPass();
(void) llvm::createDomViewerPass();
(void) llvm::createGCOVProfilerPass();
+ (void) llvm::createInstrProfilingPass();
(void) llvm::createFunctionInliningPass();
(void) llvm::createAlwaysInlinerPass();
(void) llvm::createGlobalDCEPass();
@@ -107,6 +111,7 @@ namespace {
(void) llvm::createObjCARCExpandPass();
(void) llvm::createObjCARCContractPass();
(void) llvm::createObjCARCOptPass();
+ (void) llvm::createPAEvalPass();
(void) llvm::createPromoteMemoryToRegisterPass();
(void) llvm::createDemoteRegisterToMemoryPass();
(void) llvm::createPruneEHPass();
@@ -134,7 +139,7 @@ namespace {
(void) llvm::createConstantHoistingPass();
(void) llvm::createCodeGenPreparePass();
(void) llvm::createEarlyCSEPass();
- (void)llvm::createMergedLoadStoreMotionPass();
+ (void) llvm::createMergedLoadStoreMotionPass();
(void) llvm::createGVNPass();
(void) llvm::createMemCpyOptPass();
(void) llvm::createLoopDeletionPass();
@@ -160,15 +165,15 @@ namespace {
(void) llvm::createPartiallyInlineLibCallsPass();
(void) llvm::createScalarizerPass();
(void) llvm::createSeparateConstOffsetFromGEPPass();
+ (void) llvm::createRewriteSymbolsPass();
(void)new llvm::IntervalPartition();
- (void)new llvm::FindUsedTypes();
(void)new llvm::ScalarEvolution();
((llvm::Function*)nullptr)->viewCFGOnly();
llvm::RGPassManager RGM;
((llvm::RegionPass*)nullptr)->runOnRegion((llvm::Region*)nullptr, RGM);
llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)nullptr);
- X.add((llvm::Value*)nullptr, 0, nullptr); // for -print-alias-sets
+ X.add(nullptr, 0, llvm::AAMDNodes()); // for -print-alias-sets
}
} ForcePassLinking; // Force link by creating a global definition.
}
diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h
index 6254bbb6d6d5..9c3ecea590bd 100644
--- a/include/llvm/Linker/Linker.h
+++ b/include/llvm/Linker/Linker.h
@@ -10,52 +10,78 @@
#ifndef LLVM_LINKER_LINKER_H
#define LLVM_LINKER_LINKER_H
-#include "llvm/ADT/SmallPtrSet.h"
-#include <string>
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/IR/DiagnosticInfo.h"
namespace llvm {
-
-class Comdat;
-class GlobalValue;
class Module;
-class StringRef;
class StructType;
+class Type;
/// This class provides the core functionality of linking in LLVM. It keeps a
/// pointer to the merged module so far. It doesn't take ownership of the
/// module since it is assumed that the user of this class will want to do
/// something with it after the linking.
class Linker {
- public:
- enum LinkerMode {
- DestroySource = 0, // Allow source module to be destroyed.
- PreserveSource = 1 // Preserve the source module.
+public:
+ struct StructTypeKeyInfo {
+ struct KeyTy {
+ ArrayRef<Type *> ETypes;
+ bool IsPacked;
+ KeyTy(ArrayRef<Type *> E, bool P);
+ KeyTy(const StructType *ST);
+ bool operator==(const KeyTy &that) const;
+ bool operator!=(const KeyTy &that) const;
};
+ static StructType *getEmptyKey();
+ static StructType *getTombstoneKey();
+ static unsigned getHashValue(const KeyTy &Key);
+ static unsigned getHashValue(const StructType *ST);
+ static bool isEqual(const KeyTy &LHS, const StructType *RHS);
+ static bool isEqual(const StructType *LHS, const StructType *RHS);
+ };
+
+ typedef DenseSet<StructType *, StructTypeKeyInfo> NonOpaqueStructTypeSet;
+ typedef DenseSet<StructType *> OpaqueStructTypeSet;
+
+ struct IdentifiedStructTypeSet {
+ // The set of opaque types is the composite module.
+ OpaqueStructTypeSet OpaqueStructTypes;
+
+ // The set of identified but non opaque structures in the composite module.
+ NonOpaqueStructTypeSet NonOpaqueStructTypes;
+
+ void addNonOpaque(StructType *Ty);
+ void addOpaque(StructType *Ty);
+ StructType *findNonOpaque(ArrayRef<Type *> ETypes, bool IsPacked);
+ bool hasType(StructType *Ty);
+ };
+
+ Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler);
+ Linker(Module *M);
+ ~Linker();
+
+ Module *getModule() const { return Composite; }
+ void deleteModule();
- Linker(Module *M, bool SuppressWarnings=false);
- ~Linker();
+ /// \brief Link \p Src into the composite. The source is destroyed.
+ /// Returns true on error.
+ bool linkInModule(Module *Src);
- Module *getModule() const { return Composite; }
- void deleteModule();
+ static bool LinkModules(Module *Dest, Module *Src,
+ DiagnosticHandlerFunction DiagnosticHandler);
- /// \brief Link \p Src into the composite. The source is destroyed if
- /// \p Mode is DestroySource and preserved if it is PreserveSource.
- /// If \p ErrorMsg is not null, information about any error is written
- /// to it.
- /// Returns true on error.
- bool linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg);
- bool linkInModule(Module *Src, std::string *ErrorMsg) {
- return linkInModule(Src, Linker::DestroySource, ErrorMsg);
- }
+ static bool LinkModules(Module *Dest, Module *Src);
- static bool LinkModules(Module *Dest, Module *Src, unsigned Mode,
- std::string *ErrorMsg);
+private:
+ void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler);
+ Module *Composite;
- private:
- Module *Composite;
- SmallPtrSet<StructType*, 32> IdentifiedStructTypes;
+ IdentifiedStructTypeSet IdentifiedStructTypes;
- bool SuppressWarnings;
+ DiagnosticHandlerFunction DiagnosticHandler;
};
} // End llvm namespace
diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h
index 2e76074db774..1fc0332f63c2 100644
--- a/include/llvm/MC/ConstantPools.h
+++ b/include/llvm/MC/ConstantPools.h
@@ -12,10 +12,12 @@
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_CONSTANTPOOL_H
-#define LLVM_MC_CONSTANTPOOL_H
+#ifndef LLVM_MC_CONSTANTPOOLS_H
+#define LLVM_MC_CONSTANTPOOLS_H
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
+
namespace llvm {
class MCContext;
class MCExpr;
diff --git a/include/llvm/MC/MCAnalysis/MCAtom.h b/include/llvm/MC/MCAnalysis/MCAtom.h
deleted file mode 100644
index 33f3431a59a9..000000000000
--- a/include/llvm/MC/MCAnalysis/MCAtom.h
+++ /dev/null
@@ -1,199 +0,0 @@
-//===-- MCAtom.h ------------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the MCAtom class, which is used to
-// represent a contiguous region in a decoded object that is uniformly data or
-// instructions.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MC_MCANALYSIS_MCATOM_H
-#define LLVM_MC_MCANALYSIS_MCATOM_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/Support/DataTypes.h"
-#include <vector>
-
-namespace llvm {
-
-class MCModule;
-
-class MCAtom;
-class MCTextAtom;
-class MCDataAtom;
-
-/// \brief Represents a contiguous range of either instructions (a TextAtom)
-/// or data (a DataAtom). Address ranges are expressed as _closed_ intervals.
-class MCAtom {
- virtual void anchor();
-public:
- virtual ~MCAtom() {}
-
- enum AtomKind { TextAtom, DataAtom };
- AtomKind getKind() const { return Kind; }
-
- /// \brief Get the start address of the atom.
- uint64_t getBeginAddr() const { return Begin; }
- /// \brief Get the end address, i.e. the last one inside the atom.
- uint64_t getEndAddr() const { return End; }
-
- /// \name Atom modification methods:
- /// When modifying a TextAtom, keep instruction boundaries in mind.
- /// For instance, split must me given the start address of an instruction.
- /// @{
-
- /// \brief Splits the atom in two at a given address.
- /// \param SplitPt Address at which to start a new atom, splitting this one.
- /// \returns The newly created atom starting at \p SplitPt.
- virtual MCAtom *split(uint64_t SplitPt) = 0;
-
- /// \brief Truncates an atom, discarding everything after \p TruncPt.
- /// \param TruncPt Last byte address to be contained in this atom.
- virtual void truncate(uint64_t TruncPt) = 0;
- /// @}
-
- /// \name Naming:
- ///
- /// This is mostly for display purposes, and may contain anything that hints
- /// at what the atom contains: section or symbol name, BB start address, ..
- /// @{
- StringRef getName() const { return Name; }
- void setName(StringRef NewName) { Name = NewName.str(); }
- /// @}
-
-protected:
- const AtomKind Kind;
- std::string Name;
- MCModule *Parent;
- uint64_t Begin, End;
-
- friend class MCModule;
- MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E)
- : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { }
-
- /// \name Atom remapping helpers
- /// @{
-
- /// \brief Remap the atom, using the given range, updating Begin/End.
- /// One or both of the bounds can remain the same, but overlapping with other
- /// atoms in the module is still forbidden.
- void remap(uint64_t NewBegin, uint64_t NewEnd);
-
- /// \brief Remap the atom to prepare for a truncation at TruncPt.
- /// Equivalent to:
- /// \code
- /// // Bound checks
- /// remap(Begin, TruncPt);
- /// \endcode
- void remapForTruncate(uint64_t TruncPt);
-
- /// \brief Remap the atom to prepare for a split at SplitPt.
- /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}.
- /// The current atom is truncated to \p LEnd.
- void remapForSplit(uint64_t SplitPt,
- uint64_t &LBegin, uint64_t &LEnd,
- uint64_t &RBegin, uint64_t &REnd);
- /// @}
-};
-
-/// \name Text atom
-/// @{
-
-/// \brief An entry in an MCTextAtom: a disassembled instruction.
-/// NOTE: Both the Address and Size field are actually redundant when taken in
-/// the context of the text atom, and may better be exposed in an iterator
-/// instead of stored in the atom, which would replace this class.
-class MCDecodedInst {
-public:
- MCInst Inst;
- uint64_t Address;
- uint64_t Size;
- MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size)
- : Inst(Inst), Address(Address), Size(Size) {}
-};
-
-/// \brief An atom consisting of disassembled instructions.
-class MCTextAtom : public MCAtom {
-private:
- typedef std::vector<MCDecodedInst> InstListTy;
- InstListTy Insts;
-
- /// \brief The address of the next appended instruction, i.e., the
- /// address immediately after the last instruction in the atom.
- uint64_t NextInstAddress;
-public:
- /// Append an instruction, expanding the atom if necessary.
- void addInst(const MCInst &Inst, uint64_t Size);
-
- /// \name Instruction list access
- /// @{
- typedef InstListTy::const_iterator const_iterator;
- const_iterator begin() const { return Insts.begin(); }
- const_iterator end() const { return Insts.end(); }
-
- const MCDecodedInst &back() const { return Insts.back(); }
- const MCDecodedInst &at(size_t n) const { return Insts.at(n); }
- size_t size() const { return Insts.size(); }
- /// @}
-
- /// \name Atom type specific split/truncate logic.
- /// @{
- MCTextAtom *split(uint64_t SplitPt) override;
- void truncate(uint64_t TruncPt) override;
- /// @}
-
- // Class hierarchy.
- static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; }
-private:
- friend class MCModule;
- // Private constructor - only callable by MCModule
- MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End)
- : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {}
-};
-/// @}
-
-/// \name Data atom
-/// @{
-
-/// \brief An entry in an MCDataAtom.
-// NOTE: This may change to a more complex type in the future.
-typedef uint8_t MCData;
-
-/// \brief An atom consising of a sequence of bytes.
-class MCDataAtom : public MCAtom {
- std::vector<MCData> Data;
-
-public:
- /// Append a data entry, expanding the atom if necessary.
- void addData(const MCData &D);
-
- /// Get a reference to the data in this atom.
- ArrayRef<MCData> getData() const { return Data; }
-
- /// \name Atom type specific split/truncate logic.
- /// @{
- MCDataAtom *split(uint64_t SplitPt) override;
- void truncate(uint64_t TruncPt) override;
- /// @}
-
- // Class hierarchy.
- static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; }
-private:
- friend class MCModule;
- // Private constructor - only callable by MCModule
- MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End)
- : MCAtom(DataAtom, P, Begin, End) {
- Data.reserve(End + 1 - Begin);
- }
-};
-
-}
-
-#endif
diff --git a/include/llvm/MC/MCAnalysis/MCFunction.h b/include/llvm/MC/MCAnalysis/MCFunction.h
deleted file mode 100644
index 44fa4503b8e0..000000000000
--- a/include/llvm/MC/MCAnalysis/MCFunction.h
+++ /dev/null
@@ -1,142 +0,0 @@
-//===-- MCFunction.h --------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the data structures to hold a CFG reconstructed from
-// machine code.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MC_MCANALYSIS_MCFUNCTION_H
-#define LLVM_MC_MCANALYSIS_MCFUNCTION_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/MC/MCInst.h"
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-class MCFunction;
-class MCModule;
-class MCTextAtom;
-
-/// \brief Basic block containing a sequence of disassembled instructions.
-/// The basic block is backed by an MCTextAtom, which holds the instructions,
-/// and the address range it covers.
-/// Create a basic block using MCFunction::createBlock.
-class MCBasicBlock {
- const MCTextAtom *Insts;
-
- // MCFunction owns the basic block.
- MCFunction *Parent;
- friend class MCFunction;
- MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent);
-
- /// \name Predecessors/Successors, to represent the CFG.
- /// @{
- typedef std::vector<const MCBasicBlock *> BasicBlockListTy;
- BasicBlockListTy Successors;
- BasicBlockListTy Predecessors;
- /// @}
-public:
-
- /// \brief Get the backing MCTextAtom, containing the instruction sequence.
- const MCTextAtom *getInsts() const { return Insts; }
-
- /// \name Get the owning MCFunction.
- /// @{
- const MCFunction *getParent() const { return Parent; }
- MCFunction *getParent() { return Parent; }
- /// @}
-
- /// MC CFG access: Predecessors/Successors.
- /// @{
- typedef BasicBlockListTy::const_iterator succ_const_iterator;
- succ_const_iterator succ_begin() const { return Successors.begin(); }
- succ_const_iterator succ_end() const { return Successors.end(); }
-
- typedef BasicBlockListTy::const_iterator pred_const_iterator;
- pred_const_iterator pred_begin() const { return Predecessors.begin(); }
- pred_const_iterator pred_end() const { return Predecessors.end(); }
-
- void addSuccessor(const MCBasicBlock *MCBB);
- bool isSuccessor(const MCBasicBlock *MCBB) const;
-
- void addPredecessor(const MCBasicBlock *MCBB);
- bool isPredecessor(const MCBasicBlock *MCBB) const;
-
- /// \brief Split block, mirrorring NewAtom = Insts->split(..).
- /// This moves all successors to \p SplitBB, and
- /// adds a fallthrough to it.
- /// \p SplitBB The result of splitting Insts, a basic block directly following
- /// this basic block.
- void splitBasicBlock(MCBasicBlock *SplitBB);
- /// @}
-};
-
-/// \brief Represents a function in machine code, containing MCBasicBlocks.
-/// MCFunctions are created by MCModule.
-class MCFunction {
- MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION;
- MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION;
-
- std::string Name;
- MCModule *ParentModule;
- typedef std::vector<std::unique_ptr<MCBasicBlock>> BasicBlockListTy;
- BasicBlockListTy Blocks;
-
- // MCModule owns the function.
- friend class MCModule;
- MCFunction(StringRef Name, MCModule *Parent);
-
-public:
- /// \brief Create an MCBasicBlock backed by Insts and add it to this function.
- /// \param Insts Sequence of straight-line code backing the basic block.
- /// \returns The newly created basic block.
- MCBasicBlock &createBlock(const MCTextAtom &Insts);
-
- StringRef getName() const { return Name; }
-
- /// \name Get the owning MC Module.
- /// @{
- const MCModule *getParent() const { return ParentModule; }
- MCModule *getParent() { return ParentModule; }
- /// @}
-
- /// \name Access to the function's basic blocks. No ordering is enforced,
- /// except that the first block is the entry block.
- /// @{
- /// \brief Get the entry point basic block.
- const MCBasicBlock *getEntryBlock() const { return front(); }
- MCBasicBlock *getEntryBlock() { return front(); }
-
- bool empty() const { return Blocks.empty(); }
-
- typedef BasicBlockListTy::const_iterator const_iterator;
- typedef BasicBlockListTy:: iterator iterator;
- const_iterator begin() const { return Blocks.begin(); }
- iterator begin() { return Blocks.begin(); }
- const_iterator end() const { return Blocks.end(); }
- iterator end() { return Blocks.end(); }
-
- const MCBasicBlock* front() const { return Blocks.front().get(); }
- MCBasicBlock* front() { return Blocks.front().get(); }
- const MCBasicBlock* back() const { return Blocks.back().get(); }
- MCBasicBlock* back() { return Blocks.back().get(); }
-
- /// \brief Find the basic block, if any, that starts at \p StartAddr.
- const MCBasicBlock *find(uint64_t StartAddr) const;
- MCBasicBlock *find(uint64_t StartAddr);
- /// @}
-};
-
-}
-
-#endif
diff --git a/include/llvm/MC/MCAnalysis/MCModule.h b/include/llvm/MC/MCAnalysis/MCModule.h
deleted file mode 100644
index cf7e2c0a645e..000000000000
--- a/include/llvm/MC/MCAnalysis/MCModule.h
+++ /dev/null
@@ -1,134 +0,0 @@
-//===-- MCModule.h - MCModule class -----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the MCModule class, which is used to
-// represent a complete, disassembled object file or executable.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MC_MCANALYSIS_MCMODULE_H
-#define LLVM_MC_MCANALYSIS_MCMODULE_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
-#include <memory>
-#include <vector>
-
-namespace llvm {
-
-class MCAtom;
-class MCBasicBlock;
-class MCDataAtom;
-class MCFunction;
-class MCObjectDisassembler;
-class MCTextAtom;
-
-/// \brief A completely disassembled object file or executable.
-/// It comprises a list of MCAtom's, each representing a contiguous range of
-/// either instructions or data.
-/// An MCModule is created using MCObjectDisassembler::buildModule.
-class MCModule {
- /// \name Atom tracking
- /// @{
-
- /// \brief Atoms in this module, sorted by begin address.
- /// FIXME: This doesn't handle overlapping atoms (which happen when a basic
- /// block starts in the middle of an instruction of another basic block.)
- typedef std::vector<MCAtom*> AtomListTy;
- AtomListTy Atoms;
-
- // For access to map/remap.
- friend class MCAtom;
-
- /// \brief Remap \p Atom to the given range, and update its Begin/End fields.
- /// \param Atom An atom belonging to this module.
- /// An atom should always use this method to update its bounds, because this
- /// enables the owning MCModule to keep track of its atoms.
- void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd);
-
- /// \brief Insert an atom in the module, using its Begin and End addresses.
- void map(MCAtom *NewAtom);
- /// @}
-
- /// \name Basic block tracking
- /// @{
- typedef std::vector<MCBasicBlock*> BBsByAtomTy;
- BBsByAtomTy BBsByAtom;
-
- // For access to basic block > atom tracking.
- friend class MCBasicBlock;
- friend class MCTextAtom;
-
- /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom.
- /// This is used to update succs/preds when \p Atom is split.
- void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom);
- void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA);
- /// @}
-
- /// \name Function tracking
- /// @{
- typedef std::vector<std::unique_ptr<MCFunction>> FunctionListTy;
- FunctionListTy Functions;
- /// @}
-
- /// The address of the entrypoint function.
- uint64_t Entrypoint;
-
- MCModule (const MCModule &) LLVM_DELETED_FUNCTION;
- MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION;
-
- // MCObjectDisassembler creates MCModules.
- friend class MCObjectDisassembler;
-
-public:
- MCModule();
- ~MCModule();
-
- /// \name Create a new MCAtom covering the specified offset range.
- /// @{
- MCTextAtom *createTextAtom(uint64_t Begin, uint64_t End);
- MCDataAtom *createDataAtom(uint64_t Begin, uint64_t End);
- /// @}
-
- /// \name Access to the owned atom list, ordered by begin address.
- /// @{
- const MCAtom *findAtomContaining(uint64_t Addr) const;
- MCAtom *findAtomContaining(uint64_t Addr);
- const MCAtom *findFirstAtomAfter(uint64_t Addr) const;
- MCAtom *findFirstAtomAfter(uint64_t Addr);
-
- typedef AtomListTy::const_iterator const_atom_iterator;
- typedef AtomListTy:: iterator atom_iterator;
- const_atom_iterator atom_begin() const { return Atoms.begin(); }
- atom_iterator atom_begin() { return Atoms.begin(); }
- const_atom_iterator atom_end() const { return Atoms.end(); }
- atom_iterator atom_end() { return Atoms.end(); }
- /// @}
-
- /// \brief Create a new MCFunction.
- MCFunction *createFunction(StringRef Name);
-
- /// \name Access to the owned function list.
- /// @{
- typedef FunctionListTy::const_iterator const_func_iterator;
- typedef FunctionListTy:: iterator func_iterator;
- const_func_iterator func_begin() const { return Functions.begin(); }
- func_iterator func_begin() { return Functions.begin(); }
- const_func_iterator func_end() const { return Functions.end(); }
- func_iterator func_end() { return Functions.end(); }
- /// @}
-
- /// \brief Get the address of the entrypoint function, or 0 if there is none.
- uint64_t getEntrypoint() const { return Entrypoint; }
-};
-
-}
-
-#endif
diff --git a/include/llvm/MC/MCAnalysis/MCModuleYAML.h b/include/llvm/MC/MCAnalysis/MCModuleYAML.h
deleted file mode 100644
index 48562777677b..000000000000
--- a/include/llvm/MC/MCAnalysis/MCModuleYAML.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief This file declares classes for handling the YAML representation
-/// of MCModule.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MC_MCANALYSIS_MCMODULEYAML_H
-#define LLVM_MC_MCANALYSIS_MCMODULEYAML_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/MC/MCAnalysis/MCModule.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-class MCInstrInfo;
-class MCRegisterInfo;
-
-/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS.
-/// \returns The empty string on success, an error message on failure.
-StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM,
- const MCInstrInfo &MII, const MCRegisterInfo &MRI);
-
-/// \brief Creates a new module and returns it in \p MCM.
-/// \returns The empty string on success, an error message on failure.
-StringRef yaml2mcmodule(std::unique_ptr<MCModule> &MCM, StringRef YamlContent,
- const MCInstrInfo &MII, const MCRegisterInfo &MRI);
-
-} // end namespace llvm
-
-#endif
diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h
index 82b65fdaf5c8..216271086a40 100644
--- a/include/llvm/MC/MCAsmBackend.h
+++ b/include/llvm/MC/MCAsmBackend.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCAsmBack.h - MC Asm Backend --------------------*- C++ -*-===//
+//===-- llvm/MC/MCAsmBackend.h - MC Asm Backend -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -61,20 +61,6 @@ public:
/// markers. If not, data region directives will be ignored.
bool hasDataInCodeSupport() const { return HasDataInCodeSupport; }
- /// doesSectionRequireSymbols - Check whether the given section requires that
- /// all symbols (even temporaries) have symbol table entries.
- virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
- return false;
- }
-
- /// isSectionAtomizable - Check whether the given section can be split into
- /// atoms.
- ///
- /// \see MCAssembler::isSymbolLinkerVisible().
- virtual bool isSectionAtomizable(const MCSection &Section) const {
- return true;
- }
-
/// @name Target Fixup Interfaces
/// @{
@@ -146,7 +132,7 @@ public:
/// \brief Generate the compact unwind encoding for the CFI instructions.
virtual uint32_t
- generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const {
+ generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const {
return 0;
}
};
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 06e473d6b625..a750a0fd5cef 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -31,22 +31,23 @@ class MCContext;
namespace WinEH {
enum class EncodingType {
- ET_Invalid, /// Invalid
- ET_Alpha, /// Windows Alpha
- ET_Alpha64, /// Windows AXP64
- ET_ARM, /// Windows NT (Windows on ARM)
- ET_CE, /// Windows CE ARM, PowerPC, SH3, SH4
- ET_Itanium, /// Windows x64, Windows Itanium (IA-64)
- ET_MIPS = ET_Alpha,
+ Invalid, /// Invalid
+ Alpha, /// Windows Alpha
+ Alpha64, /// Windows AXP64
+ ARM, /// Windows NT (Windows on ARM)
+ CE, /// Windows CE ARM, PowerPC, SH3, SH4
+ Itanium, /// Windows x64, Windows Itanium (IA-64)
+ MIPS = Alpha,
};
}
enum class ExceptionHandling {
- None, /// No exception support
- DwarfCFI, /// DWARF-like instruction based exceptions
- SjLj, /// setjmp/longjmp based exceptions
- ARM, /// ARM EHABI
- WinEH, /// Windows Exception Handling
+ None, /// No exception support
+ DwarfCFI, /// DWARF-like instruction based exceptions
+ SjLj, /// setjmp/longjmp based exceptions
+ ARM, /// ARM EHABI
+ ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata)
+ MSVC, /// MSVC compatible exception handling
};
namespace LCOMM {
@@ -87,16 +88,11 @@ protected:
bool HasMachoTBSSDirective;
/// True if the compiler should emit a ".reference .constructors_used" or
- /// ".reference .destructors_used" directive after the a static ctor/dtor
+ /// ".reference .destructors_used" directive after the static ctor/dtor
/// list. This directive is only emitted in Static relocation model. Default
/// is false.
bool HasStaticCtorDtorReferenceInStaticMode;
- /// True if the linker has a bug and requires that the debug_line section be
- /// of a minimum size. In practice such a linker requires a non-empty line
- /// sequence if a file is present. Default to false.
- bool LinkerRequiresNonEmptyDwarfLines;
-
/// 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;
@@ -128,6 +124,10 @@ protected:
/// file. Defaults to "L"
const char *PrivateGlobalPrefix;
+ /// This prefix is used for labels for basic blocks. Defaults to the same as
+ /// PrivateGlobalPrefix.
+ const char *PrivateLabelPrefix;
+
/// This prefix is used for symbols that should be passed through the
/// assembler but be removed by the linker. This is 'l' on Darwin, currently
/// used for some ObjC metadata. The default of "" meast that for this system
@@ -220,11 +220,16 @@ protected:
//===--- Global Variable Emission Directives --------------------------===//
- /// This is the directive used to declare a global entity. Defaults to NULL.
+ /// This is the directive used to declare a global entity. Defaults to
+ /// ".globl".
const char *GlobalDirective;
- /// True if the assembler supports the .set directive. Defaults to true.
- bool HasSetDirective;
+ /// True if the expression
+ /// .long f - g
+ /// uses an relocation but it can be supressed by writting
+ /// a = f - g
+ /// .long a
+ bool SetDirectiveSuppressesReloc;
/// False if the assembler requires that we use
/// \code
@@ -265,6 +270,9 @@ protected:
/// to false.
bool HasNoDeadStrip;
+ /// Used to declare a global as being a weak symbol. Defaults to ".weak".
+ const char *WeakDirective;
+
/// This directive, if non-null, is used to declare a global as being a weak
/// undefined symbol. Defaults to NULL.
const char *WeakRefDirective;
@@ -295,9 +303,6 @@ protected:
//===--- Dwarf Emission Directives -----------------------------------===//
- /// True if target asm supports leb128 directives. Defaults to false.
- bool HasLEB128;
-
/// True if target supports emission of debugging information. Defaults to
/// false.
bool SupportsDebugInformation;
@@ -377,6 +382,12 @@ public:
return nullptr;
}
+ /// \brief True if the section is atomized using the symbols in it.
+ /// This is false if the section is not atomized at all (most ELF sections) or
+ /// if it is atomized based on its contents (MachO' __TEXT,__cstring for
+ /// example).
+ virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const;
+
virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym,
unsigned Encoding,
MCStreamer &Streamer) const;
@@ -404,9 +415,6 @@ public:
bool hasStaticCtorDtorReferenceInStaticMode() const {
return HasStaticCtorDtorReferenceInStaticMode;
}
- bool getLinkerRequiresNonEmptyDwarfLines() const {
- return LinkerRequiresNonEmptyDwarfLines;
- }
unsigned getMaxInstLength() const { return MaxInstLength; }
unsigned getMinInstAlignment() const { return MinInstAlignment; }
bool getDollarIsPC() const { return DollarIsPC; }
@@ -421,6 +429,7 @@ public:
bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; }
const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; }
+ const char *getPrivateLabelPrefix() const { return PrivateLabelPrefix; }
bool hasLinkerPrivateGlobalPrefix() const {
return LinkerPrivateGlobalPrefix[0] != '\0';
}
@@ -445,7 +454,9 @@ public:
bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; }
unsigned getTextAlignFillValue() const { return TextAlignFillValue; }
const char *getGlobalDirective() const { return GlobalDirective; }
- bool hasSetDirective() const { return HasSetDirective; }
+ bool doesSetDirectiveSuppressesReloc() const {
+ return SetDirectiveSuppressesReloc;
+ }
bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; }
bool getCOMMDirectiveAlignmentIsInBytes() const {
return COMMDirectiveAlignmentIsInBytes;
@@ -457,6 +468,7 @@ public:
bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; }
bool hasIdentDirective() const { return HasIdentDirective; }
bool hasNoDeadStrip() const { return HasNoDeadStrip; }
+ const char *getWeakDirective() const { return WeakDirective; }
const char *getWeakRefDirective() const { return WeakRefDirective; }
bool hasWeakDefDirective() const { return HasWeakDefDirective; }
bool hasWeakDefCanBeHiddenDirective() const {
@@ -471,19 +483,27 @@ public:
MCSymbolAttr getProtectedVisibilityAttr() const {
return ProtectedVisibilityAttr;
}
- bool hasLEB128() const { return HasLEB128; }
bool doesSupportDebugInformation() const { return SupportsDebugInformation; }
bool doesSupportExceptionHandling() const {
return ExceptionsType != ExceptionHandling::None;
}
ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; }
WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; }
- bool isExceptionHandlingDwarf() const {
+
+ /// Return true if the exception handling type uses the language-specific data
+ /// area (LSDA) format specified by the Itanium C++ ABI.
+ bool usesItaniumLSDAForExceptions() const {
return (ExceptionsType == ExceptionHandling::DwarfCFI ||
ExceptionsType == ExceptionHandling::ARM ||
- // Windows handler data still uses DWARF LSDA encoding.
- ExceptionsType == ExceptionHandling::WinEH);
+ // This Windows EH type uses the Itanium LSDA encoding.
+ ExceptionsType == ExceptionHandling::ItaniumWinEH);
}
+
+ bool usesWindowsCFI() const {
+ return ExceptionsType == ExceptionHandling::ItaniumWinEH ||
+ ExceptionsType == ExceptionHandling::MSVC;
+ }
+
bool doesDwarfUseRelocationsAcrossSections() const {
return DwarfUsesRelocationsAcrossSections;
}
diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h
index 3d249f93068d..d587c3ce9d54 100644
--- a/include/llvm/MC/MCAsmInfoDarwin.h
+++ b/include/llvm/MC/MCAsmInfoDarwin.h
@@ -19,9 +19,9 @@
namespace llvm {
class MCAsmInfoDarwin : public MCAsmInfo {
- virtual void anchor();
public:
explicit MCAsmInfoDarwin();
+ bool isSectionAtomizableBySymbols(const MCSection &Section) const override;
};
}
diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h
index 27fea84e7a6d..7bd246056eca 100644
--- a/include/llvm/MC/MCAsmInfoELF.h
+++ b/include/llvm/MC/MCAsmInfoELF.h
@@ -15,6 +15,9 @@
namespace llvm {
class MCAsmInfoELF : public MCAsmInfo {
virtual void anchor();
+ const MCSection *
+ getNonexecutableStackSection(MCContext &Ctx) const override final;
+
protected:
MCAsmInfoELF();
};
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 1cb34c2fe33b..31f29eb1f3ff 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -11,6 +11,8 @@
#define LLVM_MC_MCASSEMBLER_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/ilist.h"
@@ -593,7 +595,10 @@ private:
unsigned Alignment;
/// \brief Keeping track of bundle-locked state.
- BundleLockStateType BundleLockState;
+ BundleLockStateType BundleLockState;
+
+ /// \brief Current nesting depth of bundle_lock directives.
+ unsigned BundleLockNestingDepth;
/// \brief We've seen a bundle_lock directive but not its first instruction
/// yet.
@@ -665,9 +670,7 @@ public:
return BundleLockState;
}
- void setBundleLockState(BundleLockStateType NewState) {
- BundleLockState = NewState;
- }
+ void setBundleLockState(BundleLockStateType NewState);
bool isBundleGroupBeforeFirstInst() const {
return BundleGroupBeforeFirstInst;
@@ -684,34 +687,27 @@ public:
// FIXME: Same concerns as with SectionData.
class MCSymbolData : public ilist_node<MCSymbolData> {
-public:
const MCSymbol *Symbol;
- /// Fragment - The fragment this symbol's value is relative to, if any.
- MCFragment *Fragment;
-
- /// Offset - The offset to apply to the fragment address to form this symbol's
- /// value.
- uint64_t Offset;
-
- /// IsExternal - True if this symbol is visible outside this translation
- /// unit.
- unsigned IsExternal : 1;
+ /// Fragment - The fragment this symbol's value is relative to, if any. Also
+ /// stores if this symbol is visible outside this translation unit (bit 0) or
+ /// if it is private extern (bit 1).
+ PointerIntPair<MCFragment *, 2> Fragment;
- /// IsPrivateExtern - True if this symbol is private extern.
- unsigned IsPrivateExtern : 1;
+ union {
+ /// Offset - The offset to apply to the fragment address to form this
+ /// symbol's value.
+ uint64_t Offset;
- /// CommonSize - The size of the symbol, if it is 'common', or 0.
- //
- // FIXME: Pack this in with other fields? We could put it in offset, since a
- // common symbol can never get a definition.
- uint64_t CommonSize;
+ /// CommonSize - The size of the symbol, if it is 'common'.
+ uint64_t CommonSize;
+ };
/// SymbolSize - An expression describing how to calculate the size of
/// a symbol. If a symbol has no size this field will be NULL.
const MCExpr *SymbolSize;
- /// CommonAlign - The alignment of the symbol, if it is 'common'.
+ /// CommonAlign - The alignment of the symbol, if it is 'common', or -1.
//
// FIXME: Pack this in with other fields?
unsigned CommonAlign;
@@ -734,30 +730,41 @@ public:
const MCSymbol &getSymbol() const { return *Symbol; }
- MCFragment *getFragment() const { return Fragment; }
- void setFragment(MCFragment *Value) { Fragment = Value; }
+ MCFragment *getFragment() const { return Fragment.getPointer(); }
+ void setFragment(MCFragment *Value) { Fragment.setPointer(Value); }
- uint64_t getOffset() const { return Offset; }
- void setOffset(uint64_t Value) { Offset = Value; }
+ uint64_t getOffset() const {
+ assert(!isCommon());
+ return Offset;
+ }
+ void setOffset(uint64_t Value) {
+ assert(!isCommon());
+ Offset = Value;
+ }
/// @}
/// @name Symbol Attributes
/// @{
- bool isExternal() const { return IsExternal; }
- void setExternal(bool Value) { IsExternal = Value; }
+ bool isExternal() const { return Fragment.getInt() & 1; }
+ void setExternal(bool Value) {
+ Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value));
+ }
- bool isPrivateExtern() const { return IsPrivateExtern; }
- void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
+ bool isPrivateExtern() const { return Fragment.getInt() & 2; }
+ void setPrivateExtern(bool Value) {
+ Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1));
+ }
/// isCommon - Is this a 'common' symbol.
- bool isCommon() const { return CommonSize != 0; }
+ bool isCommon() const { return CommonAlign != -1U; }
/// setCommon - Mark this symbol as being 'common'.
///
/// \param Size - The size of the symbol.
/// \param Align - The alignment of the symbol.
void setCommon(uint64_t Size, unsigned Align) {
+ assert(getOffset() == 0);
CommonSize = Size;
CommonAlign = Align;
}
@@ -875,6 +882,8 @@ private:
iplist<MCSymbolData> Symbols;
+ DenseSet<const MCSymbol *> LocalsUsedInReloc;
+
/// The map of sections to their associated assembler backend data.
//
// FIXME: Avoid this indirection?
@@ -910,7 +919,6 @@ private:
unsigned BundleAlignSize;
unsigned RelaxAll : 1;
- unsigned NoExecStack : 1;
unsigned SubsectionsViaSymbols : 1;
/// ELF specific e_header flags
@@ -975,6 +983,9 @@ private:
MCFragment &F, const MCFixup &Fixup);
public:
+ void addLocalUsedInReloc(const MCSymbol &Sym);
+ bool isLocalUsedInReloc(const MCSymbol &Sym) const;
+
/// Compute the effective fragment size assuming it is laid out at the given
/// \p SectionAddress and \p FragmentOffset.
uint64_t computeFragmentSize(const MCAsmLayout &Layout,
@@ -1056,9 +1067,6 @@ public:
bool getRelaxAll() const { return RelaxAll; }
void setRelaxAll(bool Value) { RelaxAll = Value; }
- bool getNoExecStack() const { return NoExecStack; }
- void setNoExecStack(bool Value) { NoExecStack = Value; }
-
bool isBundlingEnabled() const {
return BundleAlignSize != 0;
}
diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h
index eb0340f7421a..e3163a7946a7 100644
--- a/include/llvm/MC/MCContext.h
+++ b/include/llvm/MC/MCContext.h
@@ -73,6 +73,10 @@ namespace llvm {
/// Symbols - Bindings of names to symbols.
SymbolTable Symbols;
+ /// ELF sections can have a corresponding symbol. This maps one to the
+ /// other.
+ DenseMap<const MCSectionELF*, MCSymbol*> SectionSymbols;
+
/// A maping from a local label number and an instance count to a symbol.
/// For example, in the assembly
/// 1:
@@ -231,6 +235,10 @@ namespace llvm {
MCSymbol *GetOrCreateSymbol(StringRef Name);
MCSymbol *GetOrCreateSymbol(const Twine &Name);
+ MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section);
+
+ MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName);
+
/// LookupSymbol - Get the symbol for \p Name, or null.
MCSymbol *LookupSymbol(StringRef Name) const;
MCSymbol *LookupSymbol(const Twine &Name) const;
@@ -284,6 +292,13 @@ namespace llvm {
const MCSectionCOFF *getCOFFSection(StringRef Section);
+ /// Gets or creates a section equivalent to Sec that is associated with the
+ /// section containing KeySym. For example, to create a debug info section
+ /// associated with an inline function, pass the normal debug info section
+ /// as Sec and the function symbol as KeySym.
+ const MCSectionCOFF *getAssociativeCOFFSection(const MCSectionCOFF *Sec,
+ const MCSymbol *KeySym);
+
/// @}
/// @name Dwarf Management
diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h
index 9d441bbd88fb..d6b0a305b1da 100644
--- a/include/llvm/MC/MCDisassembler.h
+++ b/include/llvm/MC/MCDisassembler.h
@@ -10,6 +10,7 @@
#define LLVM_MC_MCDISASSEMBLER_H
#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSymbolizer.h"
#include "llvm/Support/DataTypes.h"
@@ -18,12 +19,11 @@ namespace llvm {
class MCInst;
class MCSubtargetInfo;
-class MemoryObject;
class raw_ostream;
class MCContext;
-/// MCDisassembler - Superclass for all disassemblers. Consumes a memory region
-/// and provides an array of assembly instructions.
+/// Superclass for all disassemblers. Consumes a memory region and provides an
+/// array of assembly instructions.
class MCDisassembler {
public:
/// Ternary decode status. Most backends will just use Fail and
@@ -54,34 +54,31 @@ public:
Success = 3
};
- /// Constructor - Performs initial setup for the disassembler.
MCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
: Ctx(Ctx), STI(STI), Symbolizer(), CommentStream(nullptr) {}
virtual ~MCDisassembler();
- /// getInstruction - Returns the disassembly of a single instruction.
+ /// Returns the disassembly of a single instruction.
///
- /// @param instr - An MCInst to populate with the contents of the
+ /// @param Instr - An MCInst to populate with the contents of the
/// instruction.
- /// @param size - A value to populate with the size of the instruction, or
+ /// @param Size - A value to populate with the size of the instruction, or
/// the number of bytes consumed while attempting to decode
/// an invalid instruction.
- /// @param region - The memory object to use as a source for machine code.
- /// @param address - The address, in the memory space of region, of the first
+ /// @param Address - The address, in the memory space of region, of the first
/// byte of the instruction.
- /// @param vStream - The stream to print warnings and diagnostic messages on.
- /// @param cStream - The stream to print comments and annotations on.
+ /// @param VStream - The stream to print warnings and diagnostic messages on.
+ /// @param CStream - The stream to print comments and annotations on.
/// @return - MCDisassembler::Success if the instruction is valid,
/// MCDisassembler::SoftFail if the instruction was
/// disassemblable but invalid,
/// MCDisassembler::Fail if the instruction was invalid.
- virtual DecodeStatus getInstruction(MCInst& instr,
- uint64_t& size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream,
- raw_ostream &cStream) const = 0;
+ virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const = 0;
+
private:
MCContext &Ctx;
diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h
index 6cd9a9a21e21..c266acf2f09c 100644
--- a/include/llvm/MC/MCDwarf.h
+++ b/include/llvm/MC/MCDwarf.h
@@ -16,16 +16,16 @@
#define LLVM_MC_MCDWARF_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
-#include <vector>
#include <string>
#include <utility>
+#include <vector>
namespace llvm {
class MCAsmBackend;
@@ -457,7 +457,7 @@ public:
return Offset;
}
- const StringRef getValues() const {
+ StringRef getValues() const {
assert(Operation == OpEscape);
return StringRef(&Values[0], Values.size());
}
@@ -466,13 +466,15 @@ public:
struct MCDwarfFrameInfo {
MCDwarfFrameInfo()
: Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr),
- Instructions(), PersonalityEncoding(), LsdaEncoding(0),
- CompactUnwindEncoding(0), IsSignalFrame(false), IsSimple(false) {}
+ Instructions(), CurrentCfaRegister(0), PersonalityEncoding(),
+ LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false),
+ IsSimple(false) {}
MCSymbol *Begin;
MCSymbol *End;
const MCSymbol *Personality;
const MCSymbol *Lsda;
std::vector<MCCFIInstruction> Instructions;
+ unsigned CurrentCfaRegister;
unsigned PersonalityEncoding;
unsigned LsdaEncoding;
uint32_t CompactUnwindEncoding;
diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h
index 66729fe0147e..ab6c5e3d6124 100644
--- a/include/llvm/MC/MCELFStreamer.h
+++ b/include/llvm/MC/MCELFStreamer.h
@@ -41,10 +41,18 @@ public:
virtual ~MCELFStreamer();
+ /// state management
+ void reset() override {
+ LocalCommons.clear();
+ BindingExplicitlySet.clear();
+ SeenIdent = false;
+ MCObjectStreamer::reset();
+ }
+
/// @name MCStreamer Interface
/// @{
- void InitSections() override;
+ void InitSections(bool NoExecStack) override;
void ChangeSection(const MCSection *Section,
const MCExpr *Subsection) override;
void EmitLabel(MCSymbol *Symbol) override;
@@ -107,8 +115,7 @@ private:
MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter,
- bool RelaxAll, bool NoExecStack,
- bool IsThumb);
+ bool RelaxAll, bool IsThumb);
} // end namespace llvm
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index e96ecb4be175..bd9b2bc4751a 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -19,6 +19,7 @@ class MCAsmInfo;
class MCAsmLayout;
class MCAssembler;
class MCContext;
+class MCFixup;
class MCSection;
class MCSectionData;
class MCStreamer;
@@ -49,11 +50,17 @@ private:
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
const SectionAddrMap *Addrs) const;
+
+ bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
+ const MCAsmLayout *Layout,
+ const SectionAddrMap *Addrs, bool InSet) const;
+
protected:
explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {}
bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
+ const MCFixup *Fixup,
const SectionAddrMap *Addrs, bool InSet,
bool ForceVarExpansion) const;
@@ -87,13 +94,17 @@ public:
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
+ int64_t evaluateKnownAbsolute(const MCAsmLayout &Layout) const;
+
/// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable
/// value, i.e. an expression of the fixed form (a - b + constant).
///
/// @param Res - The relocatable value, if evaluation succeeds.
/// @param Layout - The assembler layout object to use for evaluating values.
+ /// @param Fixup - The Fixup object if available.
/// @result - True on success.
- bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout) const;
+ bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
+ const MCFixup *Fixup) const;
/// \brief Try to evaluate the expression to the form (a - b + constant) where
/// neither a nor b are variables.
@@ -101,7 +112,8 @@ public:
/// This is a more aggressive variant of EvaluateAsRelocatable. The intended
/// use is for when relocations are not available, like the symbol value in
/// the symbol table.
- bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout) const;
+ bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout,
+ const MCFixup *Fixup) const;
/// FindAssociatedSection - Find the "associated section" for this expression,
/// which is currently defined as the absolute section for constants, or
@@ -182,6 +194,7 @@ public:
VK_ARM_TARGET1,
VK_ARM_TARGET2,
VK_ARM_PREL31,
+ VK_ARM_SBREL, // symbol(sbrel)
VK_ARM_TLSLDO, // symbol(tlsldo)
VK_ARM_TLSCALL, // symbol(tlscall)
VK_ARM_TLSDESC, // symbol(tlsdesc)
@@ -238,6 +251,7 @@ public:
VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h
VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha
VK_PPC_TLSLD, // symbol@tlsld
+ VK_PPC_LOCAL, // symbol@local
VK_Mips_GPREL,
VK_Mips_GOT_CALL,
@@ -270,21 +284,20 @@ public:
};
private:
- /// The symbol being referenced.
- const MCSymbol *Symbol;
-
/// The symbol reference modifier.
- const VariantKind Kind;
+ const unsigned Kind : 16;
- /// MCAsmInfo that is used to print symbol variants correctly.
- const MCAsmInfo *MAI;
+ /// Specifies how the variant kind should be printed.
+ const unsigned UseParensForSymbolVariant : 1;
- explicit MCSymbolRefExpr(const MCSymbol *_Symbol, VariantKind _Kind,
- const MCAsmInfo *_MAI)
- : MCExpr(MCExpr::SymbolRef), Symbol(_Symbol), Kind(_Kind), MAI(_MAI) {
- assert(Symbol);
- assert(MAI);
- }
+ // FIXME: Remove this bit.
+ const unsigned HasSubsectionsViaSymbols : 1;
+
+ /// The symbol being referenced.
+ const MCSymbol *Symbol;
+
+ explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
+ const MCAsmInfo *MAI);
public:
/// @name Construction
@@ -304,9 +317,12 @@ public:
/// @{
const MCSymbol &getSymbol() const { return *Symbol; }
- const MCAsmInfo &getMCAsmInfo() const { return *MAI; }
- VariantKind getKind() const { return Kind; }
+ VariantKind getKind() const { return static_cast<VariantKind>(Kind); }
+
+ void printVariantKind(raw_ostream &OS) const;
+
+ bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; }
/// @}
/// @name Static Utility Functions
@@ -524,7 +540,8 @@ public:
virtual void PrintImpl(raw_ostream &OS) const = 0;
virtual bool EvaluateAsRelocatableImpl(MCValue &Res,
- const MCAsmLayout *Layout) const = 0;
+ const MCAsmLayout *Layout,
+ const MCFixup *Fixup) const = 0;
virtual void visitUsedExpr(MCStreamer& Streamer) const = 0;
virtual const MCSection *FindAssociatedSection() const = 0;
diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h
index 6918280a4219..25cd5ccb08fd 100644
--- a/include/llvm/MC/MCInst.h
+++ b/include/llvm/MC/MCInst.h
@@ -31,7 +31,7 @@ class MCInst;
/// MCOperand - Instances of this class represent operands of the MCInst class.
/// This is a simple discriminated union.
class MCOperand {
- enum MachineOperandType {
+ enum MachineOperandType : unsigned char {
kInvalid, ///< Uninitialized.
kRegister, ///< Register operand.
kImmediate, ///< Immediate operand.
@@ -39,7 +39,7 @@ class MCOperand {
kExpr, ///< Relocatable immediate operand.
kInst ///< Sub-instruction operand.
};
- unsigned char Kind;
+ MachineOperandType Kind;
union {
unsigned RegVal;
@@ -172,8 +172,11 @@ public:
size_t size() { return Operands.size(); }
typedef SmallVectorImpl<MCOperand>::iterator iterator;
+ typedef SmallVectorImpl<MCOperand>::const_iterator const_iterator;
iterator begin() { return Operands.begin(); }
- iterator end() { return Operands.end(); }
+ const_iterator begin() const { return Operands.begin(); }
+ iterator end() { return Operands.end(); }
+ const_iterator end() const { return Operands.end(); }
iterator insert(iterator I, const MCOperand &Op) {
return Operands.insert(I, Op);
}
diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h
index 7f55b29f8ee0..95124c3021dd 100644
--- a/include/llvm/MC/MCInstPrinter.h
+++ b/include/llvm/MC/MCInstPrinter.h
@@ -1,4 +1,4 @@
-//===-- MCInstPrinter.h - Convert an MCInst to target assembly syntax -----===//
+//===- MCInstPrinter.h - MCInst to target assembly syntax -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h
index 5896de7f76df..360989305d3a 100644
--- a/include/llvm/MC/MCInstrDesc.h
+++ b/include/llvm/MC/MCInstrDesc.h
@@ -44,11 +44,12 @@ namespace MCOI {
/// Operand Type - Operands are tagged with one of the values of this enum.
enum OperandType {
- OPERAND_UNKNOWN,
- OPERAND_IMMEDIATE,
- OPERAND_REGISTER,
- OPERAND_MEMORY,
- OPERAND_PCREL
+ OPERAND_UNKNOWN = 0,
+ OPERAND_IMMEDIATE = 1,
+ OPERAND_REGISTER = 2,
+ OPERAND_MEMORY = 3,
+ OPERAND_PCREL = 4,
+ OPERAND_FIRST_TARGET = 5
};
}
@@ -125,7 +126,10 @@ namespace MCID {
Rematerializable,
CheapAsAMove,
ExtraSrcRegAllocReq,
- ExtraDefRegAllocReq
+ ExtraDefRegAllocReq,
+ RegSequence,
+ ExtractSubreg,
+ InsertSubreg
};
}
@@ -357,6 +361,47 @@ public:
return Flags & (1 << MCID::FoldableAsLoad);
}
+ /// \brief Return true if this instruction behaves
+ /// the same way as the generic REG_SEQUENCE instructions.
+ /// E.g., on ARM,
+ /// dX VMOVDRR rY, rZ
+ /// is equivalent to
+ /// dX = REG_SEQUENCE rY, ssub_0, rZ, ssub_1.
+ ///
+ /// Note that for the optimizers to be able to take advantage of
+ /// this property, TargetInstrInfo::getRegSequenceLikeInputs has to be
+ /// override accordingly.
+ bool isRegSequenceLike() const { return Flags & (1 << MCID::RegSequence); }
+
+ /// \brief Return true if this instruction behaves
+ /// the same way as the generic EXTRACT_SUBREG instructions.
+ /// E.g., on ARM,
+ /// rX, rY VMOVRRD dZ
+ /// is equivalent to two EXTRACT_SUBREG:
+ /// rX = EXTRACT_SUBREG dZ, ssub_0
+ /// rY = EXTRACT_SUBREG dZ, ssub_1
+ ///
+ /// Note that for the optimizers to be able to take advantage of
+ /// this property, TargetInstrInfo::getExtractSubregLikeInputs has to be
+ /// override accordingly.
+ bool isExtractSubregLike() const {
+ return Flags & (1 << MCID::ExtractSubreg);
+ }
+
+ /// \brief Return true if this instruction behaves
+ /// the same way as the generic INSERT_SUBREG instructions.
+ /// E.g., on ARM,
+ /// dX = VSETLNi32 dY, rZ, Imm
+ /// is equivalent to a INSERT_SUBREG:
+ /// dX = INSERT_SUBREG dY, rZ, translateImmToSubIdx(Imm)
+ ///
+ /// Note that for the optimizers to be able to take advantage of
+ /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be
+ /// override accordingly.
+ bool isInsertSubregLike() const {
+ return Flags & (1 << MCID::InsertSubreg);
+ }
+
//===--------------------------------------------------------------------===//
// Side Effect Analysis
//===--------------------------------------------------------------------===//
@@ -451,9 +496,12 @@ public:
}
/// isRematerializable - Returns true if this instruction is a candidate for
- /// remat. This flag is deprecated, please don't use it anymore. If this
- /// flag is set, the isReallyTriviallyReMaterializable() method is called to
- /// verify the instruction is really rematable.
+ /// remat. This flag is only used in TargetInstrInfo method
+ /// isTriviallyRematerializable.
+ ///
+ /// If this flag is set, the isReallyTriviallyReMaterializable()
+ /// or isReallyTriviallyReMaterializableGeneric methods are called to verify
+ /// the instruction is really rematable.
bool isRematerializable() const {
return Flags & (1 << MCID::Rematerializable);
}
@@ -464,6 +512,9 @@ public:
/// where we would like to remat or hoist the instruction, but not if it costs
/// more than moving the instruction into the appropriate register. Note, we
/// are not marking copies from and to the same register class with this flag.
+ ///
+ /// This method could be called by interface TargetInstrInfo::isAsCheapAsAMove
+ /// for different subtargets.
bool isAsCheapAsAMove() const {
return Flags & (1 << MCID::CheapAsAMove);
}
diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h
index 5104345e1abb..94d599f672af 100644
--- a/include/llvm/MC/MCInstrItineraries.h
+++ b/include/llvm/MC/MCInstrItineraries.h
@@ -22,7 +22,7 @@
namespace llvm {
//===----------------------------------------------------------------------===//
-/// Instruction stage - These values represent a non-pipelined step in
+/// These values represent a non-pipelined step in
/// the execution of an instruction. Cycles represents the number of
/// discrete time slots needed to complete the stage. Units represent
/// the choice of functional units that can be used to complete the
@@ -67,12 +67,12 @@ struct InstrStage {
int NextCycles_; ///< Number of machine cycles to next stage
ReservationKinds Kind_; ///< Kind of the FU reservation
- /// getCycles - returns the number of cycles the stage is occupied
+ /// Returns the number of cycles the stage is occupied.
unsigned getCycles() const {
return Cycles_;
}
- /// getUnits - returns the choice of FUs
+ /// Returns the choice of FUs.
unsigned getUnits() const {
return Units_;
}
@@ -81,7 +81,7 @@ struct InstrStage {
return Kind_;
}
- /// getNextCycles - returns the number of cycles from the start of
+ /// 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_;
@@ -90,10 +90,9 @@ struct InstrStage {
//===----------------------------------------------------------------------===//
-/// Instruction itinerary - An itinerary represents the scheduling
-/// information for an instruction. This includes a set of stages
-/// occupies by the instruction, and the pipeline cycle in which
-/// operands are read and written.
+/// An itinerary represents the scheduling information for an instruction.
+/// This includes a set of stages occupied by the instruction and the pipeline
+/// cycle in which operands are read and written.
///
struct InstrItinerary {
int NumMicroOps; ///< # of micro-ops, -1 means it's variable
@@ -105,12 +104,11 @@ struct InstrItinerary {
//===----------------------------------------------------------------------===//
-/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be
-/// used by a target.
+/// Itinerary data supplied by a subtarget to be used by a target.
///
class InstrItineraryData {
public:
- const MCSchedModel *SchedModel; ///< Basic machine properties.
+ MCSchedModel SchedModel; ///< Basic machine properties.
const InstrStage *Stages; ///< Array of stages selected
const unsigned *OperandCycles; ///< Array of operand cycles selected
const unsigned *Forwardings; ///< Array of pipeline forwarding pathes
@@ -118,45 +116,38 @@ public:
/// Ctors.
///
- InstrItineraryData() : SchedModel(&MCSchedModel::DefaultSchedModel),
+ InstrItineraryData() : SchedModel(MCSchedModel::GetDefaultSchedModel()),
Stages(nullptr), OperandCycles(nullptr),
Forwardings(nullptr), Itineraries(nullptr) {}
- InstrItineraryData(const MCSchedModel *SM, const InstrStage *S,
+ InstrItineraryData(const MCSchedModel &SM, const InstrStage *S,
const unsigned *OS, const unsigned *F)
: SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F),
- Itineraries(SchedModel->InstrItineraries) {}
+ Itineraries(SchedModel.InstrItineraries) {}
- /// isEmpty - Returns true if there are no itineraries.
- ///
+ /// Returns true if there are no itineraries.
bool isEmpty() const { return Itineraries == nullptr; }
- /// isEndMarker - 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));
}
- /// beginStage - 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;
}
- /// endStage - 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;
}
- /// getStageLatency - Return the total stage latency of the given
- /// class. The latency is the maximum completion time for any stage
- /// in the itinerary.
- ///
+ /// 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 {
// If the target doesn't provide itinerary information, use a simple
@@ -174,9 +165,8 @@ public:
return Latency;
}
- /// getOperandCycle - Return the cycle for the given class and
- /// operand. Return -1 if no cycle is specified for the operand.
- ///
+ /// Return the cycle for the given class and operand.
+ /// Return -1 if no cycle is specified for the operand.
int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const {
if (isEmpty())
return -1;
@@ -189,7 +179,7 @@ public:
return (int)OperandCycles[FirstIdx + OperandIdx];
}
- /// hasPipelineForwarding - Return true if there is a pipeline forwarding
+ /// 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
@@ -212,7 +202,7 @@ public:
Forwardings[FirstUseIdx + UseIdx];
}
- /// getOperandLatency - Compute and return the use operand latency of a given
+ /// 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,
@@ -236,9 +226,8 @@ public:
return UseCycle;
}
- /// getNumMicroOps - Return the number of micro-ops that the given class
- /// decodes to. Return -1 for classes that require dynamic lookup via
- /// TargetInstrInfo.
+ /// 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())
return 1;
diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h
index 50fd527ffe2a..890d6385aacd 100644
--- a/include/llvm/MC/MCLinkerOptimizationHint.h
+++ b/include/llvm/MC/MCLinkerOptimizationHint.h
@@ -18,8 +18,8 @@
#define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCMachObjectWriter.h"
#include "llvm/Support/raw_ostream.h"
@@ -45,7 +45,7 @@ static inline StringRef MCLOHDirectiveName() {
return StringRef(".loh");
}
-static inline bool isValidMCLOHType(MCLOHType Kind) {
+static inline bool isValidMCLOHType(unsigned Kind) {
return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot;
}
diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h
index 12a7f0ee7bb5..e4681c0a3dc3 100644
--- a/include/llvm/MC/MCMachObjectWriter.h
+++ b/include/llvm/MC/MCMachObjectWriter.h
@@ -14,6 +14,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MachO.h"
#include <vector>
@@ -67,12 +68,10 @@ public:
/// @name API
/// @{
- virtual void RecordRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
+ virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
+ const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) = 0;
/// @}
@@ -96,15 +95,21 @@ class MachObjectWriter : public MCObjectWriter {
/// @name Relocation Data
/// @{
- llvm::DenseMap<const MCSectionData*,
- std::vector<MachO::any_relocation_info> > Relocations;
+ struct RelAndSymbol {
+ const MCSymbolData *Sym;
+ MachO::any_relocation_info MRE;
+ RelAndSymbol(const MCSymbolData *Sym, const MachO::any_relocation_info &MRE)
+ : Sym(Sym), MRE(MRE) {}
+ };
+
+ llvm::DenseMap<const MCSectionData *, std::vector<RelAndSymbol>> Relocations;
llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase;
/// @}
/// @name Symbol Table Data
/// @{
- SmallString<256> StringTable;
+ StringTableBuilder StringTable;
std::vector<MachSymbolData> LocalSymbolData;
std::vector<MachSymbolData> ExternalSymbolData;
std::vector<MachSymbolData> UndefinedSymbolData;
@@ -212,9 +217,15 @@ public:
// - Input errors, where something cannot be correctly encoded. 'as' allows
// these through in many cases.
- void addRelocation(const MCSectionData *SD,
+ // Add a relocation to be output in the object file. At the time this is
+ // called, the symbol indexes are not know, so if the relocation refers
+ // to a symbol it should be passed as \p RelSymbol so that it can be updated
+ // afterwards. If the relocation doesn't refer to a symbol, nullptr should be
+ // used.
+ void addRelocation(const MCSymbolData *RelSymbol, const MCSectionData *SD,
MachO::any_relocation_info &MRE) {
- Relocations[SD].push_back(MRE);
+ RelAndSymbol P(RelSymbol, MRE);
+ Relocations[SD].push_back(P);
}
void RecordScatteredRelocation(const MCAssembler &Asm,
@@ -230,7 +241,7 @@ public:
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue);
- void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override;
@@ -239,8 +250,7 @@ public:
/// ComputeSymbolTable - Compute the symbol table data
///
- /// \param StringTable [out] - The string table data.
- void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
+ void ComputeSymbolTable(MCAssembler &Asm,
std::vector<MachSymbolData> &LocalSymbolData,
std::vector<MachSymbolData> &ExternalSymbolData,
std::vector<MachSymbolData> &UndefinedSymbolData);
diff --git a/include/llvm/MC/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h
deleted file mode 100644
index 5b935db59585..000000000000
--- a/include/llvm/MC/MCObjectDisassembler.h
+++ /dev/null
@@ -1,174 +0,0 @@
-//===-- llvm/MC/MCObjectDisassembler.h --------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the MCObjectDisassembler class, which
-// can be used to construct an MCModule and an MC CFG from an ObjectFile.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MC_MCOBJECTDISASSEMBLER_H
-#define LLVM_MC_MCOBJECTDISASSEMBLER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/MemoryObject.h"
-#include <vector>
-
-namespace llvm {
-
-namespace object {
- class ObjectFile;
- class MachOObjectFile;
-}
-
-class MCBasicBlock;
-class MCDisassembler;
-class MCFunction;
-class MCInstrAnalysis;
-class MCModule;
-class MCObjectSymbolizer;
-
-/// \brief Disassemble an ObjectFile to an MCModule and MCFunctions.
-/// This class builds on MCDisassembler to disassemble whole sections, creating
-/// MCAtom (MCTextAtom for disassembled sections and MCDataAtom for raw data).
-/// It can also be used to create a control flow graph consisting of MCFunctions
-/// and MCBasicBlocks.
-class MCObjectDisassembler {
-public:
- MCObjectDisassembler(const object::ObjectFile &Obj,
- const MCDisassembler &Dis,
- const MCInstrAnalysis &MIA);
- virtual ~MCObjectDisassembler() {}
-
- /// \brief Build an MCModule, creating atoms and optionally functions.
- /// \param withCFG Also build a CFG by adding MCFunctions to the Module.
- /// If withCFG is false, the MCModule built only contains atoms, representing
- /// what was found in the object file. If withCFG is true, MCFunctions are
- /// created, containing MCBasicBlocks. All text atoms are split to form basic
- /// block atoms, which then each back an MCBasicBlock.
- MCModule *buildModule(bool withCFG = false);
-
- MCModule *buildEmptyModule();
-
- typedef std::vector<uint64_t> AddressSetTy;
- /// \name Create a new MCFunction.
- MCFunction *createFunction(MCModule *Module, uint64_t BeginAddr,
- AddressSetTy &CallTargets,
- AddressSetTy &TailCallTargets);
-
- /// \brief Set the region on which to fallback if disassembly was requested
- /// somewhere not accessible in the object file.
- /// This is used for dynamic disassembly (see RawMemoryObject).
- void setFallbackRegion(std::unique_ptr<MemoryObject> &Region) {
- FallbackRegion.reset(Region.release());
- }
-
- /// \brief Set the symbolizer to use to get information on external functions.
- /// Note that this isn't used to do instruction-level symbolization (that is,
- /// plugged into MCDisassembler), but to symbolize function call targets.
- void setSymbolizer(MCObjectSymbolizer *ObjectSymbolizer) {
- MOS = ObjectSymbolizer;
- }
-
- /// \brief Get the effective address of the entrypoint, or 0 if there is none.
- virtual uint64_t getEntrypoint();
-
- /// \name Get the addresses of static constructors/destructors in the object.
- /// The caller is expected to know how to interpret the addresses;
- /// for example, Mach-O init functions expect 5 arguments, not for ELF.
- /// The addresses are original object file load addresses, not effective.
- /// @{
- virtual ArrayRef<uint64_t> getStaticInitFunctions();
- virtual ArrayRef<uint64_t> getStaticExitFunctions();
- /// @}
-
- /// \name Translation between effective and objectfile load address.
- /// @{
- /// \brief Compute the effective load address, from an objectfile virtual
- /// address. This is implemented in a format-specific way, to take into
- /// account things like PIE/ASLR when doing dynamic disassembly.
- /// For example, on Mach-O this would be done by adding the VM addr slide,
- /// on glibc ELF by keeping a map between segment load addresses, filled
- /// using dl_iterate_phdr, etc..
- /// In most static situations and in the default impl., this returns \p Addr.
- virtual uint64_t getEffectiveLoadAddr(uint64_t Addr);
-
- /// \brief Compute the original load address, as specified in the objectfile.
- /// This is the inverse of getEffectiveLoadAddr.
- virtual uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr);
- /// @}
-
-protected:
- const object::ObjectFile &Obj;
- const MCDisassembler &Dis;
- const MCInstrAnalysis &MIA;
- MCObjectSymbolizer *MOS;
-
- /// \brief The fallback memory region, outside the object file.
- std::unique_ptr<MemoryObject> FallbackRegion;
-
- /// \brief Return a memory region suitable for reading starting at \p Addr.
- /// In most cases, this returns a StringRefMemoryObject backed by the
- /// containing section. When no section was found, this returns the
- /// FallbackRegion, if it is suitable.
- /// If it is not, or if there is no fallback region, this returns 0.
- MemoryObject *getRegionFor(uint64_t Addr);
-
-private:
- /// \brief Fill \p Module by creating an atom for each section.
- /// This could be made much smarter, using information like symbols, but also
- /// format-specific features, like mach-o function_start or data_in_code LCs.
- void buildSectionAtoms(MCModule *Module);
-
- /// \brief Enrich \p Module with a CFG consisting of MCFunctions.
- /// \param Module An MCModule returned by buildModule, with no CFG.
- /// NOTE: Each MCBasicBlock in a MCFunction is backed by a single MCTextAtom.
- /// When the CFG is built, contiguous instructions that were previously in a
- /// single MCTextAtom will be split in multiple basic block atoms.
- void buildCFG(MCModule *Module);
-
- MCBasicBlock *getBBAt(MCModule *Module, MCFunction *MCFN, uint64_t BeginAddr,
- AddressSetTy &CallTargets,
- AddressSetTy &TailCallTargets);
-};
-
-class MCMachOObjectDisassembler : public MCObjectDisassembler {
- const object::MachOObjectFile &MOOF;
-
- uint64_t VMAddrSlide;
- uint64_t HeaderLoadAddress;
-
- // __DATA;__mod_init_func support.
- llvm::StringRef ModInitContents;
- // __DATA;__mod_exit_func support.
- llvm::StringRef ModExitContents;
-
-public:
- /// \brief Construct a Mach-O specific object disassembler.
- /// \param VMAddrSlide The virtual address slide applied by dyld.
- /// \param HeaderLoadAddress The load address of the mach_header for this
- /// object.
- MCMachOObjectDisassembler(const object::MachOObjectFile &MOOF,
- const MCDisassembler &Dis,
- const MCInstrAnalysis &MIA, uint64_t VMAddrSlide,
- uint64_t HeaderLoadAddress);
-
-protected:
- uint64_t getEffectiveLoadAddr(uint64_t Addr) override;
- uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) override;
- uint64_t getEntrypoint() override;
-
- ArrayRef<uint64_t> getStaticInitFunctions() override;
- ArrayRef<uint64_t> getStaticExitFunctions() override;
-};
-
-}
-
-#endif
diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h
index 4d1715eccf5a..321043c522ee 100644
--- a/include/llvm/MC/MCObjectFileInfo.h
+++ b/include/llvm/MC/MCObjectFileInfo.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_MCBJECTFILEINFO_H
-#define LLVM_MC_MCBJECTFILEINFO_H
+#ifndef LLVM_MC_MCOBJECTFILEINFO_H
+#define LLVM_MC_MCOBJECTFILEINFO_H
#include "llvm/ADT/Triple.h"
#include "llvm/Support/CodeGen.h"
@@ -116,6 +116,7 @@ protected:
/// These are used for the Fission separate debug information files.
const MCSection *DwarfInfoDWOSection;
+ const MCSection *DwarfTypesDWOSection;
const MCSection *DwarfAbbrevDWOSection;
const MCSection *DwarfStrDWOSection;
const MCSection *DwarfLineDWOSection;
@@ -261,7 +262,9 @@ public:
return DwarfInfoDWOSection;
}
const MCSection *getDwarfTypesSection(uint64_t Hash) const;
- const MCSection *getDwarfTypesDWOSection(uint64_t Hash) const;
+ const MCSection *getDwarfTypesDWOSection() const {
+ return DwarfTypesDWOSection;
+ }
const MCSection *getDwarfAbbrevDWOSection() const {
return DwarfAbbrevDWOSection;
}
diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h
index 8d37c85b0585..0866ff5a9fc0 100644
--- a/include/llvm/MC/MCObjectStreamer.h
+++ b/include/llvm/MC/MCObjectStreamer.h
@@ -10,6 +10,7 @@
#ifndef LLVM_MC_MCOBJECTSTREAMER_H
#define LLVM_MC_MCOBJECTSTREAMER_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCStreamer.h"
@@ -37,11 +38,16 @@ class MCObjectStreamer : public MCStreamer {
MCSectionData::iterator CurInsertionPoint;
bool EmitEHFrame;
bool EmitDebugFrame;
+ SmallVector<MCSymbolData *, 2> PendingLabels;
virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0;
void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
+ // If any labels have been emitted but not assigned fragments, ensure that
+ // they get assigned, either to F if possible or to a new data fragment.
+ void flushPendingLabels(MCFragment *F);
+
protected:
MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS,
MCCodeEmitter *_Emitter);
@@ -69,14 +75,15 @@ protected:
MCFragment *getCurrentFragment() const;
- void insert(MCFragment *F) const {
+ void insert(MCFragment *F) {
+ flushPendingLabels(F);
CurSectionData->getFragmentList().insert(CurInsertionPoint, F);
F->setParent(CurSectionData);
}
/// Get a data fragment to write into, creating a new one if the current
/// fragment is not a data fragment.
- MCDataFragment *getOrCreateDataFragment() const;
+ MCDataFragment *getOrCreateDataFragment();
public:
void visitUsedSymbol(const MCSymbol &Sym) override;
@@ -126,7 +133,7 @@ public:
void EmitZeros(uint64_t NumBytes) override;
void FinishImpl() override;
- virtual bool mayHaveInstructions() const {
+ bool mayHaveInstructions() const override {
return getCurrentSectionData()->hasInstructions();
}
};
diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h
deleted file mode 100644
index f75b7f58a141..000000000000
--- a/include/llvm/MC/MCObjectSymbolizer.h
+++ /dev/null
@@ -1,83 +0,0 @@
-//===-- llvm/MC/MCObjectSymbolizer.h --------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares the MCObjectSymbolizer class, an MCSymbolizer that is
-// backed by an object::ObjectFile.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MC_MCOBJECTSYMBOLIZER_H
-#define LLVM_MC_MCOBJECTSYMBOLIZER_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/MC/MCSymbolizer.h"
-#include "llvm/Object/ObjectFile.h"
-#include <vector>
-
-namespace llvm {
-
-class MCExpr;
-class MCInst;
-class MCRelocationInfo;
-class raw_ostream;
-
-/// \brief An ObjectFile-backed symbolizer.
-class MCObjectSymbolizer : public MCSymbolizer {
-protected:
- const object::ObjectFile *Obj;
-
- // Map a load address to the first relocation that applies there. As far as I
- // know, if there are several relocations at the exact same address, they are
- // related and the others can be determined from the first that was found in
- // the relocation table. For instance, on x86-64 mach-o, a SUBTRACTOR
- // relocation (referencing the minuend symbol) is followed by an UNSIGNED
- // relocation (referencing the subtrahend symbol).
- const object::RelocationRef *findRelocationAt(uint64_t Addr);
- const object::SectionRef *findSectionContaining(uint64_t Addr);
-
- MCObjectSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo,
- const object::ObjectFile *Obj);
-
-public:
- /// \name Overridden MCSymbolizer methods:
- /// @{
- bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream,
- int64_t Value, uint64_t Address,
- bool IsBranch, uint64_t Offset,
- uint64_t InstSize) override;
-
- void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
- int64_t Value,
- uint64_t Address) override;
- /// @}
-
- /// \brief Look for an external function symbol at \p Addr.
- /// (References through the ELF PLT, Mach-O stubs, and similar).
- /// \returns An MCExpr representing the external symbol, or 0 if not found.
- virtual StringRef findExternalFunctionAt(uint64_t Addr);
-
- /// \brief Create an object symbolizer for \p Obj.
- static MCObjectSymbolizer *
- createObjectSymbolizer(MCContext &Ctx,
- std::unique_ptr<MCRelocationInfo> RelInfo,
- const object::ObjectFile *Obj);
-
-private:
- typedef DenseMap<uint64_t, object::RelocationRef> AddrToRelocMap;
- typedef std::vector<object::SectionRef> SortedSectionList;
- SortedSectionList SortedSections;
- AddrToRelocMap AddrToReloc;
-
- void buildSectionList();
- void buildRelocationByAddrMap();
-};
-
-}
-
-#endif
diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h
index 55c828c6c179..173ef416f2cc 100644
--- a/include/llvm/MC/MCObjectWriter.h
+++ b/include/llvm/MC/MCObjectWriter.h
@@ -76,12 +76,10 @@ public:
/// post layout binding. The implementation is responsible for storing
/// information about the relocation so that it can be emitted during
/// WriteObject().
- virtual void RecordRelocation(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
+ virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
- bool &IsPCRel,
- uint64_t &FixedValue) = 0;
+ bool &IsPCRel, uint64_t &FixedValue) = 0;
/// \brief Check whether the difference (A - B) between two symbol
/// references is fully resolved.
diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h
index 0b550ba627e9..a9a30f172071 100644
--- a/include/llvm/MC/MCParser/AsmLexer.h
+++ b/include/llvm/MC/MCParser/AsmLexer.h
@@ -49,7 +49,7 @@ public:
const AsmToken peekTok(bool ShouldSkipSpace = true) override;
- bool isAtStartOfComment(char Char);
+ bool isAtStartOfComment(const char *Ptr);
bool isAtStatementSeparator(const char *Ptr);
const MCAsmInfo &getMAI() const { return MAI; }
diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h
index e3d4181e086f..b05891c13250 100644
--- a/include/llvm/MC/MCParser/MCAsmLexer.h
+++ b/include/llvm/MC/MCParser/MCAsmLexer.h
@@ -18,7 +18,7 @@
namespace llvm {
-/// AsmToken - Target independent representation for an assembler token.
+/// Target independent representation for an assembler token.
class AsmToken {
public:
enum TokenKind {
@@ -74,25 +74,26 @@ public:
SMLoc getLoc() const;
SMLoc getEndLoc() const;
+ SMRange getLocRange() const;
- /// getStringContents - Get the contents of a string token (without quotes).
+ /// Get the contents of a string token (without quotes).
StringRef getStringContents() const {
assert(Kind == String && "This token isn't a string!");
return Str.slice(1, Str.size() - 1);
}
- /// getIdentifier - Get the identifier string for the current token, which
- /// should be an identifier or a string. This gets the portion of the string
- /// which should be used as the identifier, e.g., it does not include the
- /// quotes on strings.
+ /// Get the identifier string for the current token, which should be an
+ /// identifier or a string. This gets the portion of the string which should
+ /// be used as the identifier, e.g., it does not include the quotes on
+ /// strings.
StringRef getIdentifier() const {
if (Kind == Identifier)
return getString();
return getStringContents();
}
- /// getString - Get the string for the current token, this includes all
- /// characters (for example, the quotes on strings) in the token.
+ /// 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().
@@ -113,8 +114,8 @@ public:
}
};
-/// MCAsmLexer - Generic assembler lexer interface, for use by target specific
-/// assembly lexers.
+/// Generic assembler lexer interface, for use by target specific assembly
+/// lexers.
class MCAsmLexer {
/// The current token, stored in the base class for faster access.
AsmToken CurTok;
@@ -142,7 +143,7 @@ protected: // Can only create subclasses.
public:
virtual ~MCAsmLexer();
- /// Lex - Consume the next token from the input stream and return it.
+ /// Consume the next token from the input stream and return it.
///
/// The lexer will continuosly return the end-of-file token once the end of
/// the main input file has been reached.
@@ -152,37 +153,37 @@ public:
virtual StringRef LexUntilEndOfStatement() = 0;
- /// getLoc - Get the current source location.
+ /// Get the current source location.
SMLoc getLoc() const;
- /// getTok - Get the current (last) lexed token.
- const AsmToken &getTok() {
+ /// Get the current (last) lexed token.
+ const AsmToken &getTok() const {
return CurTok;
}
- /// peekTok - Look ahead at the next token to be lexed.
+ /// Look ahead at the next token to be lexed.
virtual const AsmToken peekTok(bool ShouldSkipSpace = true) = 0;
- /// getErrLoc - Get the current error location
+ /// Get the current error location
const SMLoc &getErrLoc() {
return ErrLoc;
}
- /// getErr - Get the current error string
+ /// Get the current error string
const std::string &getErr() {
return Err;
}
- /// getKind - Get the kind of current token.
+ /// Get the kind of current token.
AsmToken::TokenKind getKind() const { return CurTok.getKind(); }
- /// is - Check if the current token has kind \p K.
+ /// Check if the current token has kind \p K.
bool is(AsmToken::TokenKind K) const { return CurTok.is(K); }
- /// isNot - Check if the current token has kind \p K.
+ /// Check if the current token has kind \p K.
bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); }
- /// setSkipSpace - Set whether spaces should be ignored by the lexer
+ /// Set whether spaces should be ignored by the lexer
void setSkipSpace(bool val) { SkipSpace = val; }
bool getAllowAtInIdentifier() { return AllowAtInIdentifier; }
diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h
index 9836795450ff..34188e66e62d 100644
--- a/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/include/llvm/MC/MCParser/MCAsmParser.h
@@ -45,20 +45,22 @@ public:
}
};
-/// MCAsmParserSemaCallback - Generic Sema callback for assembly parser.
+/// Generic Sema callback for assembly parser.
class MCAsmParserSemaCallback {
public:
virtual ~MCAsmParserSemaCallback();
virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf,
InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedContext) = 0;
+ virtual StringRef LookupInlineAsmLabel(StringRef Identifier, SourceMgr &SM,
+ SMLoc Location, bool Create) = 0;
virtual bool LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset) = 0;
};
-/// MCAsmParser - Generic assembler parser interface, for use by target specific
-/// assembly parsers.
+/// Generic assembler parser interface, for use by target specific assembly
+/// parsers.
class MCAsmParser {
public:
typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc);
@@ -85,10 +87,13 @@ public:
virtual SourceMgr &getSourceManager() = 0;
virtual MCAsmLexer &getLexer() = 0;
+ const MCAsmLexer &getLexer() const {
+ return const_cast<MCAsmParser*>(this)->getLexer();
+ }
virtual MCContext &getContext() = 0;
- /// getStreamer - Return the output streamer for the assembler.
+ /// Return the output streamer for the assembler.
virtual MCStreamer &getStreamer() = 0;
MCTargetAsmParser &getTargetParser() const { return *TargetParser; }
@@ -100,51 +105,49 @@ public:
bool getShowParsedOperands() const { return ShowParsedOperands; }
void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; }
- /// Run - 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;
- /// parseMSInlineAsm - Parse ms-style inline assembly.
- virtual bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
- unsigned &NumOutputs, unsigned &NumInputs,
- SmallVectorImpl<std::pair<void *, bool> > &OpDecls,
- SmallVectorImpl<std::string> &Constraints,
- SmallVectorImpl<std::string> &Clobbers,
- const MCInstrInfo *MII,
- const MCInstPrinter *IP,
- MCAsmParserSemaCallback &SI) = 0;
-
- /// Note - Emit a note at the location \p L, with the message \p Msg.
+ /// Parse ms-style inline assembly.
+ virtual bool parseMSInlineAsm(
+ void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
+ unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
+ SmallVectorImpl<std::string> &Constraints,
+ SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
+ const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0;
+
+ /// Emit a note at the location \p L, with the message \p Msg.
virtual void Note(SMLoc L, const Twine &Msg,
ArrayRef<SMRange> Ranges = None) = 0;
- /// Warning - 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,
ArrayRef<SMRange> Ranges = None) = 0;
- /// Error - 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.
virtual bool Error(SMLoc L, const Twine &Msg,
ArrayRef<SMRange> Ranges = None) = 0;
- /// Lex - Get the next AsmToken in the stream, possibly handling file
- /// inclusion first.
+ /// Get the next AsmToken in the stream, possibly handling file inclusion
+ /// first.
virtual const AsmToken &Lex() = 0;
- /// getTok - Get the current AsmToken from the stream.
- const AsmToken &getTok();
+ /// Get the current AsmToken from the stream.
+ const AsmToken &getTok() const;
/// \brief Report an error at the current lexer location.
bool TokError(const Twine &Msg, ArrayRef<SMRange> Ranges = None);
- /// parseIdentifier - Parse an identifier or string (as a quoted identifier)
- /// and set \p Res to the identifier contents.
+ /// 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
@@ -152,15 +155,14 @@ public:
/// will be either the EndOfStatement or EOF.
virtual StringRef parseStringToEndOfStatement() = 0;
- /// parseEscapedString - Parse the current token as a string which may include
- /// escaped characters and return the string contents.
+ /// Parse the current token as a string which may include escaped characters
+ /// and return the string contents.
virtual bool parseEscapedString(std::string &Data) = 0;
- /// eatToEndOfStatement - 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;
- /// parseExpression - Parse an arbitrary expression.
+ /// Parse an arbitrary expression.
///
/// @param Res - The value of the expression. The result is undefined
/// on error.
@@ -168,31 +170,30 @@ public:
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0;
bool parseExpression(const MCExpr *&Res);
- /// parsePrimaryExpr - Parse a primary expression.
+ /// Parse a primary expression.
///
/// @param Res - The value of the expression. The result is undefined
/// on error.
/// @result - False on success.
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0;
- /// parseParenExpression - Parse an arbitrary expression, assuming that an
- /// initial '(' has already been consumed.
+ /// Parse an arbitrary expression, assuming that an initial '(' has already
+ /// been consumed.
///
/// @param Res - The value of the expression. The result is undefined
/// on error.
/// @result - False on success.
virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0;
- /// parseAbsoluteExpression - Parse an expression which must evaluate to an
- /// absolute value.
+ /// Parse an expression which must evaluate to an absolute value.
///
/// @param Res - The value of the absolute expression. The result is undefined
/// on error.
/// @result - False on success.
virtual bool parseAbsoluteExpression(int64_t &Res) = 0;
- /// checkForValidSection - Ensure that we have a valid section set in the
- /// streamer. Otherwise, report an error and switch to .text.
+ /// Ensure that we have a valid section set in the streamer. Otherwise, report
+ /// an error and switch to .text.
virtual void checkForValidSection() = 0;
};
diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h
index 2eda3a9a2143..bfc0afa132b7 100644
--- a/include/llvm/MC/MCParser/MCAsmParserExtension.h
+++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h
@@ -52,8 +52,17 @@ public:
/// @{
MCContext &getContext() { return getParser().getContext(); }
+
MCAsmLexer &getLexer() { return getParser().getLexer(); }
+ const MCAsmLexer &getLexer() const {
+ return const_cast<MCAsmParserExtension *>(this)->getLexer();
+ }
+
MCAsmParser &getParser() { return *Parser; }
+ const MCAsmParser &getParser() const {
+ return const_cast<MCAsmParserExtension*>(this)->getParser();
+ }
+
SourceMgr &getSourceManager() { return getParser().getSourceManager(); }
MCStreamer &getStreamer() { return getParser().getStreamer(); }
bool Warning(SMLoc L, const Twine &Msg) {
diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h
index 766f63182925..8e25ee18e08d 100644
--- a/include/llvm/MC/MCRegisterInfo.h
+++ b/include/llvm/MC/MCRegisterInfo.h
@@ -32,9 +32,9 @@ public:
typedef const MCPhysReg* iterator;
typedef const MCPhysReg* const_iterator;
- const char *Name;
const iterator RegsBegin;
const uint8_t *const RegSet;
+ const uint32_t NameIdx;
const uint16_t RegsSize;
const uint16_t RegSetSize;
const uint16_t ID;
@@ -46,10 +46,6 @@ public:
///
unsigned getID() const { return ID; }
- /// getName() - Return the register class name for debugging.
- ///
- const char *getName() const { return Name; }
-
/// begin/end - Return all of the registers in this class.
///
iterator begin() const { return RegsBegin; }
@@ -118,6 +114,10 @@ struct MCRegisterDesc {
// RegUnits - Points to the list of register units. The low 4 bits holds the
// Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator.
uint32_t RegUnits;
+
+ /// Index into list with lane mask sequences. The sequence contains a lanemask
+ /// for every register unit.
+ uint16_t RegUnitLaneMasks;
};
/// MCRegisterInfo base class - We assume that the target defines a static
@@ -161,7 +161,10 @@ private:
unsigned NumRegUnits; // Number of regunits.
const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table.
const MCPhysReg *DiffLists; // Pointer to the difflists array
+ const unsigned *RegUnitMaskSequences; // Pointer to lane mask sequences
+ // for register units.
const char *RegStrings; // Pointer to the string table.
+ const char *RegClassStrings; // Pointer to the class strings.
const uint16_t *SubRegIndices; // Pointer to the subreg lookup
// array.
const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered
@@ -230,8 +233,10 @@ public:
// These iterators are allowed to sub-class DiffListIterator and access
// internal list pointers.
friend class MCSubRegIterator;
+ friend class MCSubRegIndexIterator;
friend class MCSuperRegIterator;
friend class MCRegUnitIterator;
+ friend class MCRegUnitMaskIterator;
friend class MCRegUnitRootIterator;
/// \brief Initialize MCRegisterInfo, called by TableGen
@@ -242,7 +247,9 @@ public:
const MCPhysReg (*RURoots)[2],
unsigned NRU,
const MCPhysReg *DL,
+ const unsigned *RUMS,
const char *Strings,
+ const char *ClassStrings,
const uint16_t *SubIndices,
unsigned NumIndices,
const SubRegCoveredBits *SubIdxRanges,
@@ -253,7 +260,9 @@ public:
PCReg = PC;
Classes = C;
DiffLists = DL;
+ RegUnitMaskSequences = RUMS;
RegStrings = Strings;
+ RegClassStrings = ClassStrings;
NumClasses = NC;
RegUnitRoots = RURoots;
NumRegUnits = NRU;
@@ -401,6 +410,10 @@ public:
return Classes[i];
}
+ const char *getRegClassName(const MCRegisterClass *Class) const {
+ return RegClassStrings + Class->NameIdx;
+ }
+
/// \brief Returns the encoding for RegNo
uint16_t getEncodingValue(unsigned RegNo) const {
assert(RegNo < NumRegs &&
@@ -449,6 +462,38 @@ public:
}
};
+/// Iterator that enumerates the sub-registers of a Reg and the associated
+/// sub-register indices.
+class MCSubRegIndexIterator {
+ MCSubRegIterator SRIter;
+ const uint16_t *SRIndex;
+public:
+ /// Constructs an iterator that traverses subregisters and their
+ /// associated subregister indices.
+ MCSubRegIndexIterator(unsigned Reg, const MCRegisterInfo *MCRI)
+ : SRIter(Reg, MCRI) {
+ SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices;
+ }
+
+ /// Returns current sub-register.
+ unsigned getSubReg() const {
+ return *SRIter;
+ }
+ /// Returns sub-register index of the current sub-register.
+ unsigned getSubRegIndex() const {
+ return *SRIndex;
+ }
+
+ /// Returns true if this iterator is not yet at the end.
+ bool isValid() const { return SRIter.isValid(); }
+
+ /// Moves to the next position.
+ void operator++() {
+ ++SRIter;
+ ++SRIndex;
+ }
+};
+
/// MCSuperRegIterator enumerates all super-registers of Reg.
/// If IncludeSelf is set, Reg itself is included in the list.
class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator {
@@ -510,6 +555,36 @@ public:
}
};
+/// MCRegUnitIterator enumerates a list of register units and their associated
+/// lane masks for Reg. The register units are in ascending numerical order.
+class MCRegUnitMaskIterator {
+ MCRegUnitIterator RUIter;
+ const unsigned *MaskListIter;
+public:
+ MCRegUnitMaskIterator() {}
+ /// Constructs an iterator that traverses the register units and their
+ /// associated LaneMasks in Reg.
+ MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI)
+ : RUIter(Reg, MCRI) {
+ uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks;
+ MaskListIter = &MCRI->RegUnitMaskSequences[Idx];
+ }
+
+ /// Returns a (RegUnit, LaneMask) pair.
+ std::pair<unsigned,unsigned> operator*() const {
+ return std::make_pair(*RUIter, *MaskListIter);
+ }
+
+ /// Returns true if this iterator is not yet at the end.
+ bool isValid() const { return RUIter.isValid(); }
+
+ /// Moves to the next position.
+ void operator++() {
+ ++MaskListIter;
+ ++RUIter;
+ }
+};
+
// Each register unit has one or two root registers. The complete set of
// registers containing a register unit is the union of the roots and their
// super-registers. All registers aliasing Unit can be visited like this:
diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h
index 43b8672265c6..1adfedd2638a 100644
--- a/include/llvm/MC/MCSchedule.h
+++ b/include/llvm/MC/MCSchedule.h
@@ -133,10 +133,7 @@ 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.
-class MCSchedModel {
-public:
- static MCSchedModel DefaultSchedModel; // For unknown processors.
-
+struct MCSchedModel {
// IssueWidth is the maximum number of instructions that may be scheduled in
// the same per-cycle group.
unsigned IssueWidth;
@@ -191,7 +188,6 @@ public:
bool CompleteModel;
-private:
unsigned ProcID;
const MCProcResourceDesc *ProcResourceTable;
const MCSchedClassDesc *SchedClassTable;
@@ -201,37 +197,6 @@ private:
friend class InstrItineraryData;
const InstrItinerary *InstrItineraries;
-public:
- // Default's must be specified as static const literals so that tablegenerated
- // target code can use it in static initializers. The defaults need to be
- // initialized in this default ctor because some clients directly instantiate
- // MCSchedModel instead of using a generated itinerary.
- MCSchedModel(): IssueWidth(DefaultIssueWidth),
- MicroOpBufferSize(DefaultMicroOpBufferSize),
- LoopMicroOpBufferSize(DefaultLoopMicroOpBufferSize),
- LoadLatency(DefaultLoadLatency),
- HighLatency(DefaultHighLatency),
- MispredictPenalty(DefaultMispredictPenalty),
- PostRAScheduler(false), CompleteModel(true),
- ProcID(0), ProcResourceTable(nullptr),
- SchedClassTable(nullptr), NumProcResourceKinds(0),
- NumSchedClasses(0), InstrItineraries(nullptr) {
- (void)NumProcResourceKinds;
- (void)NumSchedClasses;
- }
-
- // Table-gen driven ctor.
- MCSchedModel(unsigned iw, int mbs, int lmbs, unsigned ll, unsigned hl,
- unsigned mp, bool postRASched, bool cm, unsigned pi,
- const MCProcResourceDesc *pr, const MCSchedClassDesc *sc,
- unsigned npr, unsigned nsc, const InstrItinerary *ii):
- IssueWidth(iw), MicroOpBufferSize(mbs), LoopMicroOpBufferSize(lmbs),
- LoadLatency(ll), HighLatency(hl),
- MispredictPenalty(mp), PostRAScheduler(postRASched),
- CompleteModel(cm), ProcID(pi),
- ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr),
- NumSchedClasses(nsc), InstrItineraries(ii) {}
-
unsigned getProcessorID() const { return ProcID; }
/// Does this machine model include instruction-level scheduling.
@@ -258,6 +223,26 @@ public:
assert(SchedClassIdx < NumSchedClasses && "bad scheduling class idx");
return &SchedClassTable[SchedClassIdx];
}
+
+ // /\brief Returns a default initialized model. Used for unknown processors.
+ static MCSchedModel GetDefaultSchedModel() {
+ MCSchedModel Ret = { DefaultIssueWidth,
+ DefaultMicroOpBufferSize,
+ DefaultLoopMicroOpBufferSize,
+ DefaultLoadLatency,
+ DefaultHighLatency,
+ DefaultMispredictPenalty,
+ false,
+ true,
+ 0,
+ nullptr,
+ nullptr,
+ 0,
+ 0,
+ nullptr
+ };
+ return Ret;
+ }
};
} // End llvm namespace
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 63a43d08c3f2..18855f9cf03d 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -20,7 +20,7 @@
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCLinkerOptimizationHint.h"
-#include "llvm/MC/MCWin64EH.h"
+#include "llvm/MC/MCWinEH.h"
#include "llvm/Support/DataTypes.h"
#include <string>
@@ -49,14 +49,14 @@ typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair;
///
/// If target foo wants to use this, it should implement 3 classes:
/// * FooTargetStreamer : public MCTargetStreamer
-/// * FooTargetAsmSreamer : public FooTargetStreamer
+/// * FooTargetAsmStreamer : public FooTargetStreamer
/// * FooTargetELFStreamer : public FooTargetStreamer
///
/// FooTargetStreamer should have a pure virtual method for each directive. For
/// example, for a ".bar symbol_name" directive, it should have
/// virtual emitBar(const MCSymbol &Symbol) = 0;
///
-/// The FooTargetAsmSreamer and FooTargetELFStreamer classes implement the
+/// The FooTargetAsmStreamer and FooTargetELFStreamer classes implement the
/// method. The assembly streamer just prints ".bar symbol_name". The object
/// streamer does whatever is needed to implement .bar in the object file.
///
@@ -66,8 +66,9 @@ typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair;
/// MCTargetStreamer &TS = OutStreamer.getTargetStreamer();
/// FooTargetStreamer &ATS = static_cast<FooTargetStreamer &>(TS);
///
-/// The base classes FooTargetAsmSreamer and FooTargetELFStreamer should *never*
-/// be treated differently. Callers should always talk to a FooTargetStreamer.
+/// The base classes FooTargetAsmStreamer and FooTargetELFStreamer should
+/// *never* be treated differently. Callers should always talk to a
+/// FooTargetStreamer.
class MCTargetStreamer {
protected:
MCStreamer &Streamer;
@@ -91,7 +92,6 @@ public:
AArch64TargetStreamer(MCStreamer &S);
~AArch64TargetStreamer();
-
void finish() override;
/// Callback used to implement the ldr= pseudo.
@@ -103,6 +103,9 @@ public:
/// Emit contents of constant pool for the current section.
void emitCurrentConstantPool();
+ /// Callback used to implement the .inst directive.
+ virtual void emitInst(uint32_t Inst);
+
private:
std::unique_ptr<AssemblerConstantPools> ConstantPools;
};
@@ -181,8 +184,8 @@ class MCStreamer {
MCSymbol *EmitCFICommon();
- std::vector<MCWinFrameInfo *> WinFrameInfos;
- MCWinFrameInfo *CurrentWinFrameInfo;
+ std::vector<WinEH::FrameInfo *> WinFrameInfos;
+ WinEH::FrameInfo *CurrentWinFrameInfo;
void EnsureValidWinFrameInfo();
// SymbolOrdering - Tracks an index to represent the order
@@ -196,19 +199,14 @@ class MCStreamer {
protected:
MCStreamer(MCContext &Ctx);
- const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A,
- const MCSymbol *B);
-
- const MCExpr *ForceExpAbs(const MCExpr *Expr);
-
virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame);
virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame);
- MCWinFrameInfo *getCurrentWinFrameInfo() {
+ WinEH::FrameInfo *getCurrentWinFrameInfo() {
return CurrentWinFrameInfo;
}
- void EmitWindowsUnwindTables();
+ virtual void EmitWindowsUnwindTables();
virtual void EmitRawTextImpl(StringRef String);
@@ -238,7 +236,7 @@ public:
}
unsigned getNumWinFrameInfos() { return WinFrameInfos.size(); }
- ArrayRef<MCWinFrameInfo *> getWinFrameInfos() const {
+ ArrayRef<WinEH::FrameInfo *> getWinFrameInfos() const {
return WinFrameInfos;
}
@@ -349,8 +347,8 @@ public:
/// @p Section. This is required to update CurSection.
///
/// This corresponds to assembler directives like .section, .text, etc.
- void SwitchSection(const MCSection *Section,
- const MCExpr *Subsection = nullptr) {
+ virtual void SwitchSection(const MCSection *Section,
+ const MCExpr *Subsection = nullptr) {
assert(Section && "Cannot switch to a null section!");
MCSectionSubPair curSection = SectionStack.back().first;
SectionStack.back().second = curSection;
@@ -373,7 +371,7 @@ public:
}
/// Create the default sections and set the initial one.
- virtual void InitSections();
+ virtual void InitSections(bool NoExecStack);
/// AssignSection - Sets the symbol's section.
///
@@ -552,12 +550,6 @@ public:
/// to pass in a MCExpr for constant integers.
virtual void EmitIntValue(uint64_t Value, unsigned Size);
- /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO
- /// this is done by producing
- /// foo = value
- /// .long foo
- void EmitAbsValue(const MCExpr *Value, unsigned Size);
-
virtual void EmitULEB128Value(const MCExpr *Value);
virtual void EmitSLEB128Value(const MCExpr *Value);
@@ -669,11 +661,6 @@ public:
StringRef FileName);
virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID);
-
- void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label,
- int PointerSize);
-
- virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding);
virtual void EmitCFISections(bool EH, bool Debug);
void EmitCFIStartProc(bool IsSimple);
void EmitCFIEndProc();
@@ -782,8 +769,8 @@ MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
/// createELFStreamer - Create a machine code streamer which will generate
/// ELF format object files.
MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB,
- raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll,
- bool NoExecStack);
+ raw_ostream &OS, MCCodeEmitter *CE,
+ bool RelaxAll);
} // end namespace llvm
diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h
index 088c5e7470d6..3f38bd59a576 100644
--- a/include/llvm/MC/MCSubtargetInfo.h
+++ b/include/llvm/MC/MCSubtargetInfo.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_MCSUBTARGET_H
-#define LLVM_MC_MCSUBTARGET_H
+#ifndef LLVM_MC_MCSUBTARGETINFO_H
+#define LLVM_MC_MCSUBTARGETINFO_H
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/SubtargetFeature.h"
@@ -36,7 +36,7 @@ class MCSubtargetInfo {
const MCWriteProcResEntry *WriteProcResTable;
const MCWriteLatencyEntry *WriteLatencyTable;
const MCReadAdvanceEntry *ReadAdvanceTable;
- const MCSchedModel *CPUSchedModel;
+ MCSchedModel CPUSchedModel;
const InstrStage *Stages; // Instruction itinerary stages
const unsigned *OperandCycles; // Itinerary operand cycles
@@ -65,6 +65,10 @@ public:
return FeatureBits;
}
+ /// setFeatureBits - Set the feature bits.
+ ///
+ void setFeatureBits(uint64_t FeatureBits_) { FeatureBits = FeatureBits_; }
+
/// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with
/// feature string). Recompute feature bits and scheduling model.
void InitMCProcessorInfo(StringRef CPU, StringRef FS);
@@ -82,11 +86,11 @@ public:
/// getSchedModelForCPU - Get the machine model of a CPU.
///
- const MCSchedModel *getSchedModelForCPU(StringRef CPU) const;
+ MCSchedModel getSchedModelForCPU(StringRef CPU) const;
/// getSchedModel - Get the machine model for this subtarget's CPU.
///
- const MCSchedModel *getSchedModel() const { return CPUSchedModel; }
+ const MCSchedModel &getSchedModel() const { return CPUSchedModel; }
/// Return an iterator at the first process resource consumed by the given
/// scheduling class.
@@ -132,6 +136,15 @@ public:
/// Initialize an InstrItineraryData instance.
void initInstrItins(InstrItineraryData &InstrItins) const;
+
+ /// Check whether the CPU string is valid.
+ bool isCPUStringValid(StringRef CPU) {
+ auto Found = std::find_if(ProcDesc.begin(), ProcDesc.end(),
+ [=](const SubtargetFeatureKV &KV) {
+ return CPU == KV.Key;
+ });
+ return Found != ProcDesc.end();
+ }
};
} // End llvm namespace
diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h
index 0b3c3ceb210f..47a8789d463b 100644
--- a/include/llvm/MC/MCSymbol.h
+++ b/include/llvm/MC/MCSymbol.h
@@ -53,6 +53,9 @@ namespace llvm {
/// "Lfoo" or ".foo".
unsigned IsTemporary : 1;
+ /// \brief True if this symbol can be redefined.
+ unsigned IsRedefinable : 1;
+
/// IsUsed - True if this symbol has been used.
mutable unsigned IsUsed : 1;
@@ -61,7 +64,7 @@ namespace llvm {
friend class MCContext;
MCSymbol(StringRef name, bool isTemporary)
: Name(name), Section(nullptr), Value(nullptr),
- IsTemporary(isTemporary), IsUsed(false) {}
+ IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {}
MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION;
void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION;
@@ -79,6 +82,19 @@ namespace llvm {
bool isUsed() const { return IsUsed; }
void setUsed(bool Value) const { IsUsed = Value; }
+ /// \brief Check if this symbol is redefinable.
+ bool isRedefinable() const { return IsRedefinable; }
+ /// \brief Mark this symbol as redefinable.
+ void setRedefinable(bool Value) { IsRedefinable = Value; }
+ /// \brief Prepare this symbol to be redefined.
+ void redefineIfPossible() {
+ if (IsRedefinable) {
+ Value = nullptr;
+ Section = nullptr;
+ IsRedefinable = false;
+ }
+ }
+
/// @}
/// @name Associated Sections
/// @{
diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h
index 9a5881b14b44..ea71d1f433a4 100644
--- a/include/llvm/MC/MCTargetAsmParser.h
+++ b/include/llvm/MC/MCTargetAsmParser.h
@@ -7,13 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_TARGETPARSER_H
-#define LLVM_MC_TARGETPARSER_H
+#ifndef LLVM_MC_MCTARGETASMPARSER_H
+#define LLVM_MC_MCTARGETASMPARSER_H
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
#include "llvm/MC/MCTargetOptions.h"
-
#include <memory>
namespace llvm {
@@ -38,20 +37,22 @@ enum AsmRewriteKind {
AOK_Input, // Rewrite in terms of $N.
AOK_Output, // Rewrite in terms of $N.
AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr).
+ AOK_Label, // Rewrite local labels.
AOK_Skip // Skip emission (e.g., offset/type operators).
};
const char AsmRewritePrecedence [] = {
0, // AOK_Delete
- 1, // AOK_Align
- 1, // AOK_DotOperator
- 1, // AOK_Emit
- 3, // AOK_Imm
- 3, // AOK_ImmPrefix
- 2, // AOK_Input
- 2, // AOK_Output
- 4, // AOK_SizeDirective
- 1 // AOK_Skip
+ 2, // AOK_Align
+ 2, // AOK_DotOperator
+ 2, // AOK_Emit
+ 4, // AOK_Imm
+ 4, // AOK_ImmPrefix
+ 3, // AOK_Input
+ 3, // AOK_Output
+ 5, // AOK_SizeDirective
+ 1, // AOK_Label
+ 2 // AOK_Skip
};
struct AsmRewrite {
@@ -59,9 +60,12 @@ struct AsmRewrite {
SMLoc Loc;
unsigned Len;
unsigned Val;
+ StringRef Label;
public:
AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, unsigned val = 0)
: Kind(kind), Loc(loc), Len(len), Val(val) {}
+ AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len, StringRef label)
+ : Kind(kind), Loc(loc), Len(len), Val(0), Label(label) {}
};
struct ParseInstructionInfo {
@@ -93,7 +97,7 @@ protected: // Can only create subclasses.
MCTargetAsmParser();
/// AvailableFeatures - The current set of available features.
- unsigned AvailableFeatures;
+ uint64_t AvailableFeatures;
/// ParsingInlineAsm - Are we parsing ms-style inline assembly?
bool ParsingInlineAsm;
@@ -108,12 +112,14 @@ protected: // Can only create subclasses.
public:
virtual ~MCTargetAsmParser();
- unsigned getAvailableFeatures() const { return AvailableFeatures; }
- void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; }
+ uint64_t getAvailableFeatures() const { return AvailableFeatures; }
+ void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; }
bool isParsingInlineAsm () { return ParsingInlineAsm; }
void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; }
+ MCTargetOptions getTargetOptions() const { return MCOptions; }
+
void setSemaCallback(MCAsmParserSemaCallback *Callback) {
SemaCallback = Callback;
}
@@ -121,6 +127,9 @@ public:
virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) = 0;
+ /// Sets frame register corresponding to the current MachineFunction.
+ virtual void SetFrameRegister(unsigned RegNo) {}
+
/// ParseInstruction - Parse one assembly instruction.
///
/// The parser is positioned following the instruction name. The target
@@ -161,7 +170,7 @@ public:
/// explaining the match failure.
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
- unsigned &ErrorInfo,
+ uint64_t &ErrorInfo,
bool MatchingInlineAsm) = 0;
/// Allows targets to let registers opt out of clobber lists.
diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h
index eb4348ed3ec2..ce28a196e974 100644
--- a/include/llvm/MC/MCTargetOptions.h
+++ b/include/llvm/MC/MCTargetOptions.h
@@ -10,8 +10,12 @@
#ifndef LLVM_MC_MCTARGETOPTIONS_H
#define LLVM_MC_MCTARGETOPTIONS_H
+#include <string>
+
namespace llvm {
+class StringRef;
+
class MCTargetOptions {
public:
enum AsmInstrumentation {
@@ -24,12 +28,18 @@ public:
bool MCRelaxAll : 1;
bool MCNoExecStack : 1;
+ bool MCFatalWarnings : 1;
bool MCSaveTempLabels : 1;
bool MCUseDwarfDirectory : 1;
bool ShowMCEncoding : 1;
bool ShowMCInst : 1;
bool AsmVerbose : 1;
int DwarfVersion;
+ /// getABIName - If this returns a non-empty string this represents the
+ /// textual name of the ABI that we want the backend to use, e.g. o32, or
+ /// aapcs-linux.
+ StringRef getABIName() const;
+ std::string ABIName;
MCTargetOptions();
};
@@ -38,12 +48,14 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) {
return (ARE_EQUAL(SanitizeAddress) &&
ARE_EQUAL(MCRelaxAll) &&
ARE_EQUAL(MCNoExecStack) &&
+ ARE_EQUAL(MCFatalWarnings) &&
ARE_EQUAL(MCSaveTempLabels) &&
ARE_EQUAL(MCUseDwarfDirectory) &&
ARE_EQUAL(ShowMCEncoding) &&
ARE_EQUAL(ShowMCInst) &&
ARE_EQUAL(AsmVerbose) &&
- ARE_EQUAL(DwarfVersion));
+ ARE_EQUAL(DwarfVersion) &&
+ ARE_EQUAL(ABIName));
#undef ARE_EQUAL
}
diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h
index 6d4eb0ef5911..af23a92e6e99 100644
--- a/include/llvm/MC/MCTargetOptionsCommandFlags.h
+++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h
@@ -15,8 +15,8 @@
#ifndef LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H
#define LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H
-#include "llvm/Support/CommandLine.h"
#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Support/CommandLine.h"
using namespace llvm;
cl::opt<MCTargetOptions::AsmInstrumentation> AsmInstrumentation(
@@ -40,6 +40,11 @@ cl::opt<bool> ShowMCInst("asm-show-inst",
cl::desc("Emit internal instruction representation to "
"assembly file"));
+cl::opt<std::string>
+ABIName("target-abi", cl::Hidden,
+ cl::desc("The name of the ABI to be targeted from the backend."),
+ cl::init(""));
+
static inline MCTargetOptions InitMCTargetOptionsFromFlags() {
MCTargetOptions Options;
Options.SanitizeAddress =
@@ -47,6 +52,7 @@ static inline MCTargetOptions InitMCTargetOptionsFromFlags() {
Options.MCRelaxAll = RelaxAll;
Options.DwarfVersion = DwarfVersion;
Options.ShowMCInst = ShowMCInst;
+ Options.ABIName = ABIName;
return Options;
}
diff --git a/include/llvm/MC/MCWin64EH.h b/include/llvm/MC/MCWin64EH.h
index 3df0d0ab8c46..0e81a191cd2c 100644
--- a/include/llvm/MC/MCWin64EH.h
+++ b/include/llvm/MC/MCWin64EH.h
@@ -20,9 +20,8 @@
#include <vector>
namespace llvm {
- class StringRef;
- class MCStreamer;
- class MCSymbol;
+class MCStreamer;
+class MCSymbol;
namespace Win64EH {
struct Instruction {
@@ -52,36 +51,13 @@ struct Instruction {
return WinEH::Instruction(UOP_SetFPReg, L, Reg, Off);
}
};
-}
-
- struct MCWinFrameInfo {
- MCWinFrameInfo()
- : Begin(nullptr), End(nullptr),ExceptionHandler(nullptr),
- Function(nullptr), PrologEnd(nullptr), Symbol(nullptr),
- HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
- ChainedParent(nullptr), Instructions() {}
- MCSymbol *Begin;
- MCSymbol *End;
- const MCSymbol *ExceptionHandler;
- const MCSymbol *Function;
- MCSymbol *PrologEnd;
- MCSymbol *Symbol;
- bool HandlesUnwind;
- bool HandlesExceptions;
- int LastFrameInst;
- MCWinFrameInfo *ChainedParent;
- std::vector<WinEH::Instruction> Instructions;
- };
- class MCWin64EHUnwindEmitter {
- public:
- static StringRef GetSectionSuffix(const MCSymbol *func);
- //
- // This emits the unwind info sections (.pdata and .xdata in PE/COFF).
- //
- static void Emit(MCStreamer &streamer);
- static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info);
- };
+class UnwindEmitter : public WinEH::UnwindEmitter {
+public:
+ void Emit(MCStreamer &Streamer) const override;
+ void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI) const override;
+};
+}
} // end namespace llvm
#endif
diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h
index 7d2d0e4f5560..57a75cec2204 100644
--- a/include/llvm/MC/MCWinCOFFStreamer.h
+++ b/include/llvm/MC/MCWinCOFFStreamer.h
@@ -30,10 +30,16 @@ public:
MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE,
raw_ostream &OS);
+ /// state management
+ void reset() override {
+ CurSymbol = nullptr;
+ MCObjectStreamer::reset();
+ }
+
/// \name MCStreamer interface
/// \{
- void InitSections() override;
+ void InitSections(bool NoExecStack) override;
void EmitLabel(MCSymbol *Symbol) override;
void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
void EmitThumbFunc(MCSymbol *Func) override;
diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h
index 1cd1b0f1b8ca..05b58c753b66 100644
--- a/include/llvm/MC/MCWinEH.h
+++ b/include/llvm/MC/MCWinEH.h
@@ -10,8 +10,14 @@
#ifndef LLVM_MC_MCWINEH_H
#define LLVM_MC_MCWINEH_H
+#include <vector>
+
namespace llvm {
+class MCContext;
+class MCSection;
+class MCStreamer;
class MCSymbol;
+class StringRef;
namespace WinEH {
struct Instruction {
@@ -23,6 +29,55 @@ struct Instruction {
Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off)
: Label(L), Offset(Off), Register(Reg), Operation(Op) {}
};
+
+struct FrameInfo {
+ const MCSymbol *Begin;
+ const MCSymbol *End;
+ const MCSymbol *ExceptionHandler;
+ const MCSymbol *Function;
+ const MCSymbol *PrologEnd;
+ const MCSymbol *Symbol;
+
+ bool HandlesUnwind;
+ bool HandlesExceptions;
+
+ int LastFrameInst;
+ const FrameInfo *ChainedParent;
+ std::vector<Instruction> Instructions;
+
+ FrameInfo()
+ : Begin(nullptr), End(nullptr), ExceptionHandler(nullptr),
+ Function(nullptr), PrologEnd(nullptr), Symbol(nullptr),
+ HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
+ ChainedParent(nullptr), Instructions() {}
+ FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel)
+ : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr),
+ Function(Function), PrologEnd(nullptr), Symbol(nullptr),
+ HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
+ ChainedParent(nullptr), Instructions() {}
+ FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel,
+ const FrameInfo *ChainedParent)
+ : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr),
+ Function(Function), PrologEnd(nullptr), Symbol(nullptr),
+ HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
+ ChainedParent(ChainedParent), Instructions() {}
+};
+
+class UnwindEmitter {
+public:
+ static const MCSection *getPDataSection(const MCSymbol *Function,
+ MCContext &Context);
+ static const MCSection *getXDataSection(const MCSymbol *Function,
+ MCContext &Context);
+
+ virtual ~UnwindEmitter() { }
+
+ //
+ // This emits the unwind info sections (.pdata and .xdata in PE/COFF).
+ //
+ virtual void Emit(MCStreamer &Streamer) const = 0;
+ virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI) const = 0;
+};
}
}
diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h
index 065e9e06e2c9..897d449254ea 100644
--- a/include/llvm/MC/StringTableBuilder.h
+++ b/include/llvm/MC/StringTableBuilder.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_MC_STRINGTABLE_BUILDER_H
-#define LLVM_MC_STRINGTABLE_BUILDER_H
+#ifndef LLVM_MC_STRINGTABLEBUILDER_H
+#define LLVM_MC_STRINGTABLEBUILDER_H
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
@@ -26,12 +26,18 @@ public:
/// copy of s. Can only be used before the table is finalized.
StringRef add(StringRef s) {
assert(!isFinalized());
- return StringIndexMap.GetOrCreateValue(s, 0).getKey();
+ return StringIndexMap.insert(std::make_pair(s, 0)).first->first();
}
+ enum Kind {
+ ELF,
+ WinCOFF,
+ MachO
+ };
+
/// \brief Analyze the strings and build the final table. No more strings can
/// be added after this point.
- void finalize();
+ void finalize(Kind kind);
/// \brief Retrieve the string table data. Can only be used after the table
/// is finalized.
@@ -48,6 +54,8 @@ public:
return StringIndexMap[s];
}
+ void clear();
+
private:
bool isFinalized() {
return !StringTable.empty();
diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h
index c5d62a6cbae8..bfecb8ba6ab0 100644
--- a/include/llvm/MC/SubtargetFeature.h
+++ b/include/llvm/MC/SubtargetFeature.h
@@ -72,21 +72,21 @@ struct SubtargetInfoKV {
class SubtargetFeatures {
std::vector<std::string> Features; // Subtarget features as a vector
public:
- explicit SubtargetFeatures(const StringRef Initial = "");
+ explicit SubtargetFeatures(StringRef Initial = "");
/// Features string accessors.
std::string getString() const;
/// Adding Features.
- void AddFeature(const StringRef String);
+ void AddFeature(StringRef String);
/// ToggleFeature - Toggle a feature and returns the newly updated feature
/// bits.
- uint64_t ToggleFeature(uint64_t Bits, const StringRef String,
+ uint64_t ToggleFeature(uint64_t Bits, StringRef String,
ArrayRef<SubtargetFeatureKV> FeatureTable);
/// Get feature bits of a CPU.
- uint64_t getFeatureBits(const StringRef CPU,
+ uint64_t getFeatureBits(StringRef CPU,
ArrayRef<SubtargetFeatureKV> CPUTable,
ArrayRef<SubtargetFeatureKV> FeatureTable);
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index af6c995c1d05..4e96205a93ba 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -15,6 +15,7 @@
#define LLVM_OBJECT_ARCHIVE_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
@@ -83,14 +84,13 @@ public:
return getHeader()->getAccessMode();
}
/// \return the size of the archive member without the header or padding.
- uint64_t getSize() const { return Data.size() - StartOfFile; }
+ uint64_t getSize() const;
StringRef getBuffer() const {
return StringRef(Data.data() + StartOfFile, getSize());
}
- ErrorOr<std::unique_ptr<MemoryBuffer>>
- getMemoryBuffer(bool FullPath = false) const;
+ ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
ErrorOr<std::unique_ptr<Binary>>
getAsBinary(LLVMContext *Context = nullptr) const;
@@ -98,12 +98,12 @@ public:
class child_iterator {
Child child;
+
public:
child_iterator() : child(Child(nullptr, nullptr)) {}
child_iterator(const Child &c) : child(c) {}
- const Child* operator->() const {
- return &child;
- }
+ const Child *operator->() const { return &child; }
+ const Child &operator*() const { return child; }
bool operator==(const child_iterator &other) const {
return child == other.child;
@@ -113,11 +113,11 @@ public:
return !(*this == other);
}
- bool operator <(const child_iterator &other) const {
+ bool operator<(const child_iterator &other) const {
return child < other.child;
}
- child_iterator& operator++() { // Preincrement
+ child_iterator &operator++() { // Preincrement
child = child.getNext();
return *this;
}
@@ -164,8 +164,8 @@ public:
}
};
- Archive(std::unique_ptr<MemoryBuffer> Source, std::error_code &EC);
- static ErrorOr<Archive *> create(std::unique_ptr<MemoryBuffer> Source);
+ Archive(MemoryBufferRef Source, std::error_code &EC);
+ static ErrorOr<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
enum Kind {
K_GNU,
@@ -173,12 +173,14 @@ public:
K_COFF
};
- Kind kind() const {
- return Format;
- }
+ Kind kind() const { return (Kind)Format; }
child_iterator child_begin(bool SkipInternal = true) const;
child_iterator child_end() const;
+ iterator_range<child_iterator> children(bool SkipInternal = true) const {
+ return iterator_range<child_iterator>(child_begin(SkipInternal),
+ child_end());
+ }
symbol_iterator symbol_begin() const;
symbol_iterator symbol_end() const;
@@ -197,7 +199,8 @@ private:
child_iterator SymbolTable;
child_iterator StringTable;
child_iterator FirstRegular;
- Kind Format;
+ unsigned Format : 2;
+ unsigned IsThin : 1;
};
}
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 91984cb52715..4b2b7e6835cc 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -17,11 +17,11 @@
#include "llvm/Object/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
namespace llvm {
class LLVMContext;
-class MemoryBuffer;
class StringRef;
namespace object {
@@ -34,9 +34,9 @@ private:
unsigned int TypeID;
protected:
- std::unique_ptr<MemoryBuffer> Data;
+ MemoryBufferRef Data;
- Binary(unsigned int Type, std::unique_ptr<MemoryBuffer> Source);
+ Binary(unsigned int Type, MemoryBufferRef Source);
enum {
ID_Archive,
@@ -78,8 +78,8 @@ public:
virtual ~Binary();
StringRef getData() const;
- MemoryBuffer *releaseBuffer() { return Data.release(); }
StringRef getFileName() const;
+ MemoryBufferRef getMemoryBufferRef() const;
// Cast methods.
unsigned int getType() const { return TypeID; }
@@ -126,10 +126,58 @@ public:
/// @brief Create a Binary from Source, autodetecting the file type.
///
/// @param Source The data to create the Binary from.
-ErrorOr<Binary *> createBinary(std::unique_ptr<MemoryBuffer> Source,
- LLVMContext *Context = nullptr);
+ErrorOr<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
+ LLVMContext *Context = nullptr);
-ErrorOr<Binary *> createBinary(StringRef Path);
+template <typename T> class OwningBinary {
+ std::unique_ptr<T> Bin;
+ std::unique_ptr<MemoryBuffer> Buf;
+
+public:
+ OwningBinary();
+ OwningBinary(std::unique_ptr<T> Bin, std::unique_ptr<MemoryBuffer> Buf);
+ OwningBinary(OwningBinary<T>&& Other);
+ OwningBinary<T> &operator=(OwningBinary<T> &&Other);
+
+ std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> takeBinary();
+
+ T* getBinary();
+ const T* getBinary() const;
+};
+
+template <typename T>
+OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin,
+ std::unique_ptr<MemoryBuffer> Buf)
+ : Bin(std::move(Bin)), Buf(std::move(Buf)) {}
+
+template <typename T> OwningBinary<T>::OwningBinary() {}
+
+template <typename T>
+OwningBinary<T>::OwningBinary(OwningBinary &&Other)
+ : Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {}
+
+template <typename T>
+OwningBinary<T> &OwningBinary<T>::operator=(OwningBinary &&Other) {
+ Bin = std::move(Other.Bin);
+ Buf = std::move(Other.Buf);
+ return *this;
+}
+
+template <typename T>
+std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>>
+OwningBinary<T>::takeBinary() {
+ return std::make_pair(std::move(Bin), std::move(Buf));
+}
+
+template <typename T> T* OwningBinary<T>::getBinary() {
+ return Bin.get();
+}
+
+template <typename T> const T* OwningBinary<T>::getBinary() const {
+ return Bin.get();
+}
+
+ErrorOr<OwningBinary<Binary>> createBinary(StringRef Path);
}
}
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index e2da070d47bd..522bf68c6cbd 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -14,22 +14,31 @@
#ifndef LLVM_OBJECT_COFF_H
#define LLVM_OBJECT_COFF_H
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorOr.h"
namespace llvm {
template <typename T> class ArrayRef;
namespace object {
class ImportDirectoryEntryRef;
+class DelayImportDirectoryEntryRef;
class ExportDirectoryEntryRef;
+class ImportedSymbolRef;
+class BaseRelocRef;
typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
+typedef content_iterator<DelayImportDirectoryEntryRef>
+ delay_import_directory_iterator;
typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator;
+typedef content_iterator<ImportedSymbolRef> imported_symbol_iterator;
+typedef content_iterator<BaseRelocRef> base_reloc_iterator;
/// The DOS compatible header at the front of all PE/COFF executables.
struct dos_header {
- support::ulittle16_t Magic;
+ char Magic[2];
support::ulittle16_t UsedBytesInTheLastPage;
support::ulittle16_t FileSizeInPages;
support::ulittle16_t NumberOfRelocationItems;
@@ -62,6 +71,22 @@ struct coff_file_header {
bool isImportLibrary() const { return NumberOfSections == 0xffff; }
};
+struct coff_bigobj_file_header {
+ support::ulittle16_t Sig1;
+ support::ulittle16_t Sig2;
+ support::ulittle16_t Version;
+ support::ulittle16_t Machine;
+ support::ulittle32_t TimeDateStamp;
+ uint8_t UUID[16];
+ support::ulittle32_t unused1;
+ support::ulittle32_t unused2;
+ support::ulittle32_t unused3;
+ support::ulittle32_t unused4;
+ support::ulittle32_t NumberOfSections;
+ support::ulittle32_t PointerToSymbolTable;
+ support::ulittle32_t NumberOfSymbols;
+};
+
/// The 32-bit PE header that follows the COFF header.
struct pe32_header {
support::ulittle16_t Magic;
@@ -87,12 +112,14 @@ struct pe32_header {
support::ulittle32_t SizeOfHeaders;
support::ulittle32_t CheckSum;
support::ulittle16_t Subsystem;
+ // FIXME: This should be DllCharacteristics.
support::ulittle16_t DLLCharacteristics;
support::ulittle32_t SizeOfStackReserve;
support::ulittle32_t SizeOfStackCommit;
support::ulittle32_t SizeOfHeapReserve;
support::ulittle32_t SizeOfHeapCommit;
support::ulittle32_t LoaderFlags;
+ // FIXME: This should be NumberOfRvaAndSizes.
support::ulittle32_t NumberOfRvaAndSize;
};
@@ -142,22 +169,40 @@ struct import_directory_table_entry {
support::ulittle32_t ImportAddressTableRVA;
};
-struct import_lookup_table_entry32 {
- support::ulittle32_t data;
+template <typename IntTy>
+struct import_lookup_table_entry {
+ IntTy Data;
- bool isOrdinal() const { return data & 0x80000000; }
+ bool isOrdinal() const { return Data < 0; }
uint16_t getOrdinal() const {
assert(isOrdinal() && "ILT entry is not an ordinal!");
- return data & 0xFFFF;
+ return Data & 0xFFFF;
}
uint32_t getHintNameRVA() const {
assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
- return data;
+ return Data & 0xFFFFFFFF;
}
};
+typedef import_lookup_table_entry<support::little32_t>
+ import_lookup_table_entry32;
+typedef import_lookup_table_entry<support::little64_t>
+ import_lookup_table_entry64;
+
+struct delay_import_directory_table_entry {
+ // dumpbin reports this field as "Characteristics" instead of "Attributes".
+ support::ulittle32_t Attributes;
+ support::ulittle32_t Name;
+ support::ulittle32_t ModuleHandle;
+ support::ulittle32_t DelayImportAddressTable;
+ support::ulittle32_t DelayImportNameTable;
+ support::ulittle32_t BoundDelayImportTable;
+ support::ulittle32_t UnloadDelayImportTable;
+ support::ulittle32_t TimeStamp;
+};
+
struct export_directory_table_entry {
support::ulittle32_t ExportFlags;
support::ulittle32_t TimeDateStamp;
@@ -180,67 +225,156 @@ union export_address_table_entry {
typedef support::ulittle32_t export_name_pointer_table_entry;
typedef support::ulittle16_t export_ordinal_table_entry;
-struct coff_symbol {
- struct StringTableOffset {
- support::ulittle32_t Zeroes;
- support::ulittle32_t Offset;
- };
+struct StringTableOffset {
+ support::ulittle32_t Zeroes;
+ support::ulittle32_t Offset;
+};
+template <typename SectionNumberType>
+struct coff_symbol {
union {
- char ShortName[8];
+ char ShortName[COFF::NameSize];
StringTableOffset Offset;
} Name;
support::ulittle32_t Value;
- support::ulittle16_t SectionNumber;
+ SectionNumberType SectionNumber;
support::ulittle16_t Type;
- support::ulittle8_t StorageClass;
- support::ulittle8_t NumberOfAuxSymbols;
+ uint8_t StorageClass;
+ uint8_t NumberOfAuxSymbols;
+};
+
+typedef coff_symbol<support::ulittle16_t> coff_symbol16;
+typedef coff_symbol<support::ulittle32_t> coff_symbol32;
+
+class COFFSymbolRef {
+public:
+ COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS), CS32(nullptr) {}
+ COFFSymbolRef(const coff_symbol32 *CS) : CS16(nullptr), CS32(CS) {}
+ COFFSymbolRef() : CS16(nullptr), CS32(nullptr) {}
+
+ const void *getRawPtr() const {
+ return CS16 ? static_cast<const void *>(CS16) : CS32;
+ }
+
+ friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) {
+ return A.getRawPtr() < B.getRawPtr();
+ }
+
+ bool isBigObj() const {
+ if (CS16)
+ return false;
+ if (CS32)
+ return true;
+ llvm_unreachable("COFFSymbolRef points to nothing!");
+ }
+
+ const char *getShortName() const {
+ return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName;
+ }
+
+ const StringTableOffset &getStringTableOffset() const {
+ assert(isSet() && "COFFSymbolRef points to nothing!");
+ return CS16 ? CS16->Name.Offset : CS32->Name.Offset;
+ }
+
+ uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; }
+
+ int32_t getSectionNumber() const {
+ assert(isSet() && "COFFSymbolRef points to nothing!");
+ if (CS16) {
+ // Reserved sections are returned as negative numbers.
+ if (CS16->SectionNumber <= COFF::MaxNumberOfSections16)
+ return CS16->SectionNumber;
+ return static_cast<int16_t>(CS16->SectionNumber);
+ }
+ return static_cast<int32_t>(CS32->SectionNumber);
+ }
+
+ uint16_t getType() const {
+ assert(isSet() && "COFFSymbolRef points to nothing!");
+ return CS16 ? CS16->Type : CS32->Type;
+ }
+
+ uint8_t getStorageClass() const {
+ assert(isSet() && "COFFSymbolRef points to nothing!");
+ return CS16 ? CS16->StorageClass : CS32->StorageClass;
+ }
+
+ uint8_t getNumberOfAuxSymbols() const {
+ assert(isSet() && "COFFSymbolRef points to nothing!");
+ return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols;
+ }
+
+ uint8_t getBaseType() const { return getType() & 0x0F; }
- uint8_t getBaseType() const { return Type & 0x0F; }
+ uint8_t getComplexType() const {
+ return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT;
+ }
+
+ bool isExternal() const {
+ return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL;
+ }
+
+ bool isCommon() const {
+ return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
+ getValue() != 0;
+ }
+
+ bool isUndefined() const {
+ return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
+ getValue() == 0;
+ }
- uint8_t getComplexType() const { return (Type & 0xF0) >> 4; }
+ bool isWeakExternal() const {
+ return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
+ }
bool isFunctionDefinition() const {
- return StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
- getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
+ return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
- !COFF::isReservedSectionNumber(SectionNumber);
+ !COFF::isReservedSectionNumber(getSectionNumber());
}
bool isFunctionLineInfo() const {
- return StorageClass == COFF::IMAGE_SYM_CLASS_FUNCTION;
+ return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION;
}
- bool isWeakExternal() const {
- return StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL ||
- (StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
- SectionNumber == COFF::IMAGE_SYM_UNDEFINED && Value == 0);
+ bool isAnyUndefined() const {
+ return isUndefined() || isWeakExternal();
}
bool isFileRecord() const {
- return StorageClass == COFF::IMAGE_SYM_CLASS_FILE;
+ return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
}
bool isSectionDefinition() const {
// C++/CLI creates external ABS symbols for non-const appdomain globals.
// These are also followed by an auxiliary section definition.
- bool isAppdomainGlobal = StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
- SectionNumber == COFF::IMAGE_SYM_ABSOLUTE;
- bool isOrdinarySection =
- StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Value == 0;
+ bool isAppdomainGlobal =
+ getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
+ getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE;
+ bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC;
+ if (!getNumberOfAuxSymbols())
+ return false;
return isAppdomainGlobal || isOrdinarySection;
}
bool isCLRToken() const {
- return StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN;
+ return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN;
}
+
+private:
+ bool isSet() const { return CS16 || CS32; }
+
+ const coff_symbol16 *CS16;
+ const coff_symbol32 *CS32;
};
struct coff_section {
- char Name[8];
+ char Name[COFF::NameSize];
support::ulittle32_t VirtualSize;
support::ulittle32_t VirtualAddress;
support::ulittle32_t SizeOfRawData;
@@ -254,9 +388,9 @@ struct coff_section {
// Returns true if the actual number of relocations is stored in
// VirtualAddress field of the first relocation table entry.
bool hasExtendedRelocations() const {
- return Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL &&
- NumberOfRelocations == UINT16_MAX;
- };
+ return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) &&
+ NumberOfRelocations == UINT16_MAX;
+ }
};
struct coff_relocation {
@@ -270,7 +404,6 @@ struct coff_aux_function_definition {
support::ulittle32_t TotalSize;
support::ulittle32_t PointerToLinenumber;
support::ulittle32_t PointerToNextFunction;
- char Unused[2];
};
struct coff_aux_bf_and_ef_symbol {
@@ -278,17 +411,11 @@ struct coff_aux_bf_and_ef_symbol {
support::ulittle16_t Linenumber;
char Unused2[6];
support::ulittle32_t PointerToNextFunction;
- char Unused3[2];
};
struct coff_aux_weak_external {
support::ulittle32_t TagIndex;
support::ulittle32_t Characteristics;
- char Unused[10];
-};
-
-struct coff_aux_file {
- char FileName[18];
};
struct coff_aux_section_definition {
@@ -296,16 +423,22 @@ struct coff_aux_section_definition {
support::ulittle16_t NumberOfRelocations;
support::ulittle16_t NumberOfLinenumbers;
support::ulittle32_t CheckSum;
- support::ulittle16_t Number;
- support::ulittle8_t Selection;
- char Unused[3];
+ support::ulittle16_t NumberLowPart;
+ uint8_t Selection;
+ uint8_t Unused;
+ support::ulittle16_t NumberHighPart;
+ int32_t getNumber(bool IsBigObj) const {
+ uint32_t Number = static_cast<uint32_t>(NumberLowPart);
+ if (IsBigObj)
+ Number |= static_cast<uint32_t>(NumberHighPart) << 16;
+ return static_cast<int32_t>(Number);
+ }
};
struct coff_aux_clr_token {
- support::ulittle8_t AuxType;
- support::ulittle8_t Reserved;
+ uint8_t AuxType;
+ uint8_t Reserved;
support::ulittle32_t SymbolTableIndex;
- char Unused[12];
};
struct coff_load_configuration32 {
@@ -324,7 +457,7 @@ struct coff_load_configuration32 {
support::ulittle32_t ProcessAffinityMask;
support::ulittle32_t ProcessHeapFlags;
support::ulittle16_t CSDVersion;
- uint16_t Reserved;
+ support::ulittle16_t Reserved;
support::ulittle32_t EditList;
support::ulittle32_t SecurityCookie;
support::ulittle32_t SEHandlerTable;
@@ -337,32 +470,114 @@ struct coff_runtime_function_x64 {
support::ulittle32_t UnwindInformation;
};
+struct coff_base_reloc_block_header {
+ support::ulittle32_t PageRVA;
+ support::ulittle32_t BlockSize;
+};
+
+struct coff_base_reloc_block_entry {
+ support::ulittle16_t Data;
+ int getType() const { return Data >> 12; }
+ int getOffset() const { return Data & ((1 << 12) - 1); }
+};
+
class COFFObjectFile : public ObjectFile {
private:
friend class ImportDirectoryEntryRef;
friend class ExportDirectoryEntryRef;
const coff_file_header *COFFHeader;
+ const coff_bigobj_file_header *COFFBigObjHeader;
const pe32_header *PE32Header;
const pe32plus_header *PE32PlusHeader;
const data_directory *DataDirectory;
const coff_section *SectionTable;
- const coff_symbol *SymbolTable;
+ const coff_symbol16 *SymbolTable16;
+ const coff_symbol32 *SymbolTable32;
const char *StringTable;
uint32_t StringTableSize;
const import_directory_table_entry *ImportDirectory;
uint32_t NumberOfImportDirectory;
+ const delay_import_directory_table_entry *DelayImportDirectory;
+ uint32_t NumberOfDelayImportDirectory;
const export_directory_table_entry *ExportDirectory;
+ const coff_base_reloc_block_header *BaseRelocHeader;
+ const coff_base_reloc_block_header *BaseRelocEnd;
std::error_code getString(uint32_t offset, StringRef &Res) const;
- const coff_symbol *toSymb(DataRefImpl Symb) const;
+ template <typename coff_symbol_type>
+ const coff_symbol_type *toSymb(DataRefImpl Symb) const;
const coff_section *toSec(DataRefImpl Sec) const;
const coff_relocation *toRel(DataRefImpl Rel) const;
std::error_code initSymbolTablePtr();
std::error_code initImportTablePtr();
+ std::error_code initDelayImportTablePtr();
std::error_code initExportTablePtr();
+ std::error_code initBaseRelocPtr();
+public:
+ uintptr_t getSymbolTable() const {
+ if (SymbolTable16)
+ return reinterpret_cast<uintptr_t>(SymbolTable16);
+ if (SymbolTable32)
+ return reinterpret_cast<uintptr_t>(SymbolTable32);
+ return uintptr_t(0);
+ }
+ uint16_t getMachine() const {
+ if (COFFHeader)
+ return COFFHeader->Machine;
+ if (COFFBigObjHeader)
+ return COFFBigObjHeader->Machine;
+ llvm_unreachable("no COFF header!");
+ }
+ uint16_t getSizeOfOptionalHeader() const {
+ if (COFFHeader)
+ return COFFHeader->isImportLibrary() ? 0
+ : COFFHeader->SizeOfOptionalHeader;
+ // bigobj doesn't have this field.
+ if (COFFBigObjHeader)
+ return 0;
+ llvm_unreachable("no COFF header!");
+ }
+ uint16_t getCharacteristics() const {
+ if (COFFHeader)
+ return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics;
+ // bigobj doesn't have characteristics to speak of,
+ // editbin will silently lie to you if you attempt to set any.
+ if (COFFBigObjHeader)
+ return 0;
+ llvm_unreachable("no COFF header!");
+ }
+ uint32_t getTimeDateStamp() const {
+ if (COFFHeader)
+ return COFFHeader->TimeDateStamp;
+ if (COFFBigObjHeader)
+ return COFFBigObjHeader->TimeDateStamp;
+ llvm_unreachable("no COFF header!");
+ }
+ uint32_t getNumberOfSections() const {
+ if (COFFHeader)
+ return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections;
+ if (COFFBigObjHeader)
+ return COFFBigObjHeader->NumberOfSections;
+ llvm_unreachable("no COFF header!");
+ }
+ uint32_t getPointerToSymbolTable() const {
+ if (COFFHeader)
+ return COFFHeader->isImportLibrary() ? 0
+ : COFFHeader->PointerToSymbolTable;
+ if (COFFBigObjHeader)
+ return COFFBigObjHeader->PointerToSymbolTable;
+ llvm_unreachable("no COFF header!");
+ }
+ uint32_t getNumberOfSymbols() const {
+ if (COFFHeader)
+ return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols;
+ if (COFFBigObjHeader)
+ return COFFBigObjHeader->NumberOfSymbols;
+ llvm_unreachable("no COFF header!");
+ }
protected:
void moveSymbolNext(DataRefImpl &Symb) const override;
std::error_code getSymbolName(DataRefImpl Symb,
@@ -378,24 +593,16 @@ protected:
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
- std::error_code getSectionAddress(DataRefImpl Sec,
- uint64_t &Res) const override;
- std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override;
+ uint64_t getSectionAddress(DataRefImpl Sec) const override;
+ uint64_t getSectionSize(DataRefImpl Sec) const override;
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
- std::error_code getSectionAlignment(DataRefImpl Sec,
- uint64_t &Res) const override;
- std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionReadOnlyData(DataRefImpl Sec,
- bool &Res) const override;
- std::error_code isSectionRequiredForExecution(DataRefImpl Sec,
- bool &Res) const override;
- std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
- bool &Result) const override;
+ uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionText(DataRefImpl Sec) const override;
+ bool isSectionData(DataRefImpl Sec) const override;
+ bool isSectionBSS(DataRefImpl Sec) const override;
+ bool isSectionVirtual(DataRefImpl Sec) const override;
+ bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
@@ -414,54 +621,93 @@ protected:
getRelocationValueString(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override;
- std::error_code getLibraryNext(DataRefImpl LibData,
- LibraryRef &Result) const override;
- std::error_code getLibraryPath(DataRefImpl LibData,
- StringRef &Result) const override;
-
public:
- COFFObjectFile(std::unique_ptr<MemoryBuffer> Object, std::error_code &EC);
+ COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
basic_symbol_iterator symbol_begin_impl() const override;
basic_symbol_iterator symbol_end_impl() const override;
- library_iterator needed_library_begin() const override;
- library_iterator needed_library_end() const override;
section_iterator section_begin() const override;
section_iterator section_end() const override;
const coff_section *getCOFFSection(const SectionRef &Section) const;
- const coff_symbol *getCOFFSymbol(const SymbolRef &Symbol) const;
+ COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const;
+ COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const;
const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const;
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
unsigned getArch() const override;
- StringRef getLoadName() const override;
import_directory_iterator import_directory_begin() const;
import_directory_iterator import_directory_end() const;
+ delay_import_directory_iterator delay_import_directory_begin() const;
+ delay_import_directory_iterator delay_import_directory_end() const;
export_directory_iterator export_directory_begin() const;
export_directory_iterator export_directory_end() const;
-
- std::error_code getHeader(const coff_file_header *&Res) const;
- std::error_code getCOFFHeader(const coff_file_header *&Res) const;
+ base_reloc_iterator base_reloc_begin() const;
+ base_reloc_iterator base_reloc_end() const;
+
+ iterator_range<import_directory_iterator> import_directories() const;
+ iterator_range<delay_import_directory_iterator>
+ delay_import_directories() const;
+ iterator_range<export_directory_iterator> export_directories() const;
+ iterator_range<base_reloc_iterator> base_relocs() const;
+
+ const dos_header *getDOSHeader() const {
+ if (!PE32Header && !PE32PlusHeader)
+ return nullptr;
+ return reinterpret_cast<const dos_header *>(base());
+ }
std::error_code getPE32Header(const pe32_header *&Res) const;
std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const;
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 getSymbol(uint32_t index, const coff_symbol *&Res) const;
+ template <typename coff_symbol_type>
+ std::error_code getSymbol(uint32_t Index,
+ const coff_symbol_type *&Res) const {
+ if (Index >= getNumberOfSymbols())
+ return object_error::parse_failed;
+
+ Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
+ return object_error::success;
+ }
+ ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const {
+ if (SymbolTable16) {
+ const coff_symbol16 *Symb = nullptr;
+ if (std::error_code EC = getSymbol(index, Symb))
+ return EC;
+ return COFFSymbolRef(Symb);
+ }
+ if (SymbolTable32) {
+ const coff_symbol32 *Symb = nullptr;
+ if (std::error_code EC = getSymbol(index, Symb))
+ return EC;
+ return COFFSymbolRef(Symb);
+ }
+ return object_error::parse_failed;
+ }
template <typename T>
std::error_code getAuxSymbol(uint32_t index, const T *&Res) const {
- const coff_symbol *s;
- std::error_code ec = getSymbol(index, s);
- Res = reinterpret_cast<const T *>(s);
- return ec;
+ ErrorOr<COFFSymbolRef> s = getSymbol(index);
+ if (std::error_code EC = s.getError())
+ return EC;
+ Res = reinterpret_cast<const T *>(s->getRawPtr());
+ return object_error::success;
+ }
+ std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
+
+ ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const;
+
+ size_t getSymbolTableEntrySize() const {
+ if (COFFHeader)
+ return sizeof(coff_symbol16);
+ if (COFFBigObjHeader)
+ return sizeof(coff_symbol32);
+ llvm_unreachable("null symbol table pointer!");
}
- std::error_code getSymbolName(const coff_symbol *symbol,
- StringRef &Res) const;
- ArrayRef<uint8_t> getSymbolAuxData(const coff_symbol *symbol) const;
std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
+ uint64_t getSectionSize(const coff_section *Sec) const;
std::error_code getSectionContents(const coff_section *Sec,
ArrayRef<uint8_t> &Res) const;
@@ -470,6 +716,9 @@ public:
std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
StringRef &Name) const;
+ bool isRelocatableObject() const override;
+ bool is64() const { return PE32PlusHeader; }
+
static inline bool classof(const Binary *v) { return v->isCOFF(); }
};
@@ -483,7 +732,14 @@ public:
bool operator==(const ImportDirectoryEntryRef &Other) const;
void moveNext();
+
+ imported_symbol_iterator imported_symbol_begin() const;
+ imported_symbol_iterator imported_symbol_end() const;
+ iterator_range<imported_symbol_iterator> imported_symbols() const;
+
std::error_code getName(StringRef &Result) const;
+ std::error_code getImportLookupTableRVA(uint32_t &Result) const;
+ std::error_code getImportAddressTableRVA(uint32_t &Result) const;
std::error_code
getImportTableEntry(const import_directory_table_entry *&Result) const;
@@ -497,6 +753,31 @@ private:
const COFFObjectFile *OwningObject;
};
+class DelayImportDirectoryEntryRef {
+public:
+ DelayImportDirectoryEntryRef() : OwningObject(nullptr) {}
+ DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T,
+ uint32_t I, const COFFObjectFile *Owner)
+ : Table(T), Index(I), OwningObject(Owner) {}
+
+ bool operator==(const DelayImportDirectoryEntryRef &Other) const;
+ void moveNext();
+
+ imported_symbol_iterator imported_symbol_begin() const;
+ imported_symbol_iterator imported_symbol_end() const;
+ iterator_range<imported_symbol_iterator> imported_symbols() const;
+
+ std::error_code getName(StringRef &Result) const;
+ std::error_code getDelayImportTable(
+ const delay_import_directory_table_entry *&Result) const;
+ std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const;
+
+private:
+ const delay_import_directory_table_entry *Table;
+ uint32_t Index;
+ const COFFObjectFile *OwningObject;
+};
+
// The iterator for the export directory table entry.
class ExportDirectoryEntryRef {
public:
@@ -519,6 +800,49 @@ private:
uint32_t Index;
const COFFObjectFile *OwningObject;
};
+
+class ImportedSymbolRef {
+public:
+ ImportedSymbolRef() : OwningObject(nullptr) {}
+ ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I,
+ const COFFObjectFile *Owner)
+ : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {}
+ ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I,
+ const COFFObjectFile *Owner)
+ : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {}
+
+ bool operator==(const ImportedSymbolRef &Other) const;
+ void moveNext();
+
+ std::error_code getSymbolName(StringRef &Result) const;
+ std::error_code getOrdinal(uint16_t &Result) const;
+
+private:
+ const import_lookup_table_entry32 *Entry32;
+ const import_lookup_table_entry64 *Entry64;
+ uint32_t Index;
+ const COFFObjectFile *OwningObject;
+};
+
+class BaseRelocRef {
+public:
+ BaseRelocRef() : OwningObject(nullptr) {}
+ BaseRelocRef(const coff_base_reloc_block_header *Header,
+ const COFFObjectFile *Owner)
+ : Header(Header), Index(0), OwningObject(Owner) {}
+
+ bool operator==(const BaseRelocRef &Other) const;
+ void moveNext();
+
+ std::error_code getType(uint8_t &Type) const;
+ std::error_code getRVA(uint32_t &Result) const;
+
+private:
+ const coff_base_reloc_block_header *Header;
+ uint32_t Index;
+ const COFFObjectFile *OwningObject;
+};
+
} // end namespace object
} // end namespace llvm
diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h
index 4aba08f75ddc..12a25223bd37 100644
--- a/include/llvm/Object/COFFYAML.h
+++ b/include/llvm/Object/COFFYAML.h
@@ -31,6 +31,12 @@ inline SectionCharacteristics operator|(SectionCharacteristics a,
uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b);
return static_cast<SectionCharacteristics>(Ret);
}
+
+inline DLLCharacteristics operator|(DLLCharacteristics a,
+ DLLCharacteristics b) {
+ uint16_t Ret = static_cast<uint16_t>(a) | static_cast<uint16_t>(b);
+ return static_cast<DLLCharacteristics>(Ret);
+}
}
// The structure of the yaml files is not an exact 1:1 match to COFF. In order
@@ -69,7 +75,13 @@ namespace COFFYAML {
Symbol();
};
+ struct PEHeader {
+ COFF::PE32Header Header;
+ Optional<COFF::DataDirectory> DataDirectories[COFF::NUM_DATA_DIRECTORIES];
+ };
+
struct Object {
+ Optional<PEHeader> OptionalHeader;
COFF::header Header;
std::vector<Section> Sections;
std::vector<Symbol> Symbols;
@@ -131,6 +143,11 @@ struct ScalarEnumerationTraits<COFF::RelocationTypeAMD64> {
};
template <>
+struct ScalarEnumerationTraits<COFF::WindowsSubsystem> {
+ static void enumeration(IO &IO, COFF::WindowsSubsystem &Value);
+};
+
+template <>
struct ScalarBitSetTraits<COFF::Characteristics> {
static void bitset(IO &IO, COFF::Characteristics &Value);
};
@@ -141,11 +158,26 @@ struct ScalarBitSetTraits<COFF::SectionCharacteristics> {
};
template <>
+struct ScalarBitSetTraits<COFF::DLLCharacteristics> {
+ static void bitset(IO &IO, COFF::DLLCharacteristics &Value);
+};
+
+template <>
struct MappingTraits<COFFYAML::Relocation> {
static void mapping(IO &IO, COFFYAML::Relocation &Rel);
};
template <>
+struct MappingTraits<COFFYAML::PEHeader> {
+ static void mapping(IO &IO, COFFYAML::PEHeader &PH);
+};
+
+template <>
+struct MappingTraits<COFF::DataDirectory> {
+ static void mapping(IO &IO, COFF::DataDirectory &DD);
+};
+
+template <>
struct MappingTraits<COFF::header> {
static void mapping(IO &IO, COFF::header &H);
};
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index fbc48e6d7218..7c10bbf6e5ab 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -540,7 +540,7 @@ ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const {
if (Sec->sh_offset + Sec->sh_size > Buf.size())
return object_error::parse_failed;
const uint8_t *Start = base() + Sec->sh_offset;
- return ArrayRef<uint8_t>(Start, Sec->sh_size);
+ return makeArrayRef(Start, Sec->sh_size);
}
template <class ELFT>
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 069f38112def..c2d6438f45ba 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_OBJECT_ELF_OBJECT_FILE_H
-#define LLVM_OBJECT_ELF_OBJECT_FILE_H
+#ifndef LLVM_OBJECT_ELFOBJECTFILE_H
+#define LLVM_OBJECT_ELFOBJECTFILE_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -35,8 +35,26 @@
namespace llvm {
namespace object {
-template <class ELFT>
-class ELFObjectFile : public ObjectFile {
+class ELFObjectFileBase : public ObjectFile {
+protected:
+ ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source);
+
+public:
+ virtual std::error_code getRelocationAddend(DataRefImpl Rel,
+ int64_t &Res) const = 0;
+ virtual std::pair<symbol_iterator, symbol_iterator>
+ getELFDynamicSymbolIterators() const = 0;
+
+ virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version,
+ bool &IsDefault) const = 0;
+
+ virtual uint64_t getSectionFlags(SectionRef Sec) const = 0;
+ virtual uint32_t getSectionType(SectionRef Sec) const = 0;
+
+ static inline bool classof(const Binary *v) { return v->isELF(); }
+};
+
+template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
public:
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
@@ -71,32 +89,19 @@ protected:
std::error_code getSymbolSection(DataRefImpl Symb,
section_iterator &Res) const override;
- std::error_code getLibraryNext(DataRefImpl Data,
- LibraryRef &Result) const override;
- std::error_code getLibraryPath(DataRefImpl Data,
- StringRef &Res) const override;
-
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
- std::error_code getSectionAddress(DataRefImpl Sec,
- uint64_t &Res) const override;
- std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override;
+ uint64_t getSectionAddress(DataRefImpl Sec) const override;
+ uint64_t getSectionSize(DataRefImpl Sec) const override;
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
- std::error_code getSectionAlignment(DataRefImpl Sec,
- uint64_t &Res) const override;
- std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionRequiredForExecution(DataRefImpl Sec,
- bool &Res) const override;
- std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionReadOnlyData(DataRefImpl Sec,
- bool &Res) const override;
- std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
- bool &Result) const override;
+ uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionText(DataRefImpl Sec) const override;
+ bool isSectionData(DataRefImpl Sec) const override;
+ bool isSectionBSS(DataRefImpl Sec) const override;
+ bool isSectionVirtual(DataRefImpl Sec) const override;
+ bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
section_iterator getRelocatedSection(DataRefImpl Sec) const override;
@@ -178,7 +183,7 @@ protected:
bool isDyldELFObject;
public:
- ELFObjectFile(std::unique_ptr<MemoryBuffer> Object, std::error_code &EC);
+ ELFObjectFile(MemoryBufferRef Object, std::error_code &EC);
const Elf_Sym *getSymbol(DataRefImpl Symb) const;
@@ -191,17 +196,18 @@ public:
section_iterator section_begin() const override;
section_iterator section_end() const override;
- library_iterator needed_library_begin() const override;
- library_iterator needed_library_end() const override;
-
- std::error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const;
+ std::error_code getRelocationAddend(DataRefImpl Rel,
+ int64_t &Res) const override;
std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version,
- bool &IsDefault) const;
+ bool &IsDefault) const override;
+
+ uint64_t getSectionFlags(SectionRef Sec) const override;
+ uint32_t getSectionType(SectionRef Sec) const override;
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
unsigned getArch() const override;
- StringRef getLoadName() const override;
+ StringRef getLoadName() const;
std::error_code getPlatformFlags(unsigned &Result) const override {
Result = EF.getHeader()->e_flags;
@@ -215,6 +221,11 @@ public:
return v->getType() == getELFType(ELFT::TargetEndianness == support::little,
ELFT::Is64Bits);
}
+
+ std::pair<symbol_iterator, symbol_iterator>
+ getELFDynamicSymbolIterators() const override;
+
+ bool isRelocatableObject() const override;
};
// Use an alignment of 2 for the typedefs since that is the worst case for
@@ -254,6 +265,18 @@ std::error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef,
}
template <class ELFT>
+uint64_t ELFObjectFile<ELFT>::getSectionFlags(SectionRef Sec) const {
+ DataRefImpl DRI = Sec.getRawDataRefImpl();
+ return toELFShdrIter(DRI)->sh_flags;
+}
+
+template <class ELFT>
+uint32_t ELFObjectFile<ELFT>::getSectionType(SectionRef Sec) const {
+ DataRefImpl DRI = Sec.getRawDataRefImpl();
+ return toELFShdrIter(DRI)->sh_type;
+}
+
+template <class ELFT>
std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
uint64_t &Result) const {
const Elf_Sym *ESym = getSymbol(Symb);
@@ -272,8 +295,9 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
const Elf_Ehdr *Header = EF.getHeader();
Result = ESym->st_value;
- // Clear the ARM/Thumb indicator flag.
- if (Header->e_machine == ELF::EM_ARM && ESym->getType() == ELF::STT_FUNC)
+ // Clear the ARM/Thumb or microMIPS indicator flag.
+ if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) &&
+ ESym->getType() == ELF::STT_FUNC)
Result &= ~1;
if (Header->e_type == ELF::ET_REL)
@@ -400,17 +424,13 @@ std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec,
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec,
- uint64_t &Result) const {
- Result = toELFShdrIter(Sec)->sh_addr;
- return object_error::success;
+uint64_t ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec) const {
+ return toELFShdrIter(Sec)->sh_addr;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec,
- uint64_t &Result) const {
- Result = toELFShdrIter(Sec)->sh_size;
- return object_error::success;
+uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const {
+ return toELFShdrIter(Sec)->sh_size;
}
template <class ELFT>
@@ -423,79 +443,43 @@ ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec,
- uint64_t &Result) const {
- Result = toELFShdrIter(Sec)->sh_addralign;
- return object_error::success;
+uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const {
+ return toELFShdrIter(Sec)->sh_addralign;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec,
- bool &Result) const {
- Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR;
- return object_error::success;
+bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
+ return toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec,
- bool &Result) const {
+bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const {
Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
- Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
- EShdr->sh_type == ELF::SHT_PROGBITS;
- return object_error::success;
+ return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
+ EShdr->sh_type == ELF::SHT_PROGBITS;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec,
- bool &Result) const {
+bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const {
Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
- Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
- EShdr->sh_type == ELF::SHT_NOBITS;
- return object_error::success;
-}
-
-template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::isSectionRequiredForExecution(DataRefImpl Sec,
- bool &Result) const {
- Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC;
- return object_error::success;
+ return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) &&
+ EShdr->sh_type == ELF::SHT_NOBITS;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec,
- bool &Result) const {
- Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS;
- return object_error::success;
+bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
+ return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec,
- bool &Result) const {
- Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS;
- return object_error::success;
-}
-
-template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec,
- bool &Result) const {
- Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
- Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR));
- return object_error::success;
-}
-
-template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec,
- DataRefImpl Symb,
- bool &Result) const {
+bool ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec,
+ DataRefImpl Symb) const {
Elf_Sym_Iter ESym = toELFSymIter(Symb);
uintX_t Index = ESym->st_shndx;
bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE;
- Result = !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx));
- return object_error::success;
+ return !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx));
}
template <class ELFT>
@@ -754,6 +738,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationValueString(
Result.append(fmtbuf.begin(), fmtbuf.end());
break;
}
+ case ELF::EM_386:
case ELF::EM_ARM:
case ELF::EM_HEXAGON:
case ELF::EM_MIPS:
@@ -786,13 +771,13 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
}
template <class ELFT>
-ELFObjectFile<ELFT>::ELFObjectFile(std::unique_ptr<MemoryBuffer> Object,
- std::error_code &EC)
- : ObjectFile(getELFType(static_cast<endianness>(ELFT::TargetEndianness) ==
- support::little,
- ELFT::Is64Bits),
- std::move(Object)),
- EF(Data->getBuffer(), EC) {}
+ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC)
+ : ELFObjectFileBase(
+ getELFType(static_cast<endianness>(ELFT::TargetEndianness) ==
+ support::little,
+ ELFT::Is64Bits),
+ Object),
+ EF(Data.getBuffer(), EC) {}
template <class ELFT>
basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin_impl() const {
@@ -838,50 +823,13 @@ StringRef ELFObjectFile<ELFT>::getLoadName() const {
}
template <class ELFT>
-library_iterator ELFObjectFile<ELFT>::needed_library_begin() const {
- Elf_Dyn_Iter DI = EF.begin_dynamic_table();
- Elf_Dyn_Iter DE = EF.end_dynamic_table();
-
- while (DI != DE && DI->getTag() != ELF::DT_SONAME)
- ++DI;
-
- return library_iterator(LibraryRef(toDRI(DI), this));
-}
-
-template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data,
- LibraryRef &Result) const {
- Elf_Dyn_Iter DI = toELFDynIter(Data);
- Elf_Dyn_Iter DE = EF.end_dynamic_table();
-
- // Skip to the next DT_NEEDED entry.
- do
- ++DI;
- while (DI != DE && DI->getTag() != ELF::DT_NEEDED);
-
- Result = LibraryRef(toDRI(DI), this);
- return object_error::success;
-}
-
-template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data,
- StringRef &Res) const {
- Res = EF.getDynamicString(toELFDynIter(Data)->getVal());
- return object_error::success;
-}
-
-template <class ELFT>
-library_iterator ELFObjectFile<ELFT>::needed_library_end() const {
- return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this));
-}
-
-template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const {
return ELFT::Is64Bits ? 8 : 4;
}
template <class ELFT>
StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
+ bool IsLittleEndian = ELFT::TargetEndianness == support::little;
switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) {
case ELF::ELFCLASS32:
switch (EF.getHeader()->e_machine) {
@@ -890,7 +838,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
case ELF::EM_X86_64:
return "ELF32-x86-64";
case ELF::EM_ARM:
- return "ELF32-arm";
+ return (IsLittleEndian ? "ELF32-arm-little" : "ELF32-arm-big");
case ELF::EM_HEXAGON:
return "ELF32-hexagon";
case ELF::EM_MIPS:
@@ -910,7 +858,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
case ELF::EM_X86_64:
return "ELF64-x86-64";
case ELF::EM_AARCH64:
- return "ELF64-aarch64";
+ return (IsLittleEndian ? "ELF64-aarch64-little" : "ELF64-aarch64-big");
case ELF::EM_PPC64:
return "ELF64-ppc64";
case ELF::EM_S390:
@@ -951,6 +899,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
default:
report_fatal_error("Invalid ELFCLASS!");
}
+ case ELF::EM_PPC:
+ return Triple::ppc;
case ELF::EM_PPC64:
return IsLittleEndian ? Triple::ppc64le : Triple::ppc64;
case ELF::EM_S390:
@@ -967,73 +917,34 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
}
}
-/// FIXME: Maybe we should have a base ElfObjectFile that is not a template
-/// and make these member functions?
+template <class ELFT>
+std::pair<symbol_iterator, symbol_iterator>
+ELFObjectFile<ELFT>::getELFDynamicSymbolIterators() const {
+ return std::make_pair(dynamic_symbol_begin(), dynamic_symbol_end());
+}
+
+template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const {
+ return EF.getHeader()->e_type == ELF::ET_REL;
+}
+
inline std::error_code getELFRelocationAddend(const RelocationRef R,
int64_t &Addend) {
const ObjectFile *Obj = R.getObjectFile();
DataRefImpl DRI = R.getRawDataRefImpl();
- // Little-endian 32-bit
- if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
- return ELFObj->getRelocationAddend(DRI, Addend);
-
- // Big-endian 32-bit
- if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
- return ELFObj->getRelocationAddend(DRI, Addend);
-
- // Little-endian 64-bit
- if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
- return ELFObj->getRelocationAddend(DRI, Addend);
-
- // Big-endian 64-bit
- if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
- return ELFObj->getRelocationAddend(DRI, Addend);
-
- llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF");
+ return cast<ELFObjectFileBase>(Obj)->getRelocationAddend(DRI, Addend);
}
inline std::pair<symbol_iterator, symbol_iterator>
-getELFDynamicSymbolIterators(SymbolicFile *Obj) {
- if (const ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj))
- return std::make_pair(ELF->dynamic_symbol_begin(),
- ELF->dynamic_symbol_end());
- if (const ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj))
- return std::make_pair(ELF->dynamic_symbol_begin(),
- ELF->dynamic_symbol_end());
- if (const ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj))
- return std::make_pair(ELF->dynamic_symbol_begin(),
- ELF->dynamic_symbol_end());
- if (const ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj))
- return std::make_pair(ELF->dynamic_symbol_begin(),
- ELF->dynamic_symbol_end());
-
- llvm_unreachable(
- "Object passed to getELFDynamicSymbolIterators() is not ELF");
+getELFDynamicSymbolIterators(const SymbolicFile *Obj) {
+ return cast<ELFObjectFileBase>(Obj)->getELFDynamicSymbolIterators();
}
-/// This is a generic interface for retrieving GNU symbol version
-/// information from an ELFObjectFile.
inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj,
const SymbolRef &Sym,
StringRef &Version,
bool &IsDefault) {
- // Little-endian 32-bit
- if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
- return ELFObj->getSymbolVersion(Sym, Version, IsDefault);
-
- // Big-endian 32-bit
- if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
- return ELFObj->getSymbolVersion(Sym, Version, IsDefault);
-
- // Little-endian 64-bit
- if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
- return ELFObj->getSymbolVersion(Sym, Version, IsDefault);
-
- // Big-endian 64-bit
- if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
- return ELFObj->getSymbolVersion(Sym, Version, IsDefault);
-
- llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF");
+ return cast<ELFObjectFileBase>(Obj)
+ ->getSymbolVersion(Sym, Version, IsDefault);
}
}
}
diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h
index 84b603125a69..4bc0c7c2016e 100644
--- a/include/llvm/Object/ELFTypes.h
+++ b/include/llvm/Object/ELFTypes.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_OBJECT_ELF_TYPES_H
-#define LLVM_OBJECT_ELF_TYPES_H
+#ifndef LLVM_OBJECT_ELFTYPES_H
+#define LLVM_OBJECT_ELFTYPES_H
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/DataTypes.h"
@@ -176,6 +176,7 @@ struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > {
template <class ELFT>
struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
using Elf_Sym_Base<ELFT>::st_info;
+ using Elf_Sym_Base<ELFT>::st_other;
// These accessors and mutators correspond to the ELF32_ST_BIND,
// ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification:
@@ -186,6 +187,9 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
void setBindingAndType(unsigned char b, unsigned char t) {
st_info = (b << 4) + (t & 0x0f);
}
+
+ /// Access to the STV_xxx flag stored in the first two bits of st_other.
+ unsigned char getVisibility() const { return st_other & 0x3; }
};
/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section
diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h
index fc8cc9581655..b71946d98b5d 100644
--- a/include/llvm/Object/ELFYAML.h
+++ b/include/llvm/Object/ELFYAML.h
@@ -40,11 +40,12 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI)
// Just use 64, since it can hold 32-bit values too.
LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)
-LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_REL)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL)
// Just use 64, since it can hold 32-bit values too.
LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV)
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO)
// For now, hardcode 64 bits everywhere that 32 or 64 would be needed
// since 64-bit can hold 32-bit values too.
@@ -63,7 +64,7 @@ struct Symbol {
StringRef Section;
llvm::yaml::Hex64 Value;
llvm::yaml::Hex64 Size;
- ELF_STV Visibility;
+ uint8_t Other;
};
struct LocalGlobalWeakSymbols {
std::vector<Symbol> Local;
@@ -175,6 +176,11 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_STV> {
};
template <>
+struct ScalarBitSetTraits<ELFYAML::ELF_STO> {
+ static void bitset(IO &IO, ELFYAML::ELF_STO &Value);
+};
+
+template <>
struct ScalarEnumerationTraits<ELFYAML::ELF_REL> {
static void enumeration(IO &IO, ELFYAML::ELF_REL &Value);
};
diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h
index 701da1272cd5..90c2bd74b43c 100644
--- a/include/llvm/Object/Error.h
+++ b/include/llvm/Object/Error.h
@@ -26,7 +26,8 @@ enum class object_error {
arch_not_found,
invalid_file_type,
parse_failed,
- unexpected_eof
+ unexpected_eof,
+ bitcode_section_not_found,
};
inline std::error_code make_error_code(object_error e) {
diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h
index b33cc263b9bd..74f46667ce64 100644
--- a/include/llvm/Object/IRObjectFile.h
+++ b/include/llvm/Object/IRObjectFile.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_OBJECT_IR_OBJECT_FILE_H
-#define LLVM_OBJECT_IR_OBJECT_FILE_H
+#ifndef LLVM_OBJECT_IROBJECTFILE_H
+#define LLVM_OBJECT_IROBJECTFILE_H
#include "llvm/Object/SymbolicFile.h"
@@ -22,19 +22,24 @@ class Module;
class GlobalValue;
namespace object {
+class ObjectFile;
+
class IRObjectFile : public SymbolicFile {
std::unique_ptr<Module> M;
std::unique_ptr<Mangler> Mang;
std::vector<std::pair<std::string, uint32_t>> AsmSymbols;
public:
- IRObjectFile(std::unique_ptr<MemoryBuffer> Object, std::unique_ptr<Module> M);
+ IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> M);
~IRObjectFile();
void moveSymbolNext(DataRefImpl &Symb) const override;
std::error_code printSymbolName(raw_ostream &OS,
DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
- const GlobalValue *getSymbolGV(DataRefImpl Symb) const;
+ GlobalValue *getSymbolGV(DataRefImpl Symb);
+ const GlobalValue *getSymbolGV(DataRefImpl Symb) const {
+ return const_cast<IRObjectFile *>(this)->getSymbolGV(Symb);
+ }
basic_symbol_iterator symbol_begin_impl() const override;
basic_symbol_iterator symbol_end_impl() const override;
@@ -44,14 +49,24 @@ public:
Module &getModule() {
return *M;
}
+ std::unique_ptr<Module> takeModule();
static inline bool classof(const Binary *v) {
return v->isIR();
}
- static ErrorOr<IRObjectFile *>
- createIRObjectFile(std::unique_ptr<MemoryBuffer> Object,
- LLVMContext &Context);
+ /// \brief Finds and returns bitcode embedded in the given object file, or an
+ /// error code if not found.
+ static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj);
+
+ /// \brief 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 ErrorOr<MemoryBufferRef>
+ findBitcodeInMemBuffer(MemoryBufferRef Object);
+
+ static ErrorOr<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object,
+ LLVMContext &Context);
};
}
}
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 4835eb80bd65..bee1f6ce0b01 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -49,6 +49,141 @@ public:
};
typedef content_iterator<DiceRef> dice_iterator;
+/// ExportEntry encapsulates the current-state-of-the-walk used when doing a
+/// non-recursive walk of the trie data structure. This allows you to iterate
+/// across all exported symbols using:
+/// for (const llvm::object::ExportEntry &AnExport : Obj->exports()) {
+/// }
+class ExportEntry {
+public:
+ ExportEntry(ArrayRef<uint8_t> Trie);
+
+ StringRef name() const;
+ uint64_t flags() const;
+ uint64_t address() const;
+ uint64_t other() const;
+ StringRef otherName() const;
+ uint32_t nodeOffset() const;
+
+ bool operator==(const ExportEntry &) const;
+
+ void moveNext();
+
+private:
+ friend class MachOObjectFile;
+ void moveToFirst();
+ void moveToEnd();
+ uint64_t readULEB128(const uint8_t *&p);
+ void pushDownUntilBottom();
+ void pushNode(uint64_t Offset);
+
+ // Represents a node in the mach-o exports trie.
+ struct NodeState {
+ NodeState(const uint8_t *Ptr);
+ const uint8_t *Start;
+ const uint8_t *Current;
+ uint64_t Flags;
+ uint64_t Address;
+ uint64_t Other;
+ const char *ImportName;
+ unsigned ChildCount;
+ unsigned NextChildIndex;
+ unsigned ParentStringLength;
+ bool IsExportNode;
+ };
+
+ ArrayRef<uint8_t> Trie;
+ SmallString<256> CumulativeString;
+ SmallVector<NodeState, 16> Stack;
+ bool Malformed;
+ bool Done;
+};
+typedef content_iterator<ExportEntry> export_iterator;
+
+/// MachORebaseEntry encapsulates the current state in the decompression of
+/// rebasing opcodes. This allows you to iterate through the compressed table of
+/// rebasing using:
+/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) {
+/// }
+class MachORebaseEntry {
+public:
+ MachORebaseEntry(ArrayRef<uint8_t> opcodes, bool is64Bit);
+
+ uint32_t segmentIndex() const;
+ uint64_t segmentOffset() const;
+ StringRef typeName() const;
+
+ bool operator==(const MachORebaseEntry &) const;
+
+ void moveNext();
+
+private:
+ friend class MachOObjectFile;
+ void moveToFirst();
+ void moveToEnd();
+ uint64_t readULEB128();
+
+ ArrayRef<uint8_t> Opcodes;
+ const uint8_t *Ptr;
+ uint64_t SegmentOffset;
+ uint32_t SegmentIndex;
+ uint64_t RemainingLoopCount;
+ uint64_t AdvanceAmount;
+ uint8_t RebaseType;
+ uint8_t PointerSize;
+ bool Malformed;
+ bool Done;
+};
+typedef content_iterator<MachORebaseEntry> rebase_iterator;
+
+/// MachOBindEntry encapsulates the current state in the decompression of
+/// binding opcodes. This allows you to iterate through the compressed table of
+/// bindings using:
+/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) {
+/// }
+class MachOBindEntry {
+public:
+ enum class Kind { Regular, Lazy, Weak };
+
+ MachOBindEntry(ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind);
+
+ uint32_t segmentIndex() const;
+ uint64_t segmentOffset() const;
+ StringRef typeName() const;
+ StringRef symbolName() const;
+ uint32_t flags() const;
+ int64_t addend() const;
+ int ordinal() const;
+
+ bool operator==(const MachOBindEntry &) const;
+
+ void moveNext();
+
+private:
+ friend class MachOObjectFile;
+ void moveToFirst();
+ void moveToEnd();
+ uint64_t readULEB128();
+ int64_t readSLEB128();
+
+ ArrayRef<uint8_t> Opcodes;
+ const uint8_t *Ptr;
+ uint64_t SegmentOffset;
+ uint32_t SegmentIndex;
+ StringRef SymbolName;
+ int Ordinal;
+ uint32_t Flags;
+ int64_t Addend;
+ uint64_t RemainingLoopCount;
+ uint64_t AdvanceAmount;
+ uint8_t BindType;
+ uint8_t PointerSize;
+ Kind TableKind;
+ bool Malformed;
+ bool Done;
+};
+typedef content_iterator<MachOBindEntry> bind_iterator;
+
class MachOObjectFile : public ObjectFile {
public:
struct LoadCommandInfo {
@@ -56,8 +191,8 @@ public:
MachO::load_command C; // The command itself.
};
- MachOObjectFile(std::unique_ptr<MemoryBuffer> Object, bool IsLittleEndian,
- bool Is64Bits, std::error_code &EC);
+ MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
+ std::error_code &EC);
void moveSymbolNext(DataRefImpl &Symb) const override;
std::error_code getSymbolName(DataRefImpl Symb,
@@ -65,6 +200,7 @@ public:
// MachO specific.
std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const;
+ unsigned getSectionType(SectionRef Sec) const;
std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const override;
@@ -80,24 +216,16 @@ public:
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
- std::error_code getSectionAddress(DataRefImpl Sec,
- uint64_t &Res) const override;
- std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override;
+ uint64_t getSectionAddress(DataRefImpl Sec) const override;
+ uint64_t getSectionSize(DataRefImpl Sec) const override;
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
- std::error_code getSectionAlignment(DataRefImpl Sec,
- uint64_t &Res) const override;
- std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionRequiredForExecution(DataRefImpl Sec,
- bool &Res) const override;
- std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override;
- std::error_code isSectionReadOnlyData(DataRefImpl Sec,
- bool &Res) const override;
- std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
- bool &Result) const override;
+ uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionText(DataRefImpl Sec) const override;
+ bool isSectionData(DataRefImpl Sec) const override;
+ bool isSectionBSS(DataRefImpl Sec) const override;
+ bool isSectionVirtual(DataRefImpl Sec) const override;
+ bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
@@ -118,13 +246,8 @@ public:
std::error_code getRelocationHidden(DataRefImpl Rel,
bool &Result) const override;
- std::error_code getLibraryNext(DataRefImpl LibData,
- LibraryRef &Res) const override;
- std::error_code getLibraryPath(DataRefImpl LibData,
- StringRef &Res) const override;
-
// MachO specific.
- std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &Res);
+ std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
// TODO: Would be useful to have an iterator based version
// of the load command interface too.
@@ -138,21 +261,45 @@ public:
section_iterator section_begin() const override;
section_iterator section_end() const override;
- library_iterator needed_library_begin() const override;
- library_iterator needed_library_end() const override;
-
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
unsigned getArch() const override;
-
- StringRef getLoadName() const override;
+ Triple getArch(const char **McpuDefault, Triple *ThumbTriple) const;
relocation_iterator section_rel_begin(unsigned Index) const;
relocation_iterator section_rel_end(unsigned Index) const;
dice_iterator begin_dices() const;
dice_iterator end_dices() const;
+
+ /// For use iterating over all exported symbols.
+ iterator_range<export_iterator> exports() const;
+
+ /// For use examining a trie not in a MachOObjectFile.
+ static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie);
+
+ /// For use iterating over all rebase table entries.
+ iterator_range<rebase_iterator> rebaseTable() const;
+
+ /// For use examining rebase opcodes not in a MachOObjectFile.
+ static iterator_range<rebase_iterator> rebaseTable(ArrayRef<uint8_t> Opcodes,
+ bool is64);
+
+ /// For use iterating over all bind table entries.
+ iterator_range<bind_iterator> bindTable() const;
+
+ /// For use iterating over all lazy bind table entries.
+ iterator_range<bind_iterator> lazyBindTable() const;
+
+ /// For use iterating over all lazy bind table entries.
+ iterator_range<bind_iterator> weakBindTable() const;
+
+ /// For use examining bind opcodes not in a MachOObjectFile.
+ static iterator_range<bind_iterator> bindTable(ArrayRef<uint8_t> Opcodes,
+ bool is64,
+ MachOBindEntry::Kind);
+
// 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
@@ -173,6 +320,8 @@ public:
const MachO::any_relocation_info &RE) const;
uint32_t getScatteredRelocationValue(
const MachO::any_relocation_info &RE) const;
+ uint32_t getScatteredRelocationType(
+ const MachO::any_relocation_info &RE) const;
unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const;
unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
@@ -197,12 +346,42 @@ public:
getSegmentLoadCommand(const LoadCommandInfo &L) const;
MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo &L) const;
- MachO::linker_options_command
- getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const;
+ MachO::linker_option_command
+ getLinkerOptionLoadCommand(const LoadCommandInfo &L) const;
MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo &L) const;
MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo &L) const;
+ MachO::dyld_info_command
+ getDyldInfoLoadCommand(const LoadCommandInfo &L) const;
+ MachO::dylinker_command
+ getDylinkerCommand(const LoadCommandInfo &L) const;
+ MachO::uuid_command
+ getUuidCommand(const LoadCommandInfo &L) const;
+ MachO::rpath_command
+ getRpathCommand(const LoadCommandInfo &L) const;
+ MachO::source_version_command
+ getSourceVersionCommand(const LoadCommandInfo &L) const;
+ MachO::entry_point_command
+ getEntryPointCommand(const LoadCommandInfo &L) const;
+ MachO::encryption_info_command
+ getEncryptionInfoCommand(const LoadCommandInfo &L) const;
+ MachO::encryption_info_command_64
+ getEncryptionInfoCommand64(const LoadCommandInfo &L) const;
+ MachO::sub_framework_command
+ getSubFrameworkCommand(const LoadCommandInfo &L) const;
+ MachO::sub_umbrella_command
+ getSubUmbrellaCommand(const LoadCommandInfo &L) const;
+ MachO::sub_library_command
+ getSubLibraryCommand(const LoadCommandInfo &L) const;
+ MachO::sub_client_command
+ getSubClientCommand(const LoadCommandInfo &L) const;
+ MachO::routines_command
+ getRoutinesCommand(const LoadCommandInfo &L) const;
+ MachO::routines_command_64
+ getRoutinesCommand64(const LoadCommandInfo &L) const;
+ MachO::thread_command
+ getThreadCommand(const LoadCommandInfo &L) const;
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const;
MachO::data_in_code_entry getDice(DataRefImpl Rel) const;
@@ -216,6 +395,12 @@ public:
MachO::symtab_command getSymtabLoadCommand() const;
MachO::dysymtab_command getDysymtabLoadCommand() const;
MachO::linkedit_data_command getDataInCodeLoadCommand() const;
+ ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const;
+ ArrayRef<uint8_t> getDyldInfoBindOpcodes() const;
+ ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;
+ ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const;
+ ArrayRef<uint8_t> getDyldInfoExportsTrie() const;
+ ArrayRef<uint8_t> getUuid() const;
StringRef getStringTableData() const;
bool is64Bit() const;
@@ -225,10 +410,19 @@ public:
StringRef &Suffix);
static Triple::ArchType getArch(uint32_t CPUType);
- static Triple getArch(uint32_t CPUType, uint32_t CPUSubType);
- static Triple getArch(StringRef ArchFlag);
+ static Triple getArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault = nullptr);
+ static Triple getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault = nullptr);
+ static Triple getArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault, Triple *ThumbTriple);
+ static bool isValidArch(StringRef ArchFlag);
static Triple getHostArch();
+ bool isRelocatableObject() const override;
+
+ bool hasPageZeroSegment() const { return HasPageZeroSegment; }
+
static bool classof(const Binary *v) {
return v->isMachO();
}
@@ -239,10 +433,13 @@ private:
typedef SmallVector<const char*, 1> LibraryList;
LibraryList Libraries;
typedef SmallVector<StringRef, 1> LibraryShortName;
- LibraryShortName LibrariesShortNames;
+ mutable LibraryShortName LibrariesShortNames;
const char *SymtabLoadCmd;
const char *DysymtabLoadCmd;
const char *DataInCodeLoadCmd;
+ const char *DyldInfoLoadCmd;
+ const char *UuidLoadCmd;
+ bool HasPageZeroSegment;
};
/// DiceRef
diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h
index e6677f5bf28b..93f665438821 100644
--- a/include/llvm/Object/MachOUniversal.h
+++ b/include/llvm/Object/MachOUniversal.h
@@ -16,8 +16,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Object/Binary.h"
#include "llvm/Object/Archive.h"
+#include "llvm/Object/Binary.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MachO.h"
@@ -25,8 +25,6 @@
namespace llvm {
namespace object {
-class ObjectFile;
-
class MachOUniversalBinary : public Binary {
virtual void anchor();
@@ -53,14 +51,18 @@ public:
ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
uint32_t getCPUType() const { return Header.cputype; }
+ uint32_t getCPUSubType() const { return Header.cpusubtype; }
+ uint32_t getOffset() const { return Header.offset; }
+ uint32_t getSize() const { return Header.size; }
+ uint32_t getAlign() const { return Header.align; }
std::string getArchTypeName() const {
Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype);
return T.getArchName();
}
- ErrorOr<std::unique_ptr<ObjectFile>> getAsObjectFile() const;
+ ErrorOr<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const;
- std::error_code getAsArchive(std::unique_ptr<Archive> &Result) const;
+ ErrorOr<std::unique_ptr<Archive>> getAsArchive() const;
};
class object_iterator {
@@ -84,10 +86,9 @@ public:
}
};
- MachOUniversalBinary(std::unique_ptr<MemoryBuffer> Source,
- std::error_code &ec);
- static ErrorOr<MachOUniversalBinary *>
- create(std::unique_ptr<MemoryBuffer> Source);
+ MachOUniversalBinary(MemoryBufferRef Souce, std::error_code &EC);
+ static ErrorOr<std::unique_ptr<MachOUniversalBinary>>
+ create(MemoryBufferRef Source);
object_iterator begin_objects() const {
return ObjectForArch(this, 0);
@@ -103,7 +104,7 @@ public:
return V->isMachOUniversalBinary();
}
- ErrorOr<std::unique_ptr<ObjectFile>>
+ ErrorOr<std::unique_ptr<MachOObjectFile>>
getObjectForArch(Triple::ArchType Arch) const;
};
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index a4370a3f30d0..6aa985d7e67b 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -27,6 +27,8 @@ namespace llvm {
namespace object {
class ObjectFile;
+class COFFObjectFile;
+class MachOObjectFile;
class SymbolRef;
class symbol_iterator;
@@ -93,23 +95,19 @@ public:
void moveNext();
std::error_code getName(StringRef &Result) const;
- std::error_code getAddress(uint64_t &Result) const;
- std::error_code getSize(uint64_t &Result) const;
+ uint64_t getAddress() const;
+ 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).
- std::error_code getAlignment(uint64_t &Result) const;
+ uint64_t getAlignment() const;
- // FIXME: Move to the normalization layer when it's created.
- std::error_code isText(bool &Result) const;
- std::error_code isData(bool &Result) const;
- std::error_code isBSS(bool &Result) const;
- std::error_code isRequiredForExecution(bool &Result) const;
- std::error_code isVirtual(bool &Result) const;
- std::error_code isZeroInit(bool &Result) const;
- std::error_code isReadOnlyData(bool &Result) const;
+ bool isText() const;
+ bool isData() const;
+ bool isBSS() const;
+ bool isVirtual() const;
- std::error_code containsSymbol(SymbolRef S, bool &Result) const;
+ bool containsSymbol(SymbolRef S) const;
relocation_iterator relocation_begin() const;
relocation_iterator relocation_end() const;
@@ -120,6 +118,7 @@ public:
section_iterator getRelocatedSection() const;
DataRefImpl getRawDataRefImpl() const;
+ const ObjectFile *getObject() const;
};
/// SymbolRef - This is a value type class that represents a single symbol in
@@ -176,30 +175,6 @@ public:
}
};
-/// LibraryRef - This is a value type class that represents a single library in
-/// the list of libraries needed by a shared or dynamic object.
-class LibraryRef {
- friend class SectionRef;
- DataRefImpl LibraryPimpl;
- const ObjectFile *OwningObject;
-
-public:
- LibraryRef() : OwningObject(nullptr) { }
-
- LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner);
-
- bool operator==(const LibraryRef &Other) const;
- bool operator<(const LibraryRef &Other) const;
-
- std::error_code getNext(LibraryRef &Result) const;
-
- // Get the path to this library, as stored in the object file.
- std::error_code getPath(StringRef &Result) const;
-
- DataRefImpl getRawDataRefImpl() const;
-};
-typedef content_iterator<LibraryRef> library_iterator;
-
/// ObjectFile - This class is the base class for all object file types.
/// Concrete instances of this object are created by createObjectFile, which
/// figures out which type to create.
@@ -209,10 +184,10 @@ class ObjectFile : public SymbolicFile {
ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION;
protected:
- ObjectFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source);
+ ObjectFile(unsigned int Type, MemoryBufferRef Source);
const uint8_t *base() const {
- return reinterpret_cast<const uint8_t *>(Data->getBufferStart());
+ return reinterpret_cast<const uint8_t *>(Data.getBufferStart());
}
// These functions are for SymbolRef to call internally. The main goal of
@@ -248,29 +223,18 @@ protected:
virtual void moveSectionNext(DataRefImpl &Sec) const = 0;
virtual std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const = 0;
- virtual std::error_code getSectionAddress(DataRefImpl Sec,
- uint64_t &Res) const = 0;
- virtual std::error_code getSectionSize(DataRefImpl Sec,
- uint64_t &Res) const = 0;
+ virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0;
+ virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0;
virtual std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const = 0;
- virtual std::error_code getSectionAlignment(DataRefImpl Sec,
- uint64_t &Res) const = 0;
- virtual std::error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0;
- virtual std::error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0;
- virtual std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const = 0;
- virtual std::error_code isSectionRequiredForExecution(DataRefImpl Sec,
- bool &Res) const = 0;
+ virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
+ virtual bool isSectionText(DataRefImpl Sec) const = 0;
+ virtual bool isSectionData(DataRefImpl Sec) const = 0;
+ virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
// A section is 'virtual' if its contents aren't present in the object image.
- virtual std::error_code isSectionVirtual(DataRefImpl Sec,
- bool &Res) const = 0;
- virtual std::error_code isSectionZeroInit(DataRefImpl Sec,
- bool &Res) const = 0;
- virtual std::error_code isSectionReadOnlyData(DataRefImpl Sec,
- bool &Res) const = 0;
- virtual std::error_code sectionContainsSymbol(DataRefImpl Sec,
- DataRefImpl Symb,
- bool &Result) const = 0;
+ virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
+ virtual bool sectionContainsSymbol(DataRefImpl Sec,
+ DataRefImpl Symb) const = 0;
virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
@@ -297,13 +261,6 @@ protected:
return object_error::success;
}
- // Same for LibraryRef
- friend class LibraryRef;
- virtual std::error_code getLibraryNext(DataRefImpl Lib,
- LibraryRef &Res) const = 0;
- virtual std::error_code getLibraryPath(DataRefImpl Lib,
- StringRef &Res) const = 0;
-
public:
typedef iterator_range<symbol_iterator> symbol_iterator_range;
symbol_iterator_range symbols() const {
@@ -318,9 +275,6 @@ public:
return section_iterator_range(section_begin(), section_end());
}
- virtual library_iterator needed_library_begin() const = 0;
- virtual library_iterator needed_library_end() const = 0;
-
/// @brief The number of bytes used to represent an address in this object
/// file format.
virtual uint8_t getBytesInAddress() const = 0;
@@ -328,27 +282,26 @@ public:
virtual StringRef getFileFormatName() const = 0;
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
- /// For shared objects, returns the name which this object should be
- /// loaded from at runtime. This corresponds to DT_SONAME on ELF and
- /// LC_ID_DYLIB (install name) on MachO.
- virtual StringRef getLoadName() const = 0;
-
/// Returns platform-specific object flags, if any.
virtual std::error_code getPlatformFlags(unsigned &Result) const {
Result = 0;
return object_error::invalid_file_type;
}
+ /// True if this is a relocatable object (.o/.obj).
+ virtual bool isRelocatableObject() const = 0;
+
/// @returns Pointer to ObjectFile subclass to handle this type of object.
/// @param ObjectPath The path to the object file. ObjectPath.isObject must
/// return true.
/// @brief Create ObjectFile from path.
- static ErrorOr<ObjectFile *> createObjectFile(StringRef ObjectPath);
- static ErrorOr<ObjectFile *>
- createObjectFile(std::unique_ptr<MemoryBuffer> &Object,
- sys::fs::file_magic Type);
- static ErrorOr<ObjectFile *>
- createObjectFile(std::unique_ptr<MemoryBuffer> &Object) {
+ static ErrorOr<OwningBinary<ObjectFile>>
+ createObjectFile(StringRef ObjectPath);
+
+ static ErrorOr<std::unique_ptr<ObjectFile>>
+ createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type);
+ static ErrorOr<std::unique_ptr<ObjectFile>>
+ createObjectFile(MemoryBufferRef Object) {
return createObjectFile(Object, sys::fs::file_magic::unknown);
}
@@ -357,13 +310,14 @@ public:
return v->isObject();
}
-public:
- static ErrorOr<ObjectFile *>
- createCOFFObjectFile(std::unique_ptr<MemoryBuffer> Object);
- static ErrorOr<ObjectFile *>
- createELFObjectFile(std::unique_ptr<MemoryBuffer> &Object);
- static ErrorOr<ObjectFile *>
- createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Object);
+ static ErrorOr<std::unique_ptr<COFFObjectFile>>
+ createCOFFObjectFile(MemoryBufferRef Object);
+
+ static ErrorOr<std::unique_ptr<ObjectFile>>
+ createELFObjectFile(MemoryBufferRef Object);
+
+ static ErrorOr<std::unique_ptr<MachOObjectFile>>
+ createMachOObjectFile(MemoryBufferRef Object);
};
// Inline function definitions.
@@ -430,54 +384,41 @@ inline std::error_code SectionRef::getName(StringRef &Result) const {
return OwningObject->getSectionName(SectionPimpl, Result);
}
-inline std::error_code SectionRef::getAddress(uint64_t &Result) const {
- return OwningObject->getSectionAddress(SectionPimpl, Result);
+inline uint64_t SectionRef::getAddress() const {
+ return OwningObject->getSectionAddress(SectionPimpl);
}
-inline std::error_code SectionRef::getSize(uint64_t &Result) const {
- return OwningObject->getSectionSize(SectionPimpl, Result);
+inline uint64_t SectionRef::getSize() const {
+ return OwningObject->getSectionSize(SectionPimpl);
}
inline std::error_code SectionRef::getContents(StringRef &Result) const {
return OwningObject->getSectionContents(SectionPimpl, Result);
}
-inline std::error_code SectionRef::getAlignment(uint64_t &Result) const {
- return OwningObject->getSectionAlignment(SectionPimpl, Result);
+inline uint64_t SectionRef::getAlignment() const {
+ return OwningObject->getSectionAlignment(SectionPimpl);
}
-inline std::error_code SectionRef::isText(bool &Result) const {
- return OwningObject->isSectionText(SectionPimpl, Result);
+inline bool SectionRef::isText() const {
+ return OwningObject->isSectionText(SectionPimpl);
}
-inline std::error_code SectionRef::isData(bool &Result) const {
- return OwningObject->isSectionData(SectionPimpl, Result);
+inline bool SectionRef::isData() const {
+ return OwningObject->isSectionData(SectionPimpl);
}
-inline std::error_code SectionRef::isBSS(bool &Result) const {
- return OwningObject->isSectionBSS(SectionPimpl, Result);
+inline bool SectionRef::isBSS() const {
+ return OwningObject->isSectionBSS(SectionPimpl);
}
-inline std::error_code SectionRef::isRequiredForExecution(bool &Result) const {
- return OwningObject->isSectionRequiredForExecution(SectionPimpl, Result);
+inline bool SectionRef::isVirtual() const {
+ return OwningObject->isSectionVirtual(SectionPimpl);
}
-inline std::error_code SectionRef::isVirtual(bool &Result) const {
- return OwningObject->isSectionVirtual(SectionPimpl, Result);
-}
-
-inline std::error_code SectionRef::isZeroInit(bool &Result) const {
- return OwningObject->isSectionZeroInit(SectionPimpl, Result);
-}
-
-inline std::error_code SectionRef::isReadOnlyData(bool &Result) const {
- return OwningObject->isSectionReadOnlyData(SectionPimpl, Result);
-}
-
-inline std::error_code SectionRef::containsSymbol(SymbolRef S,
- bool &Result) const {
+inline bool SectionRef::containsSymbol(SymbolRef S) const {
return OwningObject->sectionContainsSymbol(SectionPimpl,
- S.getRawDataRefImpl(), Result);
+ S.getRawDataRefImpl());
}
inline relocation_iterator SectionRef::relocation_begin() const {
@@ -496,6 +437,10 @@ inline DataRefImpl SectionRef::getRawDataRefImpl() const {
return SectionPimpl;
}
+inline const ObjectFile *SectionRef::getObject() const {
+ return OwningObject;
+}
+
/// RelocationRef
inline RelocationRef::RelocationRef(DataRefImpl RelocationP,
const ObjectFile *Owner)
@@ -548,26 +493,6 @@ inline const ObjectFile *RelocationRef::getObjectFile() const {
return OwningObject;
}
-// Inline function definitions.
-inline LibraryRef::LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner)
- : LibraryPimpl(LibraryP)
- , OwningObject(Owner) {}
-
-inline bool LibraryRef::operator==(const LibraryRef &Other) const {
- return LibraryPimpl == Other.LibraryPimpl;
-}
-
-inline bool LibraryRef::operator<(const LibraryRef &Other) const {
- return LibraryPimpl < Other.LibraryPimpl;
-}
-
-inline std::error_code LibraryRef::getNext(LibraryRef &Result) const {
- return OwningObject->getLibraryNext(LibraryPimpl, Result);
-}
-
-inline std::error_code LibraryRef::getPath(StringRef &Result) const {
- return OwningObject->getLibraryPath(LibraryPimpl, Result);
-}
} // end namespace object
} // end namespace llvm
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
index 5ca245057a55..91eafd55ad76 100644
--- a/include/llvm/Object/RelocVisitor.h
+++ b/include/llvm/Object/RelocVisitor.h
@@ -17,6 +17,7 @@
#define LLVM_OBJECT_RELOCVISITOR_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Debug.h"
@@ -40,22 +41,39 @@ struct RelocToApply {
/// @brief Base class for object file relocation visitors.
class RelocVisitor {
public:
- explicit RelocVisitor(StringRef FileFormat)
- : FileFormat(FileFormat), HasError(false) {}
+ explicit RelocVisitor(const ObjectFile &Obj)
+ : ObjToVisit(Obj), HasError(false) {}
// TODO: Should handle multiple applied relocations via either passing in the
// previously computed value or just count paired relocations as a single
// visit.
- RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0,
- uint64_t Value = 0) {
- if (FileFormat == "ELF64-x86-64") {
- switch (RelocType) {
+ RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
+ if (isa<ELFObjectFileBase>(ObjToVisit))
+ return visitELF(RelocType, R, Value);
+ if (isa<COFFObjectFile>(ObjToVisit))
+ return visitCOFF(RelocType, R, Value);
+
+ HasError = true;
+ return RelocToApply();
+ }
+
+ bool error() { return HasError; }
+
+private:
+ const ObjectFile &ObjToVisit;
+ bool HasError;
+
+ RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
+ if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
+ switch (ObjToVisit.getArch()) {
+ case Triple::x86_64:
+ switch (RelocType) {
case llvm::ELF::R_X86_64_NONE:
return visitELF_X86_64_NONE(R);
case llvm::ELF::R_X86_64_64:
return visitELF_X86_64_64(R, Value);
case llvm::ELF::R_X86_64_PC32:
- return visitELF_X86_64_PC32(R, Value, SecAddr);
+ return visitELF_X86_64_PC32(R, Value);
case llvm::ELF::R_X86_64_32:
return visitELF_X86_64_32(R, Value);
case llvm::ELF::R_X86_64_32S:
@@ -63,116 +81,147 @@ public:
default:
HasError = true;
return RelocToApply();
- }
- } else if (FileFormat == "ELF32-i386") {
- switch (RelocType) {
- case llvm::ELF::R_386_NONE:
- return visitELF_386_NONE(R);
- case llvm::ELF::R_386_32:
- return visitELF_386_32(R, Value);
- case llvm::ELF::R_386_PC32:
- return visitELF_386_PC32(R, Value, SecAddr);
- default:
- HasError = true;
- return RelocToApply();
- }
- } else if (FileFormat == "ELF64-ppc64") {
- switch (RelocType) {
- case llvm::ELF::R_PPC64_ADDR32:
- return visitELF_PPC64_ADDR32(R, Value);
- case llvm::ELF::R_PPC64_ADDR64:
- return visitELF_PPC64_ADDR64(R, Value);
- default:
- HasError = true;
- return RelocToApply();
- }
- } else if (FileFormat == "ELF32-ppc") {
- switch (RelocType) {
- case llvm::ELF::R_PPC_ADDR32:
- return visitELF_PPC_ADDR32(R, Value);
- default:
- HasError = true;
- return RelocToApply();
- }
- } else if (FileFormat == "ELF32-mips") {
- switch (RelocType) {
- case llvm::ELF::R_MIPS_32:
- return visitELF_MIPS_32(R, Value);
- default:
- HasError = true;
- return RelocToApply();
- }
- } else if (FileFormat == "ELF64-mips") {
- switch (RelocType) {
- case llvm::ELF::R_MIPS_32:
- return visitELF_MIPS_32(R, Value);
- case llvm::ELF::R_MIPS_64:
- return visitELF_MIPS_64(R, Value);
- default:
- HasError = true;
- return RelocToApply();
- }
- } else if (FileFormat == "ELF64-aarch64") {
- switch (RelocType) {
- case llvm::ELF::R_AARCH64_ABS32:
- return visitELF_AARCH64_ABS32(R, Value);
- case llvm::ELF::R_AARCH64_ABS64:
- return visitELF_AARCH64_ABS64(R, Value);
- default:
- HasError = true;
- return RelocToApply();
- }
- } else if (FileFormat == "ELF64-s390") {
- switch (RelocType) {
- case llvm::ELF::R_390_32:
- return visitELF_390_32(R, Value);
- case llvm::ELF::R_390_64:
- return visitELF_390_64(R, Value);
+ }
+ case Triple::aarch64:
+ switch (RelocType) {
+ case llvm::ELF::R_AARCH64_ABS32:
+ return visitELF_AARCH64_ABS32(R, Value);
+ case llvm::ELF::R_AARCH64_ABS64:
+ return visitELF_AARCH64_ABS64(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
+ case Triple::mips64el:
+ case Triple::mips64:
+ switch (RelocType) {
+ case llvm::ELF::R_MIPS_32:
+ return visitELF_MIPS_32(R, Value);
+ case llvm::ELF::R_MIPS_64:
+ return visitELF_MIPS_64(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
+ case Triple::ppc64le:
+ case Triple::ppc64:
+ switch (RelocType) {
+ case llvm::ELF::R_PPC64_ADDR32:
+ return visitELF_PPC64_ADDR32(R, Value);
+ case llvm::ELF::R_PPC64_ADDR64:
+ return visitELF_PPC64_ADDR64(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
+ case Triple::systemz:
+ switch (RelocType) {
+ case llvm::ELF::R_390_32:
+ return visitELF_390_32(R, Value);
+ case llvm::ELF::R_390_64:
+ return visitELF_390_64(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
+ case Triple::sparcv9:
+ switch (RelocType) {
+ case llvm::ELF::R_SPARC_32:
+ case llvm::ELF::R_SPARC_UA32:
+ return visitELF_SPARCV9_32(R, Value);
+ case llvm::ELF::R_SPARC_64:
+ case llvm::ELF::R_SPARC_UA64:
+ return visitELF_SPARCV9_64(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
default:
HasError = true;
return RelocToApply();
}
- } else if (FileFormat == "ELF32-sparc") {
- switch (RelocType) {
- case llvm::ELF::R_SPARC_32:
- case llvm::ELF::R_SPARC_UA32:
- return visitELF_SPARC_32(R, Value);
+ } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
+ switch (ObjToVisit.getArch()) {
+ case Triple::x86:
+ switch (RelocType) {
+ case llvm::ELF::R_386_NONE:
+ return visitELF_386_NONE(R);
+ case llvm::ELF::R_386_32:
+ return visitELF_386_32(R, Value);
+ case llvm::ELF::R_386_PC32:
+ return visitELF_386_PC32(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
+ case Triple::ppc:
+ switch (RelocType) {
+ case llvm::ELF::R_PPC_ADDR32:
+ return visitELF_PPC_ADDR32(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
+ case Triple::arm:
+ case Triple::armeb:
+ switch (RelocType) {
+ default:
+ HasError = true;
+ return RelocToApply();
+ case llvm::ELF::R_ARM_ABS32:
+ return visitELF_ARM_ABS32(R, Value);
+ }
+ case Triple::mipsel:
+ case Triple::mips:
+ switch (RelocType) {
+ case llvm::ELF::R_MIPS_32:
+ return visitELF_MIPS_32(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
+ case Triple::sparc:
+ switch (RelocType) {
+ case llvm::ELF::R_SPARC_32:
+ case llvm::ELF::R_SPARC_UA32:
+ return visitELF_SPARC_32(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
default:
HasError = true;
return RelocToApply();
}
- } else if (FileFormat == "ELF64-sparc") {
+ } else {
+ report_fatal_error("Invalid word size in object file");
+ }
+ }
+
+ RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
+ switch (ObjToVisit.getArch()) {
+ case Triple::x86:
switch (RelocType) {
- case llvm::ELF::R_SPARC_32:
- case llvm::ELF::R_SPARC_UA32:
- return visitELF_SPARCV9_32(R, Value);
- case llvm::ELF::R_SPARC_64:
- case llvm::ELF::R_SPARC_UA64:
- return visitELF_SPARCV9_64(R, Value);
- default:
- HasError = true;
- return RelocToApply();
+ case COFF::IMAGE_REL_I386_SECREL:
+ return visitCOFF_I386_SECREL(R, Value);
+ case COFF::IMAGE_REL_I386_DIR32:
+ return visitCOFF_I386_DIR32(R, Value);
}
- } else if (FileFormat == "ELF32-arm") {
+ break;
+ case Triple::x86_64:
switch (RelocType) {
- default:
- HasError = true;
- return RelocToApply();
- case llvm::ELF::R_ARM_ABS32:
- return visitELF_ARM_ABS32(R, Value);
+ case COFF::IMAGE_REL_AMD64_SECREL:
+ return visitCOFF_AMD64_SECREL(R, Value);
+ case COFF::IMAGE_REL_AMD64_ADDR64:
+ return visitCOFF_AMD64_ADDR64(R, Value);
}
+ break;
}
HasError = true;
return RelocToApply();
}
- bool error() { return HasError; }
-
-private:
- StringRef FileFormat;
- bool HasError;
-
- int64_t getAddend32LE(RelocationRef R) {
+ int64_t getELFAddend32LE(RelocationRef R) {
const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile());
DataRefImpl DRI = R.getRawDataRefImpl();
int64_t Addend;
@@ -180,7 +229,7 @@ private:
return Addend;
}
- int64_t getAddend64LE(RelocationRef R) {
+ int64_t getELFAddend64LE(RelocationRef R) {
const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile());
DataRefImpl DRI = R.getRawDataRefImpl();
int64_t Addend;
@@ -188,7 +237,7 @@ private:
return Addend;
}
- int64_t getAddend32BE(RelocationRef R) {
+ int64_t getELFAddend32BE(RelocationRef R) {
const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile());
DataRefImpl DRI = R.getRawDataRefImpl();
int64_t Addend;
@@ -196,7 +245,7 @@ private:
return Addend;
}
- int64_t getAddend64BE(RelocationRef R) {
+ int64_t getELFAddend64BE(RelocationRef R) {
const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile());
DataRefImpl DRI = R.getRawDataRefImpl();
int64_t Addend;
@@ -213,13 +262,12 @@ private:
// Ideally the Addend here will be the addend in the data for
// the relocation. It's not actually the case for Rel relocations.
RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend32LE(R);
+ int64_t Addend = getELFAddend32LE(R);
return RelocToApply(Value + Addend, 4);
}
- RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value,
- uint64_t SecAddr) {
- int64_t Addend = getAddend32LE(R);
+ RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) {
+ int64_t Addend = getELFAddend32LE(R);
uint64_t Address;
R.getOffset(Address);
return RelocToApply(Value + Addend - Address, 4);
@@ -230,23 +278,22 @@ private:
return RelocToApply(0, 0);
}
RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend64LE(R);
+ int64_t Addend = getELFAddend64LE(R);
return RelocToApply(Value + Addend, 8);
}
- RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value,
- uint64_t SecAddr) {
- int64_t Addend = getAddend64LE(R);
+ RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
+ int64_t Addend = getELFAddend64LE(R);
uint64_t Address;
R.getOffset(Address);
return RelocToApply(Value + Addend - Address, 4);
}
RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend64LE(R);
+ int64_t Addend = getELFAddend64LE(R);
uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
return RelocToApply(Res, 4);
}
RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend64LE(R);
+ int64_t Addend = getELFAddend64LE(R);
int32_t Res = (Value + Addend) & 0xFFFFFFFF;
return RelocToApply(Res, 4);
}
@@ -266,7 +313,7 @@ private:
/// PPC32 ELF
RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend32BE(R);
+ int64_t Addend = getELFAddend32BE(R);
uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
return RelocToApply(Res, 4);
}
@@ -288,7 +335,8 @@ private:
// AArch64 ELF
RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend64LE(R);
+ int64_t Addend;
+ getELFRelocationAddend(R, Addend);
int64_t Res = Value + Addend;
// Overflow check allows for both signed and unsigned interpretation.
@@ -299,13 +347,14 @@ private:
}
RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend64LE(R);
+ int64_t Addend;
+ getELFRelocationAddend(R, Addend);
return RelocToApply(Value + Addend, 8);
}
// SystemZ ELF
RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend64BE(R);
+ int64_t Addend = getELFAddend64BE(R);
int64_t Res = Value + Addend;
// Overflow check allows for both signed and unsigned interpretation.
@@ -316,30 +365,54 @@ private:
}
RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend64BE(R);
+ int64_t Addend = getELFAddend64BE(R);
return RelocToApply(Value + Addend, 8);
}
RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
- int32_t Addend = getAddend32BE(R);
+ int32_t Addend = getELFAddend32BE(R);
return RelocToApply(Value + Addend, 4);
}
RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
- int32_t Addend = getAddend64BE(R);
+ int32_t Addend = getELFAddend64BE(R);
return RelocToApply(Value + Addend, 4);
}
RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend64BE(R);
+ int64_t Addend = getELFAddend64BE(R);
return RelocToApply(Value + Addend, 8);
}
RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getAddend32LE(R);
- return RelocToApply(Value + Addend, 4);
+ int64_t Addend;
+ getELFRelocationAddend(R, Addend);
+ int64_t Res = Value + Addend;
+
+ // Overflow check allows for both signed and unsigned interpretation.
+ if (Res < INT32_MIN || Res > UINT32_MAX)
+ HasError = true;
+
+ return RelocToApply(static_cast<uint32_t>(Res), 4);
}
+ /// I386 COFF
+ RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
+ return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
+ }
+
+ RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
+ return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
+ }
+
+ /// AMD64 COFF
+ RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
+ return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
+ }
+
+ RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
+ return RelocToApply(Value, /*Width=*/8);
+ }
};
}
diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h
index 77eef4a546aa..435799a34ebc 100644
--- a/include/llvm/Object/SymbolicFile.h
+++ b/include/llvm/Object/SymbolicFile.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_OBJECT_SYMBOLIC_FILE_H
-#define LLVM_OBJECT_SYMBOLIC_FILE_H
+#ifndef LLVM_OBJECT_SYMBOLICFILE_H
+#define LLVM_OBJECT_SYMBOLICFILE_H
#include "llvm/Object/Binary.h"
@@ -87,8 +87,9 @@ public:
SF_Absolute = 1U << 3, // Absolute symbol
SF_Common = 1U << 4, // Symbol has common linkage
SF_Indirect = 1U << 5, // Symbol is an alias to another symbol
- SF_FormatSpecific = 1U << 6 // Specific to the object file format
+ SF_FormatSpecific = 1U << 6, // Specific to the object file format
// (e.g. section symbols)
+ SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary
};
BasicSymbolRef() : OwningObject(nullptr) { }
@@ -115,7 +116,7 @@ const uint64_t UnknownAddressOrSize = ~0ULL;
class SymbolicFile : public Binary {
public:
virtual ~SymbolicFile();
- SymbolicFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source);
+ SymbolicFile(unsigned int Type, MemoryBufferRef Source);
// virtual interface.
virtual void moveSymbolNext(DataRefImpl &Symb) const = 0;
@@ -142,15 +143,16 @@ public:
}
// construction aux.
- static ErrorOr<SymbolicFile *>
- createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object,
- sys::fs::file_magic Type, LLVMContext *Context);
+ static ErrorOr<std::unique_ptr<SymbolicFile>>
+ createSymbolicFile(MemoryBufferRef Object, sys::fs::file_magic Type,
+ LLVMContext *Context);
- static ErrorOr<SymbolicFile *>
- createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object) {
+ static ErrorOr<std::unique_ptr<SymbolicFile>>
+ createSymbolicFile(MemoryBufferRef Object) {
return createSymbolicFile(Object, sys::fs::file_magic::unknown, nullptr);
}
- static ErrorOr<SymbolicFile *> createSymbolicFile(StringRef ObjectPath);
+ static ErrorOr<OwningBinary<SymbolicFile>>
+ createSymbolicFile(StringRef ObjectPath);
static inline bool classof(const Binary *v) {
return v->isSymbolic();
diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h
index d46b0e892faf..3f8547e7fe41 100644
--- a/include/llvm/Option/ArgList.h
+++ b/include/llvm/Option/ArgList.h
@@ -187,6 +187,7 @@ public:
///
/// \p Claim Whether the argument should be claimed, if it exists.
Arg *getLastArgNoClaim(OptSpecifier Id) const;
+ Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1) const;
Arg *getLastArg(OptSpecifier Id) const;
Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const;
Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const;
diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h
index 1558c51bde48..8c28ef5e7e61 100644
--- a/include/llvm/PassRegistry.h
+++ b/include/llvm/PassRegistry.h
@@ -42,61 +42,51 @@ class PassRegistry {
mutable sys::SmartRWMutex<true> Lock;
/// PassInfoMap - Keep track of the PassInfo object for each registered pass.
- typedef DenseMap<const void*, const PassInfo*> MapType;
+ typedef DenseMap<const void *, const PassInfo *> MapType;
MapType PassInfoMap;
-
- typedef StringMap<const PassInfo*> StringMapType;
+
+ typedef StringMap<const PassInfo *> StringMapType;
StringMapType PassInfoStringMap;
-
- /// AnalysisGroupInfo - Keep track of information for each analysis group.
- struct AnalysisGroupInfo {
- SmallPtrSet<const PassInfo *, 8> Implementations;
- };
- DenseMap<const PassInfo*, AnalysisGroupInfo> AnalysisGroupInfoMap;
-
+
std::vector<std::unique_ptr<const PassInfo>> ToFree;
- std::vector<PassRegistrationListener*> Listeners;
-
+ std::vector<PassRegistrationListener *> Listeners;
+
public:
- PassRegistry() { }
+ PassRegistry() {}
~PassRegistry();
-
- /// getPassRegistry - Access the global registry object, which is
+
+ /// getPassRegistry - Access the global registry object, which is
/// automatically initialized at application launch and destroyed by
/// llvm_shutdown.
static PassRegistry *getPassRegistry();
-
+
/// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass'
/// type identifier (&MyPass::ID).
const PassInfo *getPassInfo(const void *TI) const;
-
+
/// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass'
/// argument string.
const PassInfo *getPassInfo(StringRef Arg) const;
-
- /// registerPass - Register a pass (by means of its PassInfo) with the
+
+ /// registerPass - Register a pass (by means of its PassInfo) with the
/// registry. Required in order to use the pass with a PassManager.
void registerPass(const PassInfo &PI, bool ShouldFree = false);
-
- /// registerPass - Unregister a pass (by means of its PassInfo) with the
- /// registry.
- void unregisterPass(const PassInfo &PI);
-
+
/// registerAnalysisGroup - Register an analysis group (or a pass implementing
- // an analysis group) with the registry. Like registerPass, this is required
+ // an analysis group) with the registry. Like registerPass, this is required
// in order for a PassManager to be able to use this group/pass.
void registerAnalysisGroup(const void *InterfaceID, const void *PassID,
- PassInfo& Registeree, bool isDefault,
+ PassInfo &Registeree, bool isDefault,
bool ShouldFree = false);
-
+
/// enumerateWith - Enumerate the registered passes, calling the provided
/// PassRegistrationListener's passEnumerate() callback on each of them.
void enumerateWith(PassRegistrationListener *L);
-
+
/// addRegistrationListener - Register the given PassRegistrationListener
/// to receive passRegistered() callbacks whenever a new pass is registered.
void addRegistrationListener(PassRegistrationListener *L);
-
+
/// removeRegistrationListener - Unregister a PassRegistrationListener so that
/// it no longer receives passRegistered() callbacks.
void removeRegistrationListener(PassRegistrationListener *L);
diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h
index 449bc9281084..6cb6516412e8 100644
--- a/include/llvm/PassSupport.h
+++ b/include/llvm/PassSupport.h
@@ -82,6 +82,15 @@ class TargetMachine;
CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
}
+#define INITIALIZE_PASS_WITH_OPTIONS(PassName, Arg, Name, Cfg, Analysis) \
+ INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \
+ PassName::registerOptions(); \
+ INITIALIZE_PASS_END(PassName, Arg, Name, Cfg, Analysis)
+
+#define INITIALIZE_PASS_WITH_OPTIONS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \
+ INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \
+ PassName::registerOptions(); \
+
template<typename PassName>
Pass *callDefaultCtor() { return new PassName(); }
diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h
new file mode 100644
index 000000000000..38fc8ca7c77c
--- /dev/null
+++ b/include/llvm/ProfileData/CoverageMapping.h
@@ -0,0 +1,448 @@
+//=-- CoverageMapping.h - Code coverage mapping support ---------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Code coverage mapping data is generated by clang and read by
+// llvm-cov to show code coverage statistics for a file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PROFILEDATA_COVERAGEMAPPING_H_
+#define LLVM_PROFILEDATA_COVERAGEMAPPING_H_
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/raw_ostream.h"
+#include <system_error>
+
+namespace llvm {
+class IndexedInstrProfReader;
+namespace coverage {
+
+class ObjectFileCoverageMappingReader;
+
+class CoverageMapping;
+struct CounterExpressions;
+
+enum CoverageMappingVersion { CoverageMappingVersion1 };
+
+/// \brief A Counter is an abstract value that describes how to compute the
+/// execution count for a region of code using the collected profile count data.
+struct Counter {
+ enum CounterKind { Zero, CounterValueReference, Expression };
+ static const unsigned EncodingTagBits = 2;
+ static const unsigned EncodingTagMask = 0x3;
+ static const unsigned EncodingCounterTagAndExpansionRegionTagBits =
+ EncodingTagBits + 1;
+
+private:
+ CounterKind Kind;
+ unsigned ID;
+
+ Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
+
+public:
+ Counter() : Kind(Zero), ID(0) {}
+
+ CounterKind getKind() const { return Kind; }
+
+ bool isZero() const { return Kind == Zero; }
+
+ bool isExpression() const { return Kind == Expression; }
+
+ unsigned getCounterID() const { return ID; }
+
+ unsigned getExpressionID() const { return ID; }
+
+ bool operator==(const Counter &Other) const {
+ return Kind == Other.Kind && ID == Other.ID;
+ }
+
+ friend bool operator<(const Counter &LHS, const Counter &RHS) {
+ return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID);
+ }
+
+ /// \brief Return the counter that represents the number zero.
+ static Counter getZero() { return Counter(); }
+
+ /// \brief Return the counter that corresponds to a specific profile counter.
+ static Counter getCounter(unsigned CounterId) {
+ return Counter(CounterValueReference, CounterId);
+ }
+
+ /// \brief Return the counter that corresponds to a specific
+ /// addition counter expression.
+ static Counter getExpression(unsigned ExpressionId) {
+ return Counter(Expression, ExpressionId);
+ }
+};
+
+/// \brief A Counter expression is a value that represents an arithmetic
+/// operation with two counters.
+struct CounterExpression {
+ enum ExprKind { Subtract, Add };
+ ExprKind Kind;
+ Counter LHS, RHS;
+
+ CounterExpression(ExprKind Kind, Counter LHS, Counter RHS)
+ : Kind(Kind), LHS(LHS), RHS(RHS) {}
+};
+
+/// \brief A Counter expression builder is used to construct the
+/// counter expressions. It avoids unecessary duplication
+/// and simplifies algebraic expressions.
+class CounterExpressionBuilder {
+ /// \brief A list of all the counter expressions
+ std::vector<CounterExpression> Expressions;
+ /// \brief A lookup table for the index of a given expression.
+ llvm::DenseMap<CounterExpression, unsigned> ExpressionIndices;
+
+ /// \brief Return the counter which corresponds to the given expression.
+ ///
+ /// If the given expression is already stored in the builder, a counter
+ /// that references that expression is returned. Otherwise, the given
+ /// expression is added to the builder's collection of expressions.
+ Counter get(const CounterExpression &E);
+
+ /// \brief Gather the terms of the expression tree for processing.
+ ///
+ /// This collects each addition and subtraction referenced by the counter into
+ /// a sequence that can be sorted and combined to build a simplified counter
+ /// expression.
+ void extractTerms(Counter C, int Sign,
+ SmallVectorImpl<std::pair<unsigned, int>> &Terms);
+
+ /// \brief Simplifies the given expression tree
+ /// by getting rid of algebraically redundant operations.
+ Counter simplify(Counter ExpressionTree);
+
+public:
+ ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
+
+ /// \brief Return a counter that represents the expression
+ /// that adds LHS and RHS.
+ Counter add(Counter LHS, Counter RHS);
+
+ /// \brief Return a counter that represents the expression
+ /// that subtracts RHS from LHS.
+ Counter subtract(Counter LHS, Counter RHS);
+};
+
+/// \brief A Counter mapping region associates a source range with
+/// a specific counter.
+struct CounterMappingRegion {
+ enum RegionKind {
+ /// \brief A CodeRegion associates some code with a counter
+ CodeRegion,
+
+ /// \brief An ExpansionRegion represents a file expansion region that
+ /// associates a source range with the expansion of a virtual source file,
+ /// such as for a macro instantiation or #include file.
+ ExpansionRegion,
+
+ /// \brief A SkippedRegion represents a source range with code that
+ /// was skipped by a preprocessor or similar means.
+ SkippedRegion
+ };
+
+ static const unsigned EncodingHasCodeBeforeBits = 1;
+
+ Counter Count;
+ unsigned FileID, ExpandedFileID;
+ unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
+ RegionKind Kind;
+ /// \brief A flag that is set to true when there is already code before
+ /// this region on the same line.
+ /// This is useful to accurately compute the execution counts for a line.
+ bool HasCodeBefore;
+
+ CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart,
+ unsigned ColumnStart, unsigned LineEnd,
+ unsigned ColumnEnd, bool HasCodeBefore = false,
+ RegionKind Kind = CodeRegion)
+ : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart),
+ ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
+ Kind(Kind), HasCodeBefore(HasCodeBefore) {}
+
+ inline std::pair<unsigned, unsigned> startLoc() const {
+ return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
+ }
+
+ inline std::pair<unsigned, unsigned> endLoc() const {
+ return std::pair<unsigned, unsigned>(LineEnd, ColumnEnd);
+ }
+
+ bool operator<(const CounterMappingRegion &Other) const {
+ if (FileID != Other.FileID)
+ return FileID < Other.FileID;
+ return startLoc() < Other.startLoc();
+ }
+
+ bool contains(const CounterMappingRegion &Other) const {
+ if (FileID != Other.FileID)
+ return false;
+ if (startLoc() > Other.startLoc())
+ return false;
+ if (endLoc() < Other.endLoc())
+ return false;
+ return true;
+ }
+};
+
+/// \brief Associates a source range with an execution count.
+struct CountedRegion : public CounterMappingRegion {
+ uint64_t ExecutionCount;
+
+ CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
+ : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {}
+};
+
+/// \brief A Counter mapping context is used to connect the counters,
+/// expressions and the obtained counter values.
+class CounterMappingContext {
+ ArrayRef<CounterExpression> Expressions;
+ ArrayRef<uint64_t> CounterValues;
+
+public:
+ CounterMappingContext(ArrayRef<CounterExpression> Expressions,
+ ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>())
+ : Expressions(Expressions), CounterValues(CounterValues) {}
+
+ void dump(const Counter &C, llvm::raw_ostream &OS) const;
+ void dump(const Counter &C) const { dump(C, llvm::outs()); }
+
+ /// \brief Return the number of times that a region of code associated with
+ /// this counter was executed.
+ ErrorOr<int64_t> evaluate(const Counter &C) const;
+};
+
+/// \brief Code coverage information for a single function.
+struct FunctionRecord {
+ /// \brief Raw function name.
+ std::string Name;
+ /// \brief Associated files.
+ std::vector<std::string> Filenames;
+ /// \brief Regions in the function along with their counts.
+ std::vector<CountedRegion> CountedRegions;
+ /// \brief The number of times this function was executed.
+ uint64_t ExecutionCount;
+
+ FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames,
+ uint64_t ExecutionCount)
+ : Name(Name), Filenames(Filenames.begin(), Filenames.end()),
+ ExecutionCount(ExecutionCount) {}
+};
+
+/// \brief Iterator over Functions, optionally filtered to a single file.
+class FunctionRecordIterator
+ : public iterator_facade_base<FunctionRecordIterator,
+ std::forward_iterator_tag, FunctionRecord> {
+ ArrayRef<FunctionRecord> Records;
+ ArrayRef<FunctionRecord>::iterator Current;
+ StringRef Filename;
+
+ /// \brief Skip records whose primary file is not \c Filename.
+ void skipOtherFiles();
+
+public:
+ FunctionRecordIterator(ArrayRef<FunctionRecord> Records_,
+ StringRef Filename = "")
+ : Records(Records_), Current(Records.begin()), Filename(Filename) {
+ skipOtherFiles();
+ }
+
+ FunctionRecordIterator() : Current(Records.begin()) {}
+
+ bool operator==(const FunctionRecordIterator &RHS) const {
+ return Current == RHS.Current && Filename == RHS.Filename;
+ }
+
+ const FunctionRecord &operator*() const { return *Current; }
+
+ FunctionRecordIterator &operator++() {
+ assert(Current != Records.end() && "incremented past end");
+ ++Current;
+ skipOtherFiles();
+ return *this;
+ }
+};
+
+/// \brief Coverage information for a macro expansion or #included file.
+///
+/// When covered code has pieces that can be expanded for more detail, such as a
+/// preprocessor macro use and its definition, these are represented as
+/// expansions whose coverage can be looked up independently.
+struct ExpansionRecord {
+ /// \brief The abstract file this expansion covers.
+ unsigned FileID;
+ /// \brief The region that expands to this record.
+ const CountedRegion &Region;
+ /// \brief Coverage for the expansion.
+ const FunctionRecord &Function;
+
+ ExpansionRecord(const CountedRegion &Region,
+ const FunctionRecord &Function)
+ : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
+};
+
+/// \brief The execution count information starting at a point in a file.
+///
+/// A sequence of CoverageSegments gives execution counts for a file in format
+/// that's simple to iterate through for processing.
+struct CoverageSegment {
+ /// \brief The line where this segment begins.
+ unsigned Line;
+ /// \brief The column where this segment begins.
+ unsigned Col;
+ /// \brief The execution count, or zero if no count was recorded.
+ uint64_t Count;
+ /// \brief When false, the segment was uninstrumented or skipped.
+ bool HasCount;
+ /// \brief Whether this enters a new region or returns to a previous count.
+ bool IsRegionEntry;
+
+ CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
+ : Line(Line), Col(Col), Count(0), HasCount(false),
+ IsRegionEntry(IsRegionEntry) {}
+ void setCount(uint64_t NewCount) {
+ Count = NewCount;
+ HasCount = true;
+ }
+ void addCount(uint64_t NewCount) { setCount(Count + NewCount); }
+};
+
+/// \brief Coverage information to be processed or displayed.
+///
+/// This represents the coverage of an entire file, expansion, or function. It
+/// provides a sequence of CoverageSegments to iterate through, as well as the
+/// list of expansions that can be further processed.
+class CoverageData {
+ std::string Filename;
+ std::vector<CoverageSegment> Segments;
+ std::vector<ExpansionRecord> Expansions;
+ friend class CoverageMapping;
+
+public:
+ CoverageData() {}
+
+ CoverageData(StringRef Filename) : Filename(Filename) {}
+
+ CoverageData(CoverageData &&RHS)
+ : Filename(std::move(RHS.Filename)), Segments(std::move(RHS.Segments)),
+ Expansions(std::move(RHS.Expansions)) {}
+
+ /// \brief Get the name of the file this data covers.
+ StringRef getFilename() { return Filename; }
+
+ std::vector<CoverageSegment>::iterator begin() { return Segments.begin(); }
+ std::vector<CoverageSegment>::iterator end() { return Segments.end(); }
+ bool empty() { return Segments.empty(); }
+
+ /// \brief Expansions that can be further processed.
+ std::vector<ExpansionRecord> getExpansions() { return Expansions; }
+};
+
+/// \brief The mapping of profile information to coverage data.
+///
+/// This is the main interface to get coverage information, using a profile to
+/// fill out execution counts.
+class CoverageMapping {
+ std::vector<FunctionRecord> Functions;
+ unsigned MismatchedFunctionCount;
+
+ CoverageMapping() : MismatchedFunctionCount(0) {}
+
+public:
+ /// \brief Load the coverage mapping using the given readers.
+ static ErrorOr<std::unique_ptr<CoverageMapping>>
+ load(ObjectFileCoverageMappingReader &CoverageReader,
+ IndexedInstrProfReader &ProfileReader);
+
+ /// \brief Load the coverage mapping from the given files.
+ static ErrorOr<std::unique_ptr<CoverageMapping>>
+ load(StringRef ObjectFilename, StringRef ProfileFilename);
+
+ /// \brief The number of functions that couldn't have their profiles mapped.
+ ///
+ /// This is a count of functions whose profile is out of date or otherwise
+ /// can't be associated with any coverage information.
+ unsigned getMismatchedCount() { return MismatchedFunctionCount; }
+
+ /// \brief Returns the list of files that are covered.
+ std::vector<StringRef> getUniqueSourceFiles() const;
+
+ /// \brief Get the coverage for a particular file.
+ ///
+ /// The given filename must be the name as recorded in the coverage
+ /// information. That is, only names returned from getUniqueSourceFiles will
+ /// yield a result.
+ CoverageData getCoverageForFile(StringRef Filename);
+
+ /// \brief Gets all of the functions covered by this profile.
+ iterator_range<FunctionRecordIterator> getCoveredFunctions() const {
+ return make_range(FunctionRecordIterator(Functions),
+ FunctionRecordIterator());
+ }
+
+ /// \brief Gets all of the functions in a particular file.
+ iterator_range<FunctionRecordIterator>
+ getCoveredFunctions(StringRef Filename) const {
+ return make_range(FunctionRecordIterator(Functions, Filename),
+ FunctionRecordIterator());
+ }
+
+ /// \brief Get the list of function instantiations in the file.
+ ///
+ /// Fucntions that are instantiated more than once, such as C++ template
+ /// specializations, have distinct coverage records for each instantiation.
+ std::vector<const FunctionRecord *> getInstantiations(StringRef Filename);
+
+ /// \brief Get the coverage for a particular function.
+ CoverageData getCoverageForFunction(const FunctionRecord &Function);
+
+ /// \brief Get the coverage for an expansion within a coverage set.
+ CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion);
+};
+
+} // end namespace coverage
+
+/// \brief Provide DenseMapInfo for CounterExpression
+template<> struct DenseMapInfo<coverage::CounterExpression> {
+ static inline coverage::CounterExpression getEmptyKey() {
+ using namespace coverage;
+ return CounterExpression(CounterExpression::ExprKind::Subtract,
+ Counter::getCounter(~0U),
+ Counter::getCounter(~0U));
+ }
+
+ static inline coverage::CounterExpression getTombstoneKey() {
+ using namespace coverage;
+ return CounterExpression(CounterExpression::ExprKind::Add,
+ Counter::getCounter(~0U),
+ Counter::getCounter(~0U));
+ }
+
+ static unsigned getHashValue(const coverage::CounterExpression &V) {
+ return static_cast<unsigned>(
+ hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(),
+ V.RHS.getKind(), V.RHS.getCounterID()));
+ }
+
+ static bool isEqual(const coverage::CounterExpression &LHS,
+ const coverage::CounterExpression &RHS) {
+ return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS;
+ }
+};
+
+
+} // end namespace llvm
+
+#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_
diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h
new file mode 100644
index 000000000000..5a6b44b8d9ef
--- /dev/null
+++ b/include/llvm/ProfileData/CoverageMappingReader.h
@@ -0,0 +1,208 @@
+//=-- CoverageMappingReader.h - Code coverage mapping reader ------*- 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 reading coverage mapping data for
+// instrumentation based coverage.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H
+#define LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/ProfileData/CoverageMapping.h"
+#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <iterator>
+
+namespace llvm {
+namespace coverage {
+
+class ObjectFileCoverageMappingReader;
+
+/// \brief Coverage mapping information for a single function.
+struct CoverageMappingRecord {
+ StringRef FunctionName;
+ uint64_t FunctionHash;
+ ArrayRef<StringRef> Filenames;
+ ArrayRef<CounterExpression> Expressions;
+ ArrayRef<CounterMappingRegion> MappingRegions;
+};
+
+/// \brief A file format agnostic iterator over coverage mapping data.
+class CoverageMappingIterator
+ : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> {
+ ObjectFileCoverageMappingReader *Reader;
+ CoverageMappingRecord Record;
+
+ void increment();
+
+public:
+ CoverageMappingIterator() : Reader(nullptr) {}
+ CoverageMappingIterator(ObjectFileCoverageMappingReader *Reader)
+ : Reader(Reader) {
+ increment();
+ }
+
+ CoverageMappingIterator &operator++() {
+ increment();
+ return *this;
+ }
+ bool operator==(const CoverageMappingIterator &RHS) {
+ return Reader == RHS.Reader;
+ }
+ bool operator!=(const CoverageMappingIterator &RHS) {
+ return Reader != RHS.Reader;
+ }
+ CoverageMappingRecord &operator*() { return Record; }
+ CoverageMappingRecord *operator->() { return &Record; }
+};
+
+/// \brief Base class for the raw coverage mapping and filenames data readers.
+class RawCoverageReader {
+protected:
+ StringRef Data;
+
+ /// \brief Return the error code.
+ std::error_code error(std::error_code EC) { return EC; }
+
+ /// \brief Clear the current error code and return a successful one.
+ std::error_code success() { return error(instrprof_error::success); }
+
+ RawCoverageReader(StringRef Data) : Data(Data) {}
+
+ std::error_code readULEB128(uint64_t &Result);
+ std::error_code readIntMax(uint64_t &Result, uint64_t MaxPlus1);
+ std::error_code readSize(uint64_t &Result);
+ std::error_code readString(StringRef &Result);
+};
+
+/// \brief Reader for the raw coverage filenames.
+class RawCoverageFilenamesReader : public RawCoverageReader {
+ std::vector<StringRef> &Filenames;
+
+ RawCoverageFilenamesReader(const RawCoverageFilenamesReader &)
+ LLVM_DELETED_FUNCTION;
+ RawCoverageFilenamesReader &
+ operator=(const RawCoverageFilenamesReader &) LLVM_DELETED_FUNCTION;
+
+public:
+ RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
+ : RawCoverageReader(Data), Filenames(Filenames) {}
+
+ std::error_code read();
+};
+
+/// \brief Reader for the raw coverage mapping data.
+class RawCoverageMappingReader : public RawCoverageReader {
+ StringRef FunctionName;
+ ArrayRef<StringRef> TranslationUnitFilenames;
+ std::vector<StringRef> &Filenames;
+ std::vector<CounterExpression> &Expressions;
+ std::vector<CounterMappingRegion> &MappingRegions;
+
+ RawCoverageMappingReader(const RawCoverageMappingReader &)
+ LLVM_DELETED_FUNCTION;
+ RawCoverageMappingReader &
+ operator=(const RawCoverageMappingReader &) LLVM_DELETED_FUNCTION;
+
+public:
+ RawCoverageMappingReader(StringRef FunctionName, StringRef MappingData,
+ ArrayRef<StringRef> TranslationUnitFilenames,
+ std::vector<StringRef> &Filenames,
+ std::vector<CounterExpression> &Expressions,
+ std::vector<CounterMappingRegion> &MappingRegions)
+ : RawCoverageReader(MappingData), FunctionName(FunctionName),
+ TranslationUnitFilenames(TranslationUnitFilenames),
+ Filenames(Filenames), Expressions(Expressions),
+ MappingRegions(MappingRegions) {}
+
+ std::error_code read(CoverageMappingRecord &Record);
+
+private:
+ std::error_code decodeCounter(unsigned Value, Counter &C);
+ std::error_code readCounter(Counter &C);
+ std::error_code
+ readMappingRegionsSubArray(std::vector<CounterMappingRegion> &MappingRegions,
+ unsigned InferredFileID, size_t NumFileIDs);
+};
+
+/// \brief Reader for the coverage mapping data that is emitted by the
+/// frontend and stored in an object file.
+class ObjectFileCoverageMappingReader {
+public:
+ struct ProfileMappingRecord {
+ CoverageMappingVersion Version;
+ StringRef FunctionName;
+ uint64_t FunctionHash;
+ StringRef CoverageMapping;
+ size_t FilenamesBegin;
+ size_t FilenamesSize;
+
+ ProfileMappingRecord(CoverageMappingVersion Version, StringRef FunctionName,
+ uint64_t FunctionHash, StringRef CoverageMapping,
+ size_t FilenamesBegin, size_t FilenamesSize)
+ : Version(Version), FunctionName(FunctionName),
+ FunctionHash(FunctionHash), CoverageMapping(CoverageMapping),
+ FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {}
+ };
+
+private:
+ std::error_code LastError;
+ object::OwningBinary<object::ObjectFile> Object;
+ std::vector<StringRef> Filenames;
+ std::vector<ProfileMappingRecord> MappingRecords;
+ size_t CurrentRecord;
+ std::vector<StringRef> FunctionsFilenames;
+ std::vector<CounterExpression> Expressions;
+ std::vector<CounterMappingRegion> MappingRegions;
+
+ ObjectFileCoverageMappingReader(const ObjectFileCoverageMappingReader &)
+ LLVM_DELETED_FUNCTION;
+ ObjectFileCoverageMappingReader &
+ operator=(const ObjectFileCoverageMappingReader &) LLVM_DELETED_FUNCTION;
+
+ /// \brief Set the current error_code and return same.
+ std::error_code error(std::error_code EC) {
+ LastError = EC;
+ return EC;
+ }
+
+ /// \brief Clear the current error code and return a successful one.
+ std::error_code success() { return error(instrprof_error::success); }
+
+public:
+ ObjectFileCoverageMappingReader(StringRef FileName);
+ ObjectFileCoverageMappingReader(
+ std::unique_ptr<MemoryBuffer> &ObjectBuffer,
+ sys::fs::file_magic Type = sys::fs::file_magic::unknown);
+
+ std::error_code readHeader();
+ std::error_code readNextRecord(CoverageMappingRecord &Record);
+
+ /// Iterator over profile data.
+ CoverageMappingIterator begin() { return CoverageMappingIterator(this); }
+ CoverageMappingIterator end() { return CoverageMappingIterator(); }
+
+ /// \brief Return true if the reader has finished reading the profile data.
+ bool isEOF() { return LastError == instrprof_error::eof; }
+ /// \brief Return true if the reader encountered an error reading profiling
+ /// data.
+ bool hasError() { return LastError && !isEOF(); }
+ /// \brief Get the current error code.
+ std::error_code getError() { return LastError; }
+};
+
+} // end namespace coverage
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/ProfileData/CoverageMappingWriter.h b/include/llvm/ProfileData/CoverageMappingWriter.h
new file mode 100644
index 000000000000..2e3b0378d032
--- /dev/null
+++ b/include/llvm/ProfileData/CoverageMappingWriter.h
@@ -0,0 +1,63 @@
+//=-- CoverageMappingWriter.h - Code coverage mapping writer ------*- 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 coverage mapping data for
+// instrumentation based coverage.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H
+#define LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ProfileData/CoverageMapping.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace coverage {
+
+/// \brief Writer of the filenames section for the instrumentation
+/// based code coverage.
+class CoverageFilenamesSectionWriter {
+ ArrayRef<StringRef> Filenames;
+
+public:
+ CoverageFilenamesSectionWriter(ArrayRef<StringRef> Filenames)
+ : Filenames(Filenames) {}
+
+ /// \brief Write encoded filenames to the given output stream.
+ void write(raw_ostream &OS);
+};
+
+/// \brief Writer for instrumentation based coverage mapping data.
+class CoverageMappingWriter {
+ ArrayRef<unsigned> VirtualFileMapping;
+ ArrayRef<CounterExpression> Expressions;
+ MutableArrayRef<CounterMappingRegion> MappingRegions;
+
+public:
+ CoverageMappingWriter(ArrayRef<unsigned> VirtualFileMapping,
+ ArrayRef<CounterExpression> Expressions,
+ MutableArrayRef<CounterMappingRegion> MappingRegions)
+ : VirtualFileMapping(VirtualFileMapping), Expressions(Expressions),
+ MappingRegions(MappingRegions) {}
+
+ CoverageMappingWriter(ArrayRef<CounterExpression> Expressions,
+ MutableArrayRef<CounterMappingRegion> MappingRegions)
+ : Expressions(Expressions), MappingRegions(MappingRegions) {}
+
+ /// \brief Write encoded coverage mapping data to the given output stream.
+ void write(raw_ostream &OS);
+};
+
+} // end namespace coverage
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h
index 7a5a71dc6a31..9655d66edc92 100644
--- a/include/llvm/ProfileData/InstrProfReader.h
+++ b/include/llvm/ProfileData/InstrProfReader.h
@@ -12,17 +12,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_INSTRPROF_READER_H_
-#define LLVM_PROFILEDATA_INSTRPROF_READER_H_
+#ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H
+#define LLVM_PROFILEDATA_INSTRPROFREADER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/EndianStream.h"
#include "llvm/Support/OnDiskHashTable.h"
-
#include <iterator>
namespace llvm {
@@ -94,8 +94,7 @@ public:
/// Factory method to create an appropriately typed reader for the given
/// instrprof file.
- static std::error_code create(std::string Path,
- std::unique_ptr<InstrProfReader> &Result);
+ static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path);
};
/// Reader for the simple text based instrprof format.
@@ -120,7 +119,7 @@ private:
LLVM_DELETED_FUNCTION;
public:
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
- : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, '#') {}
+ : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
/// Read the header.
std::error_code readHeader() override { return success(); }
@@ -206,12 +205,17 @@ enum class HashT : uint32_t;
/// Trait for lookups into the on-disk hash table for the binary instrprof
/// format.
class InstrProfLookupTrait {
- std::vector<uint64_t> CountBuffer;
+ std::vector<uint64_t> DataBuffer;
IndexedInstrProf::HashT HashType;
public:
InstrProfLookupTrait(IndexedInstrProf::HashT HashType) : HashType(HashType) {}
- typedef InstrProfRecord data_type;
+ struct data_type {
+ data_type(StringRef Name, ArrayRef<uint64_t> Data)
+ : Name(Name), Data(Data) {}
+ StringRef Name;
+ ArrayRef<uint64_t> Data;
+ };
typedef StringRef internal_key_type;
typedef StringRef external_key_type;
typedef uint64_t hash_value_type;
@@ -234,25 +238,20 @@ public:
return StringRef((const char *)D, N);
}
- InstrProfRecord ReadData(StringRef K, const unsigned char *D, offset_type N) {
- if (N < 2 * sizeof(uint64_t) || N % sizeof(uint64_t)) {
+ data_type ReadData(StringRef K, const unsigned char *D, offset_type N) {
+ DataBuffer.clear();
+ if (N % sizeof(uint64_t))
// The data is corrupt, don't try to read it.
- CountBuffer.clear();
- return InstrProfRecord("", 0, CountBuffer);
- }
+ return data_type("", DataBuffer);
using namespace support;
-
- // The first stored value is the hash.
- uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
- // Each counter follows.
- unsigned NumCounters = N / sizeof(uint64_t) - 1;
- CountBuffer.clear();
- CountBuffer.reserve(NumCounters - 1);
- for (unsigned I = 0; I < NumCounters; ++I)
- CountBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
-
- return InstrProfRecord(K, Hash, CountBuffer);
+ // We just treat the data as opaque here. It's simpler to handle in
+ // IndexedInstrProfReader.
+ unsigned NumEntries = N / sizeof(uint64_t);
+ DataBuffer.reserve(NumEntries);
+ for (unsigned I = 0; I < NumEntries; ++I)
+ DataBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
+ return data_type(K, DataBuffer);
}
};
typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait>
@@ -267,7 +266,11 @@ private:
std::unique_ptr<InstrProfReaderIndex> Index;
/// Iterator over the profile data.
InstrProfReaderIndex::data_iterator RecordIterator;
- /// The maximal execution count among all fucntions.
+ /// Offset into our current data set.
+ size_t CurrentOffset;
+ /// The file format version of the profile data.
+ uint64_t FormatVersion;
+ /// The maximal execution count among all functions.
uint64_t MaxFunctionCount;
IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION;
@@ -275,8 +278,7 @@ private:
LLVM_DELETED_FUNCTION;
public:
IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
- : DataBuffer(std::move(DataBuffer)), Index(nullptr),
- RecordIterator(InstrProfReaderIndex::data_iterator()) {}
+ : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {}
/// Return true if the given buffer is in an indexed instrprof format.
static bool hasFormat(const MemoryBuffer &DataBuffer);
@@ -287,7 +289,7 @@ public:
std::error_code readNextRecord(InstrProfRecord &Record) override;
/// Fill Counts with the profile data for the given function name.
- std::error_code getFunctionCounts(StringRef FuncName, uint64_t &FuncHash,
+ std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
std::vector<uint64_t> &Counts);
/// Return the maximum of all known function counts.
uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
@@ -299,4 +301,4 @@ public:
} // end namespace llvm
-#endif // LLVM_PROFILEDATA_INSTRPROF_READER_H_
+#endif
diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h
index 6e68bee30eb8..a23c56772a2f 100644
--- a/include/llvm/ProfileData/InstrProfWriter.h
+++ b/include/llvm/ProfileData/InstrProfWriter.h
@@ -12,15 +12,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_INSTRPROF_WRITER_H_
-#define LLVM_PROFILEDATA_INSTRPROF_WRITER_H_
+#ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H
+#define LLVM_PROFILEDATA_INSTRPROFWRITER_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/raw_ostream.h"
-
#include <vector>
namespace llvm {
@@ -28,13 +28,13 @@ namespace llvm {
/// Writer for instrumentation based profile data.
class InstrProfWriter {
public:
- struct CounterData {
- uint64_t Hash;
- std::vector<uint64_t> Counts;
- };
+ typedef SmallDenseMap<uint64_t, std::vector<uint64_t>, 1> CounterData;
private:
StringMap<CounterData> FunctionData;
+ uint64_t MaxFunctionCount;
public:
+ InstrProfWriter() : MaxFunctionCount(0) {}
+
/// Add function counts for the given function. If there are already counts
/// for this function and the hash and number of counts match, each counter is
/// summed.
@@ -47,4 +47,4 @@ public:
} // end namespace llvm
-#endif // LLVM_PROFILE_INSTRPROF_WRITER_H_
+#endif
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h
new file mode 100644
index 000000000000..df0a055c2a79
--- /dev/null
+++ b/include/llvm/ProfileData/SampleProf.h
@@ -0,0 +1,247 @@
+//=-- SampleProf.h - Sampling profiling format support --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains common definitions used in the reading and writing of
+// sample profile data.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H_
+#define LLVM_PROFILEDATA_SAMPLEPROF_H_
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <system_error>
+
+namespace llvm {
+
+const std::error_category &sampleprof_category();
+
+enum class sampleprof_error {
+ success = 0,
+ bad_magic,
+ unsupported_version,
+ too_large,
+ truncated,
+ malformed,
+ unrecognized_format
+};
+
+inline std::error_code make_error_code(sampleprof_error E) {
+ return std::error_code(static_cast<int>(E), sampleprof_category());
+}
+
+} // end namespace llvm
+
+namespace std {
+template <>
+struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {};
+}
+
+namespace llvm {
+
+namespace sampleprof {
+
+static inline uint64_t SPMagic() {
+ 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);
+}
+
+static inline uint64_t SPVersion() { return 100; }
+
+/// \brief Represents the relative location of an instruction.
+///
+/// Instruction locations are specified by the line offset from the
+/// beginning of the function (marked by the line where the function
+/// header is) and the discriminator value within that line.
+///
+/// The discriminator value is useful to distinguish instructions
+/// that are on the same line but belong to different basic blocks
+/// (e.g., the two post-increment instructions in "if (p) x++; else y++;").
+struct LineLocation {
+ LineLocation(int L, unsigned D) : LineOffset(L), Discriminator(D) {}
+ int LineOffset;
+ unsigned Discriminator;
+};
+
+} // End namespace sampleprof
+
+template <> struct DenseMapInfo<sampleprof::LineLocation> {
+ typedef DenseMapInfo<int> OffsetInfo;
+ typedef DenseMapInfo<unsigned> DiscriminatorInfo;
+ static inline sampleprof::LineLocation getEmptyKey() {
+ return sampleprof::LineLocation(OffsetInfo::getEmptyKey(),
+ DiscriminatorInfo::getEmptyKey());
+ }
+ static inline sampleprof::LineLocation getTombstoneKey() {
+ return sampleprof::LineLocation(OffsetInfo::getTombstoneKey(),
+ DiscriminatorInfo::getTombstoneKey());
+ }
+ static inline unsigned getHashValue(sampleprof::LineLocation Val) {
+ return DenseMapInfo<std::pair<int, unsigned>>::getHashValue(
+ std::pair<int, unsigned>(Val.LineOffset, Val.Discriminator));
+ }
+ static inline bool isEqual(sampleprof::LineLocation LHS,
+ sampleprof::LineLocation RHS) {
+ return LHS.LineOffset == RHS.LineOffset &&
+ LHS.Discriminator == RHS.Discriminator;
+ }
+};
+
+namespace sampleprof {
+
+/// \brief Representation of a single sample record.
+///
+/// A sample record is represented by a positive integer value, which
+/// indicates how frequently was the associated line location executed.
+///
+/// Additionally, if the associated location contains a function call,
+/// the record will hold a list of all the possible called targets. For
+/// direct calls, this will be the exact function being invoked. For
+/// indirect calls (function pointers, virtual table dispatch), this
+/// will be a list of one or more functions.
+class SampleRecord {
+public:
+ typedef StringMap<unsigned> CallTargetMap;
+
+ SampleRecord() : NumSamples(0), CallTargets() {}
+
+ /// \brief Increment the number of samples for this record by \p S.
+ ///
+ /// Sample counts accumulate using saturating arithmetic, to avoid wrapping
+ /// around unsigned integers.
+ void addSamples(unsigned S) {
+ if (NumSamples <= std::numeric_limits<unsigned>::max() - S)
+ NumSamples += S;
+ else
+ NumSamples = std::numeric_limits<unsigned>::max();
+ }
+
+ /// \brief Add called function \p F with samples \p S.
+ ///
+ /// Sample counts accumulate using saturating arithmetic, to avoid wrapping
+ /// around unsigned integers.
+ void addCalledTarget(StringRef F, unsigned S) {
+ unsigned &TargetSamples = CallTargets[F];
+ if (TargetSamples <= std::numeric_limits<unsigned>::max() - S)
+ TargetSamples += S;
+ else
+ TargetSamples = std::numeric_limits<unsigned>::max();
+ }
+
+ /// \brief Return true if this sample record contains function calls.
+ bool hasCalls() const { return CallTargets.size() > 0; }
+
+ unsigned getSamples() const { return NumSamples; }
+ const CallTargetMap &getCallTargets() const { return CallTargets; }
+
+ /// \brief Merge the samples in \p Other into this record.
+ void merge(const SampleRecord &Other) {
+ addSamples(Other.getSamples());
+ for (const auto &I : Other.getCallTargets())
+ addCalledTarget(I.first(), I.second);
+ }
+
+private:
+ unsigned NumSamples;
+ CallTargetMap CallTargets;
+};
+
+typedef DenseMap<LineLocation, SampleRecord> BodySampleMap;
+
+/// \brief Representation of the samples collected for a function.
+///
+/// This data structure contains all the collected samples for the body
+/// of a function. Each sample corresponds to a LineLocation instance
+/// within the body of the function.
+class FunctionSamples {
+public:
+ FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {}
+ void print(raw_ostream &OS = dbgs());
+ void addTotalSamples(unsigned Num) { TotalSamples += Num; }
+ void addHeadSamples(unsigned Num) { TotalHeadSamples += Num; }
+ void addBodySamples(int LineOffset, unsigned Discriminator, unsigned Num) {
+ assert(LineOffset >= 0);
+ // When dealing with instruction weights, we use the value
+ // zero to indicate the absence of a sample. If we read an
+ // actual zero from the profile file, use the value 1 to
+ // avoid the confusion later on.
+ if (Num == 0)
+ Num = 1;
+ BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(Num);
+ }
+ void addCalledTargetSamples(int LineOffset, unsigned Discriminator,
+ std::string FName, unsigned Num) {
+ assert(LineOffset >= 0);
+ BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(FName,
+ Num);
+ }
+
+ /// \brief Return the sample record at the given location.
+ /// Each location is specified by \p LineOffset and \p Discriminator.
+ SampleRecord &sampleRecordAt(const LineLocation &Loc) {
+ return BodySamples[Loc];
+ }
+
+ /// \brief Return the number of samples collected at the given location.
+ /// Each location is specified by \p LineOffset and \p Discriminator.
+ unsigned samplesAt(int LineOffset, unsigned Discriminator) {
+ return sampleRecordAt(LineLocation(LineOffset, Discriminator)).getSamples();
+ }
+
+ bool empty() const { return BodySamples.empty(); }
+
+ /// \brief Return the total number of samples collected inside the function.
+ unsigned getTotalSamples() const { return TotalSamples; }
+
+ /// \brief Return the total number of samples collected at the head of the
+ /// function.
+ unsigned getHeadSamples() const { return TotalHeadSamples; }
+
+ /// \brief Return all the samples collected in the body of the function.
+ const BodySampleMap &getBodySamples() const { return BodySamples; }
+
+ /// \brief Merge the samples in \p Other into this one.
+ void merge(const FunctionSamples &Other) {
+ addTotalSamples(Other.getTotalSamples());
+ addHeadSamples(Other.getHeadSamples());
+ for (const auto &I : Other.getBodySamples()) {
+ const LineLocation &Loc = I.first;
+ const SampleRecord &Rec = I.second;
+ sampleRecordAt(Loc).merge(Rec);
+ }
+ }
+
+private:
+ /// \brief Total number of samples collected inside this function.
+ ///
+ /// Samples are cumulative, they include all the samples collected
+ /// inside this function and all its inlined callees.
+ unsigned TotalSamples;
+
+ /// \brief Total number of samples collected at the head of the function.
+ unsigned TotalHeadSamples;
+
+ /// \brief Map instruction locations to collected samples.
+ ///
+ /// Each entry in this map contains the number of samples
+ /// collected at the corresponding line offset. All line locations
+ /// are an offset from the start of the function.
+ BodySampleMap BodySamples;
+};
+
+} // End namespace sampleprof
+
+} // End namespace llvm
+
+#endif // LLVM_PROFILEDATA_SAMPLEPROF_H_
diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h
new file mode 100644
index 000000000000..c082a1abe951
--- /dev/null
+++ b/include/llvm/ProfileData/SampleProfReader.h
@@ -0,0 +1,170 @@
+//===- SampleProfReader.h - Read LLVM sample profile data -----------------===//
+//
+// 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 needed for reading sample profiles.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H
+#define LLVM_PROFILEDATA_SAMPLEPROFREADER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/ProfileData/SampleProf.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+namespace sampleprof {
+
+/// \brief Sample-based profile reader.
+///
+/// Each profile contains sample counts for all the functions
+/// executed. Inside each function, statements are annotated with the
+/// collected samples on all the instructions associated with that
+/// statement.
+///
+/// For this to produce meaningful data, the program needs to be
+/// compiled with some debug information (at minimum, line numbers:
+/// -gline-tables-only). Otherwise, it will be impossible to match IR
+/// instructions to the line numbers collected by the profiler.
+///
+/// From the profile file, we are interested in collecting the
+/// following information:
+///
+/// * A list of functions included in the profile (mangled names).
+///
+/// * For each function F:
+/// 1. The total number of samples collected in F.
+///
+/// 2. The samples collected at each line in F. To provide some
+/// protection against source code shuffling, line numbers should
+/// be relative to the start of the function.
+///
+/// The reader supports two file formats: text and binary. The text format
+/// is useful for debugging and testing, while the binary format is more
+/// compact. 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)) {}
+
+ virtual ~SampleProfileReader() {}
+
+ /// \brief Read and validate the file header.
+ virtual std::error_code readHeader() = 0;
+
+ /// \brief Read sample profiles from the associated file.
+ virtual std::error_code read() = 0;
+
+ /// \brief 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.
+ void dump(raw_ostream &OS = dbgs());
+
+ /// \brief Return the samples collected for function \p F.
+ FunctionSamples *getSamplesFor(const Function &F) {
+ return &Profiles[F.getName()];
+ }
+
+ /// \brief Return all the profiles.
+ StringMap<FunctionSamples> &getProfiles() { return Profiles; }
+
+ /// \brief Report a parse error message.
+ void reportParseError(int64_t LineNumber, Twine Msg) const {
+ Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(),
+ LineNumber, Msg));
+ }
+
+ /// \brief Create a sample profile reader appropriate to the file format.
+ static ErrorOr<std::unique_ptr<SampleProfileReader>>
+ create(StringRef Filename, LLVMContext &C);
+
+protected:
+ /// \brief 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.
+ LLVMContext &Ctx;
+
+ /// \brief Memory buffer holding the profile file.
+ std::unique_ptr<MemoryBuffer> Buffer;
+};
+
+class SampleProfileReaderText : public SampleProfileReader {
+public:
+ SampleProfileReaderText(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
+ : SampleProfileReader(std::move(B), C) {}
+
+ /// \brief Read and validate the file header.
+ std::error_code readHeader() override { return sampleprof_error::success; }
+
+ /// \brief Read sample profiles from the associated file.
+ std::error_code read() override;
+};
+
+class SampleProfileReaderBinary : public SampleProfileReader {
+public:
+ SampleProfileReaderBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
+ : SampleProfileReader(std::move(B), C), Data(nullptr), End(nullptr) {}
+
+ /// \brief Read and validate the file header.
+ std::error_code readHeader() override;
+
+ /// \brief 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.
+ ///
+ /// If an error occurs during decoding, a diagnostic message is emitted and
+ /// EC is set.
+ ///
+ /// \returns the read value.
+ template <typename T> ErrorOr<T> readNumber();
+
+ /// \brief Read a string from the profile.
+ ///
+ /// If an error occurs during decoding, a diagnostic message is emitted and
+ /// EC is set.
+ ///
+ /// \returns the read value.
+ ErrorOr<StringRef> readString();
+
+ /// \brief Return true if we've reached the end of file.
+ bool at_eof() const { return Data >= End; }
+
+ /// \brief Points to the current location in the buffer.
+ const uint8_t *Data;
+
+ /// \brief Points to the end of the buffer.
+ const uint8_t *End;
+};
+
+} // End namespace sampleprof
+
+} // End namespace llvm
+
+#endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H
diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h
new file mode 100644
index 000000000000..302a82d32861
--- /dev/null
+++ b/include/llvm/ProfileData/SampleProfWriter.h
@@ -0,0 +1,110 @@
+//===- SampleProfWriter.h - Write LLVM sample profile data ----------------===//
+//
+// 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 needed for writing sample profiles.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
+#define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/ProfileData/SampleProf.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+namespace sampleprof {
+
+enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC };
+
+/// \brief Sample-based profile writer. Base class.
+class SampleProfileWriter {
+public:
+ SampleProfileWriter(StringRef Filename, std::error_code &EC,
+ sys::fs::OpenFlags Flags)
+ : OS(Filename, EC, Flags) {}
+ virtual ~SampleProfileWriter() {}
+
+ /// \brief Write sample profiles in \p S for function \p FName.
+ ///
+ /// \returns true if the file was updated successfully. False, otherwise.
+ virtual bool write(StringRef FName, const FunctionSamples &S) = 0;
+
+ /// \brief Write sample profiles in \p S for function \p F.
+ bool write(const Function &F, const FunctionSamples &S) {
+ return write(F.getName(), S);
+ }
+
+ /// \brief Write all the sample profiles for all the functions in \p M.
+ ///
+ /// \returns true if the file was updated successfully. False, otherwise.
+ bool write(const Module &M, StringMap<FunctionSamples> &P) {
+ for (const auto &F : M) {
+ StringRef Name = F.getName();
+ if (!write(Name, P[Name]))
+ return false;
+ }
+ return true;
+ }
+
+ /// \brief Write all the sample profiles in the given map of samples.
+ ///
+ /// \returns true if the file was updated successfully. False, otherwise.
+ bool write(StringMap<FunctionSamples> &ProfileMap) {
+ for (auto &I : ProfileMap) {
+ StringRef FName = I.first();
+ FunctionSamples &Profile = I.second;
+ if (!write(FName, Profile))
+ return false;
+ }
+ return true;
+ }
+
+ /// \brief Profile writer factory. Create a new writer based on the value of
+ /// \p Format.
+ static ErrorOr<std::unique_ptr<SampleProfileWriter>>
+ create(StringRef Filename, SampleProfileFormat Format);
+
+protected:
+ /// \brief Output stream where to emit the profile to.
+ raw_fd_ostream OS;
+};
+
+/// \brief Sample-based profile writer (text format).
+class SampleProfileWriterText : public SampleProfileWriter {
+public:
+ SampleProfileWriterText(StringRef F, std::error_code &EC)
+ : SampleProfileWriter(F, EC, sys::fs::F_Text) {}
+
+ bool write(StringRef FName, const FunctionSamples &S) override;
+ bool write(const Module &M, StringMap<FunctionSamples> &P) {
+ return SampleProfileWriter::write(M, P);
+ }
+};
+
+/// \brief Sample-based profile writer (binary format).
+class SampleProfileWriterBinary : public SampleProfileWriter {
+public:
+ SampleProfileWriterBinary(StringRef F, std::error_code &EC);
+
+ bool write(StringRef F, const FunctionSamples &S) override;
+ bool write(const Module &M, StringMap<FunctionSamples> &P) {
+ return SampleProfileWriter::write(M, P);
+ }
+};
+
+} // End namespace sampleprof
+
+} // End namespace llvm
+
+#endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h
index f63e0a61f639..96a8219bfb85 100644
--- a/include/llvm/Support/ARMBuildAttributes.h
+++ b/include/llvm/Support/ARMBuildAttributes.h
@@ -16,8 +16,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H
-#define LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H
+#ifndef LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
+#define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
namespace llvm {
class StringRef;
@@ -146,6 +146,12 @@ enum {
AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations)
AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted
+ // Tag_ABI_PCS_R9_use, (=14), uleb128
+ R9IsGPR = 0, // R9 used as v6 (just another callee-saved register)
+ R9IsSB = 1, // R9 used as a global static base rgister
+ R9IsTLSPointer = 2, // R9 used as a thread local storage pointer
+ R9Reserved = 3, // R9 not used by code associated with attributed entity
+
// Tag_ABI_PCS_RW_data, (=15), uleb128
AddressRWPCRel = 1, // Address RW static data PC-relative
AddressRWSBRel = 2, // Address RW static data SB-relative
@@ -165,6 +171,8 @@ enum {
WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4
// Tag_ABI_FP_denormal, (=20), uleb128
+ PositiveZero = 0,
+ IEEEDenormals = 1,
PreserveFPSign = 2, // sign when flushed-to-zero is preserved
// Tag_ABI_FP_number_model, (=23), uleb128
@@ -192,6 +200,9 @@ enum {
// Tag_FP_HP_extension, (=36), uleb128
AllowHPFP = 1, // Allow use of Half Precision FP
+ // Tag_FP_16bit_format, (=38), uleb128
+ FP16FormatIEEE = 1,
+
// Tag_MPextension_use, (=42), uleb128
AllowMP = 1, // Allow use of MP extensions
@@ -214,4 +225,4 @@ enum {
} // namespace ARMBuildAttrs
} // namespace llvm
-#endif // LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H
+#endif
diff --git a/include/llvm/Support/ARMEHABI.h b/include/llvm/Support/ARMEHABI.h
index c7ac54aeb6de..9b052df0a908 100644
--- a/include/llvm/Support/ARMEHABI.h
+++ b/include/llvm/Support/ARMEHABI.h
@@ -19,8 +19,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_ARM_EHABI_H
-#define LLVM_SUPPORT_ARM_EHABI_H
+#ifndef LLVM_SUPPORT_ARMEHABI_H
+#define LLVM_SUPPORT_ARMEHABI_H
namespace llvm {
namespace ARM {
@@ -131,4 +131,4 @@ namespace EHABI {
}
}
-#endif // ARM_UNWIND_OP_H
+#endif
diff --git a/include/llvm/Support/ARMWinEH.h b/include/llvm/Support/ARMWinEH.h
index 78deb8d36a98..1463629f45dc 100644
--- a/include/llvm/Support/ARMWinEH.h
+++ b/include/llvm/Support/ARMWinEH.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_WINARMEH_H
-#define LLVM_SUPPORT_WINARMEH_H
+#ifndef LLVM_SUPPORT_ARMWINEH_H
+#define LLVM_SUPPORT_ARMWINEH_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Endian.h"
@@ -350,16 +350,15 @@ struct ExceptionDataRecord {
ArrayRef<support::ulittle32_t> EpilogueScopes() const {
assert(E() == 0 && "epilogue scopes are only present when the E bit is 0");
size_t Offset = HeaderWords(*this);
- return ArrayRef<support::ulittle32_t>(&Data[Offset], EpilogueCount());
+ return makeArrayRef(&Data[Offset], EpilogueCount());
}
- ArrayRef<support::ulittle8_t> UnwindByteCode() const {
+ ArrayRef<uint8_t> UnwindByteCode() const {
const size_t Offset = HeaderWords(*this)
+ (E() ? 0 : EpilogueCount());
- const support::ulittle8_t *ByteCode =
- reinterpret_cast<const support::ulittle8_t *>(&Data[Offset]);
- return ArrayRef<support::ulittle8_t>(ByteCode,
- CodeWords() * sizeof(uint32_t));
+ const uint8_t *ByteCode =
+ reinterpret_cast<const uint8_t *>(&Data[Offset]);
+ return makeArrayRef(ByteCode, CodeWords() * sizeof(uint32_t));
}
uint32_t ExceptionHandlerRVA() const {
@@ -381,4 +380,3 @@ inline size_t HeaderWords(const ExceptionDataRecord &XR) {
}
#endif
-
diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h
index 7a7e4c0a13e2..de317719714d 100644
--- a/include/llvm/Support/Allocator.h
+++ b/include/llvm/Support/Allocator.h
@@ -90,7 +90,10 @@ class MallocAllocator : public AllocatorBase<MallocAllocator> {
public:
void Reset() {}
- void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); }
+ LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
+ size_t /*Alignment*/) {
+ return malloc(Size);
+ }
// Pull in base class overloads.
using AllocatorBase<MallocAllocator>::Allocate;
@@ -116,8 +119,8 @@ void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
/// \brief 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 boundless contiguous heap. However, it has
-/// bump-pointer semantics in that is a monotonically growing pool of memory
+/// memory rather than relying on a boundless contiguous heap. However, it has
+/// bump-pointer semantics in that it is a monotonically growing pool of memory
/// where every allocation is found by merely allocating the next N bytes in
/// the slab, or the next N bytes in the next slab.
///
@@ -200,28 +203,24 @@ public:
}
/// \brief Allocate space at the specified alignment.
- void *Allocate(size_t Size, size_t Alignment) {
- if (!CurPtr) // Start a new slab if we haven't allocated one already.
- StartNewSlab();
+ LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) {
+ assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
// Keep track of how many bytes we've allocated.
BytesAllocated += Size;
- // 0-byte alignment means 1-byte alignment.
- if (Alignment == 0)
- Alignment = 1;
-
- // Allocate the aligned space, going forwards from CurPtr.
- char *Ptr = alignPtr(CurPtr, Alignment);
+ size_t Adjustment = alignmentAdjustment(CurPtr, Alignment);
+ assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow");
- // Check if we can hold it.
- if (Ptr + Size <= End) {
- CurPtr = Ptr + Size;
+ // Check if we have enough space.
+ if (Adjustment + Size <= size_t(End - CurPtr)) {
+ char *AlignedPtr = CurPtr + Adjustment;
+ CurPtr = AlignedPtr + Size;
// Update the allocation point of this memory block in MemorySanitizer.
// Without this, MemorySanitizer messages for values originated from here
// will point to the allocation of the entire slab.
- __msan_allocated_memory(Ptr, Size);
- return Ptr;
+ __msan_allocated_memory(AlignedPtr, Size);
+ return AlignedPtr;
}
// If Size is really big, allocate a separate slab for it.
@@ -230,19 +229,22 @@ public:
void *NewSlab = Allocator.Allocate(PaddedSize, 0);
CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize));
- Ptr = alignPtr((char *)NewSlab, Alignment);
- assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + PaddedSize);
- __msan_allocated_memory(Ptr, Size);
- return Ptr;
+ uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment);
+ assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize);
+ char *AlignedPtr = (char*)AlignedAddr;
+ __msan_allocated_memory(AlignedPtr, Size);
+ return AlignedPtr;
}
// Otherwise, start a new slab and try again.
StartNewSlab();
- Ptr = alignPtr(CurPtr, Alignment);
- CurPtr = Ptr + Size;
- assert(CurPtr <= End && "Unable to allocate memory!");
- __msan_allocated_memory(Ptr, Size);
- return Ptr;
+ uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
+ assert(AlignedAddr + Size <= (uintptr_t)End &&
+ "Unable to allocate memory!");
+ char *AlignedPtr = (char*)AlignedAddr;
+ CurPtr = AlignedPtr + Size;
+ __msan_allocated_memory(AlignedPtr, Size);
+ return AlignedPtr;
}
// Pull in base class overloads.
@@ -320,8 +322,10 @@ private:
#ifndef NDEBUG
// Poison the memory so stale pointers crash sooner. Note we must
// preserve the Size and NextPtr fields at the beginning.
- sys::Memory::setRangeWritable(*I, AllocatedSlabSize);
- memset(*I, 0xCD, AllocatedSlabSize);
+ if (AllocatedSlabSize != 0) {
+ sys::Memory::setRangeWritable(*I, AllocatedSlabSize);
+ memset(*I, 0xCD, AllocatedSlabSize);
+ }
#endif
Allocator.Deallocate(*I, AllocatedSlabSize);
}
@@ -373,7 +377,7 @@ public:
/// all memory allocated so far.
void DestroyAll() {
auto DestroyElements = [](char *Begin, char *End) {
- assert(Begin == alignPtr(Begin, alignOf<T>()));
+ assert(Begin == (char*)alignAddr(Begin, alignOf<T>()));
for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T))
reinterpret_cast<T *>(Ptr)->~T();
};
@@ -382,7 +386,7 @@ public:
++I) {
size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize(
std::distance(Allocator.Slabs.begin(), I));
- char *Begin = alignPtr((char *)*I, alignOf<T>());
+ char *Begin = (char*)alignAddr(*I, alignOf<T>());
char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr
: (char *)*I + AllocatedSlabSize;
@@ -392,7 +396,7 @@ public:
for (auto &PtrAndSize : Allocator.CustomSizedSlabs) {
void *Ptr = PtrAndSize.first;
size_t Size = PtrAndSize.second;
- DestroyElements(alignPtr((char *)Ptr, alignOf<T>()), (char *)Ptr + Size);
+ DestroyElements((char*)alignAddr(Ptr, alignOf<T>()), (char *)Ptr + Size);
}
Allocator.Reset();
diff --git a/include/llvm/Support/CBindingWrapping.h b/include/llvm/Support/CBindingWrapping.h
index 51097b820220..786ba183b3b0 100644
--- a/include/llvm/Support/CBindingWrapping.h
+++ b/include/llvm/Support/CBindingWrapping.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_C_BINDING_WRAPPING_H
-#define LLVM_C_BINDING_WRAPPING_H
+#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H
+#define LLVM_SUPPORT_CBINDINGWRAPPING_H
#include "llvm/Support/Casting.h"
diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h
index e09ef07d81db..150bce50d9ae 100644
--- a/include/llvm/Support/COFF.h
+++ b/include/llvm/Support/COFF.h
@@ -31,23 +31,30 @@ namespace llvm {
namespace COFF {
// The maximum number of sections that a COFF object can have (inclusive).
- const int MaxNumberOfSections = 65299;
+ const int32_t MaxNumberOfSections16 = 65279;
// The PE signature bytes that follows the DOS stub header.
static const char PEMagic[] = { 'P', 'E', '\0', '\0' };
+ static const char BigObjMagic[] = {
+ '\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b',
+ '\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8',
+ };
+
// Sizes in bytes of various things in the COFF format.
enum {
- HeaderSize = 20,
+ Header16Size = 20,
+ Header32Size = 56,
NameSize = 8,
- SymbolSize = 18,
+ Symbol16Size = 18,
+ Symbol32Size = 20,
SectionSize = 40,
RelocationSize = 10
};
struct header {
uint16_t Machine;
- uint16_t NumberOfSections;
+ int32_t NumberOfSections;
uint32_t TimeDateStamp;
uint32_t PointerToSymbolTable;
uint32_t NumberOfSymbols;
@@ -55,6 +62,24 @@ namespace COFF {
uint16_t Characteristics;
};
+ struct BigObjHeader {
+ enum : uint16_t { MinBigObjectVersion = 2 };
+
+ uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0).
+ uint16_t Sig2; ///< Must be 0xFFFF.
+ uint16_t Version;
+ uint16_t Machine;
+ uint32_t TimeDateStamp;
+ uint8_t UUID[16];
+ uint32_t unused1;
+ uint32_t unused2;
+ uint32_t unused3;
+ uint32_t unused4;
+ uint32_t NumberOfSections;
+ uint32_t PointerToSymbolTable;
+ uint32_t NumberOfSymbols;
+ };
+
enum MachineTypes {
MT_Invalid = 0xffff,
@@ -124,7 +149,7 @@ namespace COFF {
struct symbol {
char Name[NameSize];
uint32_t Value;
- uint16_t SectionNumber;
+ int32_t SectionNumber;
uint16_t Type;
uint8_t StorageClass;
uint8_t NumberOfAuxSymbols;
@@ -140,9 +165,9 @@ namespace COFF {
SF_WeakExternal = 0x01000000
};
- enum SymbolSectionNumber {
- IMAGE_SYM_DEBUG = 0xFFFE,
- IMAGE_SYM_ABSOLUTE = 0xFFFF,
+ enum SymbolSectionNumber : int32_t {
+ IMAGE_SYM_DEBUG = -2,
+ IMAGE_SYM_ABSOLUTE = -1,
IMAGE_SYM_UNDEFINED = 0
};
@@ -367,18 +392,14 @@ namespace COFF {
IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3
};
- struct AuxiliaryFile {
- uint8_t FileName[18];
- };
-
struct AuxiliarySectionDefinition {
uint32_t Length;
uint16_t NumberOfRelocations;
uint16_t NumberOfLinenumbers;
uint32_t CheckSum;
- uint16_t Number;
+ uint32_t Number;
uint8_t Selection;
- char unused[3];
+ char unused;
};
struct AuxiliaryCLRToken {
@@ -392,7 +413,6 @@ namespace COFF {
AuxiliaryFunctionDefinition FunctionDefinition;
AuxiliarybfAndefSymbol bfAndefSymbol;
AuxiliaryWeakExternal WeakExternal;
- AuxiliaryFile File;
AuxiliarySectionDefinition SectionDefinition;
};
@@ -495,12 +515,14 @@ namespace COFF {
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
+ // FIXME: This should be DllCharacteristics to match the COFF spec.
uint16_t DLLCharacteristics;
uint32_t SizeOfStackReserve;
uint32_t SizeOfStackCommit;
uint32_t SizeOfHeapReserve;
uint32_t SizeOfHeapCommit;
uint32_t LoaderFlags;
+ // FIXME: This should be NumberOfRvaAndSizes to match the COFF spec.
uint32_t NumberOfRvaAndSize;
};
@@ -524,7 +546,9 @@ namespace COFF {
BOUND_IMPORT,
IAT,
DELAY_IMPORT_DESCRIPTOR,
- CLR_RUNTIME_HEADER
+ CLR_RUNTIME_HEADER,
+
+ NUM_DATA_DIRECTORIES
};
enum WindowsSubsystem {
@@ -642,13 +666,18 @@ namespace COFF {
enum CodeViewLineTableIdentifiers {
DEBUG_SECTION_MAGIC = 0x4,
+ DEBUG_SYMBOL_SUBSECTION = 0xF1,
DEBUG_LINE_TABLE_SUBSECTION = 0xF2,
DEBUG_STRING_TABLE_SUBSECTION = 0xF3,
- DEBUG_INDEX_SUBSECTION = 0xF4
+ DEBUG_INDEX_SUBSECTION = 0xF4,
+
+ // Symbol subsections are split into records of different types.
+ DEBUG_SYMBOL_TYPE_PROC_START = 0x1147,
+ DEBUG_SYMBOL_TYPE_PROC_END = 0x114F
};
- inline bool isReservedSectionNumber(int N) {
- return N == IMAGE_SYM_UNDEFINED || N > MaxNumberOfSections;
+ inline bool isReservedSectionNumber(int32_t SectionNumber) {
+ return SectionNumber <= 0;
}
} // End namespace COFF.
diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h
index beed31a4084f..6ba5efa47554 100644
--- a/include/llvm/Support/Casting.h
+++ b/include/llvm/Support/Casting.h
@@ -243,6 +243,26 @@ inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) {
// accepted.
//
template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
+cast_or_null(const Y &Val) {
+ if (!Val)
+ return nullptr;
+ assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+ return cast<X>(Val);
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+ !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
+cast_or_null(Y &Val) {
+ if (!Val)
+ return nullptr;
+ assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+ return cast<X>(Val);
+}
+
+template <class X, class Y>
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
cast_or_null(Y *Val) {
if (!Val) return nullptr;
@@ -282,6 +302,20 @@ dyn_cast(Y *Val) {
// value is accepted.
//
template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
+dyn_cast_or_null(const Y &Val) {
+ return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+ !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
+dyn_cast_or_null(Y &Val) {
+ return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
dyn_cast_or_null(Y *Val) {
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
diff --git a/include/llvm/Support/CodeGen.h b/include/llvm/Support/CodeGen.h
index 240eba6c8a41..243f2dd7498c 100644
--- a/include/llvm/Support/CodeGen.h
+++ b/include/llvm/Support/CodeGen.h
@@ -30,6 +30,10 @@ namespace llvm {
enum Model { Default, JITDefault, Small, Kernel, Medium, Large };
}
+ namespace PICLevel {
+ enum Level { Default=0, Small=1, Large=2 };
+ }
+
// TLS models.
namespace TLSModel {
enum Model {
diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index fdd901200fe9..1c06bf5f8c07 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/include/llvm/Support/CommandLine.h
@@ -40,7 +40,7 @@ namespace cl {
//===----------------------------------------------------------------------===//
// ParseCommandLineOptions - Command line option processing entry point.
//
-void ParseCommandLineOptions(int argc, const char * const *argv,
+void ParseCommandLineOptions(int argc, const char *const *argv,
const char *Overview = nullptr);
//===----------------------------------------------------------------------===//
@@ -66,7 +66,6 @@ void SetVersionPrinter(void (*func)());
/// information specific to the tool.
void AddExtraVersionPrinter(void (*func)());
-
// PrintOptionValues - Print option values.
// With -print-options print the difference between option values and defaults.
// With -print-all-options print all option values.
@@ -80,11 +79,11 @@ void MarkOptionsChanged();
// Flags permitted to be passed to command line arguments
//
-enum NumOccurrencesFlag { // Flags for the number of occurrences allowed
- Optional = 0x00, // Zero or One occurrence
- ZeroOrMore = 0x01, // Zero or more occurrences allowed
- Required = 0x02, // One occurrence required
- OneOrMore = 0x03, // One or more occurrences required
+enum NumOccurrencesFlag { // Flags for the number of occurrences allowed
+ Optional = 0x00, // Zero or One occurrence
+ ZeroOrMore = 0x01, // Zero or more occurrences allowed
+ Required = 0x02, // One occurrence required
+ OneOrMore = 0x03, // One or more occurrences required
// ConsumeAfter - Indicates that this option is fed anything that follows the
// last positional argument required by the application (it is an error if
@@ -93,20 +92,20 @@ enum NumOccurrencesFlag { // Flags for the number of occurrences allowed
// found. Once a filename is found, all of the succeeding arguments are
// passed, unprocessed, to the ConsumeAfter option.
//
- ConsumeAfter = 0x04
+ ConsumeAfter = 0x04
};
-enum ValueExpected { // Is a value required for the option?
+enum ValueExpected { // Is a value required for the option?
// zero reserved for the unspecified value
- ValueOptional = 0x01, // The value can appear... or not
- ValueRequired = 0x02, // The value is required to appear!
- ValueDisallowed = 0x03 // A value may not be specified (for flags)
+ ValueOptional = 0x01, // The value can appear... or not
+ ValueRequired = 0x02, // The value is required to appear!
+ ValueDisallowed = 0x03 // A value may not be specified (for flags)
};
-enum OptionHidden { // Control whether -help shows this option
- NotHidden = 0x00, // Option included in -help & -help-hidden
- Hidden = 0x01, // -help doesn't, but -help-hidden does
- ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg
+enum OptionHidden { // Control whether -help shows this option
+ NotHidden = 0x00, // Option included in -help & -help-hidden
+ Hidden = 0x01, // -help doesn't, but -help-hidden does
+ ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg
};
// Formatting flags - This controls special features that the option might have
@@ -125,16 +124,16 @@ enum OptionHidden { // Control whether -help shows this option
//
enum FormattingFlags {
- NormalFormatting = 0x00, // Nothing special
- Positional = 0x01, // Is a positional argument, no '-' required
- Prefix = 0x02, // Can this option directly prefix its value?
- Grouping = 0x03 // Can this option group with other options?
+ NormalFormatting = 0x00, // Nothing special
+ Positional = 0x01, // Is a positional argument, no '-' required
+ Prefix = 0x02, // Can this option directly prefix its value?
+ Grouping = 0x03 // Can this option group with other options?
};
-enum MiscFlags { // Miscellaneous flags to adjust argument
- CommaSeparated = 0x01, // Should this cl::list split between commas?
- PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args?
- Sink = 0x04 // Should this cl::list eat all unknown options?
+enum MiscFlags { // Miscellaneous flags to adjust argument
+ CommaSeparated = 0x01, // Should this cl::list split between commas?
+ PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args?
+ Sink = 0x04 // Should this cl::list eat all unknown options?
};
//===----------------------------------------------------------------------===//
@@ -145,9 +144,13 @@ private:
const char *const Name;
const char *const Description;
void registerCategory();
+
public:
- OptionCategory(const char *const Name, const char *const Description = nullptr)
- : Name(Name), Description(Description) { registerCategory(); }
+ OptionCategory(const char *const Name,
+ const char *const Description = nullptr)
+ : Name(Name), Description(Description) {
+ registerCategory();
+ }
const char *getName() const { return Name; }
const char *getDescription() const { return Description; }
};
@@ -176,7 +179,7 @@ class Option {
// Out of line virtual function to provide home for the class.
virtual void anchor();
- int NumOccurrences; // The number of times specified
+ int NumOccurrences; // The number of times specified
// Occurrences, HiddenFlag, and Formatting are all enum types but to avoid
// problems with signed enums in bitfields.
unsigned Occurrences : 3; // enum NumOccurrencesFlag
@@ -186,9 +189,9 @@ class Option {
unsigned HiddenFlag : 2; // enum OptionHidden
unsigned Formatting : 2; // enum FormattingFlags
unsigned Misc : 3;
- unsigned Position; // Position of last occurrence of the option
- unsigned AdditionalVals;// Greater than 0 for multi-valued option.
- Option *NextRegistered; // Singly linked list of registered options.
+ unsigned Position; // Position of last occurrence of the option
+ unsigned AdditionalVals; // Greater than 0 for multi-valued option.
+ Option *NextRegistered; // Singly linked list of registered options.
public:
const char *ArgStr; // The argument string itself (ex: "help", "o")
@@ -200,8 +203,7 @@ public:
return (enum NumOccurrencesFlag)Occurrences;
}
inline enum ValueExpected getValueExpectedFlag() const {
- return Value ? ((enum ValueExpected)Value)
- : getValueExpectedFlagDefault();
+ return Value ? ((enum ValueExpected)Value) : getValueExpectedFlagDefault();
}
inline enum OptionHidden getOptionHiddenFlag() const {
return (enum OptionHidden)HiddenFlag;
@@ -209,9 +211,7 @@ public:
inline enum FormattingFlags getFormattingFlag() const {
return (enum FormattingFlags)Formatting;
}
- inline unsigned getMiscFlags() const {
- return Misc;
- }
+ inline unsigned getMiscFlags() const { return Misc; }
inline unsigned getPosition() const { return Position; }
inline unsigned getNumAdditionalVals() const { return AdditionalVals; }
@@ -224,25 +224,24 @@ public:
void setArgStr(const char *S) { ArgStr = S; }
void setDescription(const char *S) { HelpStr = S; }
void setValueStr(const char *S) { ValueStr = S; }
- void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) {
- Occurrences = Val;
- }
+ void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; }
void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; }
void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; }
void setFormattingFlag(enum FormattingFlags V) { Formatting = V; }
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
void setPosition(unsigned pos) { Position = pos; }
void setCategory(OptionCategory &C) { Category = &C; }
+
protected:
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
enum OptionHidden Hidden)
- : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
- HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0),
- Position(0), AdditionalVals(0), NextRegistered(nullptr),
- ArgStr(""), HelpStr(""), ValueStr(""), Category(&GeneralCategory) {
- }
+ : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
+ HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0),
+ AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""),
+ ValueStr(""), Category(&GeneralCategory) {}
inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
+
public:
// addArgument - Register this argument with the commandline system.
//
@@ -266,12 +265,12 @@ public:
virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0;
- virtual void getExtraOptionNames(SmallVectorImpl<const char*> &) {}
+ virtual void getExtraOptionNames(SmallVectorImpl<const char *> &) {}
// addOccurrence - Wrapper around handleOccurrence that enforces Flags.
//
- virtual bool addOccurrence(unsigned pos, StringRef ArgName,
- StringRef Value, bool MultiArg = false);
+ virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value,
+ bool MultiArg = false);
// Prints option name followed by message. Always returns true.
bool error(const Twine &Message, StringRef ArgName = StringRef());
@@ -281,7 +280,6 @@ public:
virtual ~Option() {}
};
-
//===----------------------------------------------------------------------===//
// Command line option modifiers that can be used to modify the behavior of
// command line option parsers...
@@ -306,36 +304,31 @@ struct value_desc {
// the default constructor for the argument type does not give you what you
// want. This is only valid on "opt" arguments, not on "list" arguments.
//
-template<class Ty>
-struct initializer {
+template <class Ty> struct initializer {
const Ty &Init;
initializer(const Ty &Val) : Init(Val) {}
- template<class Opt>
- void apply(Opt &O) const { O.setInitialValue(Init); }
+ template <class Opt> void apply(Opt &O) const { O.setInitialValue(Init); }
};
-template<class Ty>
-initializer<Ty> init(const Ty &Val) {
+template <class Ty> initializer<Ty> init(const Ty &Val) {
return initializer<Ty>(Val);
}
-
// location - Allow the user to specify which external variable they want to
// store the results of the command line argument processing into, if they don't
// want to store it in the option itself.
//
-template<class Ty>
-struct LocationClass {
+template <class Ty> struct LocationClass {
Ty &Loc;
LocationClass(Ty &L) : Loc(L) {}
- template<class Opt>
- void apply(Opt &O) const { O.setLocation(O, Loc); }
+ template <class Opt> void apply(Opt &O) const { O.setLocation(O, Loc); }
};
-template<class Ty>
-LocationClass<Ty> location(Ty &L) { return LocationClass<Ty>(L); }
+template <class Ty> LocationClass<Ty> location(Ty &L) {
+ return LocationClass<Ty>(L);
+}
// cat - Specifiy the Option category for the command line argument to belong
// to.
@@ -343,11 +336,9 @@ struct cat {
OptionCategory &Category;
cat(OptionCategory &c) : Category(c) {}
- template<class Opt>
- void apply(Opt &O) const { O.setCategory(Category); }
+ template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
};
-
//===----------------------------------------------------------------------===//
// OptionValue class
@@ -360,11 +351,11 @@ private:
virtual void anchor();
};
-template<class DataType> struct OptionValue;
+template <class DataType> struct OptionValue;
// The default value safely does nothing. Option value printing is only
// best-effort.
-template<class DataType, bool isClass>
+template <class DataType, bool isClass>
struct OptionValueBase : public GenericOptionValue {
// Temporary storage for argument passing.
typedef OptionValue<DataType> WrapperType;
@@ -374,21 +365,20 @@ struct OptionValueBase : public GenericOptionValue {
const DataType &getValue() const { llvm_unreachable("no default value"); }
// Some options may take their value from a different data type.
- template<class DT>
- void setValue(const DT& /*V*/) {}
+ template <class DT> void setValue(const DT & /*V*/) {}
- bool compare(const DataType &/*V*/) const { return false; }
+ bool compare(const DataType & /*V*/) const { return false; }
- bool compare(const GenericOptionValue& /*V*/) const override {
+ bool compare(const GenericOptionValue & /*V*/) const override {
return false;
}
};
// Simple copy of the option value.
-template<class DataType>
-class OptionValueCopy : public GenericOptionValue {
+template <class DataType> class OptionValueCopy : public GenericOptionValue {
DataType Value;
bool Valid;
+
public:
OptionValueCopy() : Valid(false) {}
@@ -399,37 +389,36 @@ public:
return Value;
}
- void setValue(const DataType &V) { Valid = true; Value = V; }
-
- bool compare(const DataType &V) const {
- return Valid && (Value != V);
+ void setValue(const DataType &V) {
+ Valid = true;
+ Value = V;
}
+ bool compare(const DataType &V) const { return Valid && (Value != V); }
+
bool compare(const GenericOptionValue &V) const override {
const OptionValueCopy<DataType> &VC =
- static_cast< const OptionValueCopy<DataType>& >(V);
- if (!VC.hasValue()) return false;
+ static_cast<const OptionValueCopy<DataType> &>(V);
+ if (!VC.hasValue())
+ return false;
return compare(VC.getValue());
}
};
// Non-class option values.
-template<class DataType>
+template <class DataType>
struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> {
typedef DataType WrapperType;
};
// Top-level option class.
-template<class DataType>
+template <class DataType>
struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> {
OptionValue() {}
- OptionValue(const DataType& V) {
- this->setValue(V);
- }
+ OptionValue(const DataType &V) { this->setValue(V); }
// Some options may take their value from a different data type.
- template<class DT>
- OptionValue<DataType> &operator=(const DT& V) {
+ template <class DT> OptionValue<DataType> &operator=(const DT &V) {
this->setValue(V);
return *this;
}
@@ -437,36 +426,33 @@ struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> {
// Other safe-to-copy-by-value common option types.
enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
-template<>
+template <>
struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> {
typedef cl::boolOrDefault WrapperType;
OptionValue() {}
- OptionValue(const cl::boolOrDefault& V) {
- this->setValue(V);
- }
- OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault& V) {
+ OptionValue(const cl::boolOrDefault &V) { this->setValue(V); }
+ OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault &V) {
setValue(V);
return *this;
}
+
private:
void anchor() override;
};
-template<>
-struct OptionValue<std::string> : OptionValueCopy<std::string> {
+template <> struct OptionValue<std::string> : OptionValueCopy<std::string> {
typedef StringRef WrapperType;
OptionValue() {}
- OptionValue(const std::string& V) {
- this->setValue(V);
- }
- OptionValue<std::string> &operator=(const std::string& V) {
+ OptionValue(const std::string &V) { this->setValue(V); }
+ OptionValue<std::string> &operator=(const std::string &V) {
setValue(V);
return *this;
}
+
private:
void anchor() override;
};
@@ -476,20 +462,20 @@ private:
//
#define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC
#define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC
-#define clEnumValEnd (reinterpret_cast<void*>(0))
+#define clEnumValEnd (reinterpret_cast<void *>(0))
// values - For custom data types, allow specifying a group of values together
// as the values that go into the mapping that the option handler uses. Note
// that the values list must always have a 0 at the end of the list to indicate
// that the list has ended.
//
-template<class DataType>
-class ValuesClass {
+template <class DataType> class ValuesClass {
// Use a vector instead of a map, because the lists should be short,
// the overhead is less, and most importantly, it keeps them in the order
// inserted so we can print our option out nicely.
- SmallVector<std::pair<const char *, std::pair<int, const char *> >,4> Values;
+ SmallVector<std::pair<const char *, std::pair<int, const char *>>, 4> Values;
void processValues(va_list Vals);
+
public:
ValuesClass(const char *EnumName, DataType Val, const char *Desc,
va_list ValueArgs) {
@@ -500,27 +486,26 @@ public:
while (const char *enumName = va_arg(ValueArgs, const char *)) {
DataType EnumVal = static_cast<DataType>(va_arg(ValueArgs, int));
const char *EnumDesc = va_arg(ValueArgs, const char *);
- Values.push_back(std::make_pair(enumName, // Add value to value map
+ Values.push_back(std::make_pair(enumName, // Add value to value map
std::make_pair(EnumVal, EnumDesc)));
}
}
- template<class Opt>
- void apply(Opt &O) const {
+ template <class Opt> void apply(Opt &O) const {
for (size_t i = 0, e = Values.size(); i != e; ++i)
O.getParser().addLiteralOption(Values[i].first, Values[i].second.first,
Values[i].second.second);
}
};
-template<class DataType>
-ValuesClass<DataType> END_WITH_NULL values(const char *Arg, DataType Val,
- const char *Desc, ...) {
- va_list ValueArgs;
- va_start(ValueArgs, Desc);
- ValuesClass<DataType> Vals(Arg, Val, Desc, ValueArgs);
- va_end(ValueArgs);
- return Vals;
+template <class DataType>
+ValuesClass<DataType> LLVM_END_WITH_NULL
+values(const char *Arg, DataType Val, const char *Desc, ...) {
+ va_list ValueArgs;
+ va_start(ValueArgs, Desc);
+ ValuesClass<DataType> Vals(Arg, Val, Desc, ValueArgs);
+ va_end(ValueArgs);
+ return Vals;
}
//===----------------------------------------------------------------------===//
@@ -539,13 +524,14 @@ class generic_parser_base {
protected:
class GenericOptionInfo {
public:
- GenericOptionInfo(const char *name, const char *helpStr) :
- Name(name), HelpStr(helpStr) {}
+ GenericOptionInfo(const char *name, const char *helpStr)
+ : Name(name), HelpStr(helpStr) {}
const char *Name;
const char *HelpStr;
};
+
public:
- virtual ~generic_parser_base() {} // Base class should have virtual-dtor
+ virtual ~generic_parser_base() {} // Base class should have virtual-dtor
// getNumOptions - Virtual function implemented by generic subclass to
// indicate how many entries are in Values.
@@ -576,7 +562,7 @@ public:
//
// Template definition ensures that the option and default have the same
// DataType (via the same AnyOptionValue).
- template<class AnyOptionValue>
+ template <class AnyOptionValue>
void printOptionDiff(const Option &O, const AnyOptionValue &V,
const AnyOptionValue &Default,
size_t GlobalWidth) const {
@@ -590,7 +576,7 @@ public:
hasArgStr = O.hasArgStr();
}
- void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) {
+ void getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) {
// If there has been no argstr specified, that means that we need to add an
// argument for every possible option. This ensures that our options are
// vectored to us.
@@ -599,7 +585,6 @@ public:
OptionNames.push_back(getOption(i));
}
-
enum ValueExpected getValueExpectedFlagDefault() const {
// If there is an ArgStr specified, then we are of the form:
//
@@ -633,16 +618,16 @@ protected:
// command line option for -help. Because this is a simple mapping parser, the
// data type can be any unsupported type.
//
-template <class DataType>
-class parser : public generic_parser_base {
+template <class DataType> class parser : public generic_parser_base {
protected:
class OptionInfo : public GenericOptionInfo {
public:
- OptionInfo(const char *name, DataType v, const char *helpStr) :
- GenericOptionInfo(name, helpStr), V(v) {}
+ OptionInfo(const char *name, DataType v, const char *helpStr)
+ : GenericOptionInfo(name, helpStr), V(v) {}
OptionValue<DataType> V;
};
SmallVector<OptionInfo, 8> Values;
+
public:
typedef DataType parser_data_type;
@@ -690,14 +675,14 @@ public:
void removeLiteralOption(const char *Name) {
unsigned N = findOption(Name);
assert(N != Values.size() && "Option not found!");
- Values.erase(Values.begin()+N);
+ Values.erase(Values.begin() + N);
}
};
//--------------------------------------------------
// basic_parser - Super class of parsers to provide boilerplate code
//
-class basic_parser_impl { // non-template implementation of basic_parser<t>
+class basic_parser_impl { // non-template implementation of basic_parser<t>
public:
virtual ~basic_parser_impl() {}
@@ -705,7 +690,7 @@ public:
return ValueRequired;
}
- void getExtraOptionNames(SmallVectorImpl<const char*> &) {}
+ void getExtraOptionNames(SmallVectorImpl<const char *> &) {}
void initialize(Option &) {}
@@ -735,8 +720,7 @@ protected:
// basic_parser - The real basic parser is just a template wrapper that provides
// a typedef for the provided data type.
//
-template<class DataType>
-class basic_parser : public basic_parser_impl {
+template <class DataType> class basic_parser : public basic_parser_impl {
public:
typedef DataType parser_data_type;
typedef OptionValue<DataType> OptVal;
@@ -745,18 +729,14 @@ public:
//--------------------------------------------------
// parser<bool>
//
-template<>
-class parser<bool> : public basic_parser<bool> {
+template <> class parser<bool> : public basic_parser<bool> {
const char *ArgStr;
-public:
+public:
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val);
- template <class Opt>
- void initialize(Opt &O) {
- ArgStr = O.ArgStr;
- }
+ template <class Opt> void initialize(Opt &O) { ArgStr = O.ArgStr; }
enum ValueExpected getValueExpectedFlagDefault() const {
return ValueOptional;
@@ -776,8 +756,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>);
//--------------------------------------------------
// parser<boolOrDefault>
-template<>
-class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
+template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
public:
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val);
@@ -801,8 +780,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
//--------------------------------------------------
// parser<int>
//
-template<>
-class parser<int> : public basic_parser<int> {
+template <> class parser<int> : public basic_parser<int> {
public:
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val);
@@ -819,12 +797,10 @@ public:
EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>);
-
//--------------------------------------------------
// parser<unsigned>
//
-template<>
-class parser<unsigned> : public basic_parser<unsigned> {
+template <> class parser<unsigned> : public basic_parser<unsigned> {
public:
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val);
@@ -844,7 +820,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
//--------------------------------------------------
// parser<unsigned long long>
//
-template<>
+template <>
class parser<unsigned long long> : public basic_parser<unsigned long long> {
public:
// parse - Return true on error.
@@ -866,8 +842,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>);
//--------------------------------------------------
// parser<double>
//
-template<>
-class parser<double> : public basic_parser<double> {
+template <> class parser<double> : public basic_parser<double> {
public:
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val);
@@ -887,8 +862,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>);
//--------------------------------------------------
// parser<float>
//
-template<>
-class parser<float> : public basic_parser<float> {
+template <> class parser<float> : public basic_parser<float> {
public:
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val);
@@ -908,8 +882,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>);
//--------------------------------------------------
// parser<std::string>
//
-template<>
-class parser<std::string> : public basic_parser<std::string> {
+template <> class parser<std::string> : public basic_parser<std::string> {
public:
// parse - Return true on error.
bool parse(Option &, StringRef, StringRef Arg, std::string &Value) {
@@ -932,8 +905,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>);
//--------------------------------------------------
// parser<char>
//
-template<>
-class parser<char> : public basic_parser<char> {
+template <> class parser<char> : public basic_parser<char> {
public:
// parse - Return true on error.
bool parse(Option &, StringRef, StringRef Arg, char &Value) {
@@ -960,7 +932,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<char>);
// parser to handle all the template nastiness.
// This overloaded function is selected by the generic parser.
-template<class ParserClass, class DT>
+template <class ParserClass, class DT>
void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V,
const OptionValue<DT> &Default, size_t GlobalWidth) {
OptionValue<DT> OV = V;
@@ -969,18 +941,16 @@ void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V,
// This is instantiated for basic parsers when the parsed value has a different
// type than the option value. e.g. HelpPrinter.
-template<class ParserDT, class ValDT>
-struct OptionDiffPrinter {
- void print(const Option &O, const parser<ParserDT> P, const ValDT &/*V*/,
- const OptionValue<ValDT> &/*Default*/, size_t GlobalWidth) {
+template <class ParserDT, class ValDT> struct OptionDiffPrinter {
+ void print(const Option &O, const parser<ParserDT> P, const ValDT & /*V*/,
+ const OptionValue<ValDT> & /*Default*/, size_t GlobalWidth) {
P.printOptionNoValue(O, GlobalWidth);
}
};
// This is instantiated for basic parsers when the parsed value has the same
// type as the option value.
-template<class DT>
-struct OptionDiffPrinter<DT, DT> {
+template <class DT> struct OptionDiffPrinter<DT, DT> {
void print(const Option &O, const parser<DT> P, const DT &V,
const OptionValue<DT> &Default, size_t GlobalWidth) {
P.printOptionDiff(O, V, Default, GlobalWidth);
@@ -989,15 +959,14 @@ struct OptionDiffPrinter<DT, DT> {
// This overloaded function is selected by the basic parser, which may parse a
// different type than the option type.
-template<class ParserClass, class ValDT>
+template <class ParserClass, class ValDT>
void printOptionDiff(
- const Option &O,
- const basic_parser<typename ParserClass::parser_data_type> &P,
- const ValDT &V, const OptionValue<ValDT> &Default,
- size_t GlobalWidth) {
+ const Option &O,
+ const basic_parser<typename ParserClass::parser_data_type> &P,
+ const ValDT &V, const OptionValue<ValDT> &Default, size_t GlobalWidth) {
OptionDiffPrinter<typename ParserClass::parser_data_type, ValDT> printer;
- printer.print(O, static_cast<const ParserClass&>(P), V, Default,
+ printer.print(O, static_cast<const ParserClass &>(P), V, Default,
GlobalWidth);
}
@@ -1007,46 +976,47 @@ void printOptionDiff(
// not correctly respond to the apply method). Because the syntax to use this
// is a pain, we have the 'apply' method below to handle the nastiness...
//
-template<class Mod> struct applicator {
- template<class Opt>
- static void opt(const Mod &M, Opt &O) { M.apply(O); }
+template <class Mod> struct applicator {
+ template <class Opt> static void opt(const Mod &M, Opt &O) { M.apply(O); }
};
// Handle const char* as a special case...
-template<unsigned n> struct applicator<char[n]> {
- template<class Opt>
- static void opt(const char *Str, Opt &O) { O.setArgStr(Str); }
+template <unsigned n> struct applicator<char[n]> {
+ template <class Opt> static void opt(const char *Str, Opt &O) {
+ O.setArgStr(Str);
+ }
};
-template<unsigned n> struct applicator<const char[n]> {
- template<class Opt>
- static void opt(const char *Str, Opt &O) { O.setArgStr(Str); }
+template <unsigned n> struct applicator<const char[n]> {
+ template <class Opt> static void opt(const char *Str, Opt &O) {
+ O.setArgStr(Str);
+ }
};
-template<> struct applicator<const char*> {
- template<class Opt>
- static void opt(const char *Str, Opt &O) { O.setArgStr(Str); }
+template <> struct applicator<const char *> {
+ template <class Opt> static void opt(const char *Str, Opt &O) {
+ O.setArgStr(Str);
+ }
};
-template<> struct applicator<NumOccurrencesFlag> {
+template <> struct applicator<NumOccurrencesFlag> {
static void opt(NumOccurrencesFlag N, Option &O) {
O.setNumOccurrencesFlag(N);
}
};
-template<> struct applicator<ValueExpected> {
+template <> struct applicator<ValueExpected> {
static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); }
};
-template<> struct applicator<OptionHidden> {
+template <> struct applicator<OptionHidden> {
static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); }
};
-template<> struct applicator<FormattingFlags> {
+template <> struct applicator<FormattingFlags> {
static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); }
};
-template<> struct applicator<MiscFlags> {
+template <> struct applicator<MiscFlags> {
static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); }
};
// apply method - Apply a modifier to an option in a type safe way.
-template<class Mod, class Opt>
-void apply(const Mod &M, Opt *O) {
+template <class Mod, class Opt> void apply(const Mod &M, Opt *O) {
applicator<Mod>::opt(M, *O);
}
@@ -1057,16 +1027,17 @@ void apply(const Mod &M, Opt *O) {
// assumes the user will specify a variable to store the data into with the
// cl::location(x) modifier.
//
-template<class DataType, bool ExternalStorage, bool isClass>
+template <class DataType, bool ExternalStorage, bool isClass>
class opt_storage {
- DataType *Location; // Where to store the object...
+ DataType *Location; // Where to store the object...
OptionValue<DataType> Default;
void check_location() const {
assert(Location && "cl::location(...) not specified for a command "
- "line option with external storage, "
- "or cl::init specified before cl::location()!!");
+ "line option with external storage, "
+ "or cl::init specified before cl::location()!!");
}
+
public:
opt_storage() : Location(nullptr) {}
@@ -1078,16 +1049,21 @@ public:
return false;
}
- template<class T>
- void setValue(const T &V, bool initial = false) {
+ template <class T> void setValue(const T &V, bool initial = false) {
check_location();
*Location = V;
if (initial)
Default = V;
}
- DataType &getValue() { check_location(); return *Location; }
- const DataType &getValue() const { check_location(); return *Location; }
+ DataType &getValue() {
+ check_location();
+ return *Location;
+ }
+ const DataType &getValue() const {
+ check_location();
+ return *Location;
+ }
operator DataType() const { return this->getValue(); }
@@ -1098,13 +1074,12 @@ public:
// inherit from a class, we do so. This makes us exactly compatible with the
// object in all cases that it is used.
//
-template<class DataType>
-class opt_storage<DataType,false,true> : public DataType {
+template <class DataType>
+class opt_storage<DataType, false, true> : public DataType {
public:
OptionValue<DataType> Default;
- template<class T>
- void setValue(const T &V, bool initial = false) {
+ template <class T> void setValue(const T &V, bool initial = false) {
DataType::operator=(V);
if (initial)
Default = V;
@@ -1120,8 +1095,7 @@ public:
// this case, we store an instance through containment, and overload operators
// to get at the value.
//
-template<class DataType>
-class opt_storage<DataType, false, false> {
+template <class DataType> class opt_storage<DataType, false, false> {
public:
DataType Value;
OptionValue<DataType> Default;
@@ -1130,8 +1104,7 @@ public:
// type.
opt_storage() : Value(DataType()), Default(DataType()) {}
- template<class T>
- void setValue(const T &V, bool initial = false) {
+ template <class T> void setValue(const T &V, bool initial = false) {
Value = V;
if (initial)
Default = V;
@@ -1147,12 +1120,11 @@ public:
DataType operator->() const { return Value; }
};
-
//===----------------------------------------------------------------------===//
// opt - A scalar command line option.
//
template <class DataType, bool ExternalStorage = false,
- class ParserClass = parser<DataType> >
+ class ParserClass = parser<DataType>>
class opt : public Option,
public opt_storage<DataType, ExternalStorage,
std::is_class<DataType>::value> {
@@ -1161,9 +1133,9 @@ class opt : public Option,
bool handleOccurrence(unsigned pos, StringRef ArgName,
StringRef Arg) override {
typename ParserClass::parser_data_type Val =
- typename ParserClass::parser_data_type();
+ typename ParserClass::parser_data_type();
if (Parser.parse(*this, ArgName, Arg, Val))
- return true; // Parse error!
+ return true; // Parse error!
this->setValue(Val);
this->setPosition(pos);
return false;
@@ -1172,20 +1144,23 @@ class opt : public Option,
enum ValueExpected getValueExpectedFlagDefault() const override {
return Parser.getValueExpectedFlagDefault();
}
- void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override {
+ void
+ getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override {
return Parser.getExtraOptionNames(OptionNames);
}
// Forward printing stuff to the parser...
- size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);}
+ size_t getOptionWidth() const override {
+ return Parser.getOptionWidth(*this);
+ }
void printOptionInfo(size_t GlobalWidth) const override {
Parser.printOptionInfo(*this, GlobalWidth);
}
void printOptionValue(size_t GlobalWidth, bool Force) const override {
if (Force || this->getDefault().compare(this->getValue())) {
- cl::printOptionDiff<ParserClass>(
- *this, Parser, this->getValue(), this->getDefault(), GlobalWidth);
+ cl::printOptionDiff<ParserClass>(*this, Parser, this->getValue(),
+ this->getDefault(), GlobalWidth);
}
}
@@ -1193,81 +1168,107 @@ class opt : public Option,
addArgument();
Parser.initialize(*this);
}
+
public:
// setInitialValue - Used by the cl::init modifier...
void setInitialValue(const DataType &V) { this->setValue(V, true); }
ParserClass &getParser() { return Parser; }
- template<class T>
- DataType &operator=(const T &Val) {
+ template <class T> DataType &operator=(const T &Val) {
this->setValue(Val);
return this->getValue();
}
// One option...
- template<class M0t>
- explicit opt(const M0t &M0) : Option(Optional, NotHidden) {
+ template <class M0t>
+ explicit opt(const M0t &M0)
+ : Option(Optional, NotHidden) {
apply(M0, this);
done();
}
// Two options...
- template<class M0t, class M1t>
- opt(const M0t &M0, const M1t &M1) : Option(Optional, NotHidden) {
- apply(M0, this); apply(M1, this);
+ template <class M0t, class M1t>
+ opt(const M0t &M0, const M1t &M1)
+ : Option(Optional, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
done();
}
// Three options...
- template<class M0t, class M1t, class M2t>
- opt(const M0t &M0, const M1t &M1,
- const M2t &M2) : Option(Optional, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this);
+ template <class M0t, class M1t, class M2t>
+ opt(const M0t &M0, const M1t &M1, const M2t &M2)
+ : Option(Optional, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
done();
}
// Four options...
- template<class M0t, class M1t, class M2t, class M3t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2,
- const M3t &M3) : Option(Optional, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
+ template <class M0t, class M1t, class M2t, class M3t>
+ opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
+ : Option(Optional, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
done();
}
// Five options...
- template<class M0t, class M1t, class M2t, class M3t, class M4t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4) : Option(Optional, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
+ template <class M0t, class M1t, class M2t, class M3t, class M4t>
+ opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4)
+ : Option(Optional, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
apply(M4, this);
done();
}
// Six options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5) : Option(Optional, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this);
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
+ opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
+ const M5t &M5)
+ : Option(Optional, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
done();
}
// Seven options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5,
- const M6t &M6) : Option(Optional, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this); apply(M6, this);
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
+ class M6t>
+ opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
+ const M5t &M5, const M6t &M6)
+ : Option(Optional, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
+ apply(M6, this);
done();
}
// Eight options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t, class M7t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5, const M6t &M6,
- const M7t &M7) : Option(Optional, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this);
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
+ class M6t, class M7t>
+ opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
+ const M5t &M5, const M6t &M6, const M7t &M7)
+ : Option(Optional, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
+ apply(M6, this);
+ apply(M7, this);
done();
}
};
@@ -1285,9 +1286,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class opt<bool>);
// assumes the user will specify a variable to store the data into with the
// cl::location(x) modifier.
//
-template<class DataType, class StorageClass>
-class list_storage {
- StorageClass *Location; // Where to store the object...
+template <class DataType, class StorageClass> class list_storage {
+ StorageClass *Location; // Where to store the object...
public:
list_storage() : Location(0) {}
@@ -1299,32 +1299,30 @@ public:
return false;
}
- template<class T>
- void addValue(const T &V) {
+ template <class T> void addValue(const T &V) {
assert(Location != 0 && "cl::location(...) not specified for a command "
- "line option with external storage!");
+ "line option with external storage!");
Location->push_back(V);
}
};
-
// Define how to hold a class type object, such as a string. Since we can
// inherit from a class, we do so. This makes us exactly compatible with the
// object in all cases that it is used.
//
-template<class DataType>
+template <class DataType>
class list_storage<DataType, bool> : public std::vector<DataType> {
public:
- template<class T>
- void addValue(const T &V) { std::vector<DataType>::push_back(V); }
+ template <class T> void addValue(const T &V) {
+ std::vector<DataType>::push_back(V);
+ }
};
-
//===----------------------------------------------------------------------===//
// list - A list of command line options.
//
template <class DataType, class Storage = bool,
- class ParserClass = parser<DataType> >
+ class ParserClass = parser<DataType>>
class list : public Option, public list_storage<DataType, Storage> {
std::vector<unsigned> Positions;
ParserClass Parser;
@@ -1332,16 +1330,17 @@ class list : public Option, public list_storage<DataType, Storage> {
enum ValueExpected getValueExpectedFlagDefault() const override {
return Parser.getValueExpectedFlagDefault();
}
- void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override {
+ void
+ getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override {
return Parser.getExtraOptionNames(OptionNames);
}
bool handleOccurrence(unsigned pos, StringRef ArgName,
StringRef Arg) override {
typename ParserClass::parser_data_type Val =
- typename ParserClass::parser_data_type();
+ typename ParserClass::parser_data_type();
if (Parser.parse(*this, ArgName, Arg, Val))
- return true; // Parse Error!
+ return true; // Parse Error!
list_storage<DataType, Storage>::addValue(Val);
setPosition(pos);
Positions.push_back(pos);
@@ -1349,19 +1348,22 @@ class list : public Option, public list_storage<DataType, Storage> {
}
// Forward printing stuff to the parser...
- size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);}
+ size_t getOptionWidth() const override {
+ return Parser.getOptionWidth(*this);
+ }
void printOptionInfo(size_t GlobalWidth) const override {
Parser.printOptionInfo(*this, GlobalWidth);
}
// Unimplemented: list options don't currently store their default value.
- void printOptionValue(size_t /*GlobalWidth*/,
- bool /*Force*/) const override {}
+ void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {
+ }
void done() {
addArgument();
Parser.initialize(*this);
}
+
public:
ParserClass &getParser() { return Parser; }
@@ -1370,71 +1372,96 @@ public:
return Positions[optnum];
}
- void setNumAdditionalVals(unsigned n) {
- Option::setNumAdditionalVals(n);
- }
+ void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); }
// One option...
- template<class M0t>
- explicit list(const M0t &M0) : Option(ZeroOrMore, NotHidden) {
+ template <class M0t>
+ explicit list(const M0t &M0)
+ : Option(ZeroOrMore, NotHidden) {
apply(M0, this);
done();
}
// Two options...
- template<class M0t, class M1t>
- list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this);
+ template <class M0t, class M1t>
+ list(const M0t &M0, const M1t &M1)
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
done();
}
// Three options...
- template<class M0t, class M1t, class M2t>
+ template <class M0t, class M1t, class M2t>
list(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this);
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
done();
}
// Four options...
- template<class M0t, class M1t, class M2t, class M3t>
+ template <class M0t, class M1t, class M2t, class M3t>
list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
done();
}
// Five options...
- template<class M0t, class M1t, class M2t, class M3t, class M4t>
+ template <class M0t, class M1t, class M2t, class M3t, class M4t>
list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
+ const M4t &M4)
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
apply(M4, this);
done();
}
// Six options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t>
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this);
+ const M4t &M4, const M5t &M5)
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
done();
}
// Seven options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t>
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
+ class M6t>
list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
const M4t &M4, const M5t &M5, const M6t &M6)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this); apply(M6, this);
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
+ apply(M6, this);
done();
}
// Eight options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t, class M7t>
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
+ class M6t, class M7t>
list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5, const M6t &M6,
- const M7t &M7) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this);
+ const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7)
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
+ apply(M6, this);
+ apply(M7, this);
done();
}
};
@@ -1445,10 +1472,11 @@ struct multi_val {
explicit multi_val(unsigned N) : AdditionalVals(N) {}
template <typename D, typename S, typename P>
- void apply(list<D, S, P> &L) const { L.setNumAdditionalVals(AdditionalVals); }
+ void apply(list<D, S, P> &L) const {
+ L.setNumAdditionalVals(AdditionalVals);
+ }
};
-
//===----------------------------------------------------------------------===//
// bits_storage class
@@ -1456,15 +1484,13 @@ struct multi_val {
// assumes the user will specify a variable to store the data into with the
// cl::location(x) modifier.
//
-template<class DataType, class StorageClass>
-class bits_storage {
- unsigned *Location; // Where to store the bits...
+template <class DataType, class StorageClass> class bits_storage {
+ unsigned *Location; // Where to store the bits...
- template<class T>
- static unsigned Bit(const T &V) {
+ template <class T> static unsigned Bit(const T &V) {
unsigned BitPos = reinterpret_cast<unsigned>(V);
assert(BitPos < sizeof(unsigned) * CHAR_BIT &&
- "enum exceeds width of bit vector!");
+ "enum exceeds width of bit vector!");
return 1 << BitPos;
}
@@ -1478,57 +1504,45 @@ public:
return false;
}
- template<class T>
- void addValue(const T &V) {
+ template <class T> void addValue(const T &V) {
assert(Location != 0 && "cl::location(...) not specified for a command "
- "line option with external storage!");
+ "line option with external storage!");
*Location |= Bit(V);
}
unsigned getBits() { return *Location; }
- template<class T>
- bool isSet(const T &V) {
+ template <class T> bool isSet(const T &V) {
return (*Location & Bit(V)) != 0;
}
};
-
// Define how to hold bits. Since we can inherit from a class, we do so.
// This makes us exactly compatible with the bits in all cases that it is used.
//
-template<class DataType>
-class bits_storage<DataType, bool> {
- unsigned Bits; // Where to store the bits...
+template <class DataType> class bits_storage<DataType, bool> {
+ unsigned Bits; // Where to store the bits...
- template<class T>
- static unsigned Bit(const T &V) {
+ template <class T> static unsigned Bit(const T &V) {
unsigned BitPos = (unsigned)V;
assert(BitPos < sizeof(unsigned) * CHAR_BIT &&
- "enum exceeds width of bit vector!");
+ "enum exceeds width of bit vector!");
return 1 << BitPos;
}
public:
- template<class T>
- void addValue(const T &V) {
- Bits |= Bit(V);
- }
+ template <class T> void addValue(const T &V) { Bits |= Bit(V); }
unsigned getBits() { return Bits; }
- template<class T>
- bool isSet(const T &V) {
- return (Bits & Bit(V)) != 0;
- }
+ template <class T> bool isSet(const T &V) { return (Bits & Bit(V)) != 0; }
};
-
//===----------------------------------------------------------------------===//
// bits - A bit vector of command options.
//
template <class DataType, class Storage = bool,
- class ParserClass = parser<DataType> >
+ class ParserClass = parser<DataType>>
class bits : public Option, public bits_storage<DataType, Storage> {
std::vector<unsigned> Positions;
ParserClass Parser;
@@ -1536,16 +1550,17 @@ class bits : public Option, public bits_storage<DataType, Storage> {
enum ValueExpected getValueExpectedFlagDefault() const override {
return Parser.getValueExpectedFlagDefault();
}
- void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override {
+ void
+ getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override {
return Parser.getExtraOptionNames(OptionNames);
}
bool handleOccurrence(unsigned pos, StringRef ArgName,
StringRef Arg) override {
typename ParserClass::parser_data_type Val =
- typename ParserClass::parser_data_type();
+ typename ParserClass::parser_data_type();
if (Parser.parse(*this, ArgName, Arg, Val))
- return true; // Parse Error!
+ return true; // Parse Error!
this->addValue(Val);
setPosition(pos);
Positions.push_back(pos);
@@ -1553,19 +1568,22 @@ class bits : public Option, public bits_storage<DataType, Storage> {
}
// Forward printing stuff to the parser...
- size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);}
+ size_t getOptionWidth() const override {
+ return Parser.getOptionWidth(*this);
+ }
void printOptionInfo(size_t GlobalWidth) const override {
Parser.printOptionInfo(*this, GlobalWidth);
}
// Unimplemented: bits options don't currently store their default values.
- void printOptionValue(size_t /*GlobalWidth*/,
- bool /*Force*/) const override {}
+ void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {
+ }
void done() {
addArgument();
Parser.initialize(*this);
}
+
public:
ParserClass &getParser() { return Parser; }
@@ -1575,66 +1593,93 @@ public:
}
// One option...
- template<class M0t>
- explicit bits(const M0t &M0) : Option(ZeroOrMore, NotHidden) {
+ template <class M0t>
+ explicit bits(const M0t &M0)
+ : Option(ZeroOrMore, NotHidden) {
apply(M0, this);
done();
}
// Two options...
- template<class M0t, class M1t>
- bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this);
+ template <class M0t, class M1t>
+ bits(const M0t &M0, const M1t &M1)
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
done();
}
// Three options...
- template<class M0t, class M1t, class M2t>
+ template <class M0t, class M1t, class M2t>
bits(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this);
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
done();
}
// Four options...
- template<class M0t, class M1t, class M2t, class M3t>
+ template <class M0t, class M1t, class M2t, class M3t>
bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
done();
}
// Five options...
- template<class M0t, class M1t, class M2t, class M3t, class M4t>
+ template <class M0t, class M1t, class M2t, class M3t, class M4t>
bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
+ const M4t &M4)
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
apply(M4, this);
done();
}
// Six options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t>
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this);
+ const M4t &M4, const M5t &M5)
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
done();
}
// Seven options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t>
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
+ class M6t>
bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
const M4t &M4, const M5t &M5, const M6t &M6)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this); apply(M6, this);
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
+ apply(M6, this);
done();
}
// Eight options...
- template<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t, class M7t>
+ template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
+ class M6t, class M7t>
bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5, const M6t &M6,
- const M7t &M7) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
- apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this);
+ const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7)
+ : Option(ZeroOrMore, NotHidden) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
+ apply(M4, this);
+ apply(M5, this);
+ apply(M6, this);
+ apply(M7, this);
done();
}
};
@@ -1646,11 +1691,11 @@ public:
class alias : public Option {
Option *AliasFor;
bool handleOccurrence(unsigned pos, StringRef /*ArgName*/,
- StringRef Arg) override {
+ StringRef Arg) override {
return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg);
}
- bool addOccurrence(unsigned pos, StringRef /*ArgName*/,
- StringRef Value, bool MultiArg = false) override {
+ bool addOccurrence(unsigned pos, StringRef /*ArgName*/, StringRef Value,
+ bool MultiArg = false) override {
return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg);
}
// Handle printing stuff...
@@ -1658,8 +1703,8 @@ class alias : public Option {
void printOptionInfo(size_t GlobalWidth) const override;
// Aliases do not need to print their values.
- void printOptionValue(size_t /*GlobalWidth*/,
- bool /*Force*/) const override {}
+ void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {
+ }
ValueExpected getValueExpectedFlagDefault() const override {
return AliasFor->getValueExpectedFlag();
@@ -1670,8 +1715,9 @@ class alias : public Option {
error("cl::alias must have argument name specified!");
if (!AliasFor)
error("cl::alias must have an cl::aliasopt(option) specified!");
- addArgument();
+ addArgument();
}
+
public:
void setAliasFor(Option &O) {
if (AliasFor)
@@ -1680,30 +1726,37 @@ public:
}
// One option...
- template<class M0t>
- explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(nullptr) {
+ template <class M0t>
+ explicit alias(const M0t &M0)
+ : Option(Optional, Hidden), AliasFor(nullptr) {
apply(M0, this);
done();
}
// Two options...
- template<class M0t, class M1t>
+ template <class M0t, class M1t>
alias(const M0t &M0, const M1t &M1)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this); apply(M1, this);
+ : Option(Optional, Hidden), AliasFor(nullptr) {
+ apply(M0, this);
+ apply(M1, this);
done();
}
// Three options...
- template<class M0t, class M1t, class M2t>
+ template <class M0t, class M1t, class M2t>
alias(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this); apply(M1, this); apply(M2, this);
+ : Option(Optional, Hidden), AliasFor(nullptr) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
done();
}
// Four options...
- template<class M0t, class M1t, class M2t, class M3t>
+ template <class M0t, class M1t, class M2t, class M3t>
alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this);
+ : Option(Optional, Hidden), AliasFor(nullptr) {
+ apply(M0, this);
+ apply(M1, this);
+ apply(M2, this);
+ apply(M3, this);
done();
}
};
@@ -1720,8 +1773,8 @@ struct aliasopt {
// printed to stderr at the end of the regular help, just before
// exit is called.
struct extrahelp {
- const char * morehelp;
- explicit extrahelp(const char* help);
+ const char *morehelp;
+ explicit extrahelp(const char *help);
};
void PrintVersionMessage();
@@ -1733,8 +1786,7 @@ void PrintVersionMessage();
///
/// \param Hidden if true will print hidden options
/// \param Categorized if true print options in categories
-void PrintHelpMessage(bool Hidden=false, bool Categorized=false);
-
+void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
//===----------------------------------------------------------------------===//
// Public interface for accessing registered options.
@@ -1766,7 +1818,7 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false);
/// This interface is useful for modifying options in libraries that are out of
/// the control of the client. The options should be modified before calling
/// llvm::cl::ParseCommandLineOptions().
-void getRegisteredOptions(StringMap<Option*> &Map);
+void getRegisteredOptions(StringMap<Option *> &Map);
//===----------------------------------------------------------------------===//
// Standalone command line processing utilities.
@@ -1776,9 +1828,10 @@ void getRegisteredOptions(StringMap<Option*> &Map);
/// raw character pointer.
class StringSaver {
virtual void anchor();
+
public:
virtual const char *SaveString(const char *Str) = 0;
- virtual ~StringSaver() {}; // Pacify -Wnon-virtual-dtor.
+ virtual ~StringSaver(){}; // Pacify -Wnon-virtual-dtor.
};
/// \brief Tokenizes a command line that can contain escapes and quotes.
@@ -1790,9 +1843,12 @@ public:
///
/// \param [in] Source The string to be split on whitespace with quotes.
/// \param [in] Saver Delegates back to the caller for saving parsed strings.
+/// \param [in] MarkEOLs true if tokenizing a response file and you want end of
+/// lines and end of the response file to be marked with a nullptr string.
/// \param [out] NewArgv All parsed strings are appended to NewArgv.
void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver,
- SmallVectorImpl<const char *> &NewArgv);
+ SmallVectorImpl<const char *> &NewArgv,
+ bool MarkEOLs = false);
/// \brief Tokenizes a Windows command line which may contain quotes and escaped
/// quotes.
@@ -1802,25 +1858,36 @@ void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver,
///
/// \param [in] Source The string to be split on whitespace with quotes.
/// \param [in] Saver Delegates back to the caller for saving parsed strings.
+/// \param [in] MarkEOLs true if tokenizing a response file and you want end of
+/// lines and end of the response file to be marked with a nullptr string.
/// \param [out] NewArgv All parsed strings are appended to NewArgv.
void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver,
- SmallVectorImpl<const char *> &NewArgv);
+ SmallVectorImpl<const char *> &NewArgv,
+ bool MarkEOLs = false);
/// \brief String tokenization function type. Should be compatible with either
/// Windows or Unix command line tokenizers.
typedef void (*TokenizerCallback)(StringRef Source, StringSaver &Saver,
- SmallVectorImpl<const char *> &NewArgv);
+ SmallVectorImpl<const char *> &NewArgv,
+ bool MarkEOLs);
/// \brief 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.
+/// before expansion and will be modified in place. If requested, Argv will
+/// also be populated with nullptrs indicating where each response file line
+/// ends, which is useful for the "/link" argument that needs to consume all
+/// remaining arguments only until the next end of line, when in a response
+/// file.
///
/// \param [in] Saver Delegates back to the caller for saving parsed strings.
/// \param [in] Tokenizer Tokenization strategy. Typically Unix or Windows.
/// \param [in,out] Argv Command line into which to expand response files.
+/// \param [in] MarkEOLs Mark end of lines and the end of the response file
+/// with nullptrs in the Argv vector.
/// \return true if all @files were expanded successfully or there were none.
bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &Argv);
+ SmallVectorImpl<const char *> &Argv,
+ bool MarkEOLs = false);
} // End namespace cl
diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h
index 25bf32ade5f8..d008fec89d64 100644
--- a/include/llvm/Support/Compiler.h
+++ b/include/llvm/Support/Compiler.h
@@ -33,14 +33,19 @@
# define __has_builtin(x) 0
#endif
-/// \macro __GNUC_PREREQ
-/// \brief Defines __GNUC_PREREQ if glibc's features.h isn't available.
-#ifndef __GNUC_PREREQ
-# if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define __GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+/// \macro LLVM_GNUC_PREREQ
+/// \brief 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__)
+# define LLVM_GNUC_PREREQ(maj, min, patch) \
+ ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
+ ((maj) << 20) + ((min) << 10) + (patch))
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define LLVM_GNUC_PREREQ(maj, min, patch) \
+ ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
# else
-# define __GNUC_PREREQ(maj, min) 0
+# define LLVM_GNUC_PREREQ(maj, min, patch) 0
# endif
#endif
@@ -61,7 +66,7 @@
#define LLVM_MSC_PREREQ(version) 0
#endif
-#ifndef _MSC_VER
+#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900)
#define LLVM_NOEXCEPT noexcept
#else
#define LLVM_NOEXCEPT
@@ -70,10 +75,8 @@
/// \brief Does the compiler support r-value reference *this?
///
/// Sadly, this is separate from just r-value reference support because GCC
-/// implemented everything but this thus far. No release of GCC yet has support
-/// for this feature so it is enabled with Clang only.
-/// FIXME: This should change to a version check when GCC grows support for it.
-#if __has_feature(cxx_rvalue_references)
+/// implemented this later than everything else.
+#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1)
#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
#else
#define LLVM_HAS_RVALUE_REFERENCE_THIS 0
@@ -128,20 +131,26 @@
/// not accessible from outside it. Can also be used to mark variables and
/// functions, making them private to any shared library they are linked into.
/// On PE/COFF targets, library visibility is the default, so this isn't needed.
-#if (__has_attribute(visibility) || __GNUC_PREREQ(4, 0)) && \
+#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
#else
#define LLVM_LIBRARY_VISIBILITY
#endif
-#if __has_attribute(used) || __GNUC_PREREQ(3, 1)
+#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0)
+#define LLVM_END_WITH_NULL __attribute__((sentinel))
+#else
+#define LLVM_END_WITH_NULL
+#endif
+
+#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0)
#define LLVM_ATTRIBUTE_USED __attribute__((__used__))
#else
#define LLVM_ATTRIBUTE_USED
#endif
-#if __has_attribute(warn_unused_result) || __GNUC_PREREQ(3, 4)
+#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0)
#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__))
#else
#define LLVM_ATTRIBUTE_UNUSED_RESULT
@@ -155,14 +164,14 @@
// more portable solution:
// (void)unused_var_name;
// Prefer cast-to-void wherever it is sufficient.
-#if __has_attribute(unused) || __GNUC_PREREQ(3, 1)
+#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0)
#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__))
#else
#define LLVM_ATTRIBUTE_UNUSED
#endif
// FIXME: Provide this for PE/COFF targets.
-#if (__has_attribute(weak) || __GNUC_PREREQ(4, 0)) && \
+#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
(!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32))
#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__))
#else
@@ -185,7 +194,7 @@
#define LLVM_READONLY
#endif
-#if __has_builtin(__builtin_expect) || __GNUC_PREREQ(4, 0)
+#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0)
#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
#else
@@ -208,7 +217,7 @@
/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
/// mark a method "not for inlining".
-#if __has_attribute(noinline) || __GNUC_PREREQ(3, 4)
+#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0)
#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
#elif defined(_MSC_VER)
#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
@@ -220,7 +229,7 @@
/// so, mark a method "always inline" because it is performance sensitive. GCC
/// 3.4 supported this but is buggy in various cases and produces unimplemented
/// errors, just use it in GCC 4.0 and later.
-#if __has_attribute(always_inline) || __GNUC_PREREQ(4, 0)
+#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0)
#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline))
#elif defined(_MSC_VER)
#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline
@@ -236,6 +245,12 @@
#define LLVM_ATTRIBUTE_NORETURN
#endif
+#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0)
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
+#else
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL
+#endif
+
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
/// pedantic diagnostics.
#ifdef __GNUC__
@@ -262,7 +277,7 @@
/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
/// to an expression which states that it is undefined behavior for the
/// compiler to reach this point. Otherwise is not defined.
-#if __has_builtin(__builtin_unreachable) || __GNUC_PREREQ(4, 5)
+#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
#elif defined(_MSC_VER)
# define LLVM_BUILTIN_UNREACHABLE __assume(false)
@@ -270,7 +285,7 @@
/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression
/// which causes the program to exit abnormally.
-#if __has_builtin(__builtin_trap) || __GNUC_PREREQ(4, 3)
+#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0)
# define LLVM_BUILTIN_TRAP __builtin_trap()
#else
# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
@@ -278,7 +293,7 @@
/// \macro LLVM_ASSUME_ALIGNED
/// \brief Returns a pointer with an assumed alignment.
-#if __has_builtin(__builtin_assume_aligned) && __GNUC_PREREQ(4, 7)
+#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)
// As of today, clang does not support __builtin_assume_aligned.
diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h
index 8152b60eb098..88727fa3fcfc 100644
--- a/include/llvm/Support/Compression.h
+++ b/include/llvm/Support/Compression.h
@@ -14,9 +14,9 @@
#ifndef LLVM_SUPPORT_COMPRESSION_H
#define LLVM_SUPPORT_COMPRESSION_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
#include <memory>
-#include "llvm/ADT/SmallVector.h"
namespace llvm {
diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h
index 3869ebdc4a93..1f3965c8ade4 100644
--- a/include/llvm/Support/CrashRecoveryContext.h
+++ b/include/llvm/Support/CrashRecoveryContext.h
@@ -10,9 +10,8 @@
#ifndef LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
#define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
-#include <string>
-
#include "llvm/ADT/STLExtras.h"
+#include <string>
namespace llvm {
class StringRef;
@@ -166,9 +165,7 @@ public:
: CrashRecoveryContextCleanupBase<
CrashRecoveryContextDeleteCleanup<T>, T>(context, resource) {}
- virtual void recoverResources() {
- delete this->resource;
- }
+ void recoverResources() override { delete this->resource; }
};
template <typename T>
@@ -181,9 +178,7 @@ public:
: CrashRecoveryContextCleanupBase<CrashRecoveryContextReleaseRefCleanup<T>,
T>(context, resource) {}
- virtual void recoverResources() {
- this->resource->Release();
- }
+ void recoverResources() override { this->resource->Release(); }
};
template <typename T, typename Cleanup = CrashRecoveryContextDeleteCleanup<T> >
diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h
index e8a19cd773b5..48235d4145bd 100644
--- a/include/llvm/Support/DataExtractor.h
+++ b/include/llvm/Support/DataExtractor.h
@@ -348,6 +348,17 @@ public:
bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const {
return offset + length >= offset && isValidOffset(offset + length - 1);
}
+
+ /// Test the availability of enough bytes of data for a pointer from
+ /// \a offset. The size of a pointer is \a getAddressSize().
+ ///
+ /// @return
+ /// \b true if \a offset is a valid offset and there are enough
+ /// bytes for a pointer available at that offset, \b false
+ /// otherwise.
+ bool isValidOffsetForAddress(uint32_t offset) const {
+ return isValidOffsetForDataOfSize(offset, AddressSize);
+ }
};
} // namespace llvm
diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake
index 1f0c8eba5e11..c90bf51afaee 100644
--- a/include/llvm/Support/DataTypes.h.cmake
+++ b/include/llvm/Support/DataTypes.h.cmake
@@ -101,6 +101,13 @@ typedef signed int ssize_t;
#define PRIu64 "I64u"
#define PRIx64 "I64x"
#define PRIX64 "I64X"
+
+#define PRId32 "d"
+#define PRIi32 "i"
+#define PRIo32 "o"
+#define PRIu32 "u"
+#define PRIx32 "x"
+#define PRIX32 "X"
#endif /* HAVE_INTTYPES_H */
#endif /* _MSC_VER */
@@ -116,12 +123,6 @@ typedef signed int ssize_t;
# define UINT64_MAX 0xffffffffffffffffULL
#endif
-#if __GNUC__ > 3
-#define END_WITH_NULL __attribute__((sentinel))
-#else
-#define END_WITH_NULL
-#endif
-
#ifndef HUGE_VALF
#define HUGE_VALF (float)HUGE_VAL
#endif
diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in
index 09cfcdf3b56b..b8b2ba56ff30 100644
--- a/include/llvm/Support/DataTypes.h.in
+++ b/include/llvm/Support/DataTypes.h.in
@@ -116,12 +116,6 @@ typedef signed int ssize_t;
# define UINT64_MAX 0xffffffffffffffffULL
#endif
-#if __GNUC__ > 3
-#define END_WITH_NULL __attribute__((sentinel))
-#else
-#define END_WITH_NULL
-#endif
-
#ifndef HUGE_VALF
#define HUGE_VALF (float)HUGE_VAL
#endif
diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h
index cd9f75600cbc..47b00b1f09d8 100644
--- a/include/llvm/Support/Dwarf.h
+++ b/include/llvm/Support/Dwarf.h
@@ -7,9 +7,13 @@
//
//===----------------------------------------------------------------------===//
//
-// This file contains constants used for implementing Dwarf debug support. For
-// Details on the Dwarf 3 specfication see DWARF Debugging Information Format
-// V.3 reference manual http://dwarf.freestandards.org ,
+// \file
+// \brief This file contains constants used for implementing Dwarf
+// debug support.
+//
+// For details on the Dwarf specfication see the latest DWARF Debugging
+// Information Format standard document on http://www.dwarfstd.org. This
+// file often includes support for non-released standard features.
//
//===----------------------------------------------------------------------===//
@@ -21,22 +25,6 @@
namespace llvm {
-//===----------------------------------------------------------------------===//
-// Debug info constants.
-
-enum : uint32_t {
- LLVMDebugVersion = (12 << 16), // Current version of debug information.
- LLVMDebugVersion11 = (11 << 16), // Constant for version 11.
- LLVMDebugVersion10 = (10 << 16), // Constant for version 10.
- LLVMDebugVersion9 = (9 << 16), // Constant for version 9.
- LLVMDebugVersion8 = (8 << 16), // Constant for version 8.
- LLVMDebugVersion7 = (7 << 16), // Constant for version 7.
- LLVMDebugVersion6 = (6 << 16), // Constant for version 6.
- LLVMDebugVersion5 = (5 << 16), // Constant for version 5.
- LLVMDebugVersion4 = (4 << 16), // Constant for version 4.
- LLVMDebugVersionMask = 0xffff0000 // Mask for version number.
-};
-
namespace dwarf {
//===----------------------------------------------------------------------===//
@@ -53,6 +41,7 @@ enum LLVMConstants : uint32_t {
DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables.
DW_TAG_arg_variable = 0x101, // Tag for argument variables.
+ DW_TAG_expression = 0x102, // Tag for complex address expressions.
DW_TAG_user_base = 0x1000, // Recommended base for user tags.
@@ -779,100 +768,24 @@ enum LocationListEntry : unsigned char {
DW_LLE_offset_pair_entry
};
+/// Contstants for the DW_APPLE_PROPERTY_attributes attribute.
+/// Keep this list in sync with clang's DeclSpec.h ObjCPropertyAttributeKind.
enum ApplePropertyAttributes {
// Apple Objective-C Property Attributes
DW_APPLE_PROPERTY_readonly = 0x01,
- DW_APPLE_PROPERTY_readwrite = 0x02,
+ DW_APPLE_PROPERTY_getter = 0x02,
DW_APPLE_PROPERTY_assign = 0x04,
- DW_APPLE_PROPERTY_retain = 0x08,
- DW_APPLE_PROPERTY_copy = 0x10,
- DW_APPLE_PROPERTY_nonatomic = 0x20
+ DW_APPLE_PROPERTY_readwrite = 0x08,
+ DW_APPLE_PROPERTY_retain = 0x10,
+ DW_APPLE_PROPERTY_copy = 0x20,
+ DW_APPLE_PROPERTY_nonatomic = 0x40,
+ DW_APPLE_PROPERTY_setter = 0x80,
+ DW_APPLE_PROPERTY_atomic = 0x100,
+ DW_APPLE_PROPERTY_weak = 0x200,
+ DW_APPLE_PROPERTY_strong = 0x400,
+ DW_APPLE_PROPERTY_unsafe_unretained = 0x800
};
-/// TagString - Return the string for the specified tag.
-///
-const char *TagString(unsigned Tag);
-
-/// ChildrenString - Return the string for the specified children flag.
-///
-const char *ChildrenString(unsigned Children);
-
-/// AttributeString - Return the string for the specified attribute.
-///
-const char *AttributeString(unsigned Attribute);
-
-/// FormEncodingString - Return the string for the specified form encoding.
-///
-const char *FormEncodingString(unsigned Encoding);
-
-/// OperationEncodingString - Return the string for the specified operation
-/// encoding.
-const char *OperationEncodingString(unsigned Encoding);
-
-/// AttributeEncodingString - Return the string for the specified attribute
-/// encoding.
-const char *AttributeEncodingString(unsigned Encoding);
-
-/// DecimalSignString - Return the string for the specified decimal sign
-/// attribute.
-const char *DecimalSignString(unsigned Sign);
-
-/// EndianityString - Return the string for the specified endianity.
-///
-const char *EndianityString(unsigned Endian);
-
-/// AccessibilityString - Return the string for the specified accessibility.
-///
-const char *AccessibilityString(unsigned Access);
-
-/// VisibilityString - Return the string for the specified visibility.
-///
-const char *VisibilityString(unsigned Visibility);
-
-/// VirtualityString - Return the string for the specified virtuality.
-///
-const char *VirtualityString(unsigned Virtuality);
-
-/// LanguageString - Return the string for the specified language.
-///
-const char *LanguageString(unsigned Language);
-
-/// CaseString - Return the string for the specified identifier case.
-///
-const char *CaseString(unsigned Case);
-
-/// ConventionString - Return the string for the specified calling convention.
-///
-const char *ConventionString(unsigned Convention);
-
-/// InlineCodeString - Return the string for the specified inline code.
-///
-const char *InlineCodeString(unsigned Code);
-
-/// ArrayOrderString - Return the string for the specified array order.
-///
-const char *ArrayOrderString(unsigned Order);
-
-/// DiscriminantString - Return the string for the specified discriminant
-/// descriptor.
-const char *DiscriminantString(unsigned Discriminant);
-
-/// LNStandardString - Return the string for the specified line number standard.
-///
-const char *LNStandardString(unsigned Standard);
-
-/// LNExtendedString - Return the string for the specified line number extended
-/// opcode encodings.
-const char *LNExtendedString(unsigned Encoding);
-
-/// MacinfoString - Return the string for the specified macinfo type encodings.
-///
-const char *MacinfoString(unsigned Encoding);
-
-/// CallFrameString - Return the string for the specified call frame instruction
-/// encodings.
-const char *CallFrameString(unsigned Encoding);
-
// Constants for the DWARF5 Accelerator Table Proposal
enum AcceleratorTable {
// Data layout descriptors.
@@ -895,9 +808,6 @@ enum AcceleratorTable {
DW_hash_function_djb = 0u
};
-/// AtomTypeString - Return the string for the specified Atom type.
-const char *AtomTypeString(unsigned Atom);
-
// Constants for the GNU pubnames/pubtypes extensions supporting gdb index.
enum GDBIndexEntryKind {
GIEK_NONE,
@@ -910,15 +820,51 @@ enum GDBIndexEntryKind {
GIEK_UNUSED7
};
-const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind);
-
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.
+///
+/// @{
+const char *TagString(unsigned Tag);
+const char *ChildrenString(unsigned Children);
+const char *AttributeString(unsigned Attribute);
+const char *FormEncodingString(unsigned Encoding);
+const char *OperationEncodingString(unsigned Encoding);
+const char *AttributeEncodingString(unsigned Encoding);
+const char *DecimalSignString(unsigned Sign);
+const char *EndianityString(unsigned Endian);
+const char *AccessibilityString(unsigned Access);
+const char *VisibilityString(unsigned Visibility);
+const char *VirtualityString(unsigned Virtuality);
+const char *LanguageString(unsigned Language);
+const char *CaseString(unsigned Case);
+const char *ConventionString(unsigned Convention);
+const char *InlineCodeString(unsigned Code);
+const char *ArrayOrderString(unsigned Order);
+const char *DiscriminantString(unsigned Discriminant);
+const char *LNStandardString(unsigned Standard);
+const char *LNExtendedString(unsigned Encoding);
+const char *MacinfoString(unsigned Encoding);
+const char *CallFrameString(unsigned Encoding);
+const char *ApplePropertyString(unsigned);
+const char *AtomTypeString(unsigned Atom);
+const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind);
const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage);
+/// @}
+/// \brief Returns the symbolic string representing Val when used as a value
+/// for attribute Attr.
+const char *AttributeValueString(uint16_t Attr, unsigned Val);
+
+/// \brief Decsribes an entry of the various gnu_pub* debug sections.
+///
/// The gnu_pub* kind looks like:
///
/// 0-3 reserved
@@ -950,6 +896,7 @@ private:
};
};
+
} // End of namespace dwarf
} // End of namespace llvm
diff --git a/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h
index de47be62a795..a7d22212dbdb 100644
--- a/include/llvm/Support/DynamicLibrary.h
+++ b/include/llvm/Support/DynamicLibrary.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SYSTEM_DYNAMICLIBRARY_H
-#define LLVM_SYSTEM_DYNAMICLIBRARY_H
+#ifndef LLVM_SUPPORT_DYNAMICLIBRARY_H
+#define LLVM_SUPPORT_DYNAMICLIBRARY_H
#include <string>
@@ -43,10 +43,11 @@ namespace sys {
// Opaque data used to interface with OS-specific dynamic library handling.
void *Data;
- explicit DynamicLibrary(void *data = &Invalid) : Data(data) {}
public:
+ explicit DynamicLibrary(void *data = &Invalid) : Data(data) {}
+
/// Returns true if the object refers to a valid library.
- bool isValid() { return Data != &Invalid; }
+ bool isValid() const { return Data != &Invalid; }
/// Searches through the library for the symbol \p symbolName. If it is
/// found, the address of that symbol is returned. If not, NULL is returned.
@@ -101,4 +102,4 @@ namespace sys {
} // End sys namespace
} // End llvm namespace
-#endif // LLVM_SYSTEM_DYNAMIC_LIBRARY_H
+#endif
diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h
index 42abe8906ea3..3d49205fa168 100644
--- a/include/llvm/Support/ELF.h
+++ b/include/llvm/Support/ELF.h
@@ -350,150 +350,21 @@ enum {
ELFOSABI_STANDALONE = 255 // Standalone (embedded) application
};
+#define ELF_RELOC(name, value) name = value,
+
// X86_64 relocations.
enum {
- R_X86_64_NONE = 0,
- R_X86_64_64 = 1,
- R_X86_64_PC32 = 2,
- R_X86_64_GOT32 = 3,
- R_X86_64_PLT32 = 4,
- R_X86_64_COPY = 5,
- R_X86_64_GLOB_DAT = 6,
- R_X86_64_JUMP_SLOT = 7,
- R_X86_64_RELATIVE = 8,
- R_X86_64_GOTPCREL = 9,
- R_X86_64_32 = 10,
- R_X86_64_32S = 11,
- R_X86_64_16 = 12,
- R_X86_64_PC16 = 13,
- R_X86_64_8 = 14,
- R_X86_64_PC8 = 15,
- R_X86_64_DTPMOD64 = 16,
- R_X86_64_DTPOFF64 = 17,
- R_X86_64_TPOFF64 = 18,
- R_X86_64_TLSGD = 19,
- R_X86_64_TLSLD = 20,
- R_X86_64_DTPOFF32 = 21,
- R_X86_64_GOTTPOFF = 22,
- R_X86_64_TPOFF32 = 23,
- R_X86_64_PC64 = 24,
- R_X86_64_GOTOFF64 = 25,
- R_X86_64_GOTPC32 = 26,
- R_X86_64_GOT64 = 27,
- R_X86_64_GOTPCREL64 = 28,
- R_X86_64_GOTPC64 = 29,
- R_X86_64_GOTPLT64 = 30,
- R_X86_64_PLTOFF64 = 31,
- R_X86_64_SIZE32 = 32,
- R_X86_64_SIZE64 = 33,
- R_X86_64_GOTPC32_TLSDESC = 34,
- R_X86_64_TLSDESC_CALL = 35,
- R_X86_64_TLSDESC = 36,
- R_X86_64_IRELATIVE = 37
+#include "ELFRelocs/x86_64.def"
};
// i386 relocations.
-// TODO: this is just a subset
enum {
- R_386_NONE = 0,
- R_386_32 = 1,
- R_386_PC32 = 2,
- R_386_GOT32 = 3,
- R_386_PLT32 = 4,
- R_386_COPY = 5,
- R_386_GLOB_DAT = 6,
- R_386_JUMP_SLOT = 7,
- R_386_RELATIVE = 8,
- R_386_GOTOFF = 9,
- R_386_GOTPC = 10,
- R_386_32PLT = 11,
- R_386_TLS_TPOFF = 14,
- R_386_TLS_IE = 15,
- R_386_TLS_GOTIE = 16,
- R_386_TLS_LE = 17,
- R_386_TLS_GD = 18,
- R_386_TLS_LDM = 19,
- R_386_16 = 20,
- R_386_PC16 = 21,
- R_386_8 = 22,
- R_386_PC8 = 23,
- R_386_TLS_GD_32 = 24,
- R_386_TLS_GD_PUSH = 25,
- R_386_TLS_GD_CALL = 26,
- R_386_TLS_GD_POP = 27,
- R_386_TLS_LDM_32 = 28,
- R_386_TLS_LDM_PUSH = 29,
- R_386_TLS_LDM_CALL = 30,
- R_386_TLS_LDM_POP = 31,
- R_386_TLS_LDO_32 = 32,
- R_386_TLS_IE_32 = 33,
- R_386_TLS_LE_32 = 34,
- R_386_TLS_DTPMOD32 = 35,
- R_386_TLS_DTPOFF32 = 36,
- R_386_TLS_TPOFF32 = 37,
- R_386_TLS_GOTDESC = 39,
- R_386_TLS_DESC_CALL = 40,
- R_386_TLS_DESC = 41,
- R_386_IRELATIVE = 42,
- R_386_NUM = 43
+#include "ELFRelocs/i386.def"
};
// ELF Relocation types for PPC32
enum {
- R_PPC_NONE = 0, /* No relocation. */
- R_PPC_ADDR32 = 1,
- R_PPC_ADDR24 = 2,
- R_PPC_ADDR16 = 3,
- R_PPC_ADDR16_LO = 4,
- R_PPC_ADDR16_HI = 5,
- R_PPC_ADDR16_HA = 6,
- R_PPC_ADDR14 = 7,
- R_PPC_ADDR14_BRTAKEN = 8,
- R_PPC_ADDR14_BRNTAKEN = 9,
- R_PPC_REL24 = 10,
- R_PPC_REL14 = 11,
- R_PPC_REL14_BRTAKEN = 12,
- R_PPC_REL14_BRNTAKEN = 13,
- R_PPC_GOT16 = 14,
- R_PPC_GOT16_LO = 15,
- R_PPC_GOT16_HI = 16,
- R_PPC_GOT16_HA = 17,
- R_PPC_PLTREL24 = 18,
- R_PPC_REL32 = 26,
- R_PPC_TLS = 67,
- R_PPC_DTPMOD32 = 68,
- R_PPC_TPREL16 = 69,
- R_PPC_TPREL16_LO = 70,
- R_PPC_TPREL16_HI = 71,
- R_PPC_TPREL16_HA = 72,
- R_PPC_TPREL32 = 73,
- R_PPC_DTPREL16 = 74,
- R_PPC_DTPREL16_LO = 75,
- R_PPC_DTPREL16_HI = 76,
- R_PPC_DTPREL16_HA = 77,
- R_PPC_DTPREL32 = 78,
- R_PPC_GOT_TLSGD16 = 79,
- R_PPC_GOT_TLSGD16_LO = 80,
- R_PPC_GOT_TLSGD16_HI = 81,
- R_PPC_GOT_TLSGD16_HA = 82,
- R_PPC_GOT_TLSLD16 = 83,
- R_PPC_GOT_TLSLD16_LO = 84,
- R_PPC_GOT_TLSLD16_HI = 85,
- R_PPC_GOT_TLSLD16_HA = 86,
- R_PPC_GOT_TPREL16 = 87,
- R_PPC_GOT_TPREL16_LO = 88,
- R_PPC_GOT_TPREL16_HI = 89,
- R_PPC_GOT_TPREL16_HA = 90,
- R_PPC_GOT_DTPREL16 = 91,
- R_PPC_GOT_DTPREL16_LO = 92,
- R_PPC_GOT_DTPREL16_HI = 93,
- R_PPC_GOT_DTPREL16_HA = 94,
- R_PPC_TLSGD = 95,
- R_PPC_TLSLD = 96,
- R_PPC_REL16 = 249,
- R_PPC_REL16_LO = 250,
- R_PPC_REL16_HI = 251,
- R_PPC_REL16_HA = 252
+#include "ELFRelocs/PowerPC.def"
};
// Specific e_flags for PPC64
@@ -529,178 +400,12 @@ encodePPC64LocalEntryOffset(int64_t Offset) {
// ELF Relocation types for PPC64
enum {
- R_PPC64_NONE = 0,
- R_PPC64_ADDR32 = 1,
- R_PPC64_ADDR24 = 2,
- R_PPC64_ADDR16 = 3,
- R_PPC64_ADDR16_LO = 4,
- R_PPC64_ADDR16_HI = 5,
- R_PPC64_ADDR16_HA = 6,
- R_PPC64_ADDR14 = 7,
- R_PPC64_ADDR14_BRTAKEN = 8,
- R_PPC64_ADDR14_BRNTAKEN = 9,
- R_PPC64_REL24 = 10,
- R_PPC64_REL14 = 11,
- R_PPC64_REL14_BRTAKEN = 12,
- R_PPC64_REL14_BRNTAKEN = 13,
- R_PPC64_GOT16 = 14,
- R_PPC64_GOT16_LO = 15,
- R_PPC64_GOT16_HI = 16,
- R_PPC64_GOT16_HA = 17,
- R_PPC64_REL32 = 26,
- R_PPC64_ADDR64 = 38,
- R_PPC64_ADDR16_HIGHER = 39,
- R_PPC64_ADDR16_HIGHERA = 40,
- R_PPC64_ADDR16_HIGHEST = 41,
- R_PPC64_ADDR16_HIGHESTA = 42,
- R_PPC64_REL64 = 44,
- R_PPC64_TOC16 = 47,
- R_PPC64_TOC16_LO = 48,
- R_PPC64_TOC16_HI = 49,
- R_PPC64_TOC16_HA = 50,
- R_PPC64_TOC = 51,
- R_PPC64_ADDR16_DS = 56,
- R_PPC64_ADDR16_LO_DS = 57,
- R_PPC64_GOT16_DS = 58,
- R_PPC64_GOT16_LO_DS = 59,
- R_PPC64_TOC16_DS = 63,
- R_PPC64_TOC16_LO_DS = 64,
- R_PPC64_TLS = 67,
- R_PPC64_DTPMOD64 = 68,
- R_PPC64_TPREL16 = 69,
- R_PPC64_TPREL16_LO = 70,
- R_PPC64_TPREL16_HI = 71,
- R_PPC64_TPREL16_HA = 72,
- R_PPC64_TPREL64 = 73,
- R_PPC64_DTPREL16 = 74,
- R_PPC64_DTPREL16_LO = 75,
- R_PPC64_DTPREL16_HI = 76,
- R_PPC64_DTPREL16_HA = 77,
- R_PPC64_DTPREL64 = 78,
- R_PPC64_GOT_TLSGD16 = 79,
- R_PPC64_GOT_TLSGD16_LO = 80,
- R_PPC64_GOT_TLSGD16_HI = 81,
- R_PPC64_GOT_TLSGD16_HA = 82,
- R_PPC64_GOT_TLSLD16 = 83,
- R_PPC64_GOT_TLSLD16_LO = 84,
- R_PPC64_GOT_TLSLD16_HI = 85,
- R_PPC64_GOT_TLSLD16_HA = 86,
- R_PPC64_GOT_TPREL16_DS = 87,
- R_PPC64_GOT_TPREL16_LO_DS = 88,
- R_PPC64_GOT_TPREL16_HI = 89,
- R_PPC64_GOT_TPREL16_HA = 90,
- R_PPC64_GOT_DTPREL16_DS = 91,
- R_PPC64_GOT_DTPREL16_LO_DS = 92,
- R_PPC64_GOT_DTPREL16_HI = 93,
- R_PPC64_GOT_DTPREL16_HA = 94,
- R_PPC64_TPREL16_DS = 95,
- R_PPC64_TPREL16_LO_DS = 96,
- R_PPC64_TPREL16_HIGHER = 97,
- R_PPC64_TPREL16_HIGHERA = 98,
- R_PPC64_TPREL16_HIGHEST = 99,
- R_PPC64_TPREL16_HIGHESTA = 100,
- R_PPC64_DTPREL16_DS = 101,
- R_PPC64_DTPREL16_LO_DS = 102,
- R_PPC64_DTPREL16_HIGHER = 103,
- R_PPC64_DTPREL16_HIGHERA = 104,
- R_PPC64_DTPREL16_HIGHEST = 105,
- R_PPC64_DTPREL16_HIGHESTA = 106,
- R_PPC64_TLSGD = 107,
- R_PPC64_TLSLD = 108,
- R_PPC64_REL16 = 249,
- R_PPC64_REL16_LO = 250,
- R_PPC64_REL16_HI = 251,
- R_PPC64_REL16_HA = 252
+#include "ELFRelocs/PowerPC64.def"
};
// ELF Relocation types for AArch64
-
enum {
- R_AARCH64_NONE = 0x100,
-
- R_AARCH64_ABS64 = 0x101,
- R_AARCH64_ABS32 = 0x102,
- R_AARCH64_ABS16 = 0x103,
- R_AARCH64_PREL64 = 0x104,
- R_AARCH64_PREL32 = 0x105,
- R_AARCH64_PREL16 = 0x106,
-
- R_AARCH64_MOVW_UABS_G0 = 0x107,
- R_AARCH64_MOVW_UABS_G0_NC = 0x108,
- R_AARCH64_MOVW_UABS_G1 = 0x109,
- R_AARCH64_MOVW_UABS_G1_NC = 0x10a,
- R_AARCH64_MOVW_UABS_G2 = 0x10b,
- R_AARCH64_MOVW_UABS_G2_NC = 0x10c,
- R_AARCH64_MOVW_UABS_G3 = 0x10d,
- R_AARCH64_MOVW_SABS_G0 = 0x10e,
- R_AARCH64_MOVW_SABS_G1 = 0x10f,
- R_AARCH64_MOVW_SABS_G2 = 0x110,
-
- R_AARCH64_LD_PREL_LO19 = 0x111,
- R_AARCH64_ADR_PREL_LO21 = 0x112,
- R_AARCH64_ADR_PREL_PG_HI21 = 0x113,
- R_AARCH64_ADD_ABS_LO12_NC = 0x115,
- R_AARCH64_LDST8_ABS_LO12_NC = 0x116,
-
- R_AARCH64_TSTBR14 = 0x117,
- R_AARCH64_CONDBR19 = 0x118,
- R_AARCH64_JUMP26 = 0x11a,
- R_AARCH64_CALL26 = 0x11b,
-
- R_AARCH64_LDST16_ABS_LO12_NC = 0x11c,
- R_AARCH64_LDST32_ABS_LO12_NC = 0x11d,
- R_AARCH64_LDST64_ABS_LO12_NC = 0x11e,
-
- R_AARCH64_LDST128_ABS_LO12_NC = 0x12b,
-
- R_AARCH64_ADR_GOT_PAGE = 0x137,
- R_AARCH64_LD64_GOT_LO12_NC = 0x138,
-
- R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b,
- R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c,
- R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d,
- R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e,
- R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f,
- R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210,
- R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211,
- R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212,
- R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213,
- R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214,
- R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215,
- R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216,
- R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217,
- R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218,
- R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219,
- R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a,
-
- R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b,
- R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c,
- R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d,
- R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e,
- R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f,
-
- R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220,
- R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221,
- R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222,
- R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223,
- R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224,
- R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225,
- R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226,
- R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227,
- R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228,
- R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229,
- R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a,
- R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b,
- R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c,
- R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d,
- R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e,
- R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f,
-
- R_AARCH64_TLSDESC_ADR_PAGE = 0x232,
- R_AARCH64_TLSDESC_LD64_LO12_NC = 0x233,
- R_AARCH64_TLSDESC_ADD_LO12_NC = 0x234,
-
- R_AARCH64_TLSDESC_CALL = 0x239
+#include "ELFRelocs/AArch64.def"
};
// ARM Specific e_flags
@@ -717,140 +422,8 @@ enum : unsigned {
};
// ELF Relocation types for ARM
-// Meets 2.08 ABI Specs.
-
enum {
- R_ARM_NONE = 0x00,
- R_ARM_PC24 = 0x01,
- R_ARM_ABS32 = 0x02,
- R_ARM_REL32 = 0x03,
- R_ARM_LDR_PC_G0 = 0x04,
- R_ARM_ABS16 = 0x05,
- R_ARM_ABS12 = 0x06,
- R_ARM_THM_ABS5 = 0x07,
- R_ARM_ABS8 = 0x08,
- R_ARM_SBREL32 = 0x09,
- R_ARM_THM_CALL = 0x0a,
- R_ARM_THM_PC8 = 0x0b,
- R_ARM_BREL_ADJ = 0x0c,
- R_ARM_TLS_DESC = 0x0d,
- R_ARM_THM_SWI8 = 0x0e,
- R_ARM_XPC25 = 0x0f,
- R_ARM_THM_XPC22 = 0x10,
- R_ARM_TLS_DTPMOD32 = 0x11,
- R_ARM_TLS_DTPOFF32 = 0x12,
- R_ARM_TLS_TPOFF32 = 0x13,
- R_ARM_COPY = 0x14,
- R_ARM_GLOB_DAT = 0x15,
- R_ARM_JUMP_SLOT = 0x16,
- R_ARM_RELATIVE = 0x17,
- R_ARM_GOTOFF32 = 0x18,
- R_ARM_BASE_PREL = 0x19,
- R_ARM_GOT_BREL = 0x1a,
- R_ARM_PLT32 = 0x1b,
- R_ARM_CALL = 0x1c,
- R_ARM_JUMP24 = 0x1d,
- R_ARM_THM_JUMP24 = 0x1e,
- R_ARM_BASE_ABS = 0x1f,
- R_ARM_ALU_PCREL_7_0 = 0x20,
- R_ARM_ALU_PCREL_15_8 = 0x21,
- R_ARM_ALU_PCREL_23_15 = 0x22,
- R_ARM_LDR_SBREL_11_0_NC = 0x23,
- R_ARM_ALU_SBREL_19_12_NC = 0x24,
- R_ARM_ALU_SBREL_27_20_CK = 0x25,
- R_ARM_TARGET1 = 0x26,
- R_ARM_SBREL31 = 0x27,
- R_ARM_V4BX = 0x28,
- R_ARM_TARGET2 = 0x29,
- R_ARM_PREL31 = 0x2a,
- R_ARM_MOVW_ABS_NC = 0x2b,
- R_ARM_MOVT_ABS = 0x2c,
- R_ARM_MOVW_PREL_NC = 0x2d,
- R_ARM_MOVT_PREL = 0x2e,
- R_ARM_THM_MOVW_ABS_NC = 0x2f,
- R_ARM_THM_MOVT_ABS = 0x30,
- R_ARM_THM_MOVW_PREL_NC = 0x31,
- R_ARM_THM_MOVT_PREL = 0x32,
- R_ARM_THM_JUMP19 = 0x33,
- R_ARM_THM_JUMP6 = 0x34,
- R_ARM_THM_ALU_PREL_11_0 = 0x35,
- R_ARM_THM_PC12 = 0x36,
- R_ARM_ABS32_NOI = 0x37,
- R_ARM_REL32_NOI = 0x38,
- R_ARM_ALU_PC_G0_NC = 0x39,
- R_ARM_ALU_PC_G0 = 0x3a,
- R_ARM_ALU_PC_G1_NC = 0x3b,
- R_ARM_ALU_PC_G1 = 0x3c,
- R_ARM_ALU_PC_G2 = 0x3d,
- R_ARM_LDR_PC_G1 = 0x3e,
- R_ARM_LDR_PC_G2 = 0x3f,
- R_ARM_LDRS_PC_G0 = 0x40,
- R_ARM_LDRS_PC_G1 = 0x41,
- R_ARM_LDRS_PC_G2 = 0x42,
- R_ARM_LDC_PC_G0 = 0x43,
- R_ARM_LDC_PC_G1 = 0x44,
- R_ARM_LDC_PC_G2 = 0x45,
- R_ARM_ALU_SB_G0_NC = 0x46,
- R_ARM_ALU_SB_G0 = 0x47,
- R_ARM_ALU_SB_G1_NC = 0x48,
- R_ARM_ALU_SB_G1 = 0x49,
- R_ARM_ALU_SB_G2 = 0x4a,
- R_ARM_LDR_SB_G0 = 0x4b,
- R_ARM_LDR_SB_G1 = 0x4c,
- R_ARM_LDR_SB_G2 = 0x4d,
- R_ARM_LDRS_SB_G0 = 0x4e,
- R_ARM_LDRS_SB_G1 = 0x4f,
- R_ARM_LDRS_SB_G2 = 0x50,
- R_ARM_LDC_SB_G0 = 0x51,
- R_ARM_LDC_SB_G1 = 0x52,
- R_ARM_LDC_SB_G2 = 0x53,
- R_ARM_MOVW_BREL_NC = 0x54,
- R_ARM_MOVT_BREL = 0x55,
- R_ARM_MOVW_BREL = 0x56,
- R_ARM_THM_MOVW_BREL_NC = 0x57,
- R_ARM_THM_MOVT_BREL = 0x58,
- R_ARM_THM_MOVW_BREL = 0x59,
- R_ARM_TLS_GOTDESC = 0x5a,
- R_ARM_TLS_CALL = 0x5b,
- R_ARM_TLS_DESCSEQ = 0x5c,
- R_ARM_THM_TLS_CALL = 0x5d,
- R_ARM_PLT32_ABS = 0x5e,
- R_ARM_GOT_ABS = 0x5f,
- R_ARM_GOT_PREL = 0x60,
- R_ARM_GOT_BREL12 = 0x61,
- R_ARM_GOTOFF12 = 0x62,
- R_ARM_GOTRELAX = 0x63,
- R_ARM_GNU_VTENTRY = 0x64,
- R_ARM_GNU_VTINHERIT = 0x65,
- R_ARM_THM_JUMP11 = 0x66,
- R_ARM_THM_JUMP8 = 0x67,
- R_ARM_TLS_GD32 = 0x68,
- R_ARM_TLS_LDM32 = 0x69,
- R_ARM_TLS_LDO32 = 0x6a,
- R_ARM_TLS_IE32 = 0x6b,
- R_ARM_TLS_LE32 = 0x6c,
- R_ARM_TLS_LDO12 = 0x6d,
- R_ARM_TLS_LE12 = 0x6e,
- R_ARM_TLS_IE12GP = 0x6f,
- R_ARM_PRIVATE_0 = 0x70,
- R_ARM_PRIVATE_1 = 0x71,
- R_ARM_PRIVATE_2 = 0x72,
- R_ARM_PRIVATE_3 = 0x73,
- R_ARM_PRIVATE_4 = 0x74,
- R_ARM_PRIVATE_5 = 0x75,
- R_ARM_PRIVATE_6 = 0x76,
- R_ARM_PRIVATE_7 = 0x77,
- R_ARM_PRIVATE_8 = 0x78,
- R_ARM_PRIVATE_9 = 0x79,
- R_ARM_PRIVATE_10 = 0x7a,
- R_ARM_PRIVATE_11 = 0x7b,
- R_ARM_PRIVATE_12 = 0x7c,
- R_ARM_PRIVATE_13 = 0x7d,
- R_ARM_PRIVATE_14 = 0x7e,
- R_ARM_PRIVATE_15 = 0x7f,
- R_ARM_ME_TOO = 0x80,
- R_ARM_THM_TLS_DESCSEQ16 = 0x81,
- R_ARM_THM_TLS_DESCSEQ32 = 0x82
+#include "ELFRelocs/ARM.def"
};
// Mips Specific e_flags
@@ -861,7 +434,13 @@ enum : unsigned {
EF_MIPS_ABI2 = 0x00000020,
EF_MIPS_32BITMODE = 0x00000100,
EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding
+
+ // ABI flags
EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI
+ EF_MIPS_ABI_O64 = 0x00002000, // O32 ABI extended for 64-bit architecture.
+ EF_MIPS_ABI_EABI32 = 0x00003000, // EABI in 32 bit mode.
+ EF_MIPS_ABI_EABI64 = 0x00004000, // EABI in 64 bit mode.
+ EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant.
//ARCH_ASE
EF_MIPS_MICROMIPS = 0x02000000, // microMIPS
@@ -884,85 +463,7 @@ enum : unsigned {
// ELF Relocation types for Mips
enum {
- R_MIPS_NONE = 0,
- R_MIPS_16 = 1,
- R_MIPS_32 = 2,
- R_MIPS_REL32 = 3,
- R_MIPS_26 = 4,
- R_MIPS_HI16 = 5,
- R_MIPS_LO16 = 6,
- R_MIPS_GPREL16 = 7,
- R_MIPS_LITERAL = 8,
- R_MIPS_GOT16 = 9,
- R_MIPS_PC16 = 10,
- R_MIPS_CALL16 = 11,
- R_MIPS_GPREL32 = 12,
- R_MIPS_UNUSED1 = 13,
- R_MIPS_UNUSED2 = 14,
- R_MIPS_SHIFT5 = 16,
- R_MIPS_SHIFT6 = 17,
- R_MIPS_64 = 18,
- R_MIPS_GOT_DISP = 19,
- R_MIPS_GOT_PAGE = 20,
- R_MIPS_GOT_OFST = 21,
- R_MIPS_GOT_HI16 = 22,
- R_MIPS_GOT_LO16 = 23,
- R_MIPS_SUB = 24,
- R_MIPS_INSERT_A = 25,
- R_MIPS_INSERT_B = 26,
- R_MIPS_DELETE = 27,
- R_MIPS_HIGHER = 28,
- R_MIPS_HIGHEST = 29,
- R_MIPS_CALL_HI16 = 30,
- R_MIPS_CALL_LO16 = 31,
- R_MIPS_SCN_DISP = 32,
- R_MIPS_REL16 = 33,
- R_MIPS_ADD_IMMEDIATE = 34,
- R_MIPS_PJUMP = 35,
- R_MIPS_RELGOT = 36,
- R_MIPS_JALR = 37,
- R_MIPS_TLS_DTPMOD32 = 38,
- R_MIPS_TLS_DTPREL32 = 39,
- R_MIPS_TLS_DTPMOD64 = 40,
- R_MIPS_TLS_DTPREL64 = 41,
- R_MIPS_TLS_GD = 42,
- R_MIPS_TLS_LDM = 43,
- R_MIPS_TLS_DTPREL_HI16 = 44,
- R_MIPS_TLS_DTPREL_LO16 = 45,
- R_MIPS_TLS_GOTTPREL = 46,
- R_MIPS_TLS_TPREL32 = 47,
- R_MIPS_TLS_TPREL64 = 48,
- R_MIPS_TLS_TPREL_HI16 = 49,
- R_MIPS_TLS_TPREL_LO16 = 50,
- R_MIPS_GLOB_DAT = 51,
- R_MIPS_PC21_S2 = 60,
- R_MIPS_PC26_S2 = 61,
- R_MIPS_PC18_S3 = 62,
- R_MIPS_PC19_S2 = 63,
- R_MIPS_PCHI16 = 64,
- R_MIPS_PCLO16 = 65,
- R_MIPS16_GOT16 = 102,
- R_MIPS16_HI16 = 104,
- R_MIPS16_LO16 = 105,
- R_MIPS_COPY = 126,
- R_MIPS_JUMP_SLOT = 127,
- R_MICROMIPS_26_S1 = 133,
- R_MICROMIPS_HI16 = 134,
- R_MICROMIPS_LO16 = 135,
- R_MICROMIPS_GOT16 = 138,
- R_MICROMIPS_PC16_S1 = 141,
- R_MICROMIPS_CALL16 = 142,
- R_MICROMIPS_GOT_DISP = 145,
- R_MICROMIPS_GOT_PAGE = 146,
- R_MICROMIPS_GOT_OFST = 147,
- R_MICROMIPS_TLS_GD = 162,
- R_MICROMIPS_TLS_LDM = 163,
- R_MICROMIPS_TLS_DTPREL_HI16 = 164,
- R_MICROMIPS_TLS_DTPREL_LO16 = 165,
- R_MICROMIPS_TLS_TPREL_HI16 = 169,
- R_MICROMIPS_TLS_TPREL_LO16 = 170,
- R_MIPS_NUM = 218,
- R_MIPS_PC32 = 248
+#include "ELFRelocs/Mips.def"
};
// Special values for the st_other field in the symbol table entry for MIPS.
@@ -1003,250 +504,22 @@ enum {
};
// ELF Relocation types for Hexagon
-// Release 5 ABI
enum {
- R_HEX_NONE = 0,
- R_HEX_B22_PCREL = 1,
- R_HEX_B15_PCREL = 2,
- R_HEX_B7_PCREL = 3,
- R_HEX_LO16 = 4,
- R_HEX_HI16 = 5,
- R_HEX_32 = 6,
- R_HEX_16 = 7,
- R_HEX_8 = 8,
- R_HEX_GPREL16_0 = 9,
- R_HEX_GPREL16_1 = 10,
- R_HEX_GPREL16_2 = 11,
- R_HEX_GPREL16_3 = 12,
- R_HEX_HL16 = 13,
- R_HEX_B13_PCREL = 14,
- R_HEX_B9_PCREL = 15,
- R_HEX_B32_PCREL_X = 16,
- R_HEX_32_6_X = 17,
- R_HEX_B22_PCREL_X = 18,
- R_HEX_B15_PCREL_X = 19,
- R_HEX_B13_PCREL_X = 20,
- R_HEX_B9_PCREL_X = 21,
- R_HEX_B7_PCREL_X = 22,
- R_HEX_16_X = 23,
- R_HEX_12_X = 24,
- R_HEX_11_X = 25,
- R_HEX_10_X = 26,
- R_HEX_9_X = 27,
- R_HEX_8_X = 28,
- R_HEX_7_X = 29,
- R_HEX_6_X = 30,
- R_HEX_32_PCREL = 31,
- R_HEX_COPY = 32,
- R_HEX_GLOB_DAT = 33,
- R_HEX_JMP_SLOT = 34,
- R_HEX_RELATIVE = 35,
- R_HEX_PLT_B22_PCREL = 36,
- R_HEX_GOTREL_LO16 = 37,
- R_HEX_GOTREL_HI16 = 38,
- R_HEX_GOTREL_32 = 39,
- R_HEX_GOT_LO16 = 40,
- R_HEX_GOT_HI16 = 41,
- R_HEX_GOT_32 = 42,
- R_HEX_GOT_16 = 43,
- R_HEX_DTPMOD_32 = 44,
- R_HEX_DTPREL_LO16 = 45,
- R_HEX_DTPREL_HI16 = 46,
- R_HEX_DTPREL_32 = 47,
- R_HEX_DTPREL_16 = 48,
- R_HEX_GD_PLT_B22_PCREL = 49,
- R_HEX_GD_GOT_LO16 = 50,
- R_HEX_GD_GOT_HI16 = 51,
- R_HEX_GD_GOT_32 = 52,
- R_HEX_GD_GOT_16 = 53,
- R_HEX_IE_LO16 = 54,
- R_HEX_IE_HI16 = 55,
- R_HEX_IE_32 = 56,
- R_HEX_IE_GOT_LO16 = 57,
- R_HEX_IE_GOT_HI16 = 58,
- R_HEX_IE_GOT_32 = 59,
- R_HEX_IE_GOT_16 = 60,
- R_HEX_TPREL_LO16 = 61,
- R_HEX_TPREL_HI16 = 62,
- R_HEX_TPREL_32 = 63,
- R_HEX_TPREL_16 = 64,
- R_HEX_6_PCREL_X = 65,
- R_HEX_GOTREL_32_6_X = 66,
- R_HEX_GOTREL_16_X = 67,
- R_HEX_GOTREL_11_X = 68,
- R_HEX_GOT_32_6_X = 69,
- R_HEX_GOT_16_X = 70,
- R_HEX_GOT_11_X = 71,
- R_HEX_DTPREL_32_6_X = 72,
- R_HEX_DTPREL_16_X = 73,
- R_HEX_DTPREL_11_X = 74,
- R_HEX_GD_GOT_32_6_X = 75,
- R_HEX_GD_GOT_16_X = 76,
- R_HEX_GD_GOT_11_X = 77,
- R_HEX_IE_32_6_X = 78,
- R_HEX_IE_16_X = 79,
- R_HEX_IE_GOT_32_6_X = 80,
- R_HEX_IE_GOT_16_X = 81,
- R_HEX_IE_GOT_11_X = 82,
- R_HEX_TPREL_32_6_X = 83,
- R_HEX_TPREL_16_X = 84,
- R_HEX_TPREL_11_X = 85
+#include "ELFRelocs/Hexagon.def"
};
// ELF Relocation types for S390/zSeries
enum {
- R_390_NONE = 0,
- R_390_8 = 1,
- R_390_12 = 2,
- R_390_16 = 3,
- R_390_32 = 4,
- R_390_PC32 = 5,
- R_390_GOT12 = 6,
- R_390_GOT32 = 7,
- R_390_PLT32 = 8,
- R_390_COPY = 9,
- R_390_GLOB_DAT = 10,
- R_390_JMP_SLOT = 11,
- R_390_RELATIVE = 12,
- R_390_GOTOFF = 13,
- R_390_GOTPC = 14,
- R_390_GOT16 = 15,
- R_390_PC16 = 16,
- R_390_PC16DBL = 17,
- R_390_PLT16DBL = 18,
- R_390_PC32DBL = 19,
- R_390_PLT32DBL = 20,
- R_390_GOTPCDBL = 21,
- R_390_64 = 22,
- R_390_PC64 = 23,
- R_390_GOT64 = 24,
- R_390_PLT64 = 25,
- R_390_GOTENT = 26,
- R_390_GOTOFF16 = 27,
- R_390_GOTOFF64 = 28,
- R_390_GOTPLT12 = 29,
- R_390_GOTPLT16 = 30,
- R_390_GOTPLT32 = 31,
- R_390_GOTPLT64 = 32,
- R_390_GOTPLTENT = 33,
- R_390_PLTOFF16 = 34,
- R_390_PLTOFF32 = 35,
- R_390_PLTOFF64 = 36,
- R_390_TLS_LOAD = 37,
- R_390_TLS_GDCALL = 38,
- R_390_TLS_LDCALL = 39,
- R_390_TLS_GD32 = 40,
- R_390_TLS_GD64 = 41,
- R_390_TLS_GOTIE12 = 42,
- R_390_TLS_GOTIE32 = 43,
- R_390_TLS_GOTIE64 = 44,
- R_390_TLS_LDM32 = 45,
- R_390_TLS_LDM64 = 46,
- R_390_TLS_IE32 = 47,
- R_390_TLS_IE64 = 48,
- R_390_TLS_IEENT = 49,
- R_390_TLS_LE32 = 50,
- R_390_TLS_LE64 = 51,
- R_390_TLS_LDO32 = 52,
- R_390_TLS_LDO64 = 53,
- R_390_TLS_DTPMOD = 54,
- R_390_TLS_DTPOFF = 55,
- R_390_TLS_TPOFF = 56,
- R_390_20 = 57,
- R_390_GOT20 = 58,
- R_390_GOTPLT20 = 59,
- R_390_TLS_GOTIE20 = 60,
- R_390_IRELATIVE = 61
+#include "ELFRelocs/SystemZ.def"
};
// ELF Relocation type for Sparc.
enum {
- R_SPARC_NONE = 0,
- R_SPARC_8 = 1,
- R_SPARC_16 = 2,
- R_SPARC_32 = 3,
- R_SPARC_DISP8 = 4,
- R_SPARC_DISP16 = 5,
- R_SPARC_DISP32 = 6,
- R_SPARC_WDISP30 = 7,
- R_SPARC_WDISP22 = 8,
- R_SPARC_HI22 = 9,
- R_SPARC_22 = 10,
- R_SPARC_13 = 11,
- R_SPARC_LO10 = 12,
- R_SPARC_GOT10 = 13,
- R_SPARC_GOT13 = 14,
- R_SPARC_GOT22 = 15,
- R_SPARC_PC10 = 16,
- R_SPARC_PC22 = 17,
- R_SPARC_WPLT30 = 18,
- R_SPARC_COPY = 19,
- R_SPARC_GLOB_DAT = 20,
- R_SPARC_JMP_SLOT = 21,
- R_SPARC_RELATIVE = 22,
- R_SPARC_UA32 = 23,
- R_SPARC_PLT32 = 24,
- R_SPARC_HIPLT22 = 25,
- R_SPARC_LOPLT10 = 26,
- R_SPARC_PCPLT32 = 27,
- R_SPARC_PCPLT22 = 28,
- R_SPARC_PCPLT10 = 29,
- R_SPARC_10 = 30,
- R_SPARC_11 = 31,
- R_SPARC_64 = 32,
- R_SPARC_OLO10 = 33,
- R_SPARC_HH22 = 34,
- R_SPARC_HM10 = 35,
- R_SPARC_LM22 = 36,
- R_SPARC_PC_HH22 = 37,
- R_SPARC_PC_HM10 = 38,
- R_SPARC_PC_LM22 = 39,
- R_SPARC_WDISP16 = 40,
- R_SPARC_WDISP19 = 41,
- R_SPARC_7 = 43,
- R_SPARC_5 = 44,
- R_SPARC_6 = 45,
- R_SPARC_DISP64 = 46,
- R_SPARC_PLT64 = 47,
- R_SPARC_HIX22 = 48,
- R_SPARC_LOX10 = 49,
- R_SPARC_H44 = 50,
- R_SPARC_M44 = 51,
- R_SPARC_L44 = 52,
- R_SPARC_REGISTER = 53,
- R_SPARC_UA64 = 54,
- R_SPARC_UA16 = 55,
- R_SPARC_TLS_GD_HI22 = 56,
- R_SPARC_TLS_GD_LO10 = 57,
- R_SPARC_TLS_GD_ADD = 58,
- R_SPARC_TLS_GD_CALL = 59,
- R_SPARC_TLS_LDM_HI22 = 60,
- R_SPARC_TLS_LDM_LO10 = 61,
- R_SPARC_TLS_LDM_ADD = 62,
- R_SPARC_TLS_LDM_CALL = 63,
- R_SPARC_TLS_LDO_HIX22 = 64,
- R_SPARC_TLS_LDO_LOX10 = 65,
- R_SPARC_TLS_LDO_ADD = 66,
- R_SPARC_TLS_IE_HI22 = 67,
- R_SPARC_TLS_IE_LO10 = 68,
- R_SPARC_TLS_IE_LD = 69,
- R_SPARC_TLS_IE_LDX = 70,
- R_SPARC_TLS_IE_ADD = 71,
- R_SPARC_TLS_LE_HIX22 = 72,
- R_SPARC_TLS_LE_LOX10 = 73,
- R_SPARC_TLS_DTPMOD32 = 74,
- R_SPARC_TLS_DTPMOD64 = 75,
- R_SPARC_TLS_DTPOFF32 = 76,
- R_SPARC_TLS_DTPOFF64 = 77,
- R_SPARC_TLS_TPOFF32 = 78,
- R_SPARC_TLS_TPOFF64 = 79,
- R_SPARC_GOTDATA_HIX22 = 80,
- R_SPARC_GOTDATA_LOX22 = 81,
- R_SPARC_GOTDATA_OP_HIX22 = 82,
- R_SPARC_GOTDATA_OP_LOX22 = 83,
- R_SPARC_GOTDATA_OP = 84
+#include "ELFRelocs/Sparc.def"
};
+#undef ELF_RELOC
+
// Section header.
struct Elf32_Shdr {
Elf32_Word sh_name; // Section name (index into string table)
diff --git a/include/llvm/Support/ELFRelocs/AArch64.def b/include/llvm/Support/ELFRelocs/AArch64.def
new file mode 100644
index 000000000000..aa0c560f3e50
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/AArch64.def
@@ -0,0 +1,147 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// ABI release 1.0
+ELF_RELOC(R_AARCH64_NONE, 0)
+
+ELF_RELOC(R_AARCH64_ABS64, 0x101)
+ELF_RELOC(R_AARCH64_ABS32, 0x102)
+ELF_RELOC(R_AARCH64_ABS16, 0x103)
+ELF_RELOC(R_AARCH64_PREL64, 0x104)
+ELF_RELOC(R_AARCH64_PREL32, 0x105)
+ELF_RELOC(R_AARCH64_PREL16, 0x106)
+
+ELF_RELOC(R_AARCH64_MOVW_UABS_G0, 0x107)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G0_NC, 0x108)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G1, 0x109)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G1_NC, 0x10a)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G2, 0x10b)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G2_NC, 0x10c)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G3, 0x10d)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G0, 0x10e)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G1, 0x10f)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G2, 0x110)
+
+ELF_RELOC(R_AARCH64_LD_PREL_LO19, 0x111)
+ELF_RELOC(R_AARCH64_ADR_PREL_LO21, 0x112)
+ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21, 0x113)
+ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC, 0x114)
+ELF_RELOC(R_AARCH64_ADD_ABS_LO12_NC, 0x115)
+ELF_RELOC(R_AARCH64_LDST8_ABS_LO12_NC, 0x116)
+
+ELF_RELOC(R_AARCH64_TSTBR14, 0x117)
+ELF_RELOC(R_AARCH64_CONDBR19, 0x118)
+ELF_RELOC(R_AARCH64_JUMP26, 0x11a)
+ELF_RELOC(R_AARCH64_CALL26, 0x11b)
+
+ELF_RELOC(R_AARCH64_LDST16_ABS_LO12_NC, 0x11c)
+ELF_RELOC(R_AARCH64_LDST32_ABS_LO12_NC, 0x11d)
+ELF_RELOC(R_AARCH64_LDST64_ABS_LO12_NC, 0x11e)
+
+ELF_RELOC(R_AARCH64_MOVW_PREL_G0, 0x11f)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G0_NC, 0x120)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G1, 0x121)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G1_NC, 0x122)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G2, 0x123)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G2_NC, 0x124)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G3, 0x125)
+
+ELF_RELOC(R_AARCH64_LDST128_ABS_LO12_NC, 0x12b)
+
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0, 0x12c)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC, 0x12d)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1, 0x12e)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC, 0x12f)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2, 0x130)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC, 0x131)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G3, 0x132)
+
+ELF_RELOC(R_AARCH64_GOTREL64, 0x133)
+ELF_RELOC(R_AARCH64_GOTREL32, 0x134)
+
+ELF_RELOC(R_AARCH64_GOT_LD_PREL19, 0x135)
+ELF_RELOC(R_AARCH64_LD64_GOTOFF_LO15, 0x136)
+ELF_RELOC(R_AARCH64_ADR_GOT_PAGE, 0x137)
+ELF_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 0x138)
+ELF_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 0x139)
+
+ELF_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 0x200)
+ELF_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 0x201)
+ELF_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 0x202)
+ELF_RELOC(R_AARCH64_TLSGD_MOVW_G1, 0x203)
+ELF_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC, 0x204)
+
+ELF_RELOC(R_AARCH64_TLSLD_ADR_PREL21, 0x205)
+ELF_RELOC(R_AARCH64_TLSLD_ADR_PAGE21, 0x206)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC, 0x207)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_G1, 0x208)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC, 0x209)
+ELF_RELOC(R_AARCH64_TLSLD_LD_PREL19, 0x20a)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2, 0x20b)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1, 0x20c)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, 0x20d)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0, 0x20e)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, 0x20f)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12, 0x210)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12, 0x211)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, 0x212)
+ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, 0x213)
+ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, 0x214)
+ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, 0x215)
+ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, 0x216)
+ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, 0x217)
+ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, 0x218)
+ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, 0x219)
+ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, 0x21a)
+
+ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 0x21b)
+ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 0x21c)
+ELF_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 0x21d)
+ELF_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 0x21e)
+ELF_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 0x21f)
+
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2, 0x220)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1, 0x221)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 0x222)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0, 0x223)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 0x224)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12, 0x225)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12, 0x226)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 0x227)
+ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12, 0x228)
+ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, 0x229)
+ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12, 0x22a)
+ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, 0x22b)
+ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12, 0x22c)
+ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, 0x22d)
+ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12, 0x22e)
+ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, 0x22f)
+
+ELF_RELOC(R_AARCH64_TLSDESC_LD_PREL19, 0x230)
+ELF_RELOC(R_AARCH64_TLSDESC_ADR_PREL21, 0x231)
+ELF_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21, 0x232)
+ELF_RELOC(R_AARCH64_TLSDESC_LD64_LO12_NC, 0x233)
+ELF_RELOC(R_AARCH64_TLSDESC_ADD_LO12_NC, 0x234)
+ELF_RELOC(R_AARCH64_TLSDESC_OFF_G1, 0x235)
+ELF_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC, 0x236)
+ELF_RELOC(R_AARCH64_TLSDESC_LDR, 0x237)
+ELF_RELOC(R_AARCH64_TLSDESC_ADD, 0x238)
+ELF_RELOC(R_AARCH64_TLSDESC_CALL, 0x239)
+
+ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 0x23a)
+ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 0x23b)
+
+ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 0x23c)
+ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 0x23d)
+
+ELF_RELOC(R_AARCH64_COPY, 0x400)
+ELF_RELOC(R_AARCH64_GLOB_DAT, 0x401)
+ELF_RELOC(R_AARCH64_JUMP_SLOT, 0x402)
+ELF_RELOC(R_AARCH64_RELATIVE, 0x403)
+ELF_RELOC(R_AARCH64_TLS_DTPREL64, 0x404)
+ELF_RELOC(R_AARCH64_TLS_DTPMOD64, 0x405)
+ELF_RELOC(R_AARCH64_TLS_TPREL64, 0x406)
+ELF_RELOC(R_AARCH64_TLSDESC, 0x407)
+ELF_RELOC(R_AARCH64_IRELATIVE, 0x408)
diff --git a/include/llvm/Support/ELFRelocs/ARM.def b/include/llvm/Support/ELFRelocs/ARM.def
new file mode 100644
index 000000000000..730fc5b8836c
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/ARM.def
@@ -0,0 +1,138 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// Meets 2.09 ABI Specs.
+ELF_RELOC(R_ARM_NONE, 0x00)
+ELF_RELOC(R_ARM_PC24, 0x01)
+ELF_RELOC(R_ARM_ABS32, 0x02)
+ELF_RELOC(R_ARM_REL32, 0x03)
+ELF_RELOC(R_ARM_LDR_PC_G0, 0x04)
+ELF_RELOC(R_ARM_ABS16, 0x05)
+ELF_RELOC(R_ARM_ABS12, 0x06)
+ELF_RELOC(R_ARM_THM_ABS5, 0x07)
+ELF_RELOC(R_ARM_ABS8, 0x08)
+ELF_RELOC(R_ARM_SBREL32, 0x09)
+ELF_RELOC(R_ARM_THM_CALL, 0x0a)
+ELF_RELOC(R_ARM_THM_PC8, 0x0b)
+ELF_RELOC(R_ARM_BREL_ADJ, 0x0c)
+ELF_RELOC(R_ARM_TLS_DESC, 0x0d)
+ELF_RELOC(R_ARM_THM_SWI8, 0x0e)
+ELF_RELOC(R_ARM_XPC25, 0x0f)
+ELF_RELOC(R_ARM_THM_XPC22, 0x10)
+ELF_RELOC(R_ARM_TLS_DTPMOD32, 0x11)
+ELF_RELOC(R_ARM_TLS_DTPOFF32, 0x12)
+ELF_RELOC(R_ARM_TLS_TPOFF32, 0x13)
+ELF_RELOC(R_ARM_COPY, 0x14)
+ELF_RELOC(R_ARM_GLOB_DAT, 0x15)
+ELF_RELOC(R_ARM_JUMP_SLOT, 0x16)
+ELF_RELOC(R_ARM_RELATIVE, 0x17)
+ELF_RELOC(R_ARM_GOTOFF32, 0x18)
+ELF_RELOC(R_ARM_BASE_PREL, 0x19)
+ELF_RELOC(R_ARM_GOT_BREL, 0x1a)
+ELF_RELOC(R_ARM_PLT32, 0x1b)
+ELF_RELOC(R_ARM_CALL, 0x1c)
+ELF_RELOC(R_ARM_JUMP24, 0x1d)
+ELF_RELOC(R_ARM_THM_JUMP24, 0x1e)
+ELF_RELOC(R_ARM_BASE_ABS, 0x1f)
+ELF_RELOC(R_ARM_ALU_PCREL_7_0, 0x20)
+ELF_RELOC(R_ARM_ALU_PCREL_15_8, 0x21)
+ELF_RELOC(R_ARM_ALU_PCREL_23_15, 0x22)
+ELF_RELOC(R_ARM_LDR_SBREL_11_0_NC, 0x23)
+ELF_RELOC(R_ARM_ALU_SBREL_19_12_NC, 0x24)
+ELF_RELOC(R_ARM_ALU_SBREL_27_20_CK, 0x25)
+ELF_RELOC(R_ARM_TARGET1, 0x26)
+ELF_RELOC(R_ARM_SBREL31, 0x27)
+ELF_RELOC(R_ARM_V4BX, 0x28)
+ELF_RELOC(R_ARM_TARGET2, 0x29)
+ELF_RELOC(R_ARM_PREL31, 0x2a)
+ELF_RELOC(R_ARM_MOVW_ABS_NC, 0x2b)
+ELF_RELOC(R_ARM_MOVT_ABS, 0x2c)
+ELF_RELOC(R_ARM_MOVW_PREL_NC, 0x2d)
+ELF_RELOC(R_ARM_MOVT_PREL, 0x2e)
+ELF_RELOC(R_ARM_THM_MOVW_ABS_NC, 0x2f)
+ELF_RELOC(R_ARM_THM_MOVT_ABS, 0x30)
+ELF_RELOC(R_ARM_THM_MOVW_PREL_NC, 0x31)
+ELF_RELOC(R_ARM_THM_MOVT_PREL, 0x32)
+ELF_RELOC(R_ARM_THM_JUMP19, 0x33)
+ELF_RELOC(R_ARM_THM_JUMP6, 0x34)
+ELF_RELOC(R_ARM_THM_ALU_PREL_11_0, 0x35)
+ELF_RELOC(R_ARM_THM_PC12, 0x36)
+ELF_RELOC(R_ARM_ABS32_NOI, 0x37)
+ELF_RELOC(R_ARM_REL32_NOI, 0x38)
+ELF_RELOC(R_ARM_ALU_PC_G0_NC, 0x39)
+ELF_RELOC(R_ARM_ALU_PC_G0, 0x3a)
+ELF_RELOC(R_ARM_ALU_PC_G1_NC, 0x3b)
+ELF_RELOC(R_ARM_ALU_PC_G1, 0x3c)
+ELF_RELOC(R_ARM_ALU_PC_G2, 0x3d)
+ELF_RELOC(R_ARM_LDR_PC_G1, 0x3e)
+ELF_RELOC(R_ARM_LDR_PC_G2, 0x3f)
+ELF_RELOC(R_ARM_LDRS_PC_G0, 0x40)
+ELF_RELOC(R_ARM_LDRS_PC_G1, 0x41)
+ELF_RELOC(R_ARM_LDRS_PC_G2, 0x42)
+ELF_RELOC(R_ARM_LDC_PC_G0, 0x43)
+ELF_RELOC(R_ARM_LDC_PC_G1, 0x44)
+ELF_RELOC(R_ARM_LDC_PC_G2, 0x45)
+ELF_RELOC(R_ARM_ALU_SB_G0_NC, 0x46)
+ELF_RELOC(R_ARM_ALU_SB_G0, 0x47)
+ELF_RELOC(R_ARM_ALU_SB_G1_NC, 0x48)
+ELF_RELOC(R_ARM_ALU_SB_G1, 0x49)
+ELF_RELOC(R_ARM_ALU_SB_G2, 0x4a)
+ELF_RELOC(R_ARM_LDR_SB_G0, 0x4b)
+ELF_RELOC(R_ARM_LDR_SB_G1, 0x4c)
+ELF_RELOC(R_ARM_LDR_SB_G2, 0x4d)
+ELF_RELOC(R_ARM_LDRS_SB_G0, 0x4e)
+ELF_RELOC(R_ARM_LDRS_SB_G1, 0x4f)
+ELF_RELOC(R_ARM_LDRS_SB_G2, 0x50)
+ELF_RELOC(R_ARM_LDC_SB_G0, 0x51)
+ELF_RELOC(R_ARM_LDC_SB_G1, 0x52)
+ELF_RELOC(R_ARM_LDC_SB_G2, 0x53)
+ELF_RELOC(R_ARM_MOVW_BREL_NC, 0x54)
+ELF_RELOC(R_ARM_MOVT_BREL, 0x55)
+ELF_RELOC(R_ARM_MOVW_BREL, 0x56)
+ELF_RELOC(R_ARM_THM_MOVW_BREL_NC, 0x57)
+ELF_RELOC(R_ARM_THM_MOVT_BREL, 0x58)
+ELF_RELOC(R_ARM_THM_MOVW_BREL, 0x59)
+ELF_RELOC(R_ARM_TLS_GOTDESC, 0x5a)
+ELF_RELOC(R_ARM_TLS_CALL, 0x5b)
+ELF_RELOC(R_ARM_TLS_DESCSEQ, 0x5c)
+ELF_RELOC(R_ARM_THM_TLS_CALL, 0x5d)
+ELF_RELOC(R_ARM_PLT32_ABS, 0x5e)
+ELF_RELOC(R_ARM_GOT_ABS, 0x5f)
+ELF_RELOC(R_ARM_GOT_PREL, 0x60)
+ELF_RELOC(R_ARM_GOT_BREL12, 0x61)
+ELF_RELOC(R_ARM_GOTOFF12, 0x62)
+ELF_RELOC(R_ARM_GOTRELAX, 0x63)
+ELF_RELOC(R_ARM_GNU_VTENTRY, 0x64)
+ELF_RELOC(R_ARM_GNU_VTINHERIT, 0x65)
+ELF_RELOC(R_ARM_THM_JUMP11, 0x66)
+ELF_RELOC(R_ARM_THM_JUMP8, 0x67)
+ELF_RELOC(R_ARM_TLS_GD32, 0x68)
+ELF_RELOC(R_ARM_TLS_LDM32, 0x69)
+ELF_RELOC(R_ARM_TLS_LDO32, 0x6a)
+ELF_RELOC(R_ARM_TLS_IE32, 0x6b)
+ELF_RELOC(R_ARM_TLS_LE32, 0x6c)
+ELF_RELOC(R_ARM_TLS_LDO12, 0x6d)
+ELF_RELOC(R_ARM_TLS_LE12, 0x6e)
+ELF_RELOC(R_ARM_TLS_IE12GP, 0x6f)
+ELF_RELOC(R_ARM_PRIVATE_0, 0x70)
+ELF_RELOC(R_ARM_PRIVATE_1, 0x71)
+ELF_RELOC(R_ARM_PRIVATE_2, 0x72)
+ELF_RELOC(R_ARM_PRIVATE_3, 0x73)
+ELF_RELOC(R_ARM_PRIVATE_4, 0x74)
+ELF_RELOC(R_ARM_PRIVATE_5, 0x75)
+ELF_RELOC(R_ARM_PRIVATE_6, 0x76)
+ELF_RELOC(R_ARM_PRIVATE_7, 0x77)
+ELF_RELOC(R_ARM_PRIVATE_8, 0x78)
+ELF_RELOC(R_ARM_PRIVATE_9, 0x79)
+ELF_RELOC(R_ARM_PRIVATE_10, 0x7a)
+ELF_RELOC(R_ARM_PRIVATE_11, 0x7b)
+ELF_RELOC(R_ARM_PRIVATE_12, 0x7c)
+ELF_RELOC(R_ARM_PRIVATE_13, 0x7d)
+ELF_RELOC(R_ARM_PRIVATE_14, 0x7e)
+ELF_RELOC(R_ARM_PRIVATE_15, 0x7f)
+ELF_RELOC(R_ARM_ME_TOO, 0x80)
+ELF_RELOC(R_ARM_THM_TLS_DESCSEQ16, 0x81)
+ELF_RELOC(R_ARM_THM_TLS_DESCSEQ32, 0x82)
+ELF_RELOC(R_ARM_IRELATIVE, 0xa0)
diff --git a/include/llvm/Support/ELFRelocs/Hexagon.def b/include/llvm/Support/ELFRelocs/Hexagon.def
new file mode 100644
index 000000000000..c9d35b8bd75e
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/Hexagon.def
@@ -0,0 +1,92 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// Release 5 ABI
+ELF_RELOC(R_HEX_NONE, 0)
+ELF_RELOC(R_HEX_B22_PCREL, 1)
+ELF_RELOC(R_HEX_B15_PCREL, 2)
+ELF_RELOC(R_HEX_B7_PCREL, 3)
+ELF_RELOC(R_HEX_LO16, 4)
+ELF_RELOC(R_HEX_HI16, 5)
+ELF_RELOC(R_HEX_32, 6)
+ELF_RELOC(R_HEX_16, 7)
+ELF_RELOC(R_HEX_8, 8)
+ELF_RELOC(R_HEX_GPREL16_0, 9)
+ELF_RELOC(R_HEX_GPREL16_1, 10)
+ELF_RELOC(R_HEX_GPREL16_2, 11)
+ELF_RELOC(R_HEX_GPREL16_3, 12)
+ELF_RELOC(R_HEX_HL16, 13)
+ELF_RELOC(R_HEX_B13_PCREL, 14)
+ELF_RELOC(R_HEX_B9_PCREL, 15)
+ELF_RELOC(R_HEX_B32_PCREL_X, 16)
+ELF_RELOC(R_HEX_32_6_X, 17)
+ELF_RELOC(R_HEX_B22_PCREL_X, 18)
+ELF_RELOC(R_HEX_B15_PCREL_X, 19)
+ELF_RELOC(R_HEX_B13_PCREL_X, 20)
+ELF_RELOC(R_HEX_B9_PCREL_X, 21)
+ELF_RELOC(R_HEX_B7_PCREL_X, 22)
+ELF_RELOC(R_HEX_16_X, 23)
+ELF_RELOC(R_HEX_12_X, 24)
+ELF_RELOC(R_HEX_11_X, 25)
+ELF_RELOC(R_HEX_10_X, 26)
+ELF_RELOC(R_HEX_9_X, 27)
+ELF_RELOC(R_HEX_8_X, 28)
+ELF_RELOC(R_HEX_7_X, 29)
+ELF_RELOC(R_HEX_6_X, 30)
+ELF_RELOC(R_HEX_32_PCREL, 31)
+ELF_RELOC(R_HEX_COPY, 32)
+ELF_RELOC(R_HEX_GLOB_DAT, 33)
+ELF_RELOC(R_HEX_JMP_SLOT, 34)
+ELF_RELOC(R_HEX_RELATIVE, 35)
+ELF_RELOC(R_HEX_PLT_B22_PCREL, 36)
+ELF_RELOC(R_HEX_GOTREL_LO16, 37)
+ELF_RELOC(R_HEX_GOTREL_HI16, 38)
+ELF_RELOC(R_HEX_GOTREL_32, 39)
+ELF_RELOC(R_HEX_GOT_LO16, 40)
+ELF_RELOC(R_HEX_GOT_HI16, 41)
+ELF_RELOC(R_HEX_GOT_32, 42)
+ELF_RELOC(R_HEX_GOT_16, 43)
+ELF_RELOC(R_HEX_DTPMOD_32, 44)
+ELF_RELOC(R_HEX_DTPREL_LO16, 45)
+ELF_RELOC(R_HEX_DTPREL_HI16, 46)
+ELF_RELOC(R_HEX_DTPREL_32, 47)
+ELF_RELOC(R_HEX_DTPREL_16, 48)
+ELF_RELOC(R_HEX_GD_PLT_B22_PCREL, 49)
+ELF_RELOC(R_HEX_GD_GOT_LO16, 50)
+ELF_RELOC(R_HEX_GD_GOT_HI16, 51)
+ELF_RELOC(R_HEX_GD_GOT_32, 52)
+ELF_RELOC(R_HEX_GD_GOT_16, 53)
+ELF_RELOC(R_HEX_IE_LO16, 54)
+ELF_RELOC(R_HEX_IE_HI16, 55)
+ELF_RELOC(R_HEX_IE_32, 56)
+ELF_RELOC(R_HEX_IE_GOT_LO16, 57)
+ELF_RELOC(R_HEX_IE_GOT_HI16, 58)
+ELF_RELOC(R_HEX_IE_GOT_32, 59)
+ELF_RELOC(R_HEX_IE_GOT_16, 60)
+ELF_RELOC(R_HEX_TPREL_LO16, 61)
+ELF_RELOC(R_HEX_TPREL_HI16, 62)
+ELF_RELOC(R_HEX_TPREL_32, 63)
+ELF_RELOC(R_HEX_TPREL_16, 64)
+ELF_RELOC(R_HEX_6_PCREL_X, 65)
+ELF_RELOC(R_HEX_GOTREL_32_6_X, 66)
+ELF_RELOC(R_HEX_GOTREL_16_X, 67)
+ELF_RELOC(R_HEX_GOTREL_11_X, 68)
+ELF_RELOC(R_HEX_GOT_32_6_X, 69)
+ELF_RELOC(R_HEX_GOT_16_X, 70)
+ELF_RELOC(R_HEX_GOT_11_X, 71)
+ELF_RELOC(R_HEX_DTPREL_32_6_X, 72)
+ELF_RELOC(R_HEX_DTPREL_16_X, 73)
+ELF_RELOC(R_HEX_DTPREL_11_X, 74)
+ELF_RELOC(R_HEX_GD_GOT_32_6_X, 75)
+ELF_RELOC(R_HEX_GD_GOT_16_X, 76)
+ELF_RELOC(R_HEX_GD_GOT_11_X, 77)
+ELF_RELOC(R_HEX_IE_32_6_X, 78)
+ELF_RELOC(R_HEX_IE_16_X, 79)
+ELF_RELOC(R_HEX_IE_GOT_32_6_X, 80)
+ELF_RELOC(R_HEX_IE_GOT_16_X, 81)
+ELF_RELOC(R_HEX_IE_GOT_11_X, 82)
+ELF_RELOC(R_HEX_TPREL_32_6_X, 83)
+ELF_RELOC(R_HEX_TPREL_16_X, 84)
+ELF_RELOC(R_HEX_TPREL_11_X, 85)
diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def
new file mode 100644
index 000000000000..dc573464dcf2
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/Mips.def
@@ -0,0 +1,112 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_MIPS_NONE, 0)
+ELF_RELOC(R_MIPS_16, 1)
+ELF_RELOC(R_MIPS_32, 2)
+ELF_RELOC(R_MIPS_REL32, 3)
+ELF_RELOC(R_MIPS_26, 4)
+ELF_RELOC(R_MIPS_HI16, 5)
+ELF_RELOC(R_MIPS_LO16, 6)
+ELF_RELOC(R_MIPS_GPREL16, 7)
+ELF_RELOC(R_MIPS_LITERAL, 8)
+ELF_RELOC(R_MIPS_GOT16, 9)
+ELF_RELOC(R_MIPS_PC16, 10)
+ELF_RELOC(R_MIPS_CALL16, 11)
+ELF_RELOC(R_MIPS_GPREL32, 12)
+ELF_RELOC(R_MIPS_UNUSED1, 13)
+ELF_RELOC(R_MIPS_UNUSED2, 14)
+ELF_RELOC(R_MIPS_UNUSED3, 15)
+ELF_RELOC(R_MIPS_SHIFT5, 16)
+ELF_RELOC(R_MIPS_SHIFT6, 17)
+ELF_RELOC(R_MIPS_64, 18)
+ELF_RELOC(R_MIPS_GOT_DISP, 19)
+ELF_RELOC(R_MIPS_GOT_PAGE, 20)
+ELF_RELOC(R_MIPS_GOT_OFST, 21)
+ELF_RELOC(R_MIPS_GOT_HI16, 22)
+ELF_RELOC(R_MIPS_GOT_LO16, 23)
+ELF_RELOC(R_MIPS_SUB, 24)
+ELF_RELOC(R_MIPS_INSERT_A, 25)
+ELF_RELOC(R_MIPS_INSERT_B, 26)
+ELF_RELOC(R_MIPS_DELETE, 27)
+ELF_RELOC(R_MIPS_HIGHER, 28)
+ELF_RELOC(R_MIPS_HIGHEST, 29)
+ELF_RELOC(R_MIPS_CALL_HI16, 30)
+ELF_RELOC(R_MIPS_CALL_LO16, 31)
+ELF_RELOC(R_MIPS_SCN_DISP, 32)
+ELF_RELOC(R_MIPS_REL16, 33)
+ELF_RELOC(R_MIPS_ADD_IMMEDIATE, 34)
+ELF_RELOC(R_MIPS_PJUMP, 35)
+ELF_RELOC(R_MIPS_RELGOT, 36)
+ELF_RELOC(R_MIPS_JALR, 37)
+ELF_RELOC(R_MIPS_TLS_DTPMOD32, 38)
+ELF_RELOC(R_MIPS_TLS_DTPREL32, 39)
+ELF_RELOC(R_MIPS_TLS_DTPMOD64, 40)
+ELF_RELOC(R_MIPS_TLS_DTPREL64, 41)
+ELF_RELOC(R_MIPS_TLS_GD, 42)
+ELF_RELOC(R_MIPS_TLS_LDM, 43)
+ELF_RELOC(R_MIPS_TLS_DTPREL_HI16, 44)
+ELF_RELOC(R_MIPS_TLS_DTPREL_LO16, 45)
+ELF_RELOC(R_MIPS_TLS_GOTTPREL, 46)
+ELF_RELOC(R_MIPS_TLS_TPREL32, 47)
+ELF_RELOC(R_MIPS_TLS_TPREL64, 48)
+ELF_RELOC(R_MIPS_TLS_TPREL_HI16, 49)
+ELF_RELOC(R_MIPS_TLS_TPREL_LO16, 50)
+ELF_RELOC(R_MIPS_GLOB_DAT, 51)
+ELF_RELOC(R_MIPS_PC21_S2, 60)
+ELF_RELOC(R_MIPS_PC26_S2, 61)
+ELF_RELOC(R_MIPS_PC18_S3, 62)
+ELF_RELOC(R_MIPS_PC19_S2, 63)
+ELF_RELOC(R_MIPS_PCHI16, 64)
+ELF_RELOC(R_MIPS_PCLO16, 65)
+ELF_RELOC(R_MIPS16_26, 100)
+ELF_RELOC(R_MIPS16_GPREL, 101)
+ELF_RELOC(R_MIPS16_GOT16, 102)
+ELF_RELOC(R_MIPS16_CALL16, 103)
+ELF_RELOC(R_MIPS16_HI16, 104)
+ELF_RELOC(R_MIPS16_LO16, 105)
+ELF_RELOC(R_MIPS16_TLS_GD, 106)
+ELF_RELOC(R_MIPS16_TLS_LDM, 107)
+ELF_RELOC(R_MIPS16_TLS_DTPREL_HI16, 108)
+ELF_RELOC(R_MIPS16_TLS_DTPREL_LO16, 109)
+ELF_RELOC(R_MIPS16_TLS_GOTTPREL, 110)
+ELF_RELOC(R_MIPS16_TLS_TPREL_HI16, 111)
+ELF_RELOC(R_MIPS16_TLS_TPREL_LO16, 112)
+ELF_RELOC(R_MIPS_COPY, 126)
+ELF_RELOC(R_MIPS_JUMP_SLOT, 127)
+ELF_RELOC(R_MICROMIPS_26_S1, 133)
+ELF_RELOC(R_MICROMIPS_HI16, 134)
+ELF_RELOC(R_MICROMIPS_LO16, 135)
+ELF_RELOC(R_MICROMIPS_GPREL16, 136)
+ELF_RELOC(R_MICROMIPS_LITERAL, 137)
+ELF_RELOC(R_MICROMIPS_GOT16, 138)
+ELF_RELOC(R_MICROMIPS_PC7_S1, 139)
+ELF_RELOC(R_MICROMIPS_PC10_S1, 140)
+ELF_RELOC(R_MICROMIPS_PC16_S1, 141)
+ELF_RELOC(R_MICROMIPS_CALL16, 142)
+ELF_RELOC(R_MICROMIPS_GOT_DISP, 145)
+ELF_RELOC(R_MICROMIPS_GOT_PAGE, 146)
+ELF_RELOC(R_MICROMIPS_GOT_OFST, 147)
+ELF_RELOC(R_MICROMIPS_GOT_HI16, 148)
+ELF_RELOC(R_MICROMIPS_GOT_LO16, 149)
+ELF_RELOC(R_MICROMIPS_SUB, 150)
+ELF_RELOC(R_MICROMIPS_HIGHER, 151)
+ELF_RELOC(R_MICROMIPS_HIGHEST, 152)
+ELF_RELOC(R_MICROMIPS_CALL_HI16, 153)
+ELF_RELOC(R_MICROMIPS_CALL_LO16, 154)
+ELF_RELOC(R_MICROMIPS_SCN_DISP, 155)
+ELF_RELOC(R_MICROMIPS_JALR, 156)
+ELF_RELOC(R_MICROMIPS_HI0_LO16, 157)
+ELF_RELOC(R_MICROMIPS_TLS_GD, 162)
+ELF_RELOC(R_MICROMIPS_TLS_LDM, 163)
+ELF_RELOC(R_MICROMIPS_TLS_DTPREL_HI16, 164)
+ELF_RELOC(R_MICROMIPS_TLS_DTPREL_LO16, 165)
+ELF_RELOC(R_MICROMIPS_TLS_GOTTPREL, 166)
+ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16, 169)
+ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16, 170)
+ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172)
+ELF_RELOC(R_MICROMIPS_PC23_S2, 173)
+ELF_RELOC(R_MIPS_NUM, 218)
+ELF_RELOC(R_MIPS_PC32, 248)
diff --git a/include/llvm/Support/ELFRelocs/PowerPC.def b/include/llvm/Support/ELFRelocs/PowerPC.def
new file mode 100644
index 000000000000..b6c39419b0f7
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/PowerPC.def
@@ -0,0 +1,61 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_PPC_NONE, 0) /* No relocation. */
+ELF_RELOC(R_PPC_ADDR32, 1)
+ELF_RELOC(R_PPC_ADDR24, 2)
+ELF_RELOC(R_PPC_ADDR16, 3)
+ELF_RELOC(R_PPC_ADDR16_LO, 4)
+ELF_RELOC(R_PPC_ADDR16_HI, 5)
+ELF_RELOC(R_PPC_ADDR16_HA, 6)
+ELF_RELOC(R_PPC_ADDR14, 7)
+ELF_RELOC(R_PPC_ADDR14_BRTAKEN, 8)
+ELF_RELOC(R_PPC_ADDR14_BRNTAKEN, 9)
+ELF_RELOC(R_PPC_REL24, 10)
+ELF_RELOC(R_PPC_REL14, 11)
+ELF_RELOC(R_PPC_REL14_BRTAKEN, 12)
+ELF_RELOC(R_PPC_REL14_BRNTAKEN, 13)
+ELF_RELOC(R_PPC_GOT16, 14)
+ELF_RELOC(R_PPC_GOT16_LO, 15)
+ELF_RELOC(R_PPC_GOT16_HI, 16)
+ELF_RELOC(R_PPC_GOT16_HA, 17)
+ELF_RELOC(R_PPC_PLTREL24, 18)
+ELF_RELOC(R_PPC_JMP_SLOT, 21)
+ELF_RELOC(R_PPC_LOCAL24PC, 23)
+ELF_RELOC(R_PPC_REL32, 26)
+ELF_RELOC(R_PPC_TLS, 67)
+ELF_RELOC(R_PPC_DTPMOD32, 68)
+ELF_RELOC(R_PPC_TPREL16, 69)
+ELF_RELOC(R_PPC_TPREL16_LO, 70)
+ELF_RELOC(R_PPC_TPREL16_HI, 71)
+ELF_RELOC(R_PPC_TPREL16_HA, 72)
+ELF_RELOC(R_PPC_TPREL32, 73)
+ELF_RELOC(R_PPC_DTPREL16, 74)
+ELF_RELOC(R_PPC_DTPREL16_LO, 75)
+ELF_RELOC(R_PPC_DTPREL16_HI, 76)
+ELF_RELOC(R_PPC_DTPREL16_HA, 77)
+ELF_RELOC(R_PPC_DTPREL32, 78)
+ELF_RELOC(R_PPC_GOT_TLSGD16, 79)
+ELF_RELOC(R_PPC_GOT_TLSGD16_LO, 80)
+ELF_RELOC(R_PPC_GOT_TLSGD16_HI, 81)
+ELF_RELOC(R_PPC_GOT_TLSGD16_HA, 82)
+ELF_RELOC(R_PPC_GOT_TLSLD16, 83)
+ELF_RELOC(R_PPC_GOT_TLSLD16_LO, 84)
+ELF_RELOC(R_PPC_GOT_TLSLD16_HI, 85)
+ELF_RELOC(R_PPC_GOT_TLSLD16_HA, 86)
+ELF_RELOC(R_PPC_GOT_TPREL16, 87)
+ELF_RELOC(R_PPC_GOT_TPREL16_LO, 88)
+ELF_RELOC(R_PPC_GOT_TPREL16_HI, 89)
+ELF_RELOC(R_PPC_GOT_TPREL16_HA, 90)
+ELF_RELOC(R_PPC_GOT_DTPREL16, 91)
+ELF_RELOC(R_PPC_GOT_DTPREL16_LO, 92)
+ELF_RELOC(R_PPC_GOT_DTPREL16_HI, 93)
+ELF_RELOC(R_PPC_GOT_DTPREL16_HA, 94)
+ELF_RELOC(R_PPC_TLSGD, 95)
+ELF_RELOC(R_PPC_TLSLD, 96)
+ELF_RELOC(R_PPC_REL16, 249)
+ELF_RELOC(R_PPC_REL16_LO, 250)
+ELF_RELOC(R_PPC_REL16_HI, 251)
+ELF_RELOC(R_PPC_REL16_HA, 252)
diff --git a/include/llvm/Support/ELFRelocs/PowerPC64.def b/include/llvm/Support/ELFRelocs/PowerPC64.def
new file mode 100644
index 000000000000..7b2a3cb2235b
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/PowerPC64.def
@@ -0,0 +1,88 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_PPC64_NONE, 0)
+ELF_RELOC(R_PPC64_ADDR32, 1)
+ELF_RELOC(R_PPC64_ADDR24, 2)
+ELF_RELOC(R_PPC64_ADDR16, 3)
+ELF_RELOC(R_PPC64_ADDR16_LO, 4)
+ELF_RELOC(R_PPC64_ADDR16_HI, 5)
+ELF_RELOC(R_PPC64_ADDR16_HA, 6)
+ELF_RELOC(R_PPC64_ADDR14, 7)
+ELF_RELOC(R_PPC64_ADDR14_BRTAKEN, 8)
+ELF_RELOC(R_PPC64_ADDR14_BRNTAKEN, 9)
+ELF_RELOC(R_PPC64_REL24, 10)
+ELF_RELOC(R_PPC64_REL14, 11)
+ELF_RELOC(R_PPC64_REL14_BRTAKEN, 12)
+ELF_RELOC(R_PPC64_REL14_BRNTAKEN, 13)
+ELF_RELOC(R_PPC64_GOT16, 14)
+ELF_RELOC(R_PPC64_GOT16_LO, 15)
+ELF_RELOC(R_PPC64_GOT16_HI, 16)
+ELF_RELOC(R_PPC64_GOT16_HA, 17)
+ELF_RELOC(R_PPC64_JMP_SLOT, 21)
+ELF_RELOC(R_PPC64_REL32, 26)
+ELF_RELOC(R_PPC64_ADDR64, 38)
+ELF_RELOC(R_PPC64_ADDR16_HIGHER, 39)
+ELF_RELOC(R_PPC64_ADDR16_HIGHERA, 40)
+ELF_RELOC(R_PPC64_ADDR16_HIGHEST, 41)
+ELF_RELOC(R_PPC64_ADDR16_HIGHESTA, 42)
+ELF_RELOC(R_PPC64_REL64, 44)
+ELF_RELOC(R_PPC64_TOC16, 47)
+ELF_RELOC(R_PPC64_TOC16_LO, 48)
+ELF_RELOC(R_PPC64_TOC16_HI, 49)
+ELF_RELOC(R_PPC64_TOC16_HA, 50)
+ELF_RELOC(R_PPC64_TOC, 51)
+ELF_RELOC(R_PPC64_ADDR16_DS, 56)
+ELF_RELOC(R_PPC64_ADDR16_LO_DS, 57)
+ELF_RELOC(R_PPC64_GOT16_DS, 58)
+ELF_RELOC(R_PPC64_GOT16_LO_DS, 59)
+ELF_RELOC(R_PPC64_TOC16_DS, 63)
+ELF_RELOC(R_PPC64_TOC16_LO_DS, 64)
+ELF_RELOC(R_PPC64_TLS, 67)
+ELF_RELOC(R_PPC64_DTPMOD64, 68)
+ELF_RELOC(R_PPC64_TPREL16, 69)
+ELF_RELOC(R_PPC64_TPREL16_LO, 70)
+ELF_RELOC(R_PPC64_TPREL16_HI, 71)
+ELF_RELOC(R_PPC64_TPREL16_HA, 72)
+ELF_RELOC(R_PPC64_TPREL64, 73)
+ELF_RELOC(R_PPC64_DTPREL16, 74)
+ELF_RELOC(R_PPC64_DTPREL16_LO, 75)
+ELF_RELOC(R_PPC64_DTPREL16_HI, 76)
+ELF_RELOC(R_PPC64_DTPREL16_HA, 77)
+ELF_RELOC(R_PPC64_DTPREL64, 78)
+ELF_RELOC(R_PPC64_GOT_TLSGD16, 79)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_LO, 80)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_HI, 81)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_HA, 82)
+ELF_RELOC(R_PPC64_GOT_TLSLD16, 83)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_LO, 84)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_HI, 85)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_HA, 86)
+ELF_RELOC(R_PPC64_GOT_TPREL16_DS, 87)
+ELF_RELOC(R_PPC64_GOT_TPREL16_LO_DS, 88)
+ELF_RELOC(R_PPC64_GOT_TPREL16_HI, 89)
+ELF_RELOC(R_PPC64_GOT_TPREL16_HA, 90)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_DS, 91)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_LO_DS, 92)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_HI, 93)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_HA, 94)
+ELF_RELOC(R_PPC64_TPREL16_DS, 95)
+ELF_RELOC(R_PPC64_TPREL16_LO_DS, 96)
+ELF_RELOC(R_PPC64_TPREL16_HIGHER, 97)
+ELF_RELOC(R_PPC64_TPREL16_HIGHERA, 98)
+ELF_RELOC(R_PPC64_TPREL16_HIGHEST, 99)
+ELF_RELOC(R_PPC64_TPREL16_HIGHESTA, 100)
+ELF_RELOC(R_PPC64_DTPREL16_DS, 101)
+ELF_RELOC(R_PPC64_DTPREL16_LO_DS, 102)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHER, 103)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHERA, 104)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHEST, 105)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHESTA, 106)
+ELF_RELOC(R_PPC64_TLSGD, 107)
+ELF_RELOC(R_PPC64_TLSLD, 108)
+ELF_RELOC(R_PPC64_REL16, 249)
+ELF_RELOC(R_PPC64_REL16_LO, 250)
+ELF_RELOC(R_PPC64_REL16_HI, 251)
+ELF_RELOC(R_PPC64_REL16_HA, 252)
diff --git a/include/llvm/Support/ELFRelocs/Sparc.def b/include/llvm/Support/ELFRelocs/Sparc.def
new file mode 100644
index 000000000000..d6772ea675d6
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/Sparc.def
@@ -0,0 +1,89 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_SPARC_NONE, 0)
+ELF_RELOC(R_SPARC_8, 1)
+ELF_RELOC(R_SPARC_16, 2)
+ELF_RELOC(R_SPARC_32, 3)
+ELF_RELOC(R_SPARC_DISP8, 4)
+ELF_RELOC(R_SPARC_DISP16, 5)
+ELF_RELOC(R_SPARC_DISP32, 6)
+ELF_RELOC(R_SPARC_WDISP30, 7)
+ELF_RELOC(R_SPARC_WDISP22, 8)
+ELF_RELOC(R_SPARC_HI22, 9)
+ELF_RELOC(R_SPARC_22, 10)
+ELF_RELOC(R_SPARC_13, 11)
+ELF_RELOC(R_SPARC_LO10, 12)
+ELF_RELOC(R_SPARC_GOT10, 13)
+ELF_RELOC(R_SPARC_GOT13, 14)
+ELF_RELOC(R_SPARC_GOT22, 15)
+ELF_RELOC(R_SPARC_PC10, 16)
+ELF_RELOC(R_SPARC_PC22, 17)
+ELF_RELOC(R_SPARC_WPLT30, 18)
+ELF_RELOC(R_SPARC_COPY, 19)
+ELF_RELOC(R_SPARC_GLOB_DAT, 20)
+ELF_RELOC(R_SPARC_JMP_SLOT, 21)
+ELF_RELOC(R_SPARC_RELATIVE, 22)
+ELF_RELOC(R_SPARC_UA32, 23)
+ELF_RELOC(R_SPARC_PLT32, 24)
+ELF_RELOC(R_SPARC_HIPLT22, 25)
+ELF_RELOC(R_SPARC_LOPLT10, 26)
+ELF_RELOC(R_SPARC_PCPLT32, 27)
+ELF_RELOC(R_SPARC_PCPLT22, 28)
+ELF_RELOC(R_SPARC_PCPLT10, 29)
+ELF_RELOC(R_SPARC_10, 30)
+ELF_RELOC(R_SPARC_11, 31)
+ELF_RELOC(R_SPARC_64, 32)
+ELF_RELOC(R_SPARC_OLO10, 33)
+ELF_RELOC(R_SPARC_HH22, 34)
+ELF_RELOC(R_SPARC_HM10, 35)
+ELF_RELOC(R_SPARC_LM22, 36)
+ELF_RELOC(R_SPARC_PC_HH22, 37)
+ELF_RELOC(R_SPARC_PC_HM10, 38)
+ELF_RELOC(R_SPARC_PC_LM22, 39)
+ELF_RELOC(R_SPARC_WDISP16, 40)
+ELF_RELOC(R_SPARC_WDISP19, 41)
+ELF_RELOC(R_SPARC_7, 43)
+ELF_RELOC(R_SPARC_5, 44)
+ELF_RELOC(R_SPARC_6, 45)
+ELF_RELOC(R_SPARC_DISP64, 46)
+ELF_RELOC(R_SPARC_PLT64, 47)
+ELF_RELOC(R_SPARC_HIX22, 48)
+ELF_RELOC(R_SPARC_LOX10, 49)
+ELF_RELOC(R_SPARC_H44, 50)
+ELF_RELOC(R_SPARC_M44, 51)
+ELF_RELOC(R_SPARC_L44, 52)
+ELF_RELOC(R_SPARC_REGISTER, 53)
+ELF_RELOC(R_SPARC_UA64, 54)
+ELF_RELOC(R_SPARC_UA16, 55)
+ELF_RELOC(R_SPARC_TLS_GD_HI22, 56)
+ELF_RELOC(R_SPARC_TLS_GD_LO10, 57)
+ELF_RELOC(R_SPARC_TLS_GD_ADD, 58)
+ELF_RELOC(R_SPARC_TLS_GD_CALL, 59)
+ELF_RELOC(R_SPARC_TLS_LDM_HI22, 60)
+ELF_RELOC(R_SPARC_TLS_LDM_LO10, 61)
+ELF_RELOC(R_SPARC_TLS_LDM_ADD, 62)
+ELF_RELOC(R_SPARC_TLS_LDM_CALL, 63)
+ELF_RELOC(R_SPARC_TLS_LDO_HIX22, 64)
+ELF_RELOC(R_SPARC_TLS_LDO_LOX10, 65)
+ELF_RELOC(R_SPARC_TLS_LDO_ADD, 66)
+ELF_RELOC(R_SPARC_TLS_IE_HI22, 67)
+ELF_RELOC(R_SPARC_TLS_IE_LO10, 68)
+ELF_RELOC(R_SPARC_TLS_IE_LD, 69)
+ELF_RELOC(R_SPARC_TLS_IE_LDX, 70)
+ELF_RELOC(R_SPARC_TLS_IE_ADD, 71)
+ELF_RELOC(R_SPARC_TLS_LE_HIX22, 72)
+ELF_RELOC(R_SPARC_TLS_LE_LOX10, 73)
+ELF_RELOC(R_SPARC_TLS_DTPMOD32, 74)
+ELF_RELOC(R_SPARC_TLS_DTPMOD64, 75)
+ELF_RELOC(R_SPARC_TLS_DTPOFF32, 76)
+ELF_RELOC(R_SPARC_TLS_DTPOFF64, 77)
+ELF_RELOC(R_SPARC_TLS_TPOFF32, 78)
+ELF_RELOC(R_SPARC_TLS_TPOFF64, 79)
+ELF_RELOC(R_SPARC_GOTDATA_HIX22, 80)
+ELF_RELOC(R_SPARC_GOTDATA_LOX22, 81)
+ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22, 82)
+ELF_RELOC(R_SPARC_GOTDATA_OP_LOX22, 83)
+ELF_RELOC(R_SPARC_GOTDATA_OP, 84)
diff --git a/include/llvm/Support/ELFRelocs/SystemZ.def b/include/llvm/Support/ELFRelocs/SystemZ.def
new file mode 100644
index 000000000000..711f94011f2c
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/SystemZ.def
@@ -0,0 +1,67 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_390_NONE, 0)
+ELF_RELOC(R_390_8, 1)
+ELF_RELOC(R_390_12, 2)
+ELF_RELOC(R_390_16, 3)
+ELF_RELOC(R_390_32, 4)
+ELF_RELOC(R_390_PC32, 5)
+ELF_RELOC(R_390_GOT12, 6)
+ELF_RELOC(R_390_GOT32, 7)
+ELF_RELOC(R_390_PLT32, 8)
+ELF_RELOC(R_390_COPY, 9)
+ELF_RELOC(R_390_GLOB_DAT, 10)
+ELF_RELOC(R_390_JMP_SLOT, 11)
+ELF_RELOC(R_390_RELATIVE, 12)
+ELF_RELOC(R_390_GOTOFF, 13)
+ELF_RELOC(R_390_GOTPC, 14)
+ELF_RELOC(R_390_GOT16, 15)
+ELF_RELOC(R_390_PC16, 16)
+ELF_RELOC(R_390_PC16DBL, 17)
+ELF_RELOC(R_390_PLT16DBL, 18)
+ELF_RELOC(R_390_PC32DBL, 19)
+ELF_RELOC(R_390_PLT32DBL, 20)
+ELF_RELOC(R_390_GOTPCDBL, 21)
+ELF_RELOC(R_390_64, 22)
+ELF_RELOC(R_390_PC64, 23)
+ELF_RELOC(R_390_GOT64, 24)
+ELF_RELOC(R_390_PLT64, 25)
+ELF_RELOC(R_390_GOTENT, 26)
+ELF_RELOC(R_390_GOTOFF16, 27)
+ELF_RELOC(R_390_GOTOFF64, 28)
+ELF_RELOC(R_390_GOTPLT12, 29)
+ELF_RELOC(R_390_GOTPLT16, 30)
+ELF_RELOC(R_390_GOTPLT32, 31)
+ELF_RELOC(R_390_GOTPLT64, 32)
+ELF_RELOC(R_390_GOTPLTENT, 33)
+ELF_RELOC(R_390_PLTOFF16, 34)
+ELF_RELOC(R_390_PLTOFF32, 35)
+ELF_RELOC(R_390_PLTOFF64, 36)
+ELF_RELOC(R_390_TLS_LOAD, 37)
+ELF_RELOC(R_390_TLS_GDCALL, 38)
+ELF_RELOC(R_390_TLS_LDCALL, 39)
+ELF_RELOC(R_390_TLS_GD32, 40)
+ELF_RELOC(R_390_TLS_GD64, 41)
+ELF_RELOC(R_390_TLS_GOTIE12, 42)
+ELF_RELOC(R_390_TLS_GOTIE32, 43)
+ELF_RELOC(R_390_TLS_GOTIE64, 44)
+ELF_RELOC(R_390_TLS_LDM32, 45)
+ELF_RELOC(R_390_TLS_LDM64, 46)
+ELF_RELOC(R_390_TLS_IE32, 47)
+ELF_RELOC(R_390_TLS_IE64, 48)
+ELF_RELOC(R_390_TLS_IEENT, 49)
+ELF_RELOC(R_390_TLS_LE32, 50)
+ELF_RELOC(R_390_TLS_LE64, 51)
+ELF_RELOC(R_390_TLS_LDO32, 52)
+ELF_RELOC(R_390_TLS_LDO64, 53)
+ELF_RELOC(R_390_TLS_DTPMOD, 54)
+ELF_RELOC(R_390_TLS_DTPOFF, 55)
+ELF_RELOC(R_390_TLS_TPOFF, 56)
+ELF_RELOC(R_390_20, 57)
+ELF_RELOC(R_390_GOT20, 58)
+ELF_RELOC(R_390_GOTPLT20, 59)
+ELF_RELOC(R_390_TLS_GOTIE20, 60)
+ELF_RELOC(R_390_IRELATIVE, 61)
diff --git a/include/llvm/Support/ELFRelocs/i386.def b/include/llvm/Support/ELFRelocs/i386.def
new file mode 100644
index 000000000000..45eae7fe426b
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/i386.def
@@ -0,0 +1,47 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// TODO: this is just a subset
+ELF_RELOC(R_386_NONE, 0)
+ELF_RELOC(R_386_32, 1)
+ELF_RELOC(R_386_PC32, 2)
+ELF_RELOC(R_386_GOT32, 3)
+ELF_RELOC(R_386_PLT32, 4)
+ELF_RELOC(R_386_COPY, 5)
+ELF_RELOC(R_386_GLOB_DAT, 6)
+ELF_RELOC(R_386_JUMP_SLOT, 7)
+ELF_RELOC(R_386_RELATIVE, 8)
+ELF_RELOC(R_386_GOTOFF, 9)
+ELF_RELOC(R_386_GOTPC, 10)
+ELF_RELOC(R_386_32PLT, 11)
+ELF_RELOC(R_386_TLS_TPOFF, 14)
+ELF_RELOC(R_386_TLS_IE, 15)
+ELF_RELOC(R_386_TLS_GOTIE, 16)
+ELF_RELOC(R_386_TLS_LE, 17)
+ELF_RELOC(R_386_TLS_GD, 18)
+ELF_RELOC(R_386_TLS_LDM, 19)
+ELF_RELOC(R_386_16, 20)
+ELF_RELOC(R_386_PC16, 21)
+ELF_RELOC(R_386_8, 22)
+ELF_RELOC(R_386_PC8, 23)
+ELF_RELOC(R_386_TLS_GD_32, 24)
+ELF_RELOC(R_386_TLS_GD_PUSH, 25)
+ELF_RELOC(R_386_TLS_GD_CALL, 26)
+ELF_RELOC(R_386_TLS_GD_POP, 27)
+ELF_RELOC(R_386_TLS_LDM_32, 28)
+ELF_RELOC(R_386_TLS_LDM_PUSH, 29)
+ELF_RELOC(R_386_TLS_LDM_CALL, 30)
+ELF_RELOC(R_386_TLS_LDM_POP, 31)
+ELF_RELOC(R_386_TLS_LDO_32, 32)
+ELF_RELOC(R_386_TLS_IE_32, 33)
+ELF_RELOC(R_386_TLS_LE_32, 34)
+ELF_RELOC(R_386_TLS_DTPMOD32, 35)
+ELF_RELOC(R_386_TLS_DTPOFF32, 36)
+ELF_RELOC(R_386_TLS_TPOFF32, 37)
+ELF_RELOC(R_386_TLS_GOTDESC, 39)
+ELF_RELOC(R_386_TLS_DESC_CALL, 40)
+ELF_RELOC(R_386_TLS_DESC, 41)
+ELF_RELOC(R_386_IRELATIVE, 42)
+ELF_RELOC(R_386_NUM, 43)
diff --git a/include/llvm/Support/ELFRelocs/x86_64.def b/include/llvm/Support/ELFRelocs/x86_64.def
new file mode 100644
index 000000000000..36ad0618eb2d
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/x86_64.def
@@ -0,0 +1,44 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_X86_64_NONE, 0)
+ELF_RELOC(R_X86_64_64, 1)
+ELF_RELOC(R_X86_64_PC32, 2)
+ELF_RELOC(R_X86_64_GOT32, 3)
+ELF_RELOC(R_X86_64_PLT32, 4)
+ELF_RELOC(R_X86_64_COPY, 5)
+ELF_RELOC(R_X86_64_GLOB_DAT, 6)
+ELF_RELOC(R_X86_64_JUMP_SLOT, 7)
+ELF_RELOC(R_X86_64_RELATIVE, 8)
+ELF_RELOC(R_X86_64_GOTPCREL, 9)
+ELF_RELOC(R_X86_64_32, 10)
+ELF_RELOC(R_X86_64_32S, 11)
+ELF_RELOC(R_X86_64_16, 12)
+ELF_RELOC(R_X86_64_PC16, 13)
+ELF_RELOC(R_X86_64_8, 14)
+ELF_RELOC(R_X86_64_PC8, 15)
+ELF_RELOC(R_X86_64_DTPMOD64, 16)
+ELF_RELOC(R_X86_64_DTPOFF64, 17)
+ELF_RELOC(R_X86_64_TPOFF64, 18)
+ELF_RELOC(R_X86_64_TLSGD, 19)
+ELF_RELOC(R_X86_64_TLSLD, 20)
+ELF_RELOC(R_X86_64_DTPOFF32, 21)
+ELF_RELOC(R_X86_64_GOTTPOFF, 22)
+ELF_RELOC(R_X86_64_TPOFF32, 23)
+ELF_RELOC(R_X86_64_PC64, 24)
+ELF_RELOC(R_X86_64_GOTOFF64, 25)
+ELF_RELOC(R_X86_64_GOTPC32, 26)
+ELF_RELOC(R_X86_64_GOT64, 27)
+ELF_RELOC(R_X86_64_GOTPCREL64, 28)
+ELF_RELOC(R_X86_64_GOTPC64, 29)
+ELF_RELOC(R_X86_64_GOTPLT64, 30)
+ELF_RELOC(R_X86_64_PLTOFF64, 31)
+ELF_RELOC(R_X86_64_SIZE32, 32)
+ELF_RELOC(R_X86_64_SIZE64, 33)
+ELF_RELOC(R_X86_64_GOTPC32_TLSDESC, 34)
+ELF_RELOC(R_X86_64_TLSDESC_CALL, 35)
+ELF_RELOC(R_X86_64_TLSDESC, 36)
+ELF_RELOC(R_X86_64_IRELATIVE, 37)
+
diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h
index 455d0fc241f2..47b82fdc4975 100644
--- a/include/llvm/Support/Endian.h
+++ b/include/llvm/Support/Endian.h
@@ -93,15 +93,40 @@ struct packed_endian_specific_integral {
(void*)Value.buffer, newValue);
}
+ packed_endian_specific_integral &operator+=(value_type newValue) {
+ *this = *this + newValue;
+ return *this;
+ }
+
+ packed_endian_specific_integral &operator-=(value_type newValue) {
+ *this = *this - newValue;
+ return *this;
+ }
+
private:
AlignedCharArray<PickAlignment<value_type, alignment>::value,
sizeof(value_type)> Value;
+
+public:
+ struct ref {
+ explicit ref(void *Ptr) : Ptr(Ptr) {}
+
+ operator value_type() const {
+ return endian::read<value_type, endian, alignment>(Ptr);
+ }
+
+ void operator=(value_type NewValue) {
+ endian::write<value_type, endian, alignment>(Ptr, NewValue);
+ }
+
+ private:
+ void *Ptr;
+ };
};
+
} // end namespace detail
typedef detail::packed_endian_specific_integral
- <uint8_t, little, unaligned> ulittle8_t;
-typedef detail::packed_endian_specific_integral
<uint16_t, little, unaligned> ulittle16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, little, unaligned> ulittle32_t;
@@ -109,8 +134,6 @@ typedef detail::packed_endian_specific_integral
<uint64_t, little, unaligned> ulittle64_t;
typedef detail::packed_endian_specific_integral
- <int8_t, little, unaligned> little8_t;
-typedef detail::packed_endian_specific_integral
<int16_t, little, unaligned> little16_t;
typedef detail::packed_endian_specific_integral
<int32_t, little, unaligned> little32_t;
@@ -118,8 +141,6 @@ typedef detail::packed_endian_specific_integral
<int64_t, little, unaligned> little64_t;
typedef detail::packed_endian_specific_integral
- <uint8_t, little, aligned> aligned_ulittle8_t;
-typedef detail::packed_endian_specific_integral
<uint16_t, little, aligned> aligned_ulittle16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, little, aligned> aligned_ulittle32_t;
@@ -127,8 +148,6 @@ typedef detail::packed_endian_specific_integral
<uint64_t, little, aligned> aligned_ulittle64_t;
typedef detail::packed_endian_specific_integral
- <int8_t, little, aligned> aligned_little8_t;
-typedef detail::packed_endian_specific_integral
<int16_t, little, aligned> aligned_little16_t;
typedef detail::packed_endian_specific_integral
<int32_t, little, aligned> aligned_little32_t;
@@ -136,8 +155,6 @@ typedef detail::packed_endian_specific_integral
<int64_t, little, aligned> aligned_little64_t;
typedef detail::packed_endian_specific_integral
- <uint8_t, big, unaligned> ubig8_t;
-typedef detail::packed_endian_specific_integral
<uint16_t, big, unaligned> ubig16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, big, unaligned> ubig32_t;
@@ -145,8 +162,6 @@ typedef detail::packed_endian_specific_integral
<uint64_t, big, unaligned> ubig64_t;
typedef detail::packed_endian_specific_integral
- <int8_t, big, unaligned> big8_t;
-typedef detail::packed_endian_specific_integral
<int16_t, big, unaligned> big16_t;
typedef detail::packed_endian_specific_integral
<int32_t, big, unaligned> big32_t;
@@ -154,8 +169,6 @@ typedef detail::packed_endian_specific_integral
<int64_t, big, unaligned> big64_t;
typedef detail::packed_endian_specific_integral
- <uint8_t, big, aligned> aligned_ubig8_t;
-typedef detail::packed_endian_specific_integral
<uint16_t, big, aligned> aligned_ubig16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, big, aligned> aligned_ubig32_t;
@@ -163,8 +176,6 @@ typedef detail::packed_endian_specific_integral
<uint64_t, big, aligned> aligned_ubig64_t;
typedef detail::packed_endian_specific_integral
- <int8_t, big, aligned> aligned_big8_t;
-typedef detail::packed_endian_specific_integral
<int16_t, big, aligned> aligned_big16_t;
typedef detail::packed_endian_specific_integral
<int32_t, big, aligned> aligned_big32_t;
diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h
index 89c66d3b8480..94f372f020b4 100644
--- a/include/llvm/Support/EndianStream.h
+++ b/include/llvm/Support/EndianStream.h
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef _LLVM_SUPPORT_ENDIAN_STREAM_H_
-#define _LLVM_SUPPORT_ENDIAN_STREAM_H_
+#ifndef LLVM_SUPPORT_ENDIANSTREAM_H
+#define LLVM_SUPPORT_ENDIANSTREAM_H
-#include <llvm/Support/Endian.h>
-#include <llvm/Support/raw_ostream.h>
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace support {
@@ -36,4 +36,4 @@ template <endianness endian> struct Writer {
} // end namespace support
} // end namespace llvm
-#endif // _LLVM_SUPPORT_ENDIAN_STREAM_H_
+#endif
diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h
index 0742a2d06f71..84763deea0f9 100644
--- a/include/llvm/Support/ErrorOr.h
+++ b/include/llvm/Support/ErrorOr.h
@@ -13,8 +13,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_ERROR_OR_H
-#define LLVM_SUPPORT_ERROR_OR_H
+#ifndef LLVM_SUPPORT_ERROROR_H
+#define LLVM_SUPPORT_ERROROR_H
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/AlignOf.h"
@@ -68,9 +68,9 @@ public:
/// \endcode
///
///
-/// An implicit conversion to bool provides a way to check if there was an
-/// error. The unary * and -> operators provide pointer like access to the
-/// value. Accessing the value when there is an error has undefined behavior.
+/// Implicit conversion to bool returns true if there is a usable value. The
+/// unary * and -> operators provide pointer like access to the value. Accessing
+/// the value when there is an error has undefined behavior.
///
/// When T is a reference type the behaivor is slightly different. The reference
/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and
@@ -115,19 +115,19 @@ public:
}
template <class OtherT>
- ErrorOr(const ErrorOr<OtherT> &Other) {
+ ErrorOr(
+ const ErrorOr<OtherT> &Other,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
+ nullptr) {
copyConstruct(Other);
}
- ErrorOr &operator =(const ErrorOr &Other) {
- copyAssign(Other);
- return *this;
- }
-
template <class OtherT>
- ErrorOr &operator =(const ErrorOr<OtherT> &Other) {
- copyAssign(Other);
- return *this;
+ explicit ErrorOr(
+ const ErrorOr<OtherT> &Other,
+ typename std::enable_if<
+ !std::is_convertible<OtherT, const T &>::value>::type * = nullptr) {
+ copyConstruct(Other);
}
ErrorOr(ErrorOr &&Other) {
@@ -135,17 +135,29 @@ public:
}
template <class OtherT>
- ErrorOr(ErrorOr<OtherT> &&Other) {
+ ErrorOr(
+ ErrorOr<OtherT> &&Other,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
+ nullptr) {
moveConstruct(std::move(Other));
}
- ErrorOr &operator =(ErrorOr &&Other) {
- moveAssign(std::move(Other));
+ // This might eventually need SFINAE but it's more complex than is_convertible
+ // & I'm too lazy to write it right now.
+ template <class OtherT>
+ explicit ErrorOr(
+ ErrorOr<OtherT> &&Other,
+ typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
+ nullptr) {
+ moveConstruct(std::move(Other));
+ }
+
+ ErrorOr &operator=(const ErrorOr &Other) {
+ copyAssign(Other);
return *this;
}
- template <class OtherT>
- ErrorOr &operator =(ErrorOr<OtherT> &&Other) {
+ ErrorOr &operator=(ErrorOr &&Other) {
moveAssign(std::move(Other));
return *this;
}
@@ -161,7 +173,7 @@ public:
}
reference get() { return *getStorage(); }
- const_reference get() const { return const_cast<ErrorOr<T> >(this)->get(); }
+ const_reference get() const { return const_cast<ErrorOr<T> *>(this)->get(); }
std::error_code getError() const {
return HasError ? *getErrorStorage() : std::error_code();
diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h
index 0a9a97995156..9f02a16e3d65 100644
--- a/include/llvm/Support/FileOutputBuffer.h
+++ b/include/llvm/Support/FileOutputBuffer.h
@@ -66,7 +66,7 @@ public:
/// is called, the file is deleted in the destructor. The optional parameter
/// is used if it turns out you want the file size to be smaller than
/// initially requested.
- std::error_code commit(int64_t NewSmallerSize = -1);
+ std::error_code commit();
/// If this object was previously committed, the destructor just deletes
/// this object. If this object was not committed, the destructor
@@ -77,7 +77,7 @@ private:
FileOutputBuffer(const FileOutputBuffer &) LLVM_DELETED_FUNCTION;
FileOutputBuffer &operator=(const FileOutputBuffer &) LLVM_DELETED_FUNCTION;
- FileOutputBuffer(llvm::sys::fs::mapped_file_region *R,
+ FileOutputBuffer(std::unique_ptr<llvm::sys::fs::mapped_file_region> R,
StringRef Path, StringRef TempPath);
std::unique_ptr<llvm::sys::fs::mapped_file_region> Region;
diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h
index 556701c3ba34..b60c1b07043b 100644
--- a/include/llvm/Support/FileSystem.h
+++ b/include/llvm/Support/FileSystem.h
@@ -226,6 +226,7 @@ struct file_magic {
unknown = 0, ///< Unrecognized file
bitcode, ///< Bitcode file
archive, ///< ar style archive file
+ elf, ///< ELF Unknown type
elf_relocatable, ///< ELF Relocatable object file
elf_executable, ///< ELF Executable image
elf_shared_object, ///< ELF dynamically linked shared lib
@@ -276,14 +277,6 @@ private:
/// platform-specific error_code.
std::error_code make_absolute(SmallVectorImpl<char> &path);
-/// @brief Normalize path separators in \a Path
-///
-/// If the path contains any '\' separators, they are transformed into '/'.
-/// This is particularly useful when cross-compiling Windows on Linux, but is
-/// safe to invoke on Windows, which accepts both characters as a path
-/// separator.
-std::error_code normalize_separators(SmallVectorImpl<char> &Path);
-
/// @brief Create all the non-existent directories in path.
///
/// @param path Directories to create.
@@ -343,11 +336,11 @@ std::error_code copy_file(const Twine &From, const Twine &To);
/// @brief Resize path to size. File is resized as if by POSIX truncate().
///
-/// @param path Input path.
-/// @param size Size to resize to.
+/// @param FD Input file descriptor.
+/// @param Size Size to resize to.
/// @returns errc::success if \a path has been resized to \a size, otherwise a
/// platform-specific error_code.
-std::error_code resize_file(const Twine &path, uint64_t size);
+std::error_code resize_file(int FD, uint64_t Size);
/// @}
/// @name Physical Observers
@@ -360,33 +353,38 @@ std::error_code resize_file(const Twine &path, uint64_t size);
/// not.
bool exists(file_status status);
-/// @brief Does file exist?
+enum class AccessMode { Exist, Write, Execute };
+
+/// @brief Can the file be accessed?
///
-/// @param path Input path.
-/// @param result Set to true if the file represented by status exists, false if
-/// it does not. Undefined otherwise.
-/// @returns errc::success if result has been successfully set, otherwise a
+/// @param Path Input path.
+/// @returns errc::success if the path can be accessed, otherwise a
/// platform-specific error_code.
-std::error_code exists(const Twine &path, bool &result);
+std::error_code access(const Twine &Path, AccessMode Mode);
-/// @brief Simpler version of exists for clients that don't need to
-/// differentiate between an error and false.
-inline bool exists(const Twine &path) {
- bool result;
- return !exists(path, result) && result;
+/// @brief Does file exist?
+///
+/// @param Path Input path.
+/// @returns True if it exists, false otherwise.
+inline bool exists(const Twine &Path) {
+ return !access(Path, AccessMode::Exist);
}
/// @brief Can we execute this file?
///
/// @param Path Input path.
/// @returns True if we can execute it, false otherwise.
-bool can_execute(const Twine &Path);
+inline bool can_execute(const Twine &Path) {
+ return !access(Path, AccessMode::Execute);
+}
/// @brief Can we write this file?
///
/// @param Path Input path.
/// @returns True if we can write to it, false otherwise.
-bool can_write(const Twine &Path);
+inline bool can_write(const Twine &Path) {
+ return !access(Path, AccessMode::Write);
+}
/// @brief Do file_status's represent the same thing?
///
@@ -639,49 +637,20 @@ public:
private:
/// Platform-specific mapping state.
- mapmode Mode;
uint64_t Size;
void *Mapping;
-#ifdef LLVM_ON_WIN32
- int FileDescriptor;
- void *FileHandle;
- void *FileMappingHandle;
-#endif
- std::error_code init(int FD, bool CloseFD, uint64_t Offset);
+ std::error_code init(int FD, uint64_t Offset, mapmode Mode);
public:
- typedef char char_type;
-
- mapped_file_region(mapped_file_region&&);
- mapped_file_region &operator =(mapped_file_region&&);
-
- /// Construct a mapped_file_region at \a path starting at \a offset of length
- /// \a length and with access \a mode.
- ///
- /// \param path Path to the file to map. If it does not exist it will be
- /// created.
- /// \param mode How to map the memory.
- /// \param length Number of bytes to map in starting at \a offset. If the file
- /// is shorter than this, it will be extended. If \a length is
- /// 0, the entire file will be mapped.
- /// \param offset Byte offset from the beginning of the file where the map
- /// should begin. Must be a multiple of
- /// mapped_file_region::alignment().
- /// \param ec This is set to errc::success if the map was constructed
- /// successfully. Otherwise it is set to a platform dependent error.
- mapped_file_region(const Twine &path, mapmode mode, uint64_t length,
- uint64_t offset, std::error_code &ec);
-
/// \param fd An open file descriptor to map. mapped_file_region takes
/// ownership if closefd is true. It must have been opended in the correct
/// mode.
- mapped_file_region(int fd, bool closefd, mapmode mode, uint64_t length,
- uint64_t offset, std::error_code &ec);
+ mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset,
+ std::error_code &ec);
~mapped_file_region();
- mapmode flags() const;
uint64_t size() const;
char *data() const;
diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h
index b713cc72e852..5d599e96ec3a 100644
--- a/include/llvm/Support/Format.h
+++ b/include/llvm/Support/Format.h
@@ -23,6 +23,8 @@
#ifndef LLVM_SUPPORT_FORMAT_H
#define LLVM_SUPPORT_FORMAT_H
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <cstdio>
#ifdef _MSC_VER
@@ -41,6 +43,7 @@ namespace llvm {
class format_object_base {
protected:
const char *Fmt;
+ ~format_object_base() {} // Disallow polymorphic deletion.
virtual void home(); // Out of line virtual method.
/// Call snprintf() for this object, on the given buffer and size.
@@ -48,7 +51,6 @@ protected:
public:
format_object_base(const char *fmt) : Fmt(fmt) {}
- virtual ~format_object_base() {}
/// Format the object into the specified buffer. On success, this returns
/// the length of the formatted string. If the buffer is too small, this
@@ -79,7 +81,7 @@ public:
/// returns whether or not it is big enough.
template <typename T>
-class format_object1 : public format_object_base {
+class format_object1 final : public format_object_base {
T Val;
public:
format_object1(const char *fmt, const T &val)
@@ -92,7 +94,7 @@ public:
};
template <typename T1, typename T2>
-class format_object2 : public format_object_base {
+class format_object2 final : public format_object_base {
T1 Val1;
T2 Val2;
public:
@@ -106,7 +108,7 @@ public:
};
template <typename T1, typename T2, typename T3>
-class format_object3 : public format_object_base {
+class format_object3 final : public format_object_base {
T1 Val1;
T2 Val2;
T3 Val3;
@@ -121,7 +123,7 @@ public:
};
template <typename T1, typename T2, typename T3, typename T4>
-class format_object4 : public format_object_base {
+class format_object4 final : public format_object_base {
T1 Val1;
T2 Val2;
T3 Val3;
@@ -138,7 +140,7 @@ public:
};
template <typename T1, typename T2, typename T3, typename T4, typename T5>
-class format_object5 : public format_object_base {
+class format_object5 final : public format_object_base {
T1 Val1;
T2 Val2;
T3 Val3;
@@ -158,7 +160,7 @@ public:
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
-class format_object6 : public format_object_base {
+class format_object6 final : public format_object_base {
T1 Val1;
T2 Val2;
T3 Val3;
@@ -225,6 +227,66 @@ format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3,
Val5, Val6);
}
+/// This is a helper class used for left_justify() and right_justify().
+class FormattedString {
+ StringRef Str;
+ unsigned Width;
+ bool RightJustify;
+ friend class raw_ostream;
+public:
+ FormattedString(StringRef S, unsigned W, bool R)
+ : Str(S), Width(W), RightJustify(R) { }
+};
+
+/// left_justify - append spaces after string so total output is
+/// \p Width characters. If \p Str is larger that \p Width, full string
+/// is written with no padding.
+inline FormattedString left_justify(StringRef Str, unsigned Width) {
+ return FormattedString(Str, Width, false);
+}
+
+/// right_justify - add spaces before string so total output is
+/// \p Width characters. If \p Str is larger that \p Width, full string
+/// is written with no padding.
+inline FormattedString right_justify(StringRef Str, unsigned Width) {
+ return FormattedString(Str, Width, true);
+}
+
+/// This is a helper class used for format_hex() and format_decimal().
+class FormattedNumber {
+ uint64_t HexValue;
+ int64_t DecValue;
+ unsigned Width;
+ bool Hex;
+ bool Upper;
+ friend class raw_ostream;
+public:
+ FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U)
+ : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U) { }
+};
+
+/// format_hex - Output \p N as a fixed width hexadecimal. If number will not
+/// fit in width, full number is still printed. Examples:
+/// OS << format_hex(255, 4) => 0xff
+/// OS << format_hex(255, 4, true) => 0xFF
+/// OS << format_hex(255, 6) => 0x00ff
+/// OS << format_hex(255, 2) => 0xff
+inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) {
+ assert(Width <= 18 && "hex width must be <= 18");
+ return FormattedNumber(N, 0, Width, true, Upper);
+}
+
+/// format_decimal - Output \p N as a right justified, fixed-width decimal. If
+/// number will not fit in width, full number is still printed. Examples:
+/// OS << format_decimal(0, 5) => " 0"
+/// OS << format_decimal(255, 5) => " 255"
+/// OS << format_decimal(-1, 3) => " -1"
+/// OS << format_decimal(12345, 3) => "12345"
+inline FormattedNumber format_decimal(int64_t N, unsigned Width) {
+ return FormattedNumber(0, N, Width, false, false);
+}
+
+
} // end namespace llvm
#endif
diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h
index 0cb6cfd62ccb..e378602c7bb3 100644
--- a/include/llvm/Support/GCOV.h
+++ b/include/llvm/Support/GCOV.h
@@ -100,7 +100,7 @@ public:
/// cursor and return true otherwise return false.
bool readFunctionTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
+ if (Tag.empty() ||
Tag[0] != '\0' || Tag[1] != '\0' ||
Tag[2] != '\0' || Tag[3] != '\1') {
return false;
@@ -113,7 +113,7 @@ public:
/// cursor and return true otherwise return false.
bool readBlockTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
+ if (Tag.empty() ||
Tag[0] != '\0' || Tag[1] != '\0' ||
Tag[2] != '\x41' || Tag[3] != '\x01') {
return false;
@@ -126,7 +126,7 @@ public:
/// cursor and return true otherwise return false.
bool readEdgeTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
+ if (Tag.empty() ||
Tag[0] != '\0' || Tag[1] != '\0' ||
Tag[2] != '\x43' || Tag[3] != '\x01') {
return false;
@@ -139,7 +139,7 @@ public:
/// cursor and return true otherwise return false.
bool readLineTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
+ if (Tag.empty() ||
Tag[0] != '\0' || Tag[1] != '\0' ||
Tag[2] != '\x45' || Tag[3] != '\x01') {
return false;
@@ -152,7 +152,7 @@ public:
/// cursor and return true otherwise return false.
bool readArcTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
+ if (Tag.empty() ||
Tag[0] != '\0' || Tag[1] != '\0' ||
Tag[2] != '\xa1' || Tag[3] != '\1') {
return false;
diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h
index 876ab6ec71a5..fde56135a962 100644
--- a/include/llvm/Support/GenericDomTree.h
+++ b/include/llvm/Support/GenericDomTree.h
@@ -15,8 +15,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_GENERIC_DOM_TREE_H
-#define LLVM_SUPPORT_GENERIC_DOM_TREE_H
+#ifndef LLVM_SUPPORT_GENERICDOMTREE_H
+#define LLVM_SUPPORT_GENERICDOMTREE_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
@@ -29,76 +29,78 @@
namespace llvm {
-//===----------------------------------------------------------------------===//
-/// DominatorBase - Base class that other, more interesting dominator analyses
+/// \brief Base class that other, more interesting dominator analyses
/// inherit from.
-///
-template <class NodeT>
-class DominatorBase {
+template <class NodeT> class DominatorBase {
protected:
- std::vector<NodeT*> Roots;
- const bool IsPostDominators;
- inline explicit DominatorBase(bool isPostDom) :
- Roots(), IsPostDominators(isPostDom) {}
-public:
+ std::vector<NodeT *> Roots;
+ bool IsPostDominators;
+ explicit DominatorBase(bool isPostDom)
+ : Roots(), IsPostDominators(isPostDom) {}
+ DominatorBase(DominatorBase &&Arg)
+ : Roots(std::move(Arg.Roots)),
+ IsPostDominators(std::move(Arg.IsPostDominators)) {
+ Arg.Roots.clear();
+ }
+ DominatorBase &operator=(DominatorBase &&RHS) {
+ Roots = std::move(RHS.Roots);
+ IsPostDominators = std::move(RHS.IsPostDominators);
+ RHS.Roots.clear();
+ return *this;
+ }
+public:
/// getRoots - Return the root blocks of the current CFG. This may include
/// multiple blocks if we are computing post dominators. For forward
/// dominators, this will always be a single block (the entry node).
///
- inline const std::vector<NodeT*> &getRoots() const { return Roots; }
+ const std::vector<NodeT *> &getRoots() const { return Roots; }
/// isPostDominator - Returns true if analysis based of postdoms
///
bool isPostDominator() const { return IsPostDominators; }
};
-
-//===----------------------------------------------------------------------===//
-// DomTreeNodeBase - Dominator Tree Node
-template<class NodeT> class DominatorTreeBase;
+template <class NodeT> class DominatorTreeBase;
struct PostDominatorTree;
-template <class NodeT>
-class DomTreeNodeBase {
+/// \brief Base class for the actual dominator tree node.
+template <class NodeT> class DomTreeNodeBase {
NodeT *TheBB;
DomTreeNodeBase<NodeT> *IDom;
std::vector<DomTreeNodeBase<NodeT> *> Children;
mutable int DFSNumIn, DFSNumOut;
- template<class N> friend class DominatorTreeBase;
+ template <class N> friend class DominatorTreeBase;
friend struct PostDominatorTree;
+
public:
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator;
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::const_iterator
- const_iterator;
+ const_iterator;
- iterator begin() { return Children.begin(); }
- iterator end() { return Children.end(); }
+ iterator begin() { return Children.begin(); }
+ iterator end() { return Children.end(); }
const_iterator begin() const { return Children.begin(); }
- const_iterator end() const { return Children.end(); }
+ const_iterator end() const { return Children.end(); }
NodeT *getBlock() const { return TheBB; }
DomTreeNodeBase<NodeT> *getIDom() const { return IDom; }
- const std::vector<DomTreeNodeBase<NodeT>*> &getChildren() const {
+ const std::vector<DomTreeNodeBase<NodeT> *> &getChildren() const {
return Children;
}
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom)
- : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { }
+ : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) {}
DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) {
Children.push_back(C);
return C;
}
- size_t getNumChildren() const {
- return Children.size();
- }
+ size_t getNumChildren() const { return Children.size(); }
- void clearAllChildren() {
- Children.clear();
- }
+ void clearAllChildren() { Children.clear(); }
bool compare(const DomTreeNodeBase<NodeT> *Other) const {
if (getNumChildren() != Other->getNumChildren())
@@ -121,8 +123,8 @@ public:
void setIDom(DomTreeNodeBase<NodeT> *NewIDom) {
assert(IDom && "No immediate dominator?");
if (IDom != NewIDom) {
- typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
- std::find(IDom->Children.begin(), IDom->Children.end(), this);
+ typename std::vector<DomTreeNodeBase<NodeT> *>::iterator I =
+ std::find(IDom->Children.begin(), IDom->Children.end(), this);
assert(I != IDom->Children.end() &&
"Not in immediate dominator children set!");
// I am no longer your child...
@@ -138,18 +140,18 @@ public:
/// not call them.
unsigned getDFSNumIn() const { return DFSNumIn; }
unsigned getDFSNumOut() const { return DFSNumOut; }
+
private:
// Return true if this node is dominated by other. Use this only if DFS info
// is valid.
bool DominatedBy(const DomTreeNodeBase<NodeT> *other) const {
return this->DFSNumIn >= other->DFSNumIn &&
- this->DFSNumOut <= other->DFSNumOut;
+ this->DFSNumOut <= other->DFSNumOut;
}
};
-template<class NodeT>
-inline raw_ostream &operator<<(raw_ostream &o,
- const DomTreeNodeBase<NodeT> *Node) {
+template <class NodeT>
+raw_ostream &operator<<(raw_ostream &o, const DomTreeNodeBase<NodeT> *Node) {
if (Node->getBlock())
Node->getBlock()->printAsOperand(o, false);
else
@@ -160,25 +162,29 @@ inline raw_ostream &operator<<(raw_ostream &o,
return o << "\n";
}
-template<class NodeT>
-inline void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o,
- unsigned Lev) {
- o.indent(2*Lev) << "[" << Lev << "] " << N;
+template <class NodeT>
+void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o,
+ unsigned Lev) {
+ o.indent(2 * Lev) << "[" << Lev << "] " << N;
for (typename DomTreeNodeBase<NodeT>::const_iterator I = N->begin(),
- E = N->end(); I != E; ++I)
- PrintDomTree<NodeT>(*I, o, Lev+1);
+ E = N->end();
+ I != E; ++I)
+ PrintDomTree<NodeT>(*I, o, Lev + 1);
}
-//===----------------------------------------------------------------------===//
-/// DominatorTree - Calculate the immediate dominator tree for a function.
-///
+// The calculate routine is provided in a separate header but referenced here.
+template <class FuncT, class N>
+void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT,
+ FuncT &F);
-template<class FuncT, class N>
-void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
- FuncT& F);
+/// \brief Core dominator tree base class.
+///
+/// This class is a generic template over graph nodes. It is instantiated for
+/// various graphs in the LLVM IR or in the code generator.
+template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
+ DominatorTreeBase(const DominatorTreeBase &) LLVM_DELETED_FUNCTION;
+ DominatorTreeBase &operator=(const DominatorTreeBase &) LLVM_DELETED_FUNCTION;
-template<class NodeT>
-class DominatorTreeBase : public DominatorBase<NodeT> {
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
const DomTreeNodeBase<NodeT> *B) const {
assert(A != B);
@@ -187,12 +193,24 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
const DomTreeNodeBase<NodeT> *IDom;
while ((IDom = B->getIDom()) != nullptr && IDom != A && IDom != B)
- B = IDom; // Walk up the tree
+ B = IDom; // Walk up the tree
return IDom != nullptr;
}
+ /// \brief Wipe this tree's state without releasing any resources.
+ ///
+ /// This is essentially a post-move helper only. It leaves the object in an
+ /// assignable and destroyable state, but otherwise invalid.
+ void wipe() {
+ DomTreeNodes.clear();
+ IDoms.clear();
+ Vertex.clear();
+ Info.clear();
+ RootNode = nullptr;
+ }
+
protected:
- typedef DenseMap<NodeT*, DomTreeNodeBase<NodeT>*> DomTreeNodeMapType;
+ typedef DenseMap<NodeT *, DomTreeNodeBase<NodeT> *> DomTreeNodeMapType;
DomTreeNodeMapType DomTreeNodes;
DomTreeNodeBase<NodeT> *RootNode;
@@ -208,17 +226,18 @@ protected:
InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(nullptr) {}
};
- DenseMap<NodeT*, NodeT*> IDoms;
+ DenseMap<NodeT *, NodeT *> IDoms;
// Vertex - Map the DFS number to the NodeT*
- std::vector<NodeT*> Vertex;
+ std::vector<NodeT *> Vertex;
// Info - Collection of information used during the computation of idoms.
- DenseMap<NodeT*, InfoRec> Info;
+ DenseMap<NodeT *, InfoRec> Info;
void reset() {
for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(),
- E = DomTreeNodes.end(); I != E; ++I)
+ E = DomTreeNodes.end();
+ I != E; ++I)
delete I->second;
DomTreeNodes.clear();
IDoms.clear();
@@ -229,27 +248,29 @@ protected:
// NewBB is split and now it has one successor. Update dominator tree to
// reflect this change.
- template<class N, class GraphT>
- void Split(DominatorTreeBase<typename GraphT::NodeType>& DT,
- typename GraphT::NodeType* NewBB) {
+ template <class N, class GraphT>
+ void Split(DominatorTreeBase<typename GraphT::NodeType> &DT,
+ typename GraphT::NodeType *NewBB) {
assert(std::distance(GraphT::child_begin(NewBB),
GraphT::child_end(NewBB)) == 1 &&
"NewBB should have a single successor!");
- typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB);
-
- std::vector<typename GraphT::NodeType*> PredBlocks;
- typedef GraphTraits<Inverse<N> > InvTraits;
- for (typename InvTraits::ChildIteratorType PI =
- InvTraits::child_begin(NewBB),
- PE = InvTraits::child_end(NewBB); PI != PE; ++PI)
+ typename GraphT::NodeType *NewBBSucc = *GraphT::child_begin(NewBB);
+
+ std::vector<typename GraphT::NodeType *> PredBlocks;
+ typedef GraphTraits<Inverse<N>> InvTraits;
+ for (typename InvTraits::ChildIteratorType
+ PI = InvTraits::child_begin(NewBB),
+ PE = InvTraits::child_end(NewBB);
+ PI != PE; ++PI)
PredBlocks.push_back(*PI);
assert(!PredBlocks.empty() && "No predblocks?");
bool NewBBDominatesNewBBSucc = true;
- for (typename InvTraits::ChildIteratorType PI =
- InvTraits::child_begin(NewBBSucc),
- E = InvTraits::child_end(NewBBSucc); PI != E; ++PI) {
+ for (typename InvTraits::ChildIteratorType
+ PI = InvTraits::child_begin(NewBBSucc),
+ E = InvTraits::child_end(NewBBSucc);
+ PI != E; ++PI) {
typename InvTraits::NodeType *ND = *PI;
if (ND != NewBB && !DT.dominates(NewBBSucc, ND) &&
DT.isReachableFromEntry(ND)) {
@@ -292,8 +313,32 @@ protected:
public:
explicit DominatorTreeBase(bool isPostDom)
- : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
- virtual ~DominatorTreeBase() { reset(); }
+ : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
+ ~DominatorTreeBase() { reset(); }
+
+ DominatorTreeBase(DominatorTreeBase &&Arg)
+ : DominatorBase<NodeT>(
+ std::move(static_cast<DominatorBase<NodeT> &>(Arg))),
+ DomTreeNodes(std::move(Arg.DomTreeNodes)),
+ RootNode(std::move(Arg.RootNode)),
+ DFSInfoValid(std::move(Arg.DFSInfoValid)),
+ SlowQueries(std::move(Arg.SlowQueries)), IDoms(std::move(Arg.IDoms)),
+ Vertex(std::move(Arg.Vertex)), Info(std::move(Arg.Info)) {
+ Arg.wipe();
+ }
+ DominatorTreeBase &operator=(DominatorTreeBase &&RHS) {
+ DominatorBase<NodeT>::operator=(
+ std::move(static_cast<DominatorBase<NodeT> &>(RHS)));
+ DomTreeNodes = std::move(RHS.DomTreeNodes);
+ RootNode = std::move(RHS.RootNode);
+ DFSInfoValid = std::move(RHS.DFSInfoValid);
+ SlowQueries = std::move(RHS.SlowQueries);
+ IDoms = std::move(RHS.IDoms);
+ Vertex = std::move(RHS.Vertex);
+ Info = std::move(RHS.Info);
+ RHS.wipe();
+ return *this;
+ }
/// compare - Return false if the other dominator tree base matches this
/// dominator tree base. Otherwise return true.
@@ -304,15 +349,17 @@ public:
return true;
for (typename DomTreeNodeMapType::const_iterator
- I = this->DomTreeNodes.begin(),
- E = this->DomTreeNodes.end(); I != E; ++I) {
+ I = this->DomTreeNodes.begin(),
+ E = this->DomTreeNodes.end();
+ I != E; ++I) {
NodeT *BB = I->first;
- typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB);
+ typename DomTreeNodeMapType::const_iterator OI =
+ OtherDomTreeNodes.find(BB);
if (OI == OtherDomTreeNodes.end())
return true;
- DomTreeNodeBase<NodeT>* MyNd = I->second;
- DomTreeNodeBase<NodeT>* OtherNd = OI->second;
+ DomTreeNodeBase<NodeT> *MyNd = I->second;
+ DomTreeNodeBase<NodeT> *OtherNd = OI->second;
if (MyNd->compare(OtherNd))
return true;
@@ -321,18 +368,16 @@ public:
return false;
}
- virtual void releaseMemory() { reset(); }
+ void releaseMemory() { reset(); }
/// getNode - return the (Post)DominatorTree node for the specified basic
/// block. This is the same as using operator[] on this class.
///
- inline DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
+ DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
return DomTreeNodes.lookup(BB);
}
- inline DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const {
- return getNode(BB);
- }
+ DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { return getNode(BB); }
/// getRootNode - This returns the entry node for the CFG of the function. If
/// this tree represents the post-dominance relations for a function, however,
@@ -376,21 +421,19 @@ public:
/// isReachableFromEntry - Return true if A is dominated by the entry
/// block of the function containing it.
- bool isReachableFromEntry(const NodeT* A) const {
+ bool isReachableFromEntry(const NodeT *A) const {
assert(!this->isPostDominator() &&
"This is not implemented for post dominators");
return isReachableFromEntry(getNode(const_cast<NodeT *>(A)));
}
- inline bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const {
- return A;
- }
+ bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const { return A; }
/// dominates - Returns true iff A dominates B. Note that this is not a
/// constant time operation!
///
- inline bool dominates(const DomTreeNodeBase<NodeT> *A,
- const DomTreeNodeBase<NodeT> *B) const {
+ bool dominates(const DomTreeNodeBase<NodeT> *A,
+ const DomTreeNodeBase<NodeT> *B) const {
// A node trivially dominates itself.
if (B == A)
return true;
@@ -473,7 +516,7 @@ public:
}
// Collect NodeA dominators set.
- SmallPtrSet<DomTreeNodeBase<NodeT>*, 16> NodeADoms;
+ SmallPtrSet<DomTreeNodeBase<NodeT> *, 16> NodeADoms;
NodeADoms.insert(NodeA);
DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom();
while (IDomA) {
@@ -513,7 +556,7 @@ public:
assert(IDomNode && "Not immediate dominator specified for block!");
DFSInfoValid = false;
return DomTreeNodes[BB] =
- IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode));
+ IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode));
}
/// changeImmediateDominator - This method is used to update the dominator
@@ -538,11 +581,11 @@ public:
assert(Node && "Removing node that isn't in dominator tree.");
assert(Node->getChildren().empty() && "Node is not a leaf node.");
- // Remove node from immediate dominator's children list.
+ // Remove node from immediate dominator's children list.
DomTreeNodeBase<NodeT> *IDom = Node->getIDom();
if (IDom) {
- typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
- std::find(IDom->Children.begin(), IDom->Children.end(), Node);
+ typename std::vector<DomTreeNodeBase<NodeT> *>::iterator I =
+ std::find(IDom->Children.begin(), IDom->Children.end(), Node);
assert(I != IDom->Children.end() &&
"Not in immediate dominator children set!");
// I am no longer your child...
@@ -563,11 +606,12 @@ public:
/// splitBlock - BB is split and now it has one successor. Update dominator
/// tree to reflect this change.
- void splitBlock(NodeT* NewBB) {
+ void splitBlock(NodeT *NewBB) {
if (this->IsPostDominators)
- this->Split<Inverse<NodeT*>, GraphTraits<Inverse<NodeT*> > >(*this, NewBB);
+ this->Split<Inverse<NodeT *>, GraphTraits<Inverse<NodeT *>>>(*this,
+ NewBB);
else
- this->Split<NodeT*, GraphTraits<NodeT*> >(*this, NewBB);
+ this->Split<NodeT *, GraphTraits<NodeT *>>(*this, NewBB);
}
/// print - Convert to human readable form
@@ -588,28 +632,27 @@ public:
}
protected:
- template<class GraphT>
- friend typename GraphT::NodeType* Eval(
- DominatorTreeBase<typename GraphT::NodeType>& DT,
- typename GraphT::NodeType* V,
- unsigned LastLinked);
+ template <class GraphT>
+ friend typename GraphT::NodeType *
+ Eval(DominatorTreeBase<typename GraphT::NodeType> &DT,
+ typename GraphT::NodeType *V, unsigned LastLinked);
- template<class GraphT>
- friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
- typename GraphT::NodeType* V,
- unsigned N);
+ template <class GraphT>
+ friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType> &DT,
+ typename GraphT::NodeType *V, unsigned N);
- template<class FuncT, class N>
- friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
- FuncT& F);
+ template <class FuncT, class N>
+ friend void
+ Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, FuncT &F);
/// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
/// dominator tree in dfs order.
void updateDFSNumbers() const {
unsigned DFSNum = 0;
- SmallVector<std::pair<const DomTreeNodeBase<NodeT>*,
- typename DomTreeNodeBase<NodeT>::const_iterator>, 32> WorkStack;
+ SmallVector<std::pair<const DomTreeNodeBase<NodeT> *,
+ typename DomTreeNodeBase<NodeT>::const_iterator>,
+ 32> WorkStack;
const DomTreeNodeBase<NodeT> *ThisRoot = getRootNode();
@@ -626,7 +669,7 @@ protected:
while (!WorkStack.empty()) {
const DomTreeNodeBase<NodeT> *Node = WorkStack.back().first;
typename DomTreeNodeBase<NodeT>::const_iterator ChildIt =
- WorkStack.back().second;
+ WorkStack.back().second;
// If we visited all of the children of this node, "recurse" back up the
// stack setting the DFOutNum.
@@ -664,19 +707,14 @@ protected:
return this->DomTreeNodes[BB] = IDomNode->addChild(C);
}
- inline NodeT *getIDom(NodeT *BB) const {
- return IDoms.lookup(BB);
- }
+ NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); }
- inline void addRoot(NodeT* BB) {
- this->Roots.push_back(BB);
- }
+ void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
public:
/// recalculate - compute a dominator tree for the given function
- template<class FT>
- void recalculate(FT& F) {
- typedef GraphTraits<FT*> TraitsTy;
+ template <class FT> void recalculate(FT &F) {
+ typedef GraphTraits<FT *> TraitsTy;
reset();
this->Vertex.push_back(nullptr);
@@ -687,27 +725,29 @@ public:
this->IDoms[entry] = nullptr;
this->DomTreeNodes[entry] = nullptr;
- Calculate<FT, NodeT*>(*this, F);
+ Calculate<FT, NodeT *>(*this, F);
} else {
// Initialize the roots list
for (typename TraitsTy::nodes_iterator I = TraitsTy::nodes_begin(&F),
- E = TraitsTy::nodes_end(&F); I != E; ++I) {
+ E = TraitsTy::nodes_end(&F);
+ I != E; ++I) {
if (TraitsTy::child_begin(I) == TraitsTy::child_end(I))
addRoot(I);
- // Prepopulate maps so that we don't get iterator invalidation issues later.
+ // Prepopulate maps so that we don't get iterator invalidation issues
+ // later.
this->IDoms[I] = nullptr;
this->DomTreeNodes[I] = nullptr;
}
- Calculate<FT, Inverse<NodeT*> >(*this, F);
+ Calculate<FT, Inverse<NodeT *>>(*this, F);
}
}
};
// These two functions are declared out of line as a workaround for building
// with old (< r147295) versions of clang because of pr11642.
-template<class NodeT>
+template <class NodeT>
bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const {
if (A == B)
return true;
@@ -718,9 +758,9 @@ bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const {
return dominates(getNode(const_cast<NodeT *>(A)),
getNode(const_cast<NodeT *>(B)));
}
-template<class NodeT>
-bool
-DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) const {
+template <class NodeT>
+bool DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A,
+ const NodeT *B) const {
if (A == B)
return false;
diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h
index bcba5e0aeb43..ad4f8a9f429a 100644
--- a/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/include/llvm/Support/GenericDomTreeConstruction.h
@@ -22,8 +22,8 @@
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_GENERIC_DOM_TREE_CONSTRUCTION_H
-#define LLVM_SUPPORT_GENERIC_DOM_TREE_CONSTRUCTION_H
+#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
+#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/GenericDomTree.h"
@@ -125,7 +125,7 @@ Eval(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent];
// Process Ancestor first
- if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) {
+ if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) {
Work.push_back(VAncestor);
continue;
}
diff --git a/include/llvm/Support/IncludeFile.h b/include/llvm/Support/IncludeFile.h
deleted file mode 100644
index 2067e34f0d71..000000000000
--- a/include/llvm/Support/IncludeFile.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//===- llvm/Support/IncludeFile.h - Ensure Linking Of Library ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the FORCE_DEFINING_FILE_TO_BE_LINKED and DEFINE_FILE_FOR
-// macros.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_INCLUDEFILE_H
-#define LLVM_SUPPORT_INCLUDEFILE_H
-
-/// This macro is the public interface that IncludeFile.h exports. This gives
-/// us the option to implement the "link the definition" capability in any
-/// manner that we choose. All header files that depend on a specific .cpp
-/// file being linked at run time should use this macro instead of the
-/// IncludeFile class directly.
-///
-/// For example, foo.h would use:<br/>
-/// <tt>FORCE_DEFINING_FILE_TO_BE_LINKED(foo)</tt><br/>
-///
-/// And, foo.cp would use:<br/>
-/// <tt>DEFINING_FILE_FOR(foo)</tt><br/>
-#ifdef __GNUC__
-// If the `used' attribute is available, use it to create a variable
-// with an initializer that will force the linking of the defining file.
-#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \
- namespace llvm { \
- extern const char name ## LinkVar; \
- __attribute__((used)) static const char *const name ## LinkObj = \
- &name ## LinkVar; \
- }
-#else
-// Otherwise use a constructor call.
-#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \
- namespace llvm { \
- extern const char name ## LinkVar; \
- static const IncludeFile name ## LinkObj ( &name ## LinkVar ); \
- }
-#endif
-
-/// This macro is the counterpart to FORCE_DEFINING_FILE_TO_BE_LINKED. It should
-/// be used in a .cpp file to define the name referenced in a header file that
-/// will cause linkage of the .cpp file. It should only be used at extern level.
-#define DEFINING_FILE_FOR(name) \
- namespace llvm { const char name ## LinkVar = 0; }
-
-namespace llvm {
-
-/// This class is used in the implementation of FORCE_DEFINING_FILE_TO_BE_LINKED
-/// macro to make sure that the implementation of a header file is included
-/// into a tool that uses the header. This is solely
-/// to overcome problems linking .a files and not getting the implementation
-/// of compilation units we need. This is commonly an issue with the various
-/// Passes but also occurs elsewhere in LLVM. We like to use .a files because
-/// they link faster and provide the smallest executables. However, sometimes
-/// those executables are too small, if the program doesn't reference something
-/// that might be needed, especially by a loaded share object. This little class
-/// helps to resolve that problem. The basic strategy is to use this class in
-/// a header file and pass the address of a variable to the constructor. If the
-/// variable is defined in the header file's corresponding .cpp file then all
-/// tools/libraries that \#include the header file will require the .cpp as
-/// well.
-/// For example:<br/>
-/// <tt>extern int LinkMyCodeStub;</tt><br/>
-/// <tt>static IncludeFile LinkMyModule(&LinkMyCodeStub);</tt><br/>
-/// @brief Class to ensure linking of corresponding object file.
-struct IncludeFile {
- explicit IncludeFile(const void *);
-};
-
-}
-
-#endif
diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h
index ea76c9b58922..6a95432ca2d9 100644
--- a/include/llvm/Support/LEB128.h
+++ b/include/llvm/Support/LEB128.h
@@ -82,7 +82,7 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) {
uint64_t Value = 0;
unsigned Shift = 0;
do {
- Value += (*p & 0x7f) << Shift;
+ Value += uint64_t(*p & 0x7f) << Shift;
Shift += 7;
} while (*p++ >= 128);
if (n)
@@ -90,6 +90,26 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) {
return Value;
}
+/// Utility function to decode a SLEB128 value.
+inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr) {
+ const uint8_t *orig_p = p;
+ int64_t Value = 0;
+ unsigned Shift = 0;
+ uint8_t Byte;
+ do {
+ Byte = *p++;
+ Value |= ((Byte & 0x7f) << Shift);
+ Shift += 7;
+ } while (Byte >= 128);
+ // Sign extend negative numbers.
+ if (Byte & 0x40)
+ Value |= (-1ULL) << Shift;
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return Value;
+}
+
+
/// Utility function to get the size of the ULEB128-encoded value.
extern unsigned getULEB128Size(uint64_t Value);
diff --git a/include/llvm/Support/LineIterator.h b/include/llvm/Support/LineIterator.h
index 2a5826200143..9d4cd3bd4c6d 100644
--- a/include/llvm/Support/LineIterator.h
+++ b/include/llvm/Support/LineIterator.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_LINEITERATOR_H__
-#define LLVM_SUPPORT_LINEITERATOR_H__
+#ifndef LLVM_SUPPORT_LINEITERATOR_H
+#define LLVM_SUPPORT_LINEITERATOR_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
@@ -18,20 +18,22 @@ namespace llvm {
class MemoryBuffer;
-/// \brief A forward iterator which reads non-blank text lines from a buffer.
+/// \brief 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
/// "end" iterator.
///
-/// The iterator also is aware of what line number it is currently processing
-/// and can strip comment lines given the comment-starting character.
+/// The iterator is aware of what line number it is currently processing. It
+/// strips blank lines by default, and comment lines given a comment-starting
+/// character.
///
/// Note that this iterator requires the buffer to be nul terminated.
class line_iterator
: public std::iterator<std::forward_iterator_tag, StringRef> {
const MemoryBuffer *Buffer;
char CommentMarker;
+ bool SkipBlanks;
unsigned LineNumber;
StringRef CurrentLine;
@@ -41,7 +43,8 @@ public:
line_iterator() : Buffer(nullptr) {}
/// \brief Construct a new iterator around some memory buffer.
- explicit line_iterator(const MemoryBuffer &Buffer, char CommentMarker = '\0');
+ 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.
bool is_at_eof() const { return !Buffer; }
@@ -82,4 +85,4 @@ private:
};
}
-#endif // LLVM_SUPPORT_LINEITERATOR_H__
+#endif
diff --git a/include/llvm/Support/MD5.h b/include/llvm/Support/MD5.h
index 4eb8507ea34f..f6e1e92c9fa8 100644
--- a/include/llvm/Support/MD5.h
+++ b/include/llvm/Support/MD5.h
@@ -25,8 +25,8 @@
* See md5.c for more information.
*/
-#ifndef LLVM_SYSTEM_MD5_H
-#define LLVM_SYSTEM_MD5_H
+#ifndef LLVM_SUPPORT_MD5_H
+#define LLVM_SUPPORT_MD5_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
@@ -55,11 +55,11 @@ public:
void update(StringRef Str);
/// \brief Finishes off the hash and puts the result in result.
- void final(MD5Result &result);
+ void final(MD5Result &Result);
/// \brief 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 &Res, SmallString<32> &Str);
+ static void stringifyResult(MD5Result &Result, SmallString<32> &Str);
private:
const uint8_t *body(ArrayRef<uint8_t> Data);
diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h
index 90df1f4f140f..775127505923 100644
--- a/include/llvm/Support/MachO.h
+++ b/include/llvm/Support/MachO.h
@@ -73,7 +73,10 @@ namespace llvm {
MH_SETUID_SAFE = 0x00080000u,
MH_NO_REEXPORTED_DYLIBS = 0x00100000u,
MH_PIE = 0x00200000u,
- MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u
+ MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u,
+ MH_HAS_TLV_DESCRIPTORS = 0x00800000u,
+ MH_NO_HEAP_EXECUTION = 0x01000000u,
+ MH_APP_EXTENSION_SAFE = 0x02000000u
};
enum : uint32_t {
@@ -127,8 +130,8 @@ namespace llvm {
LC_DATA_IN_CODE = 0x00000029u,
LC_SOURCE_VERSION = 0x0000002Au,
LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu,
- // 0x0000002Cu,
- LC_LINKER_OPTIONS = 0x0000002Du,
+ LC_ENCRYPTION_INFO_64 = 0x0000002Cu,
+ LC_LINKER_OPTION = 0x0000002Du,
LC_LINKER_OPTIMIZATION_HINT = 0x0000002Eu
};
@@ -327,7 +330,8 @@ namespace llvm {
enum ExportSymbolKind {
EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00u,
- EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01u
+ EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01u,
+ EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE = 0x02u
};
@@ -838,12 +842,21 @@ namespace llvm {
uint32_t cryptid;
};
+ struct encryption_info_command_64 {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t cryptoff;
+ uint32_t cryptsize;
+ uint32_t cryptid;
+ uint32_t pad;
+ };
+
struct version_min_command {
uint32_t cmd; // LC_VERSION_MIN_MACOSX or
// LC_VERSION_MIN_IPHONEOS
uint32_t cmdsize; // sizeof(struct version_min_command)
uint32_t version; // X.Y.Z is encoded in nibbles xxxx.yy.zz
- uint32_t reserved;
+ uint32_t sdk; // X.Y.Z is encoded in nibbles xxxx.yy.zz
};
struct dyld_info_command {
@@ -861,7 +874,7 @@ namespace llvm {
uint32_t export_size;
};
- struct linker_options_command {
+ struct linker_option_command {
uint32_t cmd;
uint32_t cmdsize;
uint32_t count;
@@ -1094,12 +1107,84 @@ namespace llvm {
sys::swapByteOrder(d.dylib.compatibility_version);
}
+ inline void swapStruct(sub_framework_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.umbrella);
+ }
+
+ inline void swapStruct(sub_umbrella_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.sub_umbrella);
+ }
+
+ inline void swapStruct(sub_library_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.sub_library);
+ }
+
+ inline void swapStruct(sub_client_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.client);
+ }
+
+ inline void swapStruct(routines_command &r) {
+ sys::swapByteOrder(r.cmd);
+ sys::swapByteOrder(r.cmdsize);
+ sys::swapByteOrder(r.init_address);
+ sys::swapByteOrder(r.init_module);
+ sys::swapByteOrder(r.reserved1);
+ sys::swapByteOrder(r.reserved2);
+ sys::swapByteOrder(r.reserved3);
+ sys::swapByteOrder(r.reserved4);
+ sys::swapByteOrder(r.reserved5);
+ sys::swapByteOrder(r.reserved6);
+ }
+
+ inline void swapStruct(routines_command_64 &r) {
+ sys::swapByteOrder(r.cmd);
+ sys::swapByteOrder(r.cmdsize);
+ sys::swapByteOrder(r.init_address);
+ sys::swapByteOrder(r.init_module);
+ sys::swapByteOrder(r.reserved1);
+ sys::swapByteOrder(r.reserved2);
+ sys::swapByteOrder(r.reserved3);
+ sys::swapByteOrder(r.reserved4);
+ sys::swapByteOrder(r.reserved5);
+ sys::swapByteOrder(r.reserved6);
+ }
+
+ inline void swapStruct(thread_command &t) {
+ sys::swapByteOrder(t.cmd);
+ sys::swapByteOrder(t.cmdsize);
+ }
+
inline void swapStruct(dylinker_command &d) {
sys::swapByteOrder(d.cmd);
sys::swapByteOrder(d.cmdsize);
sys::swapByteOrder(d.name);
}
+ inline void swapStruct(uuid_command &u) {
+ sys::swapByteOrder(u.cmd);
+ sys::swapByteOrder(u.cmdsize);
+ }
+
+ inline void swapStruct(rpath_command &r) {
+ sys::swapByteOrder(r.cmd);
+ sys::swapByteOrder(r.cmdsize);
+ sys::swapByteOrder(r.path);
+ }
+
+ inline void swapStruct(source_version_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.version);
+ }
+
inline void swapStruct(entry_point_command &e) {
sys::swapByteOrder(e.cmd);
sys::swapByteOrder(e.cmdsize);
@@ -1107,6 +1192,23 @@ namespace llvm {
sys::swapByteOrder(e.stacksize);
}
+ inline void swapStruct(encryption_info_command &e) {
+ sys::swapByteOrder(e.cmd);
+ sys::swapByteOrder(e.cmdsize);
+ sys::swapByteOrder(e.cryptoff);
+ sys::swapByteOrder(e.cryptsize);
+ sys::swapByteOrder(e.cryptid);
+ }
+
+ inline void swapStruct(encryption_info_command_64 &e) {
+ sys::swapByteOrder(e.cmd);
+ sys::swapByteOrder(e.cmdsize);
+ sys::swapByteOrder(e.cryptoff);
+ sys::swapByteOrder(e.cryptsize);
+ sys::swapByteOrder(e.cryptid);
+ sys::swapByteOrder(e.pad);
+ }
+
inline void swapStruct(dysymtab_command &dst) {
sys::swapByteOrder(dst.cmd);
sys::swapByteOrder(dst.cmdsize);
@@ -1159,7 +1261,7 @@ namespace llvm {
sys::swapByteOrder(C.datasize);
}
- inline void swapStruct(linker_options_command &C) {
+ inline void swapStruct(linker_option_command &C) {
sys::swapByteOrder(C.cmd);
sys::swapByteOrder(C.cmdsize);
sys::swapByteOrder(C.count);
@@ -1169,7 +1271,7 @@ namespace llvm {
sys::swapByteOrder(C.cmd);
sys::swapByteOrder(C.cmdsize);
sys::swapByteOrder(C.version);
- sys::swapByteOrder(C.reserved);
+ sys::swapByteOrder(C.sdk);
}
inline void swapStruct(data_in_code_entry &C) {
@@ -1316,6 +1418,262 @@ namespace llvm {
CPU_SUBTYPE_MC980000_ALL = CPU_SUBTYPE_POWERPC_ALL,
CPU_SUBTYPE_MC98601 = CPU_SUBTYPE_POWERPC_601
};
+
+ struct x86_thread_state64_t {
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rdi;
+ uint64_t rsi;
+ uint64_t rbp;
+ uint64_t rsp;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rip;
+ uint64_t rflags;
+ uint64_t cs;
+ uint64_t fs;
+ uint64_t gs;
+ };
+
+ enum x86_fp_control_precis {
+ x86_FP_PREC_24B = 0,
+ x86_FP_PREC_53B = 2,
+ x86_FP_PREC_64B = 3
+ };
+
+ enum x86_fp_control_rc {
+ x86_FP_RND_NEAR = 0,
+ x86_FP_RND_DOWN = 1,
+ x86_FP_RND_UP = 2,
+ x86_FP_CHOP = 3
+ };
+
+ struct fp_control_t {
+ unsigned short
+ invalid :1,
+ denorm :1,
+ zdiv :1,
+ ovrfl :1,
+ undfl :1,
+ precis :1,
+ :2,
+ pc :2,
+ rc :2,
+ :1,
+ :3;
+ };
+
+ struct fp_status_t {
+ unsigned short
+ invalid :1,
+ denorm :1,
+ zdiv :1,
+ ovrfl :1,
+ undfl :1,
+ precis :1,
+ stkflt :1,
+ errsumm :1,
+ c0 :1,
+ c1 :1,
+ c2 :1,
+ tos :3,
+ c3 :1,
+ busy :1;
+ };
+
+ struct mmst_reg_t {
+ char mmst_reg[10];
+ char mmst_rsrv[6];
+ };
+
+ struct xmm_reg_t {
+ char xmm_reg[16];
+ };
+
+ struct x86_float_state64_t {
+ int32_t fpu_reserved[2];
+ fp_control_t fpu_fcw;
+ fp_status_t fpu_fsw;
+ uint8_t fpu_ftw;
+ uint8_t fpu_rsrv1;
+ uint16_t fpu_fop;
+ uint32_t fpu_ip;
+ uint16_t fpu_cs;
+ uint16_t fpu_rsrv2;
+ uint32_t fpu_dp;
+ uint16_t fpu_ds;
+ uint16_t fpu_rsrv3;
+ uint32_t fpu_mxcsr;
+ uint32_t fpu_mxcsrmask;
+ mmst_reg_t fpu_stmm0;
+ mmst_reg_t fpu_stmm1;
+ mmst_reg_t fpu_stmm2;
+ mmst_reg_t fpu_stmm3;
+ mmst_reg_t fpu_stmm4;
+ mmst_reg_t fpu_stmm5;
+ mmst_reg_t fpu_stmm6;
+ mmst_reg_t fpu_stmm7;
+ xmm_reg_t fpu_xmm0;
+ xmm_reg_t fpu_xmm1;
+ xmm_reg_t fpu_xmm2;
+ xmm_reg_t fpu_xmm3;
+ xmm_reg_t fpu_xmm4;
+ xmm_reg_t fpu_xmm5;
+ xmm_reg_t fpu_xmm6;
+ xmm_reg_t fpu_xmm7;
+ xmm_reg_t fpu_xmm8;
+ xmm_reg_t fpu_xmm9;
+ xmm_reg_t fpu_xmm10;
+ xmm_reg_t fpu_xmm11;
+ xmm_reg_t fpu_xmm12;
+ xmm_reg_t fpu_xmm13;
+ xmm_reg_t fpu_xmm14;
+ xmm_reg_t fpu_xmm15;
+ char fpu_rsrv4[6*16];
+ uint32_t fpu_reserved1;
+ };
+
+ struct x86_exception_state64_t {
+ uint16_t trapno;
+ uint16_t cpu;
+ uint32_t err;
+ uint64_t faultvaddr;
+ };
+
+ inline void swapStruct(x86_thread_state64_t &x) {
+ sys::swapByteOrder(x.rax);
+ sys::swapByteOrder(x.rbx);
+ sys::swapByteOrder(x.rcx);
+ sys::swapByteOrder(x.rdx);
+ sys::swapByteOrder(x.rdi);
+ sys::swapByteOrder(x.rsi);
+ sys::swapByteOrder(x.rbp);
+ sys::swapByteOrder(x.rsp);
+ sys::swapByteOrder(x.r8);
+ sys::swapByteOrder(x.r9);
+ sys::swapByteOrder(x.r10);
+ sys::swapByteOrder(x.r11);
+ sys::swapByteOrder(x.r12);
+ sys::swapByteOrder(x.r13);
+ sys::swapByteOrder(x.r14);
+ sys::swapByteOrder(x.r15);
+ sys::swapByteOrder(x.rip);
+ sys::swapByteOrder(x.rflags);
+ sys::swapByteOrder(x.cs);
+ sys::swapByteOrder(x.fs);
+ sys::swapByteOrder(x.gs);
+ }
+
+ inline void swapStruct(x86_float_state64_t &x) {
+ sys::swapByteOrder(x.fpu_reserved[0]);
+ sys::swapByteOrder(x.fpu_reserved[1]);
+ // TODO swap: fp_control_t fpu_fcw;
+ // TODO swap: fp_status_t fpu_fsw;
+ sys::swapByteOrder(x.fpu_fop);
+ sys::swapByteOrder(x.fpu_ip);
+ sys::swapByteOrder(x.fpu_cs);
+ sys::swapByteOrder(x.fpu_rsrv2);
+ sys::swapByteOrder(x.fpu_dp);
+ sys::swapByteOrder(x.fpu_ds);
+ sys::swapByteOrder(x.fpu_rsrv3);
+ sys::swapByteOrder(x.fpu_mxcsr);
+ sys::swapByteOrder(x.fpu_mxcsrmask);
+ sys::swapByteOrder(x.fpu_reserved1);
+ }
+
+ inline void swapStruct(x86_exception_state64_t &x) {
+ sys::swapByteOrder(x.trapno);
+ sys::swapByteOrder(x.cpu);
+ sys::swapByteOrder(x.err);
+ sys::swapByteOrder(x.faultvaddr);
+ }
+
+ struct x86_state_hdr_t {
+ uint32_t flavor;
+ uint32_t count;
+ };
+
+ struct x86_thread_state_t {
+ x86_state_hdr_t tsh;
+ union {
+ x86_thread_state64_t ts64;
+ } uts;
+ };
+
+ struct x86_float_state_t {
+ x86_state_hdr_t fsh;
+ union {
+ x86_float_state64_t fs64;
+ } ufs;
+ };
+
+ struct x86_exception_state_t {
+ x86_state_hdr_t esh;
+ union {
+ x86_exception_state64_t es64;
+ } ues;
+ };
+
+ inline void swapStruct(x86_state_hdr_t &x) {
+ sys::swapByteOrder(x.flavor);
+ sys::swapByteOrder(x.count);
+ }
+
+ enum X86ThreadFlavors {
+ x86_THREAD_STATE32 = 1,
+ x86_FLOAT_STATE32 = 2,
+ x86_EXCEPTION_STATE32 = 3,
+ x86_THREAD_STATE64 = 4,
+ x86_FLOAT_STATE64 = 5,
+ x86_EXCEPTION_STATE64 = 6,
+ x86_THREAD_STATE = 7,
+ x86_FLOAT_STATE = 8,
+ x86_EXCEPTION_STATE = 9,
+ x86_DEBUG_STATE32 = 10,
+ x86_DEBUG_STATE64 = 11,
+ x86_DEBUG_STATE = 12
+ };
+
+ inline void swapStruct(x86_thread_state_t &x) {
+ swapStruct(x.tsh);
+ if (x.tsh.flavor == x86_THREAD_STATE64)
+ swapStruct(x.uts.ts64);
+ }
+
+ inline void swapStruct(x86_float_state_t &x) {
+ swapStruct(x.fsh);
+ if (x.fsh.flavor == x86_FLOAT_STATE64)
+ swapStruct(x.ufs.fs64);
+ }
+
+ inline void swapStruct(x86_exception_state_t &x) {
+ swapStruct(x.esh);
+ if (x.esh.flavor == x86_EXCEPTION_STATE64)
+ swapStruct(x.ues.es64);
+ }
+
+ const uint32_t x86_THREAD_STATE64_COUNT =
+ sizeof(x86_thread_state64_t) / sizeof(uint32_t);
+ const uint32_t x86_FLOAT_STATE64_COUNT =
+ sizeof(x86_float_state64_t) / sizeof(uint32_t);
+ const uint32_t x86_EXCEPTION_STATE64_COUNT =
+ sizeof(x86_exception_state64_t) / sizeof(uint32_t);
+
+ const uint32_t x86_THREAD_STATE_COUNT =
+ sizeof(x86_thread_state_t) / sizeof(uint32_t);
+ const uint32_t x86_FLOAT_STATE_COUNT =
+ sizeof(x86_float_state_t) / sizeof(uint32_t);
+ const uint32_t x86_EXCEPTION_STATE_COUNT =
+ sizeof(x86_exception_state_t) / sizeof(uint32_t);
+
} // end namespace MachO
} // end namespace llvm
diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h
index d8fbfeb8e20c..addd34e704bc 100644
--- a/include/llvm/Support/ManagedStatic.h
+++ b/include/llvm/Support/ManagedStatic.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_MANAGED_STATIC_H
-#define LLVM_SUPPORT_MANAGED_STATIC_H
+#ifndef LLVM_SUPPORT_MANAGEDSTATIC_H
+#define LLVM_SUPPORT_MANAGEDSTATIC_H
#include "llvm/Support/Atomic.h"
#include "llvm/Support/Threading.h"
diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h
index 0abba62a2c23..698363614ac5 100644
--- a/include/llvm/Support/MathExtras.h
+++ b/include/llvm/Support/MathExtras.h
@@ -22,7 +22,6 @@
#ifdef _MSC_VER
#include <intrin.h>
-#include <limits>
#endif
namespace llvm {
@@ -73,7 +72,7 @@ countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed, std::size_t>::type
-countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION;
+countTrailingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION;
#if __GNUC__ >= 4 || _MSC_VER
template <>
@@ -81,7 +80,7 @@ inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
-#if __has_builtin(__builtin_ctz) || __GNUC_PREREQ(4, 0)
+#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0)
return __builtin_ctz(Val);
#elif _MSC_VER
unsigned long Index;
@@ -96,7 +95,7 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 64;
-#if __has_builtin(__builtin_ctzll) || __GNUC_PREREQ(4, 0)
+#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0)
return __builtin_ctzll(Val);
#elif _MSC_VER
unsigned long Index;
@@ -139,7 +138,7 @@ countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed, std::size_t>::type
-countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION;
+countLeadingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION;
#if __GNUC__ >= 4 || _MSC_VER
template <>
@@ -147,7 +146,7 @@ inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
-#if __has_builtin(__builtin_clz) || __GNUC_PREREQ(4, 0)
+#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0)
return __builtin_clz(Val);
#elif _MSC_VER
unsigned long Index;
@@ -162,7 +161,7 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 64;
-#if __has_builtin(__builtin_clzll) || __GNUC_PREREQ(4, 0)
+#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0)
return __builtin_clzll(Val);
#elif _MSC_VER
unsigned long Index;
@@ -194,7 +193,7 @@ findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed, T>::type
-findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION;
+findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION;
/// \brief Get the index of the last set bit starting from the least
/// significant bit.
@@ -220,7 +219,7 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed, T>::type
-findLastSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION;
+findLastSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION;
/// \brief Macro compressed bit reversal table for 256 bits.
///
@@ -550,16 +549,23 @@ inline uint64_t MinAlign(uint64_t A, uint64_t B) {
return (A | B) & (1 + ~(A | B));
}
-/// \brief Aligns \c Ptr to \c Alignment bytes, rounding up.
+/// \brief Aligns \c Addr to \c Alignment bytes, rounding up.
///
/// Alignment should be a power of two. This method rounds up, so
-/// AlignPtr(7, 4) == 8 and AlignPtr(8, 4) == 8.
-inline char *alignPtr(char *Ptr, size_t Alignment) {
+/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8.
+inline uintptr_t alignAddr(void *Addr, size_t Alignment) {
assert(Alignment && isPowerOf2_64((uint64_t)Alignment) &&
"Alignment is not a power of two!");
- return (char *)(((uintptr_t)Ptr + Alignment - 1) &
- ~(uintptr_t)(Alignment - 1));
+ assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr);
+
+ return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1));
+}
+
+/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment
+/// bytes, rounding up.
+inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) {
+ return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
}
/// NextPowerOf2 - Returns the next power of two (in 64-bits)
@@ -589,9 +595,10 @@ inline uint64_t PowerOf2Floor(uint64_t A) {
/// RoundUpToAlignment(5, 8) = 8
/// RoundUpToAlignment(17, 8) = 24
/// RoundUpToAlignment(~0LL, 8) = 0
+/// RoundUpToAlignment(321, 255) = 510
/// \endcode
inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) {
- return ((Value + Align - 1) / Align) * Align;
+ return (Value + Align - 1) / Align * Align;
}
/// Returns the offset to the next integer (mod 2**64) that is greater than
@@ -632,13 +639,7 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
return int64_t(X << (64 - B)) >> (64 - B);
}
-#if defined(_MSC_VER)
- // Visual Studio defines the HUGE_VAL class of macros using purposeful
- // constant arithmetic overflow, which it then warns on when encountered.
- const float huge_valf = std::numeric_limits<float>::infinity();
-#else
- const float huge_valf = HUGE_VALF;
-#endif
+extern const float huge_valf;
} // End llvm namespace
#endif
diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h
index 147be47e1c8f..e2f8d7e90fef 100644
--- a/include/llvm/Support/MemoryBuffer.h
+++ b/include/llvm/Support/MemoryBuffer.h
@@ -24,11 +24,13 @@
#include <system_error>
namespace llvm {
-/// MemoryBuffer - This interface provides simple read-only access to a block
-/// of memory, and provides simple methods for reading files and standard input
-/// into a memory buffer. In addition to basic access to the characters in the
-/// file, this interface guarantees you can read one character past the end of
-/// the file, and that this character will read as '\0'.
+class MemoryBufferRef;
+
+/// This interface provides simple read-only access to a block of memory, and
+/// provides simple methods for reading files and standard input into a memory
+/// buffer. In addition to basic access to the characters in the file, this
+/// interface guarantees you can read one character past the end of the file,
+/// and that this character will read as '\0'.
///
/// The '\0' guarantee is needed to support an optimization -- it's intended to
/// be more efficient for clients which are reading all the data to stop
@@ -55,8 +57,8 @@ public:
return StringRef(BufferStart, getBufferSize());
}
- /// getBufferIdentifier - Return an identifier for this buffer, typically the
- /// filename it was read from.
+ /// Return an identifier for this buffer, typically the filename it was read
+ /// from.
virtual const char *getBufferIdentifier() const {
return "Unknown buffer";
}
@@ -70,19 +72,15 @@ public:
/// changing, e.g. when libclang tries to parse while the user is
/// editing/updating the file.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
- getFile(Twine Filename, int64_t FileSize = -1,
+ getFile(const Twine &Filename, int64_t FileSize = -1,
bool RequiresNullTerminator = true, bool IsVolatileSize = false);
/// Given an already-open file descriptor, map some slice of it into a
/// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
/// Since this is in the middle of a file, the buffer is not null terminated.
- ///
- /// \param IsVolatileSize Set to true to indicate that the file size may be
- /// changing, e.g. when libclang tries to parse while the user is
- /// editing/updating the file.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
- getOpenFileSlice(int FD, const char *Filename, uint64_t MapSize,
- int64_t Offset, bool IsVolatileSize = false);
+ getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
+ int64_t Offset);
/// Given an already-open file descriptor, read the file and return a
/// MemoryBuffer.
@@ -91,33 +89,34 @@ public:
/// changing, e.g. when libclang tries to parse while the user is
/// editing/updating the file.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
- getOpenFile(int FD, const char *Filename, uint64_t FileSize,
+ getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
bool RequiresNullTerminator = true, bool IsVolatileSize = false);
- /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note
- /// that InputData must be null terminated if RequiresNullTerminator is true.
- static MemoryBuffer *getMemBuffer(StringRef InputData,
- StringRef BufferName = "",
- bool RequiresNullTerminator = true);
-
- /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
- /// copying the contents and taking ownership of it. InputData does not
- /// have to be null terminated.
- static MemoryBuffer *getMemBufferCopy(StringRef InputData,
- StringRef BufferName = "");
-
- /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
- /// is completely initialized to zeros. Note that the caller should
- /// initialize the memory allocated by this method. The memory is owned by
- /// the MemoryBuffer object.
- static MemoryBuffer *getNewMemBuffer(size_t Size, StringRef BufferName = "");
-
- /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
- /// that is not initialized. Note that the caller should initialize the
- /// memory allocated by this method. The memory is owned by the MemoryBuffer
- /// object.
- static MemoryBuffer *getNewUninitMemBuffer(size_t Size,
- StringRef BufferName = "");
+ /// Open the specified memory range as a MemoryBuffer. Note that InputData
+ /// must be null terminated if RequiresNullTerminator is true.
+ static std::unique_ptr<MemoryBuffer>
+ getMemBuffer(StringRef InputData, StringRef BufferName = "",
+ bool RequiresNullTerminator = true);
+
+ static std::unique_ptr<MemoryBuffer>
+ getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true);
+
+ /// Open the specified memory range as a MemoryBuffer, copying the contents
+ /// and taking ownership of it. InputData does not have to be null terminated.
+ static 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 = "");
+
+ /// Allocate a new MemoryBuffer of the specified size that is not initialized.
+ /// Note that the caller should initialize the memory allocated by this
+ /// method. The memory is owned by the MemoryBuffer object.
+ static std::unique_ptr<MemoryBuffer>
+ getNewUninitMemBuffer(size_t Size, const Twine &BufferName = "");
/// Read all of stdin into a file buffer, and return it.
static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN();
@@ -125,7 +124,11 @@ public:
/// Open the specified file as a MemoryBuffer, or open stdin if the Filename
/// is "-".
static ErrorOr<std::unique_ptr<MemoryBuffer>>
- getFileOrSTDIN(StringRef Filename, int64_t FileSize = -1);
+ getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1);
+
+ /// Map a subrange of the the specified file as a MemoryBuffer.
+ static ErrorOr<std::unique_ptr<MemoryBuffer>>
+ getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
//===--------------------------------------------------------------------===//
// Provided for performance analysis.
@@ -139,7 +142,27 @@ public:
/// Return information on the memory mechanism used to support the
/// MemoryBuffer.
- virtual BufferKind getBufferKind() const = 0;
+ virtual BufferKind getBufferKind() const = 0;
+
+ MemoryBufferRef getMemBufferRef() const;
+};
+
+class MemoryBufferRef {
+ StringRef Buffer;
+ StringRef Identifier;
+
+public:
+ MemoryBufferRef() {}
+ MemoryBufferRef(StringRef Buffer, StringRef Identifier)
+ : Buffer(Buffer), Identifier(Identifier) {}
+
+ StringRef getBuffer() const { return Buffer; }
+
+ StringRef getBufferIdentifier() const { return Identifier; }
+
+ const char *getBufferStart() const { return Buffer.begin(); }
+ const char *getBufferEnd() const { return Buffer.end(); }
+ size_t getBufferSize() const { return Buffer.size(); }
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/include/llvm/Support/MemoryObject.h b/include/llvm/Support/MemoryObject.h
index 17aa9d2f675a..e0c8749da346 100644
--- a/include/llvm/Support/MemoryObject.h
+++ b/include/llvm/Support/MemoryObject.h
@@ -14,49 +14,53 @@
namespace llvm {
-/// MemoryObject - Abstract base class for contiguous addressable memory.
-/// Necessary for cases in which the memory is in another process, in a
-/// file, or on a remote machine.
-/// All size and offset parameters are uint64_ts, to allow 32-bit processes
-/// access to 64-bit address spaces.
+/// Interface to data which might be streamed. Streamability has 2 important
+/// implications/restrictions. First, the data might not yet exist in memory
+/// when the request is made. This just means that readByte/readBytes might have
+/// to block or do some work to get it. More significantly, the exact size of
+/// the object might not be known until it has all been fetched. This means that
+/// to return the right result, getExtent must also wait for all the data to
+/// arrive; therefore it should not be called on objects which are actually
+/// streamed (this would defeat the purpose of streaming). Instead,
+/// isValidAddress can be used to test addresses without knowing the exact size
+/// of the stream. Finally, getPointer can be used instead of readBytes to avoid
+/// extra copying.
class MemoryObject {
public:
- /// Destructor - Override as necessary.
virtual ~MemoryObject();
- /// getBase - Returns the lowest valid address in the region.
- ///
- /// @result - The lowest valid address.
- virtual uint64_t getBase() const = 0;
-
- /// getExtent - Returns the size of the region in bytes. (The region is
- /// contiguous, so the highest valid address of the region
- /// is getBase() + getExtent() - 1).
+ /// Returns the size of the region in bytes. (The region is contiguous, so
+ /// the highest valid address of the region is getExtent() - 1).
///
/// @result - The size of the region.
virtual uint64_t getExtent() const = 0;
- /// readByte - Tries to read a single byte from the region.
- ///
- /// @param address - The address of the byte, in the same space as getBase().
- /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL.
- /// @result - 0 if successful; -1 if not. Failure may be due to a
- /// bounds violation or an implementation-specific error.
- virtual int readByte(uint64_t address, uint8_t *ptr) const = 0;
-
- /// readBytes - Tries to read a contiguous range of bytes from the
- /// region, up to the end of the region.
- /// You should override this function if there is a quicker
- /// way than going back and forth with individual bytes.
+ /// Tries to read a contiguous range of bytes from the region, up to the end
+ /// of the region.
///
- /// @param address - The address of the first byte, in the same space as
- /// getBase().
- /// @param size - The number of bytes to copy.
- /// @param buf - A pointer to a buffer to be filled in. Must be non-NULL
+ /// @param Buf - A pointer to a buffer to be filled in. Must be non-NULL
/// and large enough to hold size bytes.
- /// @result - 0 if successful; -1 if not. Failure may be due to a
- /// bounds violation or an implementation-specific error.
- virtual int readBytes(uint64_t address, uint64_t size, uint8_t *buf) const;
+ /// @param Size - The number of bytes to copy.
+ /// @param Address - The address of the first byte, in the same space as
+ /// getBase().
+ /// @result - The number of bytes read.
+ virtual uint64_t readBytes(uint8_t *Buf, uint64_t Size,
+ uint64_t Address) const = 0;
+
+ /// Ensures that the requested data is in memory, and returns a pointer to it.
+ /// More efficient than using readBytes if the data is already in memory. May
+ /// block until (address - base + size) bytes have been read
+ /// @param address - address of the byte, in the same space as getBase()
+ /// @param size - amount of data that must be available on return
+ /// @result - valid pointer to the requested data
+ virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0;
+
+ /// Returns true if the address is within the object (i.e. between base and
+ /// base + extent - 1 inclusive). May block until (address - base) bytes have
+ /// been read
+ /// @param address - address of the byte, in the same space as getBase()
+ /// @result - true if the address may be read with readByte()
+ virtual bool isValidAddress(uint64_t address) const = 0;
};
}
diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h
index 496a4381f3fc..97dd50115322 100644
--- a/include/llvm/Support/Mutex.h
+++ b/include/llvm/Support/Mutex.h
@@ -86,16 +86,17 @@ namespace llvm
/// indicates whether this mutex should become a no-op when we're not
/// running in multithreaded mode.
template<bool mt_only>
- class SmartMutex : public MutexImpl {
+ class SmartMutex {
+ MutexImpl impl;
unsigned acquired;
bool recursive;
public:
explicit SmartMutex(bool rec = true) :
- MutexImpl(rec), acquired(0), recursive(rec) { }
+ impl(rec), acquired(0), recursive(rec) { }
- bool acquire() {
+ bool lock() {
if (!mt_only || llvm_is_multithreaded()) {
- return MutexImpl::acquire();
+ return impl.acquire();
} else {
// Single-threaded debugging code. This would be racy in
// multithreaded mode, but provides not sanity checks in single
@@ -106,9 +107,9 @@ namespace llvm
}
}
- bool release() {
+ bool unlock() {
if (!mt_only || llvm_is_multithreaded()) {
- return MutexImpl::release();
+ return impl.release();
} else {
// Single-threaded debugging code. This would be racy in
// multithreaded mode, but provides not sanity checks in single
@@ -120,9 +121,9 @@ namespace llvm
}
}
- bool tryacquire() {
+ bool try_lock() {
if (!mt_only || llvm_is_multithreaded())
- return MutexImpl::tryacquire();
+ return impl.tryacquire();
else return true;
}
@@ -140,11 +141,11 @@ namespace llvm
public:
SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
- mtx.acquire();
+ mtx.lock();
}
~SmartScopedLock() {
- mtx.release();
+ mtx.unlock();
}
};
diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h
index 6bb162277e2b..b9f941dab323 100644
--- a/include/llvm/Support/MutexGuard.h
+++ b/include/llvm/Support/MutexGuard.h
@@ -29,8 +29,8 @@ namespace llvm {
MutexGuard(const MutexGuard &) LLVM_DELETED_FUNCTION;
void operator=(const MutexGuard &) LLVM_DELETED_FUNCTION;
public:
- MutexGuard(sys::Mutex &m) : M(m) { M.acquire(); }
- ~MutexGuard() { M.release(); }
+ MutexGuard(sys::Mutex &m) : M(m) { M.lock(); }
+ ~MutexGuard() { M.unlock(); }
/// holds - Returns true if this locker instance holds the specified lock.
/// This is mostly used in assertions to validate that the correct mutex
/// is held.
diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h
index f6d43a440788..52f133ccff68 100644
--- a/include/llvm/Support/OnDiskHashTable.h
+++ b/include/llvm/Support/OnDiskHashTable.h
@@ -11,11 +11,11 @@
/// \brief Defines facilities for reading and writing on-disk hash tables.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_ON_DISK_HASH_TABLE_H
-#define LLVM_SUPPORT_ON_DISK_HASH_TABLE_H
+#ifndef LLVM_SUPPORT_ONDISKHASHTABLE_H
+#define LLVM_SUPPORT_ONDISKHASHTABLE_H
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Host.h"
@@ -568,4 +568,4 @@ public:
} // end namespace llvm
-#endif // LLVM_SUPPORT_ON_DISK_HASH_TABLE_H
+#endif
diff --git a/include/llvm/Support/Options.h b/include/llvm/Support/Options.h
new file mode 100644
index 000000000000..4fd1bff358fd
--- /dev/null
+++ b/include/llvm/Support/Options.h
@@ -0,0 +1,120 @@
+//===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares helper objects for defining debug options that can be
+/// configured via the command line. The new API currently builds on the cl::opt
+/// API, but does not require the use of static globals.
+///
+/// With this API options are registered during initialization. For passes, this
+/// happens during pass initialization. Passes with options will call a static
+/// registerOptions method during initialization that registers options with the
+/// OptionRegistry. An example implementation of registerOptions is:
+///
+/// static void registerOptions() {
+/// OptionRegistry::registerOption<bool, Scalarizer,
+/// &Scalarizer::ScalarizeLoadStore>(
+/// "scalarize-load-store",
+/// "Allow the scalarizer pass to scalarize loads and store", false);
+/// }
+///
+/// When reading data for options the interface is via the LLVMContext. Option
+/// data for passes should be read from the context during doInitialization. An
+/// example of reading the above option would be:
+///
+/// ScalarizeLoadStore =
+/// M.getContext().getOption<bool,
+/// Scalarizer,
+/// &Scalarizer::ScalarizeLoadStore>();
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_OPTIONS_H
+#define LLVM_SUPPORT_OPTIONS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace llvm {
+
+namespace detail {
+
+// Options are keyed of the unique address of a static character synthesized
+// based on template arguments.
+template <typename ValT, typename Base, ValT(Base::*Mem)> class OptionKey {
+public:
+ static char ID;
+};
+
+template <typename ValT, typename Base, ValT(Base::*Mem)>
+char OptionKey<ValT, Base, Mem>::ID = 0;
+
+} // namespace detail
+
+/// \brief 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.
+/// This object is a singleton, only one instance should ever exist so that all
+/// options are registered in teh same place.
+class OptionRegistry {
+private:
+ DenseMap<void *, cl::Option *> Options;
+
+ /// \brief Adds a cl::Option to the registry.
+ ///
+ /// \param Key unique key for option
+ /// \param O option to map to \p Key
+ ///
+ /// Allocated cl::Options are owened by the OptionRegistry and are deallocated
+ /// on destruction or removal
+ void addOption(void *Key, cl::Option *O);
+
+public:
+ ~OptionRegistry();
+ OptionRegistry() {}
+
+ /// \brief Returns a reference to the singleton instance.
+ static OptionRegistry &instance();
+
+ /// \brief Registers an option with the OptionRegistry singleton.
+ ///
+ /// \tparam ValT type of the option's data
+ /// \tparam Base class used to key the option
+ /// \tparam Mem member of \p Base used for keying the option
+ ///
+ /// Options are keyed off the template parameters to generate unique static
+ /// characters. The template parameters are (1) the type of the data the
+ /// option stores (\p ValT), the class that will read the option (\p Base),
+ /// and the memeber that the class will store the data into (\p Mem).
+ template <typename ValT, typename Base, ValT(Base::*Mem)>
+ static void registerOption(const char *ArgStr, const char *Desc,
+ const ValT &InitValue) {
+ cl::opt<ValT> *Option = new cl::opt<ValT>(ArgStr, cl::desc(Desc),
+ cl::Hidden, cl::init(InitValue));
+ instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option);
+ }
+
+ /// \brief Returns the value of the option.
+ ///
+ /// \tparam ValT type of the option's data
+ /// \tparam Base class used to key the option
+ /// \tparam Mem member of \p Base used for keying the option
+ ///
+ /// Reads option values based on the key generated by the template parameters.
+ /// Keying for get() is the same as keying for registerOption.
+ template <typename ValT, typename Base, ValT(Base::*Mem)> ValT get() const {
+ auto It = Options.find(&detail::OptionKey<ValT, Base, Mem>::ID);
+ assert(It != Options.end() && "Option not in OptionRegistry");
+ return *(cl::opt<ValT> *)It->second;
+ }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h
index cf821f0ef4a4..8fae853e2cf4 100644
--- a/include/llvm/Support/Path.h
+++ b/include/llvm/Support/Path.h
@@ -30,13 +30,13 @@ namespace path {
/// @brief Path iterator.
///
-/// This is a bidirectional iterator that iterates over the individual
-/// components in \a path. The forward traversal order is as follows:
+/// This is an input iterator that iterates over the individual components in
+/// \a path. The traversal order is as follows:
/// * The root-name element, if present.
/// * The root-directory element, if present.
/// * Each successive filename element, if present.
/// * Dot, if one or more trailing non-root slash characters are present.
-/// The backwards traversal order is the reverse of forward traversal.
+/// Traversing backwards is possible with \a reverse_iterator
///
/// Iteration examples. Each component is separated by ',':
/// @code
@@ -47,7 +47,8 @@ namespace path {
/// ../ => ..,.
/// C:\foo\bar => C:,/,foo,bar
/// @endcode
-class const_iterator {
+class const_iterator
+ : public std::iterator<std::input_iterator_tag, const StringRef> {
StringRef Path; ///< The entire path.
StringRef Component; ///< The current component. Not necessarily in Path.
size_t Position; ///< The iterators current position within Path.
@@ -57,26 +58,39 @@ class const_iterator {
friend const_iterator end(StringRef path);
public:
- typedef const StringRef value_type;
- typedef ptrdiff_t difference_type;
- typedef value_type &reference;
- typedef value_type *pointer;
- typedef std::bidirectional_iterator_tag iterator_category;
-
reference operator*() const { return Component; }
pointer operator->() const { return &Component; }
const_iterator &operator++(); // preincrement
const_iterator &operator++(int); // postincrement
- const_iterator &operator--(); // predecrement
- const_iterator &operator--(int); // postdecrement
bool operator==(const const_iterator &RHS) const;
- bool operator!=(const const_iterator &RHS) const;
+ bool operator!=(const const_iterator &RHS) const { return !(*this == RHS); }
/// @brief Difference in bytes between this and RHS.
ptrdiff_t operator-(const const_iterator &RHS) const;
};
-typedef std::reverse_iterator<const_iterator> reverse_iterator;
+/// @brief 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
+/// of \a const_iterator
+class reverse_iterator
+ : public std::iterator<std::input_iterator_tag, const StringRef> {
+ StringRef Path; ///< The entire path.
+ StringRef Component; ///< The current component. Not necessarily in Path.
+ size_t Position; ///< The iterators current position within Path.
+
+ friend reverse_iterator rbegin(StringRef path);
+ friend reverse_iterator rend(StringRef path);
+
+public:
+ reference operator*() const { return Component; }
+ pointer operator->() const { return &Component; }
+ reverse_iterator &operator++(); // preincrement
+ reverse_iterator &operator++(int); // postincrement
+ bool operator==(const reverse_iterator &RHS) const;
+ bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); }
+};
/// @brief Get begin iterator over \a path.
/// @param path Input path.
@@ -91,16 +105,12 @@ const_iterator end(StringRef path);
/// @brief Get reverse begin iterator over \a path.
/// @param path Input path.
/// @returns Iterator initialized with the first reverse component of \a path.
-inline reverse_iterator rbegin(StringRef path) {
- return reverse_iterator(end(path));
-}
+reverse_iterator rbegin(StringRef path);
/// @brief Get reverse end iterator over \a path.
/// @param path Input path.
/// @returns Iterator initialized to the reverse end of \a path.
-inline reverse_iterator rend(StringRef path) {
- return reverse_iterator(begin(path));
-}
+reverse_iterator rend(StringRef path);
/// @}
/// @name Lexical Modifiers
@@ -194,7 +204,7 @@ void native(SmallVectorImpl<char> &path);
///
/// @param path Input path.
/// @result The root name of \a path if it has one, otherwise "".
-const StringRef root_name(StringRef path);
+StringRef root_name(StringRef path);
/// @brief Get root directory.
///
@@ -207,7 +217,7 @@ const StringRef root_name(StringRef path);
/// @param path Input path.
/// @result The root directory of \a path if it has one, otherwise
/// "".
-const StringRef root_directory(StringRef path);
+StringRef root_directory(StringRef path);
/// @brief Get root path.
///
@@ -215,7 +225,7 @@ const StringRef root_directory(StringRef path);
///
/// @param path Input path.
/// @result The root path of \a path if it has one, otherwise "".
-const StringRef root_path(StringRef path);
+StringRef root_path(StringRef path);
/// @brief Get relative path.
///
@@ -227,7 +237,7 @@ const StringRef root_path(StringRef path);
///
/// @param path Input path.
/// @result The path starting after root_path if one exists, otherwise "".
-const StringRef relative_path(StringRef path);
+StringRef relative_path(StringRef path);
/// @brief Get parent path.
///
@@ -239,7 +249,7 @@ const StringRef relative_path(StringRef path);
///
/// @param path Input path.
/// @result The parent path of \a path if one exists, otherwise "".
-const StringRef parent_path(StringRef path);
+StringRef parent_path(StringRef path);
/// @brief Get filename.
///
@@ -253,7 +263,7 @@ const StringRef parent_path(StringRef path);
/// @param path Input path.
/// @result The filename part of \a path. This is defined as the last component
/// of \a path.
-const StringRef filename(StringRef path);
+StringRef filename(StringRef path);
/// @brief Get stem.
///
@@ -271,7 +281,7 @@ const StringRef filename(StringRef path);
///
/// @param path Input path.
/// @result The stem of \a path.
-const StringRef stem(StringRef path);
+StringRef stem(StringRef path);
/// @brief Get extension.
///
@@ -287,7 +297,7 @@ const StringRef stem(StringRef path);
///
/// @param path Input path.
/// @result The extension of \a path.
-const StringRef extension(StringRef path);
+StringRef extension(StringRef path);
/// @brief Check whether the given char is a path separator on the host OS.
///
@@ -298,7 +308,7 @@ bool is_separator(char value);
/// @brief Return the preferred separator for this platform.
///
/// @result StringRef of the preferred separator, null-terminated.
-const StringRef get_separator();
+StringRef get_separator();
/// @brief Get the typical temporary directory for the system, e.g.,
/// "/var/tmp" or "C:/TEMP"
diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h
index 30973de3aac4..cfdd06c62f33 100644
--- a/include/llvm/Support/Process.h
+++ b/include/llvm/Support/Process.h
@@ -38,111 +38,13 @@ class StringRef;
namespace sys {
-class self_process;
-
-/// \brief Generic base class which exposes information about an operating
-/// system process.
-///
-/// This base class is the core interface behind any OS process. It exposes
-/// methods to query for generic information about a particular process.
-///
-/// Subclasses implement this interface based on the mechanisms available, and
-/// can optionally expose more interfaces unique to certain process kinds.
-class process {
-protected:
- /// \brief Only specific subclasses of process objects can be destroyed.
- virtual ~process();
-
-public:
- /// \brief Operating system specific type to identify a process.
- ///
- /// Note that the windows one is defined to 'unsigned long' as this is the
- /// documented type for DWORD on windows, and we don't want to pull in the
- /// Windows headers here.
-#if defined(LLVM_ON_UNIX)
- typedef pid_t id_type;
-#elif defined(LLVM_ON_WIN32)
- typedef unsigned long id_type; // Must match the type of DWORD.
-#else
-#error Unsupported operating system.
-#endif
-
- /// \brief Get the operating system specific identifier for this process.
- virtual id_type get_id() = 0;
-
- /// \brief Get the user time consumed by this process.
- ///
- /// Note that this is often an approximation and may be zero on platforms
- /// where we don't have good support for the functionality.
- virtual TimeValue get_user_time() const = 0;
-
- /// \brief Get the system time consumed by this process.
- ///
- /// Note that this is often an approximation and may be zero on platforms
- /// where we don't have good support for the functionality.
- virtual TimeValue get_system_time() const = 0;
-
- /// \brief Get the wall time consumed by this process.
- ///
- /// Note that this is often an approximation and may be zero on platforms
- /// where we don't have good support for the functionality.
- virtual TimeValue get_wall_time() const = 0;
-
- /// \name Static factory routines for processes.
- /// @{
-
- /// \brief Get the process object for the current process.
- static self_process *get_self();
-
- /// @}
-
-};
-
-/// \brief The specific class representing the current process.
-///
-/// The current process can both specialize the implementation of the routines
-/// and can expose certain information not available for other OS processes.
-class self_process : public process {
- friend class process;
-
- /// \brief Private destructor, as users shouldn't create objects of this
- /// type.
- virtual ~self_process();
-
-public:
- id_type get_id() override;
- TimeValue get_user_time() const override;
- TimeValue get_system_time() const override;
- TimeValue get_wall_time() const override;
-
- /// \name Process configuration (sysconf on POSIX)
- /// @{
-
- /// \brief Get the virtual memory page size.
- ///
- /// Query the operating system for this process's page size.
- size_t page_size() const { return PageSize; };
-
- /// @}
-
-private:
- /// \name Cached process state.
- /// @{
-
- /// \brief Cached page size, this cannot vary during the life of the process.
- size_t PageSize;
-
- /// @}
-
- /// \brief Constructor, used by \c process::get_self() only.
- self_process();
-};
-
/// \brief A collection of legacy interfaces for querying information about the
/// current executing process.
class Process {
public:
+ static unsigned getPageSize();
+
/// \brief Return process memory usage.
/// This static function will return the total amount of memory allocated
/// by the process. This only counts the memory allocated via the malloc,
@@ -186,6 +88,21 @@ public:
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
+ // components should not call this.
+ static std::error_code FixupStandardFileDescriptors();
+
+ // This function safely closes a file descriptor. It is not safe to retry
+ // close(2) when it returns with errno equivalent to EINTR; this is because
+ // *nixen cannot agree if the file descriptor is, in fact, closed when this
+ // occurs.
+ //
+ // N.B. Some operating systems, due to thread cancellation, cannot properly
+ // guarantee that it will or will not be closed one way or the other!
+ static std::error_code SafelyCloseFileDescriptor(int FD);
+
/// This function determines if the standard input is connected directly
/// to a user's input (keyboard probably), rather than coming from a file
/// or pipe.
diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h
index 51279a9b864a..40dc60fa30d6 100644
--- a/include/llvm/Support/Program.h
+++ b/include/llvm/Support/Program.h
@@ -15,6 +15,7 @@
#define LLVM_SUPPORT_PROGRAM_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Path.h"
#include <system_error>
@@ -51,17 +52,22 @@ struct ProcessInfo {
ProcessInfo();
};
- /// This function attempts to locate a program in the operating
- /// system's file system using some pre-determined set of locations to search
- /// (e.g. the PATH on Unix). Paths with slashes are returned unmodified.
+ /// \brief Find the first executable file \p Name in \p Paths.
///
- /// It does not perform hashing as a shell would but instead stats each PATH
+ /// This does not perform hashing as a shell would but instead stats each PATH
/// entry individually so should generally be avoided. Core LLVM library
/// functions and options should instead require fully specified paths.
///
- /// @returns A string containing the path of the program or an empty string if
- /// the program could not be found.
- std::string FindProgramByName(const std::string& name);
+ /// \param Name name of the executable to find. If it contains any system
+ /// slashes, it will be returned as is.
+ /// \param Paths optional list of paths to search for \p Name. If empty it
+ /// will use the system PATH environment instead.
+ ///
+ /// \returns The fully qualified path to the first \p Name in \p Paths if it
+ /// exists. \p Name if \p Name has slashes in it. Otherwise an error.
+ ErrorOr<std::string>
+ findProgramByName(StringRef Name,
+ ArrayRef<StringRef> Paths = ArrayRef<StringRef>());
// These functions change the specified standard stream (stdin or stdout) to
// binary mode. They return errc::success if the specified stream
@@ -82,7 +88,7 @@ struct ProcessInfo {
/// -2 indicates a crash during execution or timeout
int ExecuteAndWait(
StringRef Program, ///< Path of the program to be executed. It is
- /// presumed this is the result of the FindProgramByName method.
+ /// presumed this is the result of the findProgramByName method.
const char **args, ///< A vector of strings that are passed to the
///< program. The first element should be the name of the program.
///< The list *must* be terminated by a null char* entry.
@@ -126,6 +132,40 @@ struct ProcessInfo {
/// argument length limits.
bool argumentsFitWithinSystemLimits(ArrayRef<const char*> Args);
+ /// File encoding options when writing contents that a non-UTF8 tool will
+ /// read (on Windows systems). For UNIX, we always use UTF-8.
+ enum WindowsEncodingMethod {
+ /// UTF-8 is the LLVM native encoding, being the same as "do not perform
+ /// encoding conversion".
+ WEM_UTF8,
+ WEM_CurrentCodePage,
+ WEM_UTF16
+ };
+
+ /// Saves the UTF8-encoded \p contents string into the file \p FileName
+ /// using a specific encoding.
+ ///
+ /// This write file function adds the possibility to choose which encoding
+ /// to use when writing a text file. On Windows, this is important when
+ /// writing files with internationalization support with an encoding that is
+ /// different from the one used in LLVM (UTF-8). We use this when writing
+ /// response files, since GCC tools on MinGW only understand legacy code
+ /// pages, and VisualStudio tools only understand UTF-16.
+ /// For UNIX, using different encodings is silently ignored, since all tools
+ /// work well with UTF-8.
+ /// This function assumes that you only use UTF-8 *text* data and will convert
+ /// it to your desired encoding before writing to the file.
+ ///
+ /// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in
+ /// a MinGW/MinGW-w64 environment, which has serious flaws but currently is
+ /// our best shot to make gcc/ld understand international characters. This
+ /// should be changed as soon as binutils fix this to support UTF16 on mingw.
+ ///
+ /// \returns non-zero error_code if failed
+ std::error_code
+ writeFileWithEncoding(StringRef FileName, StringRef Contents,
+ WindowsEncodingMethod Encoding = WEM_UTF8);
+
/// This function waits for the process specified by \p PI to finish.
/// \returns A \see ProcessInfo struct with Pid set to:
/// \li The process id of the child process if the child process has changed
diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h
index 935b3075df58..b80b8557576b 100644
--- a/include/llvm/Support/RWMutex.h
+++ b/include/llvm/Support/RWMutex.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SYSTEM_RWMUTEX_H
-#define LLVM_SYSTEM_RWMUTEX_H
+#ifndef LLVM_SUPPORT_RWMUTEX_H
+#define LLVM_SUPPORT_RWMUTEX_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Threading.h"
@@ -85,14 +85,15 @@ namespace llvm
/// indicates whether this mutex should become a no-op when we're not
/// running in multithreaded mode.
template<bool mt_only>
- class SmartRWMutex : public RWMutexImpl {
+ class SmartRWMutex {
+ RWMutexImpl impl;
unsigned readers, writers;
public:
- explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { }
+ explicit SmartRWMutex() : impl(), readers(0), writers(0) { }
- bool reader_acquire() {
+ bool lock_shared() {
if (!mt_only || llvm_is_multithreaded())
- return RWMutexImpl::reader_acquire();
+ return impl.reader_acquire();
// Single-threaded debugging code. This would be racy in multithreaded
// mode, but provides not sanity checks in single threaded mode.
@@ -100,9 +101,9 @@ namespace llvm
return true;
}
- bool reader_release() {
+ bool unlock_shared() {
if (!mt_only || llvm_is_multithreaded())
- return RWMutexImpl::reader_release();
+ return impl.reader_release();
// Single-threaded debugging code. This would be racy in multithreaded
// mode, but provides not sanity checks in single threaded mode.
@@ -111,9 +112,9 @@ namespace llvm
return true;
}
- bool writer_acquire() {
+ bool lock() {
if (!mt_only || llvm_is_multithreaded())
- return RWMutexImpl::writer_acquire();
+ return impl.writer_acquire();
// Single-threaded debugging code. This would be racy in multithreaded
// mode, but provides not sanity checks in single threaded mode.
@@ -122,9 +123,9 @@ namespace llvm
return true;
}
- bool writer_release() {
+ bool unlock() {
if (!mt_only || llvm_is_multithreaded())
- return RWMutexImpl::writer_release();
+ return impl.writer_release();
// Single-threaded debugging code. This would be racy in multithreaded
// mode, but provides not sanity checks in single threaded mode.
@@ -145,11 +146,11 @@ namespace llvm
SmartRWMutex<mt_only>& mutex;
explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
- mutex.reader_acquire();
+ mutex.lock_shared();
}
~SmartScopedReader() {
- mutex.reader_release();
+ mutex.unlock_shared();
}
};
typedef SmartScopedReader<false> ScopedReader;
@@ -160,11 +161,11 @@ namespace llvm
SmartRWMutex<mt_only>& mutex;
explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
- mutex.writer_acquire();
+ mutex.lock();
}
~SmartScopedWriter() {
- mutex.writer_release();
+ mutex.unlock();
}
};
typedef SmartScopedWriter<false> ScopedWriter;
diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h
index cadc713659d2..7ada34f075e4 100644
--- a/include/llvm/Support/RandomNumberGenerator.h
+++ b/include/llvm/Support/RandomNumberGenerator.h
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines an abstraction for random number generation (RNG).
-// Note that the current implementation is not cryptographically secure
-// as it uses the C++11 <random> facilities.
+// This file defines an abstraction for deterministic random number
+// generation (RNG). Note that the current implementation is not
+// cryptographically secure as it uses the C++11 <random> facilities.
//
//===----------------------------------------------------------------------===//
@@ -24,26 +24,27 @@
namespace llvm {
/// A random number generator.
-/// Instances of this class should not be shared across threads.
+///
+/// Instances of this class should not be shared across threads. The
+/// seed should be set by passing the -rng-seed=<uint64> option. Use
+/// Module::createRNG to create a new RNG instance for use with that
+/// module.
class RandomNumberGenerator {
public:
- /// Seeds and salts the underlying RNG engine. The salt of type StringRef
- /// is passed into the constructor. The seed can be set on the command
- /// line via -rng-seed=<uint64>.
- /// The reason for the salt is to ensure different random streams even if
- /// the same seed is used for multiple invocations of the compiler.
- /// A good salt value should add additional entropy and be constant across
- /// different machines (i.e., no paths) to allow for reproducible builds.
- /// An instance of this class can be retrieved from the current Module.
- /// \see Module::getRNG
- RandomNumberGenerator(StringRef Salt);
-
/// Returns a random number in the range [0, Max).
- uint64_t next(uint64_t Max);
+ uint_fast64_t operator()();
private:
+ /// Seeds and salts the underlying RNG engine.
+ ///
+ /// This constructor should not be used directly. Instead use
+ /// Module::createRNG to create a new RNG salted with the Module ID.
+ RandomNumberGenerator(StringRef Salt);
+
// 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000
// http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine
+ // This RNG is deterministically portable across C++11
+ // implementations.
std::mt19937_64 Generator;
// Noncopyable.
@@ -51,6 +52,8 @@ private:
LLVM_DELETED_FUNCTION;
RandomNumberGenerator &
operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION;
+
+ friend class Module;
};
}
diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h
index b0c2e899855d..e21269b2f1d5 100644
--- a/include/llvm/Support/Registry.h
+++ b/include/llvm/Support/Registry.h
@@ -16,7 +16,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
-
#include <memory>
namespace llvm {
diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h
index 2bd7e741dd28..a1c4c80c356f 100644
--- a/include/llvm/Support/ScaledNumber.h
+++ b/include/llvm/Support/ScaledNumber.h
@@ -23,7 +23,6 @@
#define LLVM_SUPPORT_SCALEDNUMBER_H
#include "llvm/Support/MathExtras.h"
-
#include <algorithm>
#include <cstdint>
#include <limits>
diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h
index 4717553bd0de..f9e114b67cb4 100644
--- a/include/llvm/Support/SourceMgr.h
+++ b/include/llvm/Support/SourceMgr.h
@@ -19,11 +19,11 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
#include <string>
namespace llvm {
- class MemoryBuffer;
class SourceMgr;
class SMDiagnostic;
class SMFixIt;
@@ -47,10 +47,15 @@ public:
private:
struct SrcBuffer {
/// The memory buffer for the file.
- MemoryBuffer *Buffer;
+ std::unique_ptr<MemoryBuffer> Buffer;
/// This is the location of the parent include, or null if at the top level.
SMLoc IncludeLoc;
+
+ SrcBuffer() {}
+
+ SrcBuffer(SrcBuffer &&O)
+ : Buffer(std::move(O.Buffer)), IncludeLoc(O.IncludeLoc) {}
};
/// This is all of the buffers that we are reading from.
@@ -96,7 +101,7 @@ public:
const MemoryBuffer *getMemoryBuffer(unsigned i) const {
assert(isValidBufferID(i));
- return Buffers[i - 1].Buffer;
+ return Buffers[i - 1].Buffer.get();
}
unsigned getNumBuffers() const {
@@ -115,11 +120,12 @@ public:
/// Add a new source buffer to this source manager. This takes ownership of
/// the memory buffer.
- unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) {
+ unsigned AddNewSourceBuffer(std::unique_ptr<MemoryBuffer> F,
+ SMLoc IncludeLoc) {
SrcBuffer NB;
- NB.Buffer = F;
+ NB.Buffer = std::move(F);
NB.IncludeLoc = IncludeLoc;
- Buffers.push_back(NB);
+ Buffers.push_back(std::move(NB));
return Buffers.size();
}
diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h
index 098b9c7a17b7..313212e59dd2 100644
--- a/include/llvm/Support/SpecialCaseList.h
+++ b/include/llvm/Support/SpecialCaseList.h
@@ -56,17 +56,19 @@ class Regex;
class StringRef;
class SpecialCaseList {
- public:
+public:
/// Parses the special case list from a file. If Path is empty, returns
/// an empty special case list. On failure, returns 0 and writes an error
/// message to string.
- static SpecialCaseList *create(const StringRef Path, std::string &Error);
+ static std::unique_ptr<SpecialCaseList> create(StringRef Path,
+ std::string &Error);
/// Parses the special case list from a memory buffer. On failure, returns
/// 0 and writes an error message to string.
- static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error);
+ static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB,
+ std::string &Error);
/// Parses the special case list from a file. On failure, reports a fatal
/// error.
- static SpecialCaseList *createOrDie(const StringRef Path);
+ static std::unique_ptr<SpecialCaseList> createOrDie(StringRef Path);
~SpecialCaseList();
@@ -75,10 +77,10 @@ class SpecialCaseList {
/// @Section:<E>=@Category
/// \endcode
/// and @Query satisfies a wildcard expression <E>.
- bool inSection(const StringRef Section, const StringRef Query,
- const StringRef Category = StringRef()) const;
+ bool inSection(StringRef Section, StringRef Query,
+ StringRef Category = StringRef()) const;
- private:
+private:
SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
diff --git a/include/llvm/Support/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h
deleted file mode 100644
index 6e71ad47c8dd..000000000000
--- a/include/llvm/Support/StreamableMemoryObject.h
+++ /dev/null
@@ -1,178 +0,0 @@
-//===- StreamableMemoryObject.h - Streamable data interface -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H
-#define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H
-
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataStream.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryObject.h"
-#include <cassert>
-#include <memory>
-#include <vector>
-
-namespace llvm {
-
-/// StreamableMemoryObject - Interface to data which might be streamed.
-/// Streamability has 2 important implications/restrictions. First, the data
-/// might not yet exist in memory when the request is made. This just means
-/// that readByte/readBytes might have to block or do some work to get it.
-/// More significantly, the exact size of the object might not be known until
-/// it has all been fetched. This means that to return the right result,
-/// getExtent must also wait for all the data to arrive; therefore it should
-/// not be called on objects which are actually streamed (this would defeat
-/// the purpose of streaming). Instead, isValidAddress and isObjectEnd can be
-/// used to test addresses without knowing the exact size of the stream.
-/// Finally, getPointer can be used instead of readBytes to avoid extra copying.
-class StreamableMemoryObject : public MemoryObject {
- public:
- /// Destructor - Override as necessary.
- virtual ~StreamableMemoryObject();
-
- /// getBase - Returns the lowest valid address in the region.
- ///
- /// @result - The lowest valid address.
- uint64_t getBase() const override = 0;
-
- /// getExtent - Returns the size of the region in bytes. (The region is
- /// contiguous, so the highest valid address of the region
- /// is getBase() + getExtent() - 1).
- /// May block until all bytes in the stream have been read
- ///
- /// @result - The size of the region.
- uint64_t getExtent() const override = 0;
-
- /// readByte - Tries to read a single byte from the region.
- /// May block until (address - base) bytes have been read
- /// @param address - The address of the byte, in the same space as getBase().
- /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL.
- /// @result - 0 if successful; -1 if not. Failure may be due to a
- /// bounds violation or an implementation-specific error.
- int readByte(uint64_t address, uint8_t *ptr) const override = 0;
-
- /// readBytes - Tries to read a contiguous range of bytes from the
- /// region, up to the end of the region.
- /// May block until (address - base + size) bytes have
- /// been read. Additionally, StreamableMemoryObjects will
- /// not do partial reads - if size bytes cannot be read,
- /// readBytes will fail.
- ///
- /// @param address - The address of the first byte, in the same space as
- /// getBase().
- /// @param size - The number of bytes to copy.
- /// @param buf - A pointer to a buffer to be filled in. Must be non-NULL
- /// and large enough to hold size bytes.
- /// @result - 0 if successful; -1 if not. Failure may be due to a
- /// bounds violation or an implementation-specific error.
- int readBytes(uint64_t address, uint64_t size,
- uint8_t *buf) const override = 0;
-
- /// getPointer - Ensures that the requested data is in memory, and returns
- /// A pointer to it. More efficient than using readBytes if the
- /// data is already in memory.
- /// May block until (address - base + size) bytes have been read
- /// @param address - address of the byte, in the same space as getBase()
- /// @param size - amount of data that must be available on return
- /// @result - valid pointer to the requested data
- virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0;
-
- /// isValidAddress - Returns true if the address is within the object
- /// (i.e. between base and base + extent - 1 inclusive)
- /// May block until (address - base) bytes have been read
- /// @param address - address of the byte, in the same space as getBase()
- /// @result - true if the address may be read with readByte()
- virtual bool isValidAddress(uint64_t address) const = 0;
-
- /// isObjectEnd - Returns true if the address is one past the end of the
- /// object (i.e. if it is equal to base + extent)
- /// May block until (address - base) bytes have been read
- /// @param address - address of the byte, in the same space as getBase()
- /// @result - true if the address is equal to base + extent
- virtual bool isObjectEnd(uint64_t address) const = 0;
-};
-
-/// StreamingMemoryObject - interface to data which is actually streamed from
-/// a DataStreamer. In addition to inherited members, it has the
-/// dropLeadingBytes and setKnownObjectSize methods which are not applicable
-/// to non-streamed objects.
-class StreamingMemoryObject : public StreamableMemoryObject {
-public:
- StreamingMemoryObject(DataStreamer *streamer);
- uint64_t getBase() const override { return 0; }
- uint64_t getExtent() const override;
- int readByte(uint64_t address, uint8_t *ptr) const override;
- int readBytes(uint64_t address, uint64_t size,
- uint8_t *buf) const override;
- const uint8_t *getPointer(uint64_t address, uint64_t size) const override {
- // This could be fixed by ensuring the bytes are fetched and making a copy,
- // requiring that the bitcode size be known, or otherwise ensuring that
- // the memory doesn't go away/get reallocated, but it's
- // not currently necessary. Users that need the pointer don't stream.
- llvm_unreachable("getPointer in streaming memory objects not allowed");
- return nullptr;
- }
- bool isValidAddress(uint64_t address) const override;
- bool isObjectEnd(uint64_t address) const override;
-
- /// Drop s bytes from the front of the stream, pushing the positions of the
- /// remaining bytes down by s. This is used to skip past the bitcode header,
- /// since we don't know a priori if it's present, and we can't put bytes
- /// back into the stream once we've read them.
- bool dropLeadingBytes(size_t s);
-
- /// If the data object size is known in advance, many of the operations can
- /// be made more efficient, so this method should be called before reading
- /// starts (although it can be called anytime).
- void setKnownObjectSize(size_t size);
-
-private:
- const static uint32_t kChunkSize = 4096 * 4;
- mutable std::vector<unsigned char> Bytes;
- std::unique_ptr<DataStreamer> Streamer;
- mutable size_t BytesRead; // Bytes read from stream
- size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header)
- mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached
- mutable bool EOFReached;
-
- // Fetch enough bytes such that Pos can be read or EOF is reached
- // (i.e. BytesRead > Pos). Return true if Pos can be read.
- // Unlike most of the functions in BitcodeReader, returns true on success.
- // Most of the requests will be small, but we fetch at kChunkSize bytes
- // at a time to avoid making too many potentially expensive GetBytes calls
- bool fetchToPos(size_t Pos) const {
- if (EOFReached) return Pos < ObjectSize;
- while (Pos >= BytesRead) {
- Bytes.resize(BytesRead + BytesSkipped + kChunkSize);
- size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped],
- kChunkSize);
- BytesRead += bytes;
- if (bytes < kChunkSize) {
- assert((!ObjectSize || BytesRead >= Pos) &&
- "Unexpected short read fetching bitcode");
- if (BytesRead <= Pos) { // reached EOF/ran out of bytes
- ObjectSize = BytesRead;
- EOFReached = true;
- return false;
- }
- }
- }
- return true;
- }
-
- StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
- void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
-};
-
-StreamableMemoryObject *getNonStreamedMemoryObject(
- const unsigned char *Start, const unsigned char *End);
-
-}
-#endif // STREAMABLEMEMORYOBJECT_H_
diff --git a/include/llvm/Support/StreamingMemoryObject.h b/include/llvm/Support/StreamingMemoryObject.h
new file mode 100644
index 000000000000..66ed521a411c
--- /dev/null
+++ b/include/llvm/Support/StreamingMemoryObject.h
@@ -0,0 +1,92 @@
+//===- StreamingMemoryObject.h - Streamable data interface -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H
+#define LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryObject.h"
+#include <cassert>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+
+/// Interface to data which is actually streamed from a DataStreamer. In
+/// addition to inherited members, it has the dropLeadingBytes and
+/// setKnownObjectSize methods which are not applicable to non-streamed objects.
+class StreamingMemoryObject : public MemoryObject {
+public:
+ StreamingMemoryObject(DataStreamer *streamer);
+ uint64_t getExtent() const override;
+ uint64_t readBytes(uint8_t *Buf, uint64_t Size,
+ uint64_t Address) const override;
+ const uint8_t *getPointer(uint64_t address, uint64_t size) const override {
+ // This could be fixed by ensuring the bytes are fetched and making a copy,
+ // requiring that the bitcode size be known, or otherwise ensuring that
+ // the memory doesn't go away/get reallocated, but it's
+ // not currently necessary. Users that need the pointer don't stream.
+ llvm_unreachable("getPointer in streaming memory objects not allowed");
+ return nullptr;
+ }
+ bool isValidAddress(uint64_t address) const override;
+
+ /// Drop s bytes from the front of the stream, pushing the positions of the
+ /// remaining bytes down by s. This is used to skip past the bitcode header,
+ /// since we don't know a priori if it's present, and we can't put bytes
+ /// back into the stream once we've read them.
+ bool dropLeadingBytes(size_t s);
+
+ /// If the data object size is known in advance, many of the operations can
+ /// be made more efficient, so this method should be called before reading
+ /// starts (although it can be called anytime).
+ void setKnownObjectSize(size_t size);
+
+private:
+ const static uint32_t kChunkSize = 4096 * 4;
+ mutable std::vector<unsigned char> Bytes;
+ std::unique_ptr<DataStreamer> Streamer;
+ mutable size_t BytesRead; // Bytes read from stream
+ size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header)
+ mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached
+ mutable bool EOFReached;
+
+ // Fetch enough bytes such that Pos can be read or EOF is reached
+ // (i.e. BytesRead > Pos). Return true if Pos can be read.
+ // Unlike most of the functions in BitcodeReader, returns true on success.
+ // Most of the requests will be small, but we fetch at kChunkSize bytes
+ // at a time to avoid making too many potentially expensive GetBytes calls
+ bool fetchToPos(size_t Pos) const {
+ if (EOFReached)
+ return Pos < ObjectSize;
+ while (Pos >= BytesRead) {
+ Bytes.resize(BytesRead + BytesSkipped + kChunkSize);
+ size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped],
+ kChunkSize);
+ BytesRead += bytes;
+ if (bytes != kChunkSize) { // reached EOF/ran out of bytes
+ ObjectSize = BytesRead;
+ EOFReached = true;
+ break;
+ }
+ }
+ return Pos < BytesRead;
+ }
+
+ StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
+ void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
+};
+
+MemoryObject *getNonStreamedMemoryObject(
+ const unsigned char *Start, const unsigned char *End);
+
+}
+#endif // STREAMINGMEMORYOBJECT_H_
diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h
index 3e0465340c3b..b51974c946e0 100644
--- a/include/llvm/Support/StringPool.h
+++ b/include/llvm/Support/StringPool.h
@@ -29,8 +29,8 @@
#ifndef LLVM_SUPPORT_STRINGPOOL_H
#define LLVM_SUPPORT_STRINGPOOL_H
-#include "llvm/Support/Compiler.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Compiler.h"
#include <cassert>
#include <new>
diff --git a/include/llvm/Support/StringRefMemoryObject.h b/include/llvm/Support/StringRefMemoryObject.h
deleted file mode 100644
index 8a349eab84c8..000000000000
--- a/include/llvm/Support/StringRefMemoryObject.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- llvm/Support/StringRefMemoryObject.h ---------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the StringRefMemObject class, a simple
-// wrapper around StringRef implementing the MemoryObject interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_STRINGREFMEMORYOBJECT_H
-#define LLVM_SUPPORT_STRINGREFMEMORYOBJECT_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/MemoryObject.h"
-
-namespace llvm {
-
-/// StringRefMemoryObject - Simple StringRef-backed MemoryObject
-class StringRefMemoryObject : public MemoryObject {
- StringRef Bytes;
- uint64_t Base;
-public:
- StringRefMemoryObject(StringRef Bytes, uint64_t Base = 0)
- : Bytes(Bytes), Base(Base) {}
-
- uint64_t getBase() const override { return Base; }
- uint64_t getExtent() const override { return Bytes.size(); }
-
- int readByte(uint64_t Addr, uint8_t *Byte) const override;
- int readBytes(uint64_t Addr, uint64_t Size, uint8_t *Buf) const override;
-};
-
-}
-
-#endif
diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h
index 340954f4c893..9c5a3c59122e 100644
--- a/include/llvm/Support/SwapByteOrder.h
+++ b/include/llvm/Support/SwapByteOrder.h
@@ -15,6 +15,7 @@
#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H
#define LLVM_SUPPORT_SWAPBYTEORDER_H
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include <cstddef>
#include <limits>
@@ -39,8 +40,7 @@ inline uint16_t SwapByteOrder_16(uint16_t value) {
/// SwapByteOrder_32 - This function returns a byte-swapped representation of
/// the 32-bit argument.
inline uint32_t SwapByteOrder_32(uint32_t value) {
-#if defined(__llvm__) || \
-(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC)
+#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
return __builtin_bswap32(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_ulong(value);
@@ -56,8 +56,7 @@ inline uint32_t SwapByteOrder_32(uint32_t value) {
/// SwapByteOrder_64 - This function returns a byte-swapped representation of
/// the 64-bit argument.
inline uint64_t SwapByteOrder_64(uint64_t value) {
-#if defined(__llvm__) || \
-(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC)
+#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
return __builtin_bswap64(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_uint64(value);
diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h
index 5d5b86a6a2ae..8ac4b904bb88 100644
--- a/include/llvm/Support/TargetRegistry.h
+++ b/include/llvm/Support/TargetRegistry.h
@@ -123,15 +123,10 @@ namespace llvm {
const MCRegisterInfo &MRI,
const MCSubtargetInfo &STI,
MCContext &Ctx);
- typedef MCStreamer *(*MCObjectStreamerCtorTy)(const Target &T,
- StringRef TT,
- MCContext &Ctx,
- MCAsmBackend &TAB,
- raw_ostream &_OS,
- MCCodeEmitter *_Emitter,
- const MCSubtargetInfo &STI,
- bool RelaxAll,
- bool NoExecStack);
+ typedef MCStreamer *(*MCObjectStreamerCtorTy)(
+ const Target &T, StringRef TT, MCContext &Ctx, MCAsmBackend &TAB,
+ raw_ostream &_OS, MCCodeEmitter *_Emitter, const MCSubtargetInfo &STI,
+ bool RelaxAll);
typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx,
formatted_raw_ostream &OS,
bool isVerboseAsm,
@@ -423,18 +418,15 @@ namespace llvm {
/// \param _OS The stream object.
/// \param _Emitter The target independent assembler object.Takes ownership.
/// \param RelaxAll Relax all fixups?
- /// \param NoExecStack Mark file as not needing a executable stack.
MCStreamer *createMCObjectStreamer(StringRef TT, MCContext &Ctx,
- MCAsmBackend &TAB,
- raw_ostream &_OS,
+ MCAsmBackend &TAB, raw_ostream &_OS,
MCCodeEmitter *_Emitter,
const MCSubtargetInfo &STI,
- bool RelaxAll,
- bool NoExecStack) const {
+ bool RelaxAll) const {
if (!MCObjectStreamerCtorFn)
return nullptr;
return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, STI,
- RelaxAll, NoExecStack);
+ RelaxAll);
}
/// createAsmStreamer - Create a target specific MCStreamer.
diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h
index 7518626901e0..427a67e2a96d 100644
--- a/include/llvm/Support/ThreadLocal.h
+++ b/include/llvm/Support/ThreadLocal.h
@@ -36,7 +36,7 @@ namespace llvm {
ThreadLocalImpl();
virtual ~ThreadLocalImpl();
void setInstance(const void* d);
- const void* getInstance();
+ void *getInstance();
void removeInstance();
};
diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h
index 7e8758407c7c..3cca1d6a9913 100644
--- a/include/llvm/Support/Threading.h
+++ b/include/llvm/Support/Threading.h
@@ -21,7 +21,8 @@ namespace llvm {
bool llvm_is_multithreaded();
/// llvm_execute_on_thread - Execute the given \p UserFn on a separate
- /// thread, passing it the provided \p UserData.
+ /// thread, passing it the provided \p UserData and waits for thread
+ /// completion.
///
/// This function does not guarantee that the code will actually be executed
/// on a separate thread or honoring the requested stack size, but tries to do
diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h
index ee0e2866d59e..6bca58b6bc20 100644
--- a/include/llvm/Support/TimeValue.h
+++ b/include/llvm/Support/TimeValue.h
@@ -38,28 +38,38 @@ namespace sys {
/// value permissible by the class. MinTime is some point
/// in the distant past, about 300 billion years BCE.
/// @brief The smallest possible time value.
- static const TimeValue MinTime;
+ static TimeValue MinTime() {
+ return TimeValue ( INT64_MIN,0 );
+ }
/// A constant TimeValue representing the largest time
/// value permissible by the class. MaxTime is some point
/// in the distant future, about 300 billion years AD.
/// @brief The largest possible time value.
- static const TimeValue MaxTime;
+ static TimeValue MaxTime() {
+ return TimeValue ( INT64_MAX,0 );
+ }
/// A constant TimeValue representing the base time,
/// or zero time of 00:00:00 (midnight) January 1st, 2000.
/// @brief 00:00:00 Jan 1, 2000 UTC.
- static const TimeValue ZeroTime;
+ static TimeValue ZeroTime() {
+ return TimeValue ( 0,0 );
+ }
/// A constant TimeValue for the Posix base time which is
/// 00:00:00 (midnight) January 1st, 1970.
/// @brief 00:00:00 Jan 1, 1970 UTC.
- static const TimeValue PosixZeroTime;
+ static TimeValue PosixZeroTime() {
+ return TimeValue ( PosixZeroTimeSeconds,0 );
+ }
/// A constant TimeValue for the Win32 base time which is
/// 00:00:00 (midnight) January 1st, 1601.
/// @brief 00:00:00 Jan 1, 1601 UTC.
- static const TimeValue Win32ZeroTime;
+ static TimeValue Win32ZeroTime() {
+ return TimeValue ( Win32ZeroTimeSeconds,0 );
+ }
/// @}
/// @name Types
diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h
index 88f8ccc292d3..d98e7bbd51d4 100644
--- a/include/llvm/Support/ToolOutputFile.h
+++ b/include/llvm/Support/ToolOutputFile.h
@@ -29,13 +29,13 @@ class tool_output_file {
/// destructed after the raw_fd_ostream is destructed. It installs
/// cleanups in its constructor and uninstalls them in its destructor.
class CleanupInstaller {
- /// Filename - The name of the file.
+ /// The name of the file.
std::string Filename;
public:
- /// Keep - The flag which indicates whether we should not delete the file.
+ /// The flag which indicates whether we should not delete the file.
bool Keep;
- explicit CleanupInstaller(const char *filename);
+ explicit CleanupInstaller(StringRef ilename);
~CleanupInstaller();
} Installer;
@@ -44,12 +44,12 @@ class tool_output_file {
raw_fd_ostream OS;
public:
- /// tool_output_file - This constructor's arguments are passed to
- /// to raw_fd_ostream's constructor.
- tool_output_file(const char *filename, std::string &ErrorInfo,
+ /// This constructor's arguments are passed to to raw_fd_ostream's
+ /// constructor.
+ tool_output_file(StringRef Filename, std::error_code &EC,
sys::fs::OpenFlags Flags);
- tool_output_file(const char *Filename, int FD);
+ tool_output_file(StringRef Filename, int FD);
/// os - Return the contained raw_fd_ostream.
raw_fd_ostream &os() { return OS; }
diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h
new file mode 100644
index 000000000000..5a4c273e83e2
--- /dev/null
+++ b/include/llvm/Support/UniqueLock.h
@@ -0,0 +1,67 @@
+//===-- Support/UniqueLock.h - Acquire/Release Mutex In Scope ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a guard for a block of code that ensures a Mutex is locked
+// upon construction and released upon destruction.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_UNIQUE_LOCK_H
+#define LLVM_SUPPORT_UNIQUE_LOCK_H
+
+#include "llvm/Support/Mutex.h"
+
+namespace llvm {
+ /// A pared-down imitation of std::unique_lock from C++11. Contrary to the
+ /// name, it's really more of a wrapper for a lock. It may or may not have
+ /// 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.
+ template<typename MutexT>
+ class unique_lock {
+ MutexT *M;
+ bool locked;
+
+ unique_lock(const unique_lock &) LLVM_DELETED_FUNCTION;
+ void operator=(const unique_lock &) LLVM_DELETED_FUNCTION;
+ public:
+ unique_lock() : M(nullptr), locked(false) {}
+ explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); }
+
+ void operator=(unique_lock &&o) {
+ if (owns_lock())
+ M->unlock();
+ M = o.M;
+ locked = o.locked;
+ o.M = nullptr;
+ o.locked = false;
+ }
+
+ ~unique_lock() { if (owns_lock()) M->unlock(); }
+
+ void lock() {
+ assert(!locked && "mutex already locked!");
+ assert(M && "no associated mutex!");
+ M->lock();
+ locked = true;
+ }
+
+ void unlock() {
+ assert(locked && "unlocking a mutex that isn't locked!");
+ assert(M && "no associated mutex!");
+ M->unlock();
+ locked = false;
+ }
+
+ bool owns_lock() { return locked; }
+ };
+}
+
+#endif // LLVM_SUPPORT_UNIQUE_LOCK_H
diff --git a/include/llvm/Support/Win64EH.h b/include/llvm/Support/Win64EH.h
index 7ca218e87a77..f6c492794875 100644
--- a/include/llvm/Support/Win64EH.h
+++ b/include/llvm/Support/Win64EH.h
@@ -40,8 +40,8 @@ enum UnwindOpcodes {
/// or part thereof.
union UnwindCode {
struct {
- support::ulittle8_t CodeOffset;
- support::ulittle8_t UnwindOpAndOpInfo;
+ uint8_t CodeOffset;
+ uint8_t UnwindOpAndOpInfo;
} u;
support::ulittle16_t FrameOffset;
@@ -74,10 +74,10 @@ struct RuntimeFunction {
/// UnwindInfo - An entry in the exception table.
struct UnwindInfo {
- support::ulittle8_t VersionAndFlags;
- support::ulittle8_t PrologSize;
- support::ulittle8_t NumCodes;
- support::ulittle8_t FrameRegisterAndOffset;
+ uint8_t VersionAndFlags;
+ uint8_t PrologSize;
+ uint8_t NumCodes;
+ uint8_t FrameRegisterAndOffset;
UnwindCode UnwindCodes[1];
uint8_t getVersion() const {
diff --git a/include/llvm/Support/WindowsError.h b/include/llvm/Support/WindowsError.h
index 0e909a05bf4a..63bfe5976546 100644
--- a/include/llvm/Support/WindowsError.h
+++ b/include/llvm/Support/WindowsError.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_WINDOWS_ERROR_H
-#define LLVM_SUPPORT_WINDOWS_ERROR_H
+#ifndef LLVM_SUPPORT_WINDOWSERROR_H
+#define LLVM_SUPPORT_WINDOWSERROR_H
#include <system_error>
diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h
index c39874cbd2c5..de6e6544e25b 100644
--- a/include/llvm/Support/YAMLParser.h
+++ b/include/llvm/Support/YAMLParser.h
@@ -41,13 +41,13 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
#include <limits>
#include <map>
#include <utility>
namespace llvm {
-class MemoryBuffer;
class SourceMgr;
class raw_ostream;
class Twine;
@@ -79,8 +79,7 @@ public:
/// \brief This keeps a reference to the string referenced by \p Input.
Stream(StringRef Input, SourceMgr &);
- /// \brief This takes ownership of \p InputBuffer.
- Stream(MemoryBuffer *InputBuffer, SourceMgr &);
+ Stream(MemoryBufferRef InputBuffer, SourceMgr &);
~Stream();
document_iterator begin();
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index a23faf65bb59..023dcee7d54c 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -943,16 +943,17 @@ private:
};
class MapHNode : public HNode {
+ virtual void anchor();
+
public:
MapHNode(Node *n) : HNode(n) { }
- virtual ~MapHNode();
static inline bool classof(const HNode *n) {
return MappingNode::classof(n->_node);
}
static inline bool classof(const MapHNode *) { return true; }
- typedef llvm::StringMap<HNode*> NameToNode;
+ typedef llvm::StringMap<std::unique_ptr<HNode>> NameToNode;
bool isValidKey(StringRef key);
@@ -961,19 +962,20 @@ private:
};
class SequenceHNode : public HNode {
+ virtual void anchor();
+
public:
SequenceHNode(Node *n) : HNode(n) { }
- virtual ~SequenceHNode();
static inline bool classof(const HNode *n) {
return SequenceNode::classof(n->_node);
}
static inline bool classof(const SequenceHNode *) { return true; }
- std::vector<HNode*> Entries;
+ std::vector<std::unique_ptr<HNode>> Entries;
};
- Input::HNode *createHNodes(Node *node);
+ std::unique_ptr<Input::HNode> createHNodes(Node *node);
void setError(HNode *hnode, const Twine &message);
void setError(Node *node, const Twine &message);
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
index 34fbe082cda8..c9ef637940db 100644
--- a/include/llvm/Support/raw_ostream.h
+++ b/include/llvm/Support/raw_ostream.h
@@ -17,9 +17,12 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
+#include <system_error>
namespace llvm {
class format_object_base;
+ class FormattedString;
+ class FormattedNumber;
template <typename T>
class SmallVectorImpl;
@@ -210,6 +213,12 @@ public:
// Formatted output, see the format() function in Support/Format.h.
raw_ostream &operator<<(const format_object_base &Fmt);
+ // Formatted output, see the leftJustify() function in Support/Format.h.
+ raw_ostream &operator<<(const FormattedString &);
+
+ // Formatted output, see the formatHex() function in Support/Format.h.
+ raw_ostream &operator<<(const FormattedNumber &);
+
/// indent - Insert 'NumSpaces' spaces.
raw_ostream &indent(unsigned NumSpaces);
@@ -341,17 +350,17 @@ class raw_fd_ostream : public raw_ostream {
void error_detected() { Error = true; }
public:
- /// raw_fd_ostream - Open the specified file for writing. If an error occurs,
- /// information about the error is put into ErrorInfo, and the stream should
- /// be immediately destroyed; the string will be empty if no error occurred.
- /// This allows optional flags to control how the file will be opened.
+ /// Open the specified file for writing. If an error occurs, information
+ /// about the error is put into EC, and the stream should be immediately
+ /// destroyed;
+ /// \p Flags allows optional flags to control how the file will be opened.
///
/// As a special case, if Filename is "-", then the stream will use
/// STDOUT_FILENO instead of opening a file. Note that it will still consider
/// itself to own the file descriptor. In particular, it will close the
/// file descriptor when it is done (this is necessary to detect
/// output errors).
- raw_fd_ostream(const char *Filename, std::string &ErrorInfo,
+ raw_fd_ostream(StringRef Filename, std::error_code &EC,
sys::fs::OpenFlags Flags);
/// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 36464d75d5ab..4abeddd6be29 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -432,8 +432,8 @@ protected:
/// readability for really no benefit.
enum InitKind {
IK_BitInit,
- IK_BitsInit,
IK_FirstTypedInit,
+ IK_BitsInit,
IK_DagInit,
IK_DefInit,
IK_FieldInit,
@@ -651,11 +651,12 @@ public:
/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value.
/// It contains a vector of bits, whose size is determined by the type.
///
-class BitsInit : public Init, public FoldingSetNode {
+class BitsInit : public TypedInit, public FoldingSetNode {
std::vector<Init*> Bits;
BitsInit(ArrayRef<Init *> Range)
- : Init(IK_BitsInit), Bits(Range.begin(), Range.end()) {}
+ : TypedInit(IK_BitsInit, BitsRecTy::get(Range.size())),
+ Bits(Range.begin(), Range.end()) {}
BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION;
BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION;
@@ -688,6 +689,14 @@ public:
}
std::string getAsString() const override;
+ /// 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 bits<n>");
+ }
+
Init *resolveReferences(Record &R, const RecordVal *RV) const override;
Init *getBit(unsigned Bit) const override {
@@ -928,7 +937,7 @@ public:
///
class BinOpInit : public OpInit {
public:
- enum BinaryOp { ADD, SHL, SRA, SRL, LISTCONCAT, STRCONCAT, CONCAT, EQ };
+ enum BinaryOp { ADD, AND, SHL, SRA, SRL, LISTCONCAT, STRCONCAT, CONCAT, EQ };
private:
BinaryOp Opc;
@@ -1392,6 +1401,18 @@ class Record {
DefInit *TheInit;
bool IsAnonymous;
+ // 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 usie 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;
+
void init();
void checkName();
@@ -1400,13 +1421,15 @@ public:
explicit Record(const std::string &N, ArrayRef<SMLoc> locs,
RecordKeeper &records, bool Anonymous = false) :
ID(LastID++), Name(StringInit::get(N)), Locs(locs.begin(), locs.end()),
- TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) {
+ TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous),
+ ResolveFirst(false) {
init();
}
explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
bool Anonymous = false) :
ID(LastID++), Name(N), Locs(locs.begin(), locs.end()),
- TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) {
+ TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous),
+ ResolveFirst(false) {
init();
}
@@ -1416,7 +1439,8 @@ public:
ID(LastID++), Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
Values(O.Values), SuperClasses(O.SuperClasses),
SuperClassRanges(O.SuperClassRanges), TrackedRecords(O.TrackedRecords),
- TheInit(O.TheInit), IsAnonymous(O.IsAnonymous) { }
+ TheInit(O.TheInit), IsAnonymous(O.IsAnonymous),
+ ResolveFirst(O.ResolveFirst) { }
~Record() {}
@@ -1544,6 +1568,14 @@ public:
return IsAnonymous;
}
+ bool isResolveFirst() const {
+ return ResolveFirst;
+ }
+
+ void setResolveFirst(bool b) {
+ ResolveFirst = b;
+ }
+
void dump() const;
//===--------------------------------------------------------------------===//
@@ -1631,7 +1663,7 @@ raw_ostream &operator<<(raw_ostream &OS, const Record &R);
struct MultiClass {
Record Rec; // Placeholder for template args and Name.
- typedef std::vector<Record*> RecordVector;
+ typedef std::vector<std::unique_ptr<Record>> RecordVector;
RecordVector DefPrototypes;
void dump() const;
@@ -1641,53 +1673,34 @@ struct MultiClass {
};
class RecordKeeper {
- std::map<std::string, Record*> Classes, Defs;
+ typedef std::map<std::string, std::unique_ptr<Record>> RecordMap;
+ RecordMap Classes, Defs;
public:
- ~RecordKeeper() {
- for (std::map<std::string, Record*>::iterator I = Classes.begin(),
- E = Classes.end(); I != E; ++I)
- delete I->second;
- for (std::map<std::string, Record*>::iterator I = Defs.begin(),
- E = Defs.end(); I != E; ++I)
- delete I->second;
- }
-
- const std::map<std::string, Record*> &getClasses() const { return Classes; }
- const std::map<std::string, Record*> &getDefs() const { return Defs; }
+ const RecordMap &getClasses() const { return Classes; }
+ const RecordMap &getDefs() const { return Defs; }
Record *getClass(const std::string &Name) const {
- std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
- return I == Classes.end() ? nullptr : I->second;
+ auto I = Classes.find(Name);
+ return I == Classes.end() ? nullptr : I->second.get();
}
Record *getDef(const std::string &Name) const {
- std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
- return I == Defs.end() ? nullptr : I->second;
+ auto I = Defs.find(Name);
+ return I == Defs.end() ? nullptr : I->second.get();
}
- void addClass(Record *R) {
- bool Ins = Classes.insert(std::make_pair(R->getName(), R)).second;
+ void addClass(std::unique_ptr<Record> R) {
+ bool Ins = Classes.insert(std::make_pair(R->getName(),
+ std::move(R))).second;
(void)Ins;
assert(Ins && "Class already exists");
}
- void addDef(Record *R) {
- bool Ins = Defs.insert(std::make_pair(R->getName(), R)).second;
+ void addDef(std::unique_ptr<Record> R) {
+ bool Ins = Defs.insert(std::make_pair(R->getName(),
+ std::move(R))).second;
(void)Ins;
assert(Ins && "Record already exists");
}
- /// removeClass - Remove, but do not delete, the specified record.
- ///
- void removeClass(const std::string &Name) {
- assert(Classes.count(Name) && "Class does not exist!");
- Classes.erase(Name);
- }
- /// removeDef - Remove, but do not delete, the specified record.
- ///
- void removeDef(const std::string &Name) {
- assert(Defs.count(Name) && "Def does not exist!");
- Defs.erase(Name);
- }
-
//===--------------------------------------------------------------------===//
// High-level helper methods, useful for tablegen backends...
diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h
index 5baed79fb76a..76e56ec6443e 100644
--- a/include/llvm/TableGen/SetTheory.h
+++ b/include/llvm/TableGen/SetTheory.h
@@ -44,8 +44,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef SETTHEORY_H
-#define SETTHEORY_H
+#ifndef LLVM_TABLEGEN_SETTHEORY_H
+#define LLVM_TABLEGEN_SETTHEORY_H
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringMap.h"
diff --git a/include/llvm/TableGen/StringToOffsetTable.h b/include/llvm/TableGen/StringToOffsetTable.h
index c924bd8ec57d..e3277036dc76 100644
--- a/include/llvm/TableGen/StringToOffsetTable.h
+++ b/include/llvm/TableGen/StringToOffsetTable.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef TBLGEN_STRING_TO_OFFSET_TABLE_H
-#define TBLGEN_STRING_TO_OFFSET_TABLE_H
+#ifndef LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H
+#define LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -28,16 +28,16 @@ class StringToOffsetTable {
public:
unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) {
- StringMapEntry<unsigned> &Entry = StringOffset.GetOrCreateValue(Str, -1U);
- if (Entry.getValue() == -1U) {
+ auto IterBool =
+ StringOffset.insert(std::make_pair(Str, AggregateString.size()));
+ if (IterBool.second) {
// Add the string to the aggregate if this is the first time found.
- Entry.setValue(AggregateString.size());
AggregateString.append(Str.begin(), Str.end());
if (appendZero)
AggregateString += '\0';
}
- return Entry.getValue();
+ return IterBool.first->second;
}
void EmitString(raw_ostream &O) {
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index f77cc7a35eb8..6c970d0c19db 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -378,20 +378,25 @@ class Instruction {
bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction.
bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement?
bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement?
+ bit isRegSequence = 0; // Is this instruction a kind of reg sequence?
+ // If so, make sure to override
+ // TargetInstrInfo::getRegSequenceLikeInputs.
bit isPseudo = 0; // Is this instruction a pseudo-instruction?
// If so, won't have encoding information for
// the [MC]CodeEmitter stuff.
+ bit isExtractSubreg = 0; // Is this instruction a kind of extract subreg?
+ // If so, make sure to override
+ // TargetInstrInfo::getExtractSubregLikeInputs.
+ bit isInsertSubreg = 0; // Is this instruction a kind of insert subreg?
+ // If so, make sure to override
+ // TargetInstrInfo::getInsertSubregLikeInputs.
// Side effect flags - When set, the flags have these meanings:
//
// hasSideEffects - The instruction has side effects that are not
// captured by any operands of the instruction or other flags.
//
- // neverHasSideEffects (deprecated) - Set on an instruction with no pattern
- // if it has no side effects. This is now equivalent to setting
- // "hasSideEffects = 0".
bit hasSideEffects = ?;
- bit neverHasSideEffects = 0;
// Is this instruction a "real" instruction (with a distinct machine
// encoding), or is it a pseudo instruction used for codegen modeling
@@ -583,7 +588,6 @@ class Operand<ValueType ty> : DAGOperand {
string PrintMethod = "printOperand";
string EncoderMethod = "";
string DecoderMethod = "";
- string AsmOperandLowerMethod = ?;
string OperandType = "OPERAND_UNKNOWN";
dag MIOperandInfo = (ops);
@@ -620,6 +624,9 @@ class RegisterOperand<RegisterClass regclass, string pm = "printOperand">
// can match a subset of some other class, in which case the AsmOperandClass
// should declare the other operand as one of its super classes.
AsmOperandClass ParserMatchClass;
+
+ string OperandNamespace = "MCOI";
+ string OperandType = "OPERAND_REGISTER";
}
let OperandType = "OPERAND_IMMEDIATE" in {
@@ -726,7 +733,7 @@ def INLINEASM : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "";
- let neverHasSideEffects = 1; // Note side effect is encoded in an operand.
+ let hasSideEffects = 0; // Note side effect is encoded in an operand.
}
def CFI_INSTRUCTION : Instruction {
let OutOperandList = (outs);
@@ -753,26 +760,26 @@ def KILL : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def EXTRACT_SUBREG : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$supersrc, i32imm:$subidx);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def INSERT_SUBREG : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$supersrc, unknown:$subsrc, i32imm:$subidx);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let Constraints = "$supersrc = $dst";
}
def IMPLICIT_DEF : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let isReMaterializable = 1;
let isAsCheapAsAMove = 1;
}
@@ -780,33 +787,33 @@ def SUBREG_TO_REG : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$implsrc, unknown:$subsrc, i32imm:$subidx);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def COPY_TO_REGCLASS : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$src, i32imm:$regclass);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let isAsCheapAsAMove = 1;
}
def DBG_VALUE : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "DBG_VALUE";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def REG_SEQUENCE : Instruction {
let OutOperandList = (outs unknown:$dst);
- let InOperandList = (ins variable_ops);
+ let InOperandList = (ins unknown:$supersrc, variable_ops);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let isAsCheapAsAMove = 1;
}
def COPY : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$src);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let isAsCheapAsAMove = 1;
}
def BUNDLE : Instruction {
@@ -818,13 +825,13 @@ def LIFETIME_START : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins i32imm:$id);
let AsmString = "LIFETIME_START";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def LIFETIME_END : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins i32imm:$id);
let AsmString = "LIFETIME_END";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def STACKMAP : Instruction {
let OutOperandList = (outs);
@@ -841,6 +848,32 @@ def PATCHPOINT : Instruction {
let mayLoad = 1;
let usesCustomInserter = 1;
}
+def STATEPOINT : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins variable_ops);
+ let usesCustomInserter = 1;
+ let mayLoad = 1;
+ let mayStore = 1;
+ let hasSideEffects = 1;
+ let isCall = 1;
+}
+def LOAD_STACK_GUARD : Instruction {
+ let OutOperandList = (outs ptr_rc:$dst);
+ let InOperandList = (ins);
+ let mayLoad = 1;
+ bit isReMaterializable = 1;
+ let hasSideEffects = 0;
+ bit isPseudo = 1;
+}
+def FRAME_ALLOC : Instruction {
+ // This instruction is really just a label. It has to be part of the chain so
+ // that it doesn't get dropped from the DAG, but it produces nothing and has
+ // no side effects.
+ let OutOperandList = (outs);
+ let InOperandList = (ins ptr_rc:$symbol, i32imm:$id);
+ let hasSideEffects = 0;
+ let hasCtrlDep = 1;
+}
}
//===----------------------------------------------------------------------===//
@@ -989,9 +1022,6 @@ class AsmWriter {
// will specify which alternative to use. For example "{x|y|z}" with Variant
// == 1, will expand to "y".
int Variant = 0;
-
- // OperandSpacing - Space between operand columns.
- int OperandSpacing = -1;
}
def DefaultAsmWriter : AsmWriter;
diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h
index bfddd0601794..277bd98d371c 100644
--- a/include/llvm/Target/TargetFrameLowering.h
+++ b/include/llvm/Target/TargetFrameLowering.h
@@ -142,6 +142,10 @@ public:
/// the assembly prologue to explicitly handle the stack.
virtual void adjustForHiPEPrologue(MachineFunction &MF) const { }
+ /// Adjust the prologue to add an allocation at a fixed offset from the frame
+ /// pointer.
+ virtual void adjustForFrameAllocatePrologue(MachineFunction &MF) const { }
+
/// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee
/// saved registers and returns true if it isn't possible / profitable to do
/// so by issuing a series of store instructions via
@@ -199,6 +203,16 @@ public:
virtual int getFrameIndexReference(const MachineFunction &MF, int FI,
unsigned &FrameReg) const;
+ /// Same as above, except that the 'base register' will always be RSP, not
+ /// RBP on x86. This is used exclusively for lowering STATEPOINT nodes.
+ /// TODO: This should really be a parameterizable choice.
+ virtual int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI,
+ unsigned &FrameReg) const {
+ // default to calling normal version, we override this on x86 only
+ llvm_unreachable("unimplemented for non-x86");
+ return 0;
+ }
+
/// processFunctionBeforeCalleeSavedScan - This method is called immediately
/// before PrologEpilogInserter scans the physical registers used to determine
/// what callee saved registers should be spilled. This method is optional.
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index 87e7c14ac1e8..e8a50fff1fe8 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -14,10 +14,12 @@
#ifndef LLVM_TARGET_TARGETINSTRINFO_H
#define LLVM_TARGET_TARGETINSTRINFO_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
-#include "llvm/CodeGen/DFAPacketizer.h"
+#include "llvm/CodeGen/MachineCombinerPattern.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
namespace llvm {
@@ -28,7 +30,7 @@ class MachineMemOperand;
class MachineRegisterInfo;
class MDNode;
class MCInst;
-class MCSchedModel;
+struct MCSchedModel;
class MCSymbolRefExpr;
class SDNode;
class ScheduleHazardRecognizer;
@@ -38,6 +40,7 @@ class TargetRegisterClass;
class TargetRegisterInfo;
class BranchProbability;
class TargetSubtargetInfo;
+class DFAPacketizer;
template<class T> class SmallVectorImpl;
@@ -106,6 +109,12 @@ public:
int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; }
int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; }
+ /// Returns the actual stack pointer adjustment made by an instruction
+ /// as part of a call sequence. By default, only call frame setup/destroy
+ /// instructions adjust the stack, but targets may want to override this
+ /// to enable more fine-grained adjustment, or adjust by a different value.
+ virtual int getSPAdjust(const MachineInstr *MI) const;
+
/// isCoalescableExtInstr - Return true if the instruction is a "coalescable"
/// extension instruction. That is, it's like a copy where it's legal for the
/// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns
@@ -200,6 +209,15 @@ public:
unsigned &Size, unsigned &Offset,
const TargetMachine *TM) const;
+ /// isAsCheapAsAMove - Return true if the instruction is as cheap as a move
+ /// instruction.
+ ///
+ /// Targets for different archs need to override this, and different
+ /// micro-architectures can also be finely tuned inside.
+ virtual bool isAsCheapAsAMove(const MachineInstr *MI) const {
+ return MI->isAsCheapAsAMove();
+ }
+
/// reMaterialize - Re-issue the specified 'original' instruction at the
/// specific location targeting a new destination register.
/// The register in Orig->getOperand(0).getReg() will be substituted by
@@ -252,6 +270,85 @@ public:
virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
unsigned &SrcOpIdx2) const;
+ /// A pair composed of a register and a sub-register index.
+ /// Used to give some type checking when modeling Reg:SubReg.
+ struct RegSubRegPair {
+ unsigned Reg;
+ unsigned SubReg;
+ RegSubRegPair(unsigned Reg = 0, unsigned SubReg = 0)
+ : Reg(Reg), SubReg(SubReg) {}
+ };
+ /// A pair composed of a pair of a register and a sub-register index,
+ /// and another sub-register index.
+ /// Used to give some type checking when modeling Reg:SubReg1, SubReg2.
+ struct RegSubRegPairAndIdx : RegSubRegPair {
+ unsigned SubIdx;
+ RegSubRegPairAndIdx(unsigned Reg = 0, unsigned SubReg = 0,
+ unsigned SubIdx = 0)
+ : RegSubRegPair(Reg, SubReg), SubIdx(SubIdx) {}
+ };
+
+ /// Build the equivalent inputs of a REG_SEQUENCE for the given \p MI
+ /// and \p DefIdx.
+ /// \p [out] InputRegs of the equivalent REG_SEQUENCE. Each element of
+ /// the list is modeled as <Reg:SubReg, SubIdx>.
+ /// E.g., REG_SEQUENCE vreg1:sub1, sub0, vreg2, sub1 would produce
+ /// two elements:
+ /// - vreg1:sub1, sub0
+ /// - vreg2<:0>, sub1
+ ///
+ /// \returns true if it is possible to build such an input sequence
+ /// with the pair \p MI, \p DefIdx. False otherwise.
+ ///
+ /// \pre MI.isRegSequence() or MI.isRegSequenceLike().
+ ///
+ /// \note The generic implementation does not provide any support for
+ /// MI.isRegSequenceLike(). In other words, one has to override
+ /// getRegSequenceLikeInputs for target specific instructions.
+ bool
+ getRegSequenceInputs(const MachineInstr &MI, unsigned DefIdx,
+ SmallVectorImpl<RegSubRegPairAndIdx> &InputRegs) const;
+
+ /// Build the equivalent inputs of a EXTRACT_SUBREG for the given \p MI
+ /// and \p DefIdx.
+ /// \p [out] InputReg of the equivalent EXTRACT_SUBREG.
+ /// E.g., EXTRACT_SUBREG vreg1:sub1, sub0, sub1 would produce:
+ /// - vreg1:sub1, sub0
+ ///
+ /// \returns true if it is possible to build such an input sequence
+ /// with the pair \p MI, \p DefIdx. False otherwise.
+ ///
+ /// \pre MI.isExtractSubreg() or MI.isExtractSubregLike().
+ ///
+ /// \note The generic implementation does not provide any support for
+ /// MI.isExtractSubregLike(). In other words, one has to override
+ /// getExtractSubregLikeInputs for target specific instructions.
+ bool
+ getExtractSubregInputs(const MachineInstr &MI, unsigned DefIdx,
+ RegSubRegPairAndIdx &InputReg) const;
+
+ /// Build the equivalent inputs of a INSERT_SUBREG for the given \p MI
+ /// and \p DefIdx.
+ /// \p [out] BaseReg and \p [out] InsertedReg contain
+ /// the equivalent inputs of INSERT_SUBREG.
+ /// E.g., INSERT_SUBREG vreg0:sub0, vreg1:sub1, sub3 would produce:
+ /// - BaseReg: vreg0:sub0
+ /// - InsertedReg: vreg1:sub1, sub3
+ ///
+ /// \returns true if it is possible to build such an input sequence
+ /// with the pair \p MI, \p DefIdx. False otherwise.
+ ///
+ /// \pre MI.isInsertSubreg() or MI.isInsertSubregLike().
+ ///
+ /// \note The generic implementation does not provide any support for
+ /// MI.isInsertSubregLike(). In other words, one has to override
+ /// getInsertSubregLikeInputs for target specific instructions.
+ bool
+ getInsertSubregInputs(const MachineInstr &MI, unsigned DefIdx,
+ RegSubRegPair &BaseReg,
+ RegSubRegPairAndIdx &InsertedReg) const;
+
+
/// produceSameValue - Return true if two machine instructions would produce
/// identical values. By default, this is only true when the two instructions
/// are deemed identical except for defs. If this function is called when the
@@ -337,6 +434,26 @@ public:
llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!");
}
+ /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold
+ /// either the instruction returned by getUnconditionalBranch or the
+ /// instruction returned by getTrap. This only makes sense because
+ /// getUnconditionalBranch returns a single, specific instruction. This
+ /// information is needed by the jumptable construction code, since it must
+ /// decide how many bytes to use for a jumptable entry so it can generate the
+ /// right mask.
+ ///
+ /// Note that if the jumptable instruction requires alignment, then that
+ /// alignment should be factored into this required bound so that the
+ /// resulting bound gives the right alignment for the instruction.
+ virtual unsigned getJumpInstrTableEntryBound() const {
+ // This method gets called by LLVMTargetMachine always, so it can't fail
+ // just because there happens to be no implementation for this target.
+ // Any code that tries to use a jumptable annotation without defining
+ // getUnconditionalBranch on the appropriate Target will fail anyway, and
+ // the value returned here won't matter in that case.
+ return 0;
+ }
+
/// isLegalToSplitMBBAt - Return true if it's legal to split the given basic
/// block at the specified instruction (i.e. instruction would be the start
/// of a new basic block).
@@ -486,9 +603,12 @@ public:
/// a side.
///
/// @param MI Optimizable select instruction.
+ /// @param NewMIs Set that record all MIs in the basic block up to \p
+ /// MI. Has to be updated with any newly created MI or deleted ones.
/// @param PreferFalse Try to optimize FalseOp instead of TrueOp.
/// @returns Optimized instruction or NULL.
virtual MachineInstr *optimizeSelect(MachineInstr *MI,
+ SmallPtrSetImpl<MachineInstr *> &NewMIs,
bool PreferFalse = false) const {
// This function must be implemented if Optimizable is ever set.
llvm_unreachable("Target must implement TargetInstrInfo::optimizeSelect!");
@@ -563,6 +683,42 @@ public:
const SmallVectorImpl<unsigned> &Ops,
MachineInstr* LoadMI) const;
+ /// hasPattern - return true when there is potentially a faster code sequence
+ /// for an instruction chain ending in \p Root. All potential pattern are
+ /// returned in the \p Pattern vector. Pattern should be sorted in priority
+ /// order since the pattern evaluator stops checking as soon as it finds a
+ /// faster sequence.
+ /// \param Root - Instruction that could be combined with one of its operands
+ /// \param Pattern - Vector of possible combination pattern
+
+ virtual bool hasPattern(
+ MachineInstr &Root,
+ SmallVectorImpl<MachineCombinerPattern::MC_PATTERN> &Pattern) const {
+ return false;
+ }
+
+ /// genAlternativeCodeSequence - when hasPattern() finds a pattern this
+ /// function generates the instructions that could replace the original code
+ /// sequence. The client has to decide whether the actual replacementment is
+ /// beneficial or not.
+ /// \param Root - Instruction that could be combined with one of its operands
+ /// \param P - Combination pattern for Root
+ /// \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
+ /// InsInstr that defines it
+ virtual void genAlternativeCodeSequence(
+ MachineInstr &Root, MachineCombinerPattern::MC_PATTERN P,
+ SmallVectorImpl<MachineInstr *> &InsInstrs,
+ SmallVectorImpl<MachineInstr *> &DelInstrs,
+ DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const {
+ return;
+ }
+
+ /// useMachineCombiner - return true when a target supports MachineCombiner
+ virtual bool useMachineCombiner() const { return false; }
+
protected:
/// foldMemoryOperandImpl - Target-dependent implementation for
/// foldMemoryOperand. Target-independent code in foldMemoryOperand will
@@ -584,6 +740,49 @@ protected:
return nullptr;
}
+ /// \brief 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.
+ ///
+ /// \pre MI.isRegSequenceLike().
+ ///
+ /// \see TargetInstrInfo::getRegSequenceInputs.
+ virtual bool getRegSequenceLikeInputs(
+ const MachineInstr &MI, unsigned DefIdx,
+ SmallVectorImpl<RegSubRegPairAndIdx> &InputRegs) const {
+ return false;
+ }
+
+ /// \brief 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.
+ ///
+ /// \pre MI.isExtractSubregLike().
+ ///
+ /// \see TargetInstrInfo::getExtractSubregInputs.
+ virtual bool getExtractSubregLikeInputs(
+ const MachineInstr &MI, unsigned DefIdx,
+ RegSubRegPairAndIdx &InputReg) const {
+ return false;
+ }
+
+ /// \brief 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.
+ ///
+ /// \pre MI.isInsertSubregLike().
+ ///
+ /// \see TargetInstrInfo::getInsertSubregInputs.
+ virtual bool
+ getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx,
+ RegSubRegPair &BaseReg,
+ RegSubRegPairAndIdx &InsertedReg) const {
+ return false;
+ }
+
public:
/// canFoldMemoryOperand - Returns true for the specified load / store if
/// folding is possible.
@@ -677,10 +876,8 @@ public:
MachineBasicBlock::iterator MI) const;
- /// getNoopForMachoTarget - Return the noop instruction to use for a noop.
- virtual void getNoopForMachoTarget(MCInst &NopInst) const {
- // Default to just using 'nop' string.
- }
+ /// Return the noop instruction to use for a noop.
+ virtual void getNoopForMachoTarget(MCInst &NopInst) const;
/// isPredicated - Returns true if the instruction is already predicated.
@@ -784,6 +981,7 @@ public:
const MachineRegisterInfo *MRI) const {
return false;
}
+ virtual bool optimizeCondBranch(MachineInstr *MI) const { return false; }
/// optimizeLoadInstr - Try to remove the load by folding it to a register
/// operand at the use. We fold the load instructions if and only if the
@@ -862,7 +1060,7 @@ public:
SDNode *Node) const;
/// Return the default expected latency for a def based on it's opcode.
- unsigned defaultDefLatency(const MCSchedModel *SchedModel,
+ unsigned defaultDefLatency(const MCSchedModel &SchedModel,
const MachineInstr *DefMI) const;
int computeDefOperandLatency(const InstrItineraryData *ItinData,
@@ -1017,11 +1215,25 @@ public:
const TargetRegisterInfo *TRI) const {}
/// Create machine specific model for scheduling.
- virtual DFAPacketizer*
- CreateTargetScheduleState(const TargetMachine*, const ScheduleDAG*) const {
+ virtual DFAPacketizer *
+ CreateTargetScheduleState(const TargetSubtargetInfo &) const {
return nullptr;
}
+ // areMemAccessesTriviallyDisjoint - Sometimes, it is possible for the target
+ // to tell, even without aliasing information, that two MIs access different
+ // memory addresses. This function returns true if two MIs access different
+ // memory addresses, and false otherwise.
+ virtual bool
+ areMemAccessesTriviallyDisjoint(MachineInstr *MIa, MachineInstr *MIb,
+ AliasAnalysis *AA = nullptr) const {
+ assert(MIa && (MIa->mayLoad() || MIa->mayStore()) &&
+ "MIa must load from or modify a memory location");
+ assert(MIb && (MIb->mayLoad() || MIb->mayStore()) &&
+ "MIb must load from or modify a memory location");
+ return false;
+ }
+
private:
int CallFrameSetupOpcode, CallFrameDestroyOpcode;
};
diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h
index 6de264e90ef7..71c0166d49b0 100644
--- a/include/llvm/Target/TargetIntrinsicInfo.h
+++ b/include/llvm/Target/TargetIntrinsicInfo.h
@@ -52,7 +52,7 @@ public:
/// Returns true if the intrinsic can be overloaded.
virtual bool isOverloaded(unsigned IID) const = 0;
-
+
/// Create or insert an LLVM Function declaration for an intrinsic,
/// and return it. The Tys and numTys are for intrinsics with overloaded
/// types. See above for more information.
diff --git a/include/llvm/Target/TargetJITInfo.h b/include/llvm/Target/TargetJITInfo.h
deleted file mode 100644
index f9bd0fb9f981..000000000000
--- a/include/llvm/Target/TargetJITInfo.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//===- Target/TargetJITInfo.h - Target Information for JIT ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file exposes an abstract interface used by the Just-In-Time code
-// generator to perform target-specific activities, such as emitting stubs. If
-// a TargetMachine supports JIT code generation, it should provide one of these
-// objects through the getJITInfo() method.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_TARGETJITINFO_H
-#define LLVM_TARGET_TARGETJITINFO_H
-
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <cassert>
-
-namespace llvm {
- class Function;
- class GlobalValue;
- class JITCodeEmitter;
- class MachineRelocation;
-
- /// TargetJITInfo - Target specific information required by the Just-In-Time
- /// code generator.
- class TargetJITInfo {
- virtual void anchor();
- public:
- virtual ~TargetJITInfo() {}
-
- /// replaceMachineCodeForFunction - Make it so that calling the function
- /// whose machine code is at OLD turns into a call to NEW, perhaps by
- /// overwriting OLD with a branch to NEW. This is used for self-modifying
- /// code.
- ///
- virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0;
-
- /// emitGlobalValueIndirectSym - Use the specified JITCodeEmitter object
- /// to emit an indirect symbol which contains the address of the specified
- /// ptr.
- virtual void *emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr,
- JITCodeEmitter &JCE) {
- llvm_unreachable("This target doesn't implement "
- "emitGlobalValueIndirectSym!");
- }
-
- /// Records the required size and alignment for a call stub in bytes.
- struct StubLayout {
- size_t Size;
- size_t Alignment;
- };
- /// Returns the maximum size and alignment for a call stub on this target.
- virtual StubLayout getStubLayout() {
- llvm_unreachable("This target doesn't implement getStubLayout!");
- }
-
- /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a
- /// small native function that simply calls the function at the specified
- /// address. The JITCodeEmitter must already have storage allocated for the
- /// stub. Return the address of the resultant function, which may have been
- /// aligned from the address the JCE was set up to emit at.
- virtual void *emitFunctionStub(const Function* F, void *Target,
- JITCodeEmitter &JCE) {
- llvm_unreachable("This target doesn't implement emitFunctionStub!");
- }
-
- /// getPICJumpTableEntry - Returns the value of the jumptable entry for the
- /// specific basic block.
- virtual uintptr_t getPICJumpTableEntry(uintptr_t BB, uintptr_t JTBase) {
- llvm_unreachable("This target doesn't implement getPICJumpTableEntry!");
- }
-
- /// LazyResolverFn - This typedef is used to represent the function that
- /// unresolved call points should invoke. This is a target specific
- /// function that knows how to walk the stack and find out which stub the
- /// call is coming from.
- typedef void (*LazyResolverFn)();
-
- /// JITCompilerFn - This typedef is used to represent the JIT function that
- /// lazily compiles the function corresponding to a stub. The JIT keeps
- /// track of the mapping between stubs and LLVM Functions, the target
- /// provides the ability to figure out the address of a stub that is called
- /// by the LazyResolverFn.
- typedef void* (*JITCompilerFn)(void *);
-
- /// getLazyResolverFunction - This method is used to initialize the JIT,
- /// giving the target the function that should be used to compile a
- /// function, and giving the JIT the target function used to do the lazy
- /// resolving.
- virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn) {
- llvm_unreachable("Not implemented for this target!");
- }
-
- /// relocate - Before the JIT can run a block of code that has been emitted,
- /// it must rewrite the code to contain the actual addresses of any
- /// referenced global symbols.
- virtual void relocate(void *Function, MachineRelocation *MR,
- unsigned NumRelocs, unsigned char* GOTBase) {
- assert(NumRelocs == 0 && "This target does not have relocations!");
- }
-
-
- /// allocateThreadLocalMemory - Each target has its own way of
- /// handling thread local variables. This method returns a value only
- /// meaningful to the target.
- virtual char* allocateThreadLocalMemory(size_t size) {
- llvm_unreachable("This target does not implement thread local storage!");
- }
-
- /// needsGOT - Allows a target to specify that it would like the
- /// JIT to manage a GOT for it.
- bool needsGOT() const { return useGOT; }
-
- /// hasCustomConstantPool - Allows a target to specify that constant
- /// pool address resolution is handled by the target.
- virtual bool hasCustomConstantPool() const { return false; }
-
- /// hasCustomJumpTables - Allows a target to specify that jumptables
- /// are emitted by the target.
- virtual bool hasCustomJumpTables() const { return false; }
-
- /// allocateSeparateGVMemory - If true, globals should be placed in
- /// separately allocated heap memory rather than in the same
- /// code memory allocated by JITCodeEmitter.
- virtual bool allocateSeparateGVMemory() const { return false; }
- protected:
- bool useGOT;
- };
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h
index d4f9f2330594..46f87b93b001 100644
--- a/include/llvm/Target/TargetLibraryInfo.h
+++ b/include/llvm/Target/TargetLibraryInfo.h
@@ -26,10 +26,18 @@ namespace llvm {
ZdaPv,
/// void operator delete[](void*, nothrow);
ZdaPvRKSt9nothrow_t,
+ /// void operator delete[](void*, unsigned int);
+ ZdaPvj,
+ /// void operator delete[](void*, unsigned long);
+ ZdaPvm,
/// void operator delete(void*);
ZdlPv,
/// void operator delete(void*, nothrow);
ZdlPvRKSt9nothrow_t,
+ /// void operator delete(void*, unsigned int);
+ ZdlPvj,
+ /// void operator delete(void*, unsigned long);
+ ZdlPvm,
/// void *new[](unsigned int);
Znaj,
/// void *new[](unsigned int, nothrow);
@@ -54,7 +62,7 @@ namespace llvm {
cxa_atexit,
/// void __cxa_guard_abort(guard_t *guard);
/// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi.
- cxa_guard_abort,
+ cxa_guard_abort,
/// int __cxa_guard_acquire(guard_t *guard);
cxa_guard_acquire,
/// void __cxa_guard_release(guard_t *guard);
@@ -65,6 +73,11 @@ namespace llvm {
dunder_isoc99_sscanf,
/// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size);
memcpy_chk,
+ /// void *__memmove_chk(void *s1, const void *s2, size_t n,
+ /// size_t s1size);
+ memmove_chk,
+ /// void *__memset_chk(void *s, char v, size_t n, size_t s1size);
+ memset_chk,
/// double __sincospi_stret(double x);
sincospi_stret,
/// float __sincospif_stret(float x);
@@ -79,8 +92,18 @@ namespace llvm {
sqrtf_finite,
/// long double __sqrt_finite(long double x);
sqrtl_finite,
+ /// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size);
+ stpcpy_chk,
+ /// char *__stpncpy_chk(char *s1, const char *s2, size_t n,
+ /// size_t s1size);
+ stpncpy_chk,
+ /// char *__strcpy_chk(char *s1, const char *s2, size_t s1size);
+ strcpy_chk,
/// char * __strdup(const char *s);
dunder_strdup,
+ /// char *__strncpy_chk(char *s1, const char *s2, size_t n,
+ /// size_t s1size);
+ strncpy_chk,
/// char *__strndup(const char *s, size_t n);
dunder_strndup,
/// char * __strtok_r(char *s, const char *delim, char **save_ptr);
@@ -696,7 +719,7 @@ public:
TargetLibraryInfo();
TargetLibraryInfo(const Triple &T);
explicit TargetLibraryInfo(const TargetLibraryInfo &TLI);
-
+
/// getLibFunc - Search for a particular function name. If it is one of the
/// known library functions, return true and set F to the corresponding value.
bool getLibFunc(StringRef funcName, LibFunc::Func &F) const;
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index ea9a48e2db8a..c5fed02e17b8 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -30,8 +30,9 @@
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
-#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Target/TargetCallingConv.h"
#include "llvm/Target/TargetMachine.h"
@@ -50,6 +51,7 @@ namespace llvm {
class MachineFunction;
class MachineInstr;
class MachineJumpTableInfo;
+ class MachineLoop;
class Mangler;
class MCContext;
class MCExpr;
@@ -136,10 +138,9 @@ public:
llvm_unreachable("Invalid content kind");
}
- /// NOTE: The constructor takes ownership of TLOF.
- explicit TargetLoweringBase(const TargetMachine &TM,
- const TargetLoweringObjectFile *TLOF);
- virtual ~TargetLoweringBase();
+ /// NOTE: The TargetMachine owns TLOF.
+ explicit TargetLoweringBase(const TargetMachine &TM);
+ virtual ~TargetLoweringBase() {}
protected:
/// \brief Initialize all of the actions to default values.
@@ -148,7 +149,9 @@ protected:
public:
const TargetMachine &getTargetMachine() const { return TM; }
const DataLayout *getDataLayout() const { return DL; }
- const TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; }
+ const TargetLoweringObjectFile &getObjFileLowering() const {
+ return *TM.getObjFileLowering();
+ }
bool isBigEndian() const { return !IsLittleEndian; }
bool isLittleEndian() const { return IsLittleEndian; }
@@ -214,6 +217,11 @@ public:
/// several shifts, adds, and multiplies for this target.
bool isIntDivCheap() const { return IntDivIsCheap; }
+ /// Return true if sqrt(x) is as cheap or cheaper than 1 / rsqrt(x)
+ bool isFsqrtCheap() const {
+ return FsqrtIsCheap;
+ }
+
/// Returns true if target has indicated at least one type should be bypassed.
bool isSlowDivBypassed() const { return !BypassSlowDivWidths.empty(); }
@@ -223,8 +231,8 @@ public:
return BypassSlowDivWidths;
}
- /// Return true if pow2 div is cheaper than a chain of srl/add/sra.
- bool isPow2DivCheap() const { return Pow2DivIsCheap; }
+ /// Return true if pow2 sdiv is cheaper than a chain of sra/srl/add/sra.
+ bool isPow2SDivCheap() const { return Pow2SDivIsCheap; }
/// Return true if Flow Control is an expensive operation that should be
/// avoided.
@@ -247,6 +255,16 @@ public:
return true;
}
+ /// \brief Return true if it is cheap to speculate a call to intrinsic cttz.
+ virtual bool isCheapToSpeculateCttz() const {
+ return false;
+ }
+
+ /// \brief Return true if it is cheap to speculate a call to intrinsic ctlz.
+ virtual bool isCheapToSpeculateCtlz() const {
+ return false;
+ }
+
/// \brief Return if the target supports combining a
/// chain like:
/// \code
@@ -262,10 +280,32 @@ public:
return MaskAndBranchFoldingIsLegal;
}
- /// Return the ValueType of the result of SETCC operations. Also used to
- /// obtain the target's preferred type for the condition operand of SELECT and
- /// BRCOND nodes. In the case of BRCOND the argument passed is MVT::Other
- /// since there are no other operands to get a type hint from.
+ /// \brief Return true if the target wants to use the optimization that
+ /// turns ext(promotableInst1(...(promotableInstN(load)))) into
+ /// promotedInst1(...(promotedInstN(ext(load)))).
+ bool enableExtLdPromotion() const { return EnableExtLdPromotion; }
+
+ /// Return true if the target can combine store(extractelement VectorTy,
+ /// Idx).
+ /// \p Cost[out] gives the cost of that transformation when this is true.
+ virtual bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx,
+ unsigned &Cost) const {
+ return false;
+ }
+
+ /// Return true if target supports floating point exceptions.
+ bool hasFloatingPointExceptions() const {
+ return HasFloatingPointExceptions;
+ }
+
+ /// Return true if target always beneficiates from combining into FMA for a
+ /// given value type. This must typically return false on targets where FMA
+ /// takes more cycles to execute than FADD.
+ virtual bool enableAggressiveFMAFusion(EVT VT) const {
+ return false;
+ }
+
+ /// Return the ValueType of the result of SETCC operations.
virtual EVT getSetCCResultType(LLVMContext &Context, EVT VT) const;
/// Return the ValueType for comparison libcalls. Comparions libcalls include
@@ -426,10 +466,15 @@ public:
EVT memVT; // memory VT
const Value* ptrVal; // value representing memory location
int offset; // offset off of ptrVal
+ unsigned size; // the size of the memory location
+ // (taken from memVT if zero)
unsigned align; // alignment
bool vol; // is volatile?
bool readMem; // reads memory?
bool writeMem; // writes memory?
+
+ IntrinsicInfo() : opc(0), ptrVal(nullptr), offset(0), size(0), align(1),
+ vol(false), readMem(false), writeMem(false) {}
};
/// Given an intrinsic, checks if on the target the intrinsic will need to map
@@ -517,26 +562,31 @@ public:
/// Return how this load with extension should be treated: either it is legal,
/// needs to be promoted to a larger size, needs to be expanded to some other
/// code sequence, or the target has a custom expander for it.
- LegalizeAction getLoadExtAction(unsigned ExtType, MVT VT) const {
- assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE &&
- "Table isn't big enough!");
- return (LegalizeAction)LoadExtActions[VT.SimpleTy][ExtType];
+ LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, EVT MemVT) const {
+ if (ValVT.isExtended() || MemVT.isExtended()) return Expand;
+ unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy;
+ unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy;
+ assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValI < MVT::LAST_VALUETYPE &&
+ MemI < MVT::LAST_VALUETYPE && "Table isn't big enough!");
+ return (LegalizeAction)LoadExtActions[ValI][MemI][ExtType];
}
/// Return true if the specified load with extension is legal on this target.
- bool isLoadExtLegal(unsigned ExtType, EVT VT) const {
- return VT.isSimple() &&
- getLoadExtAction(ExtType, VT.getSimpleVT()) == Legal;
+ bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const {
+ return ValVT.isSimple() && MemVT.isSimple() &&
+ getLoadExtAction(ExtType, ValVT, MemVT) == Legal;
}
/// Return how this store with truncation should be treated: either it is
/// legal, needs to be promoted to a larger size, needs to be expanded to some
/// other code sequence, or the target has a custom expander for it.
- LegalizeAction getTruncStoreAction(MVT ValVT, MVT MemVT) const {
- assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE &&
+ LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const {
+ if (ValVT.isExtended() || MemVT.isExtended()) return Expand;
+ unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy;
+ unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy;
+ assert(ValI < MVT::LAST_VALUETYPE && MemI < MVT::LAST_VALUETYPE &&
"Table isn't big enough!");
- return (LegalizeAction)TruncStoreActions[ValVT.SimpleTy]
- [MemVT.SimpleTy];
+ return (LegalizeAction)TruncStoreActions[ValI][MemI];
}
/// Return true if the specified store with truncation is legal on this
@@ -551,7 +601,7 @@ public:
/// sequence, or the target has a custom expander for it.
LegalizeAction
getIndexedLoadAction(unsigned IdxMode, MVT VT) const {
- assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE &&
+ assert(IdxMode < ISD::LAST_INDEXED_MODE && VT.isValid() &&
"Table isn't big enough!");
unsigned Ty = (unsigned)VT.SimpleTy;
return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] & 0xf0) >> 4);
@@ -569,7 +619,7 @@ public:
/// sequence, or the target has a custom expander for it.
LegalizeAction
getIndexedStoreAction(unsigned IdxMode, MVT VT) const {
- assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE &&
+ assert(IdxMode < ISD::LAST_INDEXED_MODE && VT.isValid() &&
"Table isn't big enough!");
unsigned Ty = (unsigned)VT.SimpleTy;
return (LegalizeAction)(IndexedModeActions[Ty][IdxMode] & 0x0f);
@@ -725,6 +775,16 @@ public:
/// reduce runtime.
virtual bool ShouldShrinkFPConstant(EVT) const { return true; }
+ // Return true if it is profitable to reduce the given load node to a smaller
+ // type.
+ //
+ // e.g. (i16 (trunc (i32 (load x))) -> i16 load x should be performed
+ virtual bool shouldReduceLoadWidth(SDNode *Load,
+ ISD::LoadExtType ExtTy,
+ EVT NewVT) const {
+ return true;
+ }
+
/// When splitting a value of the specified type into parts, does the Lo
/// or Hi part come first? This usually follows the endianness, except
/// for ppcf128, where the Hi part always comes first.
@@ -773,14 +833,15 @@ public:
///
/// 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
- /// whether the unaligned memory access is "fast" in the third argument by
+ /// whether the unaligned memory access is "fast" in the last argument by
/// reference. This is used, for example, in situations where an array
/// copy/move/set is converted to a sequence of store operations. Its use
/// helps to ensure that such replacements don't generate code that causes an
/// alignment error (trap) on the target machine.
- virtual bool allowsUnalignedMemoryAccesses(EVT,
- unsigned AddrSpace = 0,
- bool * /*Fast*/ = nullptr) const {
+ virtual bool allowsMisalignedMemoryAccesses(EVT,
+ unsigned AddrSpace = 0,
+ unsigned Align = 1,
+ bool * /*Fast*/ = nullptr) const {
return false;
}
@@ -823,11 +884,6 @@ public:
return UseUnderscoreLongJmp;
}
- /// Return whether the target can generate code for jump tables.
- bool supportJumpTables() const {
- return SupportJumpTables;
- }
-
/// Return integer threshold on number of blocks to use jump tables rather
/// than if sequence.
int getMinimumJumpTableEntries() const {
@@ -880,7 +936,7 @@ public:
}
/// Return the preferred loop alignment.
- unsigned getPrefLoopAlignment() const {
+ virtual unsigned getPrefLoopAlignment(MachineLoop *ML = nullptr) const {
return PrefLoopAlignment;
}
@@ -922,9 +978,13 @@ public:
/// @}
//===--------------------------------------------------------------------===//
- /// \name Helpers for load-linked/store-conditional atomic expansion.
+ /// \name Helpers for atomic expansion.
/// @{
+ /// True if AtomicExpandPass should use emitLoadLinked/emitStoreConditional
+ /// and expand AtomicCmpXchgInst.
+ virtual bool hasLoadLinkedStoreConditional() const { return false; }
+
/// Perform a load-linked operation on Addr, returning a "Value *" with the
/// corresponding pointee type. This may entail some non-trivial operations to
/// truncate or reconstruct types that will be illegal in the backend. See
@@ -941,15 +1001,90 @@ public:
llvm_unreachable("Store conditional unimplemented on this target");
}
- /// Return true if the given (atomic) instruction should be expanded by the
- /// IR-level AtomicExpandLoadLinked pass into a loop involving
- /// load-linked/store-conditional pairs. Atomic stores will be expanded in the
- /// same way as "atomic xchg" operations which ignore their output if needed.
- virtual bool shouldExpandAtomicInIR(Instruction *Inst) const {
+ /// Inserts in the IR a target-specific intrinsic specifying a fence.
+ /// It is called by AtomicExpandPass before expanding an
+ /// AtomicRMW/AtomicCmpXchg/AtomicStore/AtomicLoad.
+ /// RMW and CmpXchg set both IsStore and IsLoad to true.
+ /// This function should either return a nullptr, or a pointer to an IR-level
+ /// Instruction*. Even complex fence sequences can be represented by a
+ /// single Instruction* through an intrinsic to be lowered later.
+ /// Backends with !getInsertFencesForAtomic() should keep a no-op here.
+ /// Backends should override this method to produce target-specific intrinsic
+ /// for their fences.
+ /// FIXME: Please note that the default implementation here in terms of
+ /// IR-level fences exists for historical/compatibility reasons and is
+ /// *unsound* ! Fences cannot, in general, be used to restore sequential
+ /// consistency. For example, consider the following example:
+ /// atomic<int> x = y = 0;
+ /// int r1, r2, r3, r4;
+ /// Thread 0:
+ /// x.store(1);
+ /// Thread 1:
+ /// y.store(1);
+ /// Thread 2:
+ /// r1 = x.load();
+ /// r2 = y.load();
+ /// Thread 3:
+ /// r3 = y.load();
+ /// r4 = x.load();
+ /// r1 = r3 = 1 and r2 = r4 = 0 is impossible as long as the accesses are all
+ /// seq_cst. But if they are lowered to monotonic accesses, no amount of
+ /// IR-level fences can prevent it.
+ /// @{
+ virtual Instruction* emitLeadingFence(IRBuilder<> &Builder, AtomicOrdering Ord,
+ bool IsStore, bool IsLoad) const {
+ if (!getInsertFencesForAtomic())
+ return nullptr;
+
+ if (isAtLeastRelease(Ord) && IsStore)
+ return Builder.CreateFence(Ord);
+ else
+ return nullptr;
+ }
+
+ virtual Instruction* emitTrailingFence(IRBuilder<> &Builder, AtomicOrdering Ord,
+ bool IsStore, bool IsLoad) const {
+ if (!getInsertFencesForAtomic())
+ return nullptr;
+
+ if (isAtLeastAcquire(Ord))
+ return Builder.CreateFence(Ord);
+ else
+ return nullptr;
+ }
+ /// @}
+
+ /// Returns true if the given (atomic) store should be expanded by the
+ /// IR-level AtomicExpand pass into an "atomic xchg" which ignores its input.
+ virtual bool shouldExpandAtomicStoreInIR(StoreInst *SI) const {
return false;
}
+ /// Returns true if the given (atomic) load should be expanded by the
+ /// IR-level AtomicExpand pass into a load-linked instruction
+ /// (through emitLoadLinked()).
+ virtual bool shouldExpandAtomicLoadInIR(LoadInst *LI) const { return false; }
+ /// Returns true if the given AtomicRMW should be expanded by the
+ /// IR-level AtomicExpand pass into a loop using LoadLinked/StoreConditional.
+ virtual bool shouldExpandAtomicRMWInIR(AtomicRMWInst *RMWI) const {
+ return false;
+ }
+
+ /// On some platforms, an AtomicRMW that never actually modifies the value
+ /// (such as fetch_add of 0) can be turned into a fence followed by an
+ /// atomic load. This may sound useless, but it makes it possible for the
+ /// processor to keep the cacheline shared, dramatically improving
+ /// performance. And such idempotent RMWs are useful for implementing some
+ /// kinds of locks, see for example (justification + benchmarks):
+ /// http://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
+ /// This method tries doing that transformation, returning the atomic load if
+ /// it succeeds, and nullptr otherwise.
+ /// If shouldExpandAtomicLoadInIR returns true on that load, it will undergo
+ /// another round of expansion.
+ virtual LoadInst *lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const {
+ return nullptr;
+ }
//===--------------------------------------------------------------------===//
// TargetLowering Configuration Methods - These methods should be invoked by
// the derived class constructor to configure this object for the target.
@@ -996,11 +1131,6 @@ protected:
UseUnderscoreLongJmp = Val;
}
- /// Indicate whether the target can generate code for jump tables.
- void setSupportJumpTables(bool Val) {
- SupportJumpTables = Val;
- }
-
/// Indicate the number of blocks to generate jump tables rather than if
/// sequence.
void setMinimumJumpTableEntries(int Val) {
@@ -1059,14 +1189,24 @@ protected:
/// containing an integer divide.
void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; }
+ /// Tells the code generator that fsqrt is cheap, and should not be replaced
+ /// with an alternative sequence of instructions.
+ void setFsqrtIsCheap(bool isCheap = true) { FsqrtIsCheap = isCheap; }
+
+ /// Tells the code generator that this target supports floating point
+ /// exceptions and cares about preserving floating point exception behavior.
+ void setHasFloatingPointExceptions(bool FPExceptions = true) {
+ HasFloatingPointExceptions = FPExceptions;
+ }
+
/// Tells the code generator which bitwidths to bypass.
void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth) {
BypassSlowDivWidths[SlowBitWidth] = FastBitWidth;
}
- /// Tells the code generator that it shouldn't generate srl/add/sra for a
- /// signed divide by power of two, and let the target handle it.
- void setPow2DivIsCheap(bool isCheap = true) { Pow2DivIsCheap = isCheap; }
+ /// Tells the code generator that it shouldn't generate sra/srl/add/sra for a
+ /// signed divide by power of two; let the target handle it.
+ void setPow2SDivIsCheap(bool isCheap = true) { Pow2SDivIsCheap = isCheap; }
/// Add the specified register class as an available regclass for the
/// specified value type. This indicates the selector can handle values of
@@ -1107,19 +1247,18 @@ protected:
/// Indicate that the specified load with extension does not work with the
/// specified type and indicate what to do about it.
- void setLoadExtAction(unsigned ExtType, MVT VT,
+ void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT,
LegalizeAction Action) {
- assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE &&
- "Table isn't big enough!");
- LoadExtActions[VT.SimpleTy][ExtType] = (uint8_t)Action;
+ assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValVT.isValid() &&
+ MemVT.isValid() && "Table isn't big enough!");
+ LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy][ExtType] = (uint8_t)Action;
}
/// Indicate that the specified truncating store does not work with the
/// specified type and indicate what to do about it.
void setTruncStoreAction(MVT ValVT, MVT MemVT,
LegalizeAction Action) {
- assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE &&
- "Table isn't big enough!");
+ assert(ValVT.isValid() && MemVT.isValid() && "Table isn't big enough!");
TruncStoreActions[ValVT.SimpleTy][MemVT.SimpleTy] = (uint8_t)Action;
}
@@ -1130,7 +1269,7 @@ protected:
/// TargetLowering.cpp
void setIndexedLoadAction(unsigned IdxMode, MVT VT,
LegalizeAction Action) {
- assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE &&
+ assert(VT.isValid() && IdxMode < ISD::LAST_INDEXED_MODE &&
(unsigned)Action < 0xf && "Table isn't big enough!");
// Load action are kept in the upper half.
IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0xf0;
@@ -1144,7 +1283,7 @@ protected:
/// TargetLowering.cpp
void setIndexedStoreAction(unsigned IdxMode, MVT VT,
LegalizeAction Action) {
- assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE &&
+ assert(VT.isValid() && IdxMode < ISD::LAST_INDEXED_MODE &&
(unsigned)Action < 0xf && "Table isn't big enough!");
// Store action are kept in the lower half.
IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0x0f;
@@ -1155,8 +1294,7 @@ protected:
/// target and indicate what to do about it.
void setCondCodeAction(ISD::CondCode CC, MVT VT,
LegalizeAction Action) {
- assert(VT < MVT::LAST_VALUETYPE &&
- (unsigned)CC < array_lengthof(CondCodeActions) &&
+ assert(VT.isValid() && (unsigned)CC < array_lengthof(CondCodeActions) &&
"Table isn't big enough!");
/// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 32-bit
/// value and the upper 27 bits index into the second dimension of the array
@@ -1207,7 +1345,8 @@ protected:
/// Set the target's preferred loop alignment. Default alignment is zero, it
/// means the target does not care about loop alignment. The alignment is
- /// specified in log2(bytes).
+ /// specified in log2(bytes). The target may also override
+ /// getPrefLoopAlignment to provide per-loop values.
void setPrefLoopAlignment(unsigned Align) {
PrefLoopAlignment = Align;
}
@@ -1370,6 +1509,14 @@ public:
return isZExtFree(Val.getValueType(), VT2);
}
+ /// Return true if an fpext operation is free (for instance, because
+ /// single-precision floating-point numbers are implicitly extended to
+ /// double-precision).
+ virtual bool isFPExtFree(EVT VT) const {
+ assert(VT.isFloatingPoint());
+ return false;
+ }
+
/// Return true if an fneg operation is free to the point where it is never
/// worthwhile to replace it with a bitwise operation.
virtual bool isFNegFree(EVT VT) const {
@@ -1412,6 +1559,15 @@ public:
Type *Ty) const {
return false;
}
+
+ /// Return true if EXTRACT_SUBVECTOR is cheap for this result type
+ /// with this index. This is needed because EXTRACT_SUBVECTOR usually
+ /// has custom lowering that depends on the index of the first element,
+ /// and only the target knows which lowering is cheap.
+ virtual bool isExtractSubvectorCheap(EVT ResVT, unsigned Index) const {
+ return false;
+ }
+
//===--------------------------------------------------------------------===//
// Runtime Library hooks
//
@@ -1451,7 +1607,6 @@ public:
private:
const TargetMachine &TM;
const DataLayout *DL;
- const TargetLoweringObjectFile &TLOF;
/// True if this is a little endian target.
bool IsLittleEndian;
@@ -1479,21 +1634,28 @@ private:
/// unconditionally.
bool IntDivIsCheap;
+ // Don't expand fsqrt with an approximation based on the inverse sqrt.
+ bool FsqrtIsCheap;
+
/// Tells the code generator to bypass slow divide or remainder
/// instructions. For example, BypassSlowDivWidths[32,8] tells the code
/// generator to bypass 32-bit integer div/rem with an 8-bit unsigned integer
/// div/rem when the operands are positive and less than 256.
DenseMap <unsigned int, unsigned int> BypassSlowDivWidths;
- /// Tells the code generator that it shouldn't generate srl/add/sra for a
- /// signed divide by power of two, and let the target handle it.
- bool Pow2DivIsCheap;
+ /// Tells the code generator that it shouldn't generate sra/srl/add/sra for a
+ /// signed divide by power of two; let the target handle it.
+ bool Pow2SDivIsCheap;
/// Tells the code generator that it shouldn't generate extra flow control
/// instructions and should attempt to combine flow control instructions via
/// predication.
bool JumpIsExpensive;
+ /// Whether the target supports or cares about preserving floating point
+ /// exception behavior.
+ bool HasFloatingPointExceptions;
+
/// This target prefers to use _setjmp to implement llvm.setjmp.
///
/// Defaults to false.
@@ -1504,10 +1666,6 @@ private:
/// Defaults to false.
bool UseUnderscoreLongJmp;
- /// Whether the target can generate code for jumptables. If it's not true,
- /// then each jumptable must be lowered into if-then-else's.
- bool SupportJumpTables;
-
/// Number of blocks threshold to use jump tables.
int MinimumJumpTableEntries;
@@ -1600,7 +1758,8 @@ private:
/// For each load extension type and each value type, keep a LegalizeAction
/// that indicates how instruction selection should deal with a load of a
/// specific value type and extension type.
- uint8_t LoadExtActions[MVT::LAST_VALUETYPE][ISD::LAST_LOADEXT_TYPE];
+ uint8_t LoadExtActions[MVT::LAST_VALUETYPE][MVT::LAST_VALUETYPE]
+ [ISD::LAST_LOADEXT_TYPE];
/// For each value type pair keep a LegalizeAction that indicates whether a
/// truncating store of a specific value type and truncating type is legal.
@@ -1841,6 +2000,9 @@ protected:
/// a mask of a single bit, a compare, and a branch into a single instruction.
bool MaskAndBranchFoldingIsLegal;
+ /// \see enableExtLdPromotion.
+ bool EnableExtLdPromotion;
+
protected:
/// Return true if the value types that can be represented by the specified
/// register class are all legal.
@@ -1861,9 +2023,8 @@ class TargetLowering : public TargetLoweringBase {
void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION;
public:
- /// NOTE: The constructor takes ownership of TLOF.
- explicit TargetLowering(const TargetMachine &TM,
- const TargetLoweringObjectFile *TLOF);
+ /// NOTE: The TargetMachine owns TLOF.
+ explicit TargetLowering(const TargetMachine &TM);
/// Returns true by value, base pointer and offset pointer and addressing mode
/// by reference if the node's address can be legally represented as
@@ -2150,6 +2311,7 @@ public:
SelectionDAG &DAG;
SDLoc DL;
ImmutableCallSite *CS;
+ bool IsPatchPoint;
SmallVector<ISD::OutputArg, 32> Outs;
SmallVector<SDValue, 32> OutVals;
SmallVector<ISD::InputArg, 32> Ins;
@@ -2158,7 +2320,7 @@ public:
: RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),
IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C),
- DAG(DAG), CS(nullptr) {}
+ DAG(DAG), CS(nullptr), IsPatchPoint(false) {}
CallLoweringInfo &setDebugLoc(SDLoc dl) {
DL = dl;
@@ -2240,6 +2402,11 @@ public:
return *this;
}
+ CallLoweringInfo &setIsPatchPoint(bool Value = true) {
+ IsPatchPoint = Value;
+ return *this;
+ }
+
ArgListTy &getArgs() {
return Args;
}
@@ -2324,9 +2491,9 @@ public:
/// all the time, e.g. i1 on x86-64. It is also not necessary for non-C
/// calling conventions. The frontend should handle this and include all of
/// the necessary information.
- virtual MVT getTypeForExtArgOrReturn(MVT VT,
+ virtual EVT getTypeForExtArgOrReturn(LLVMContext &Context, EVT VT,
ISD::NodeType /*ExtendKind*/) const {
- MVT MinVT = getRegisterType(MVT::i32);
+ EVT MinVT = getRegisterType(Context, MVT::i32);
return VT.bitsLT(MinVT) ? MinVT : VT;
}
@@ -2474,11 +2641,10 @@ public:
unsigned getMatchedOperand() const;
/// Copy constructor for copying from a ConstraintInfo.
- AsmOperandInfo(const InlineAsm::ConstraintInfo &info)
- : InlineAsm::ConstraintInfo(info),
- ConstraintType(TargetLowering::C_Unknown),
- CallOperandVal(nullptr), ConstraintVT(MVT::Other) {
- }
+ AsmOperandInfo(InlineAsm::ConstraintInfo Info)
+ : InlineAsm::ConstraintInfo(std::move(Info)),
+ ConstraintType(TargetLowering::C_Unknown), CallOperandVal(nullptr),
+ ConstraintVT(MVT::Other) {}
};
typedef std::vector<AsmOperandInfo> AsmOperandInfoVector;
@@ -2545,6 +2711,51 @@ public:
SDValue BuildUDIV(SDNode *N, const APInt &Divisor, SelectionDAG &DAG,
bool IsAfterLegalization,
std::vector<SDNode *> *Created) const;
+ virtual SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor,
+ SelectionDAG &DAG,
+ std::vector<SDNode *> *Created) const {
+ return SDValue();
+ }
+
+ /// Indicate whether this target prefers to combine the given number of FDIVs
+ /// with the same divisor.
+ virtual bool combineRepeatedFPDivisors(unsigned NumUsers) const {
+ return false;
+ }
+
+ /// Hooks for building estimates in place of slower divisions and square
+ /// roots.
+
+ /// Return a reciprocal square root estimate value for the input operand.
+ /// The RefinementSteps output is the number of Newton-Raphson refinement
+ /// iterations required to generate a sufficient (though not necessarily
+ /// IEEE-754 compliant) estimate for the value type.
+ /// The boolean UseOneConstNR output is used to select a Newton-Raphson
+ /// algorithm implementation that uses one constant or two constants.
+ /// A target may choose to implement its own refinement within this function.
+ /// If that's true, then return '0' as the number of RefinementSteps to avoid
+ /// any further refinement of the estimate.
+ /// An empty SDValue return means no estimate sequence can be created.
+ virtual SDValue getRsqrtEstimate(SDValue Operand,
+ DAGCombinerInfo &DCI,
+ unsigned &RefinementSteps,
+ bool &UseOneConstNR) const {
+ return SDValue();
+ }
+
+ /// Return a reciprocal estimate value for the input operand.
+ /// The RefinementSteps output is the number of Newton-Raphson refinement
+ /// iterations required to generate a sufficient (though not necessarily
+ /// IEEE-754 compliant) estimate for the value type.
+ /// A target may choose to implement its own refinement within this function.
+ /// If that's true, then return '0' as the number of RefinementSteps to avoid
+ /// any further refinement of the estimate.
+ /// An empty SDValue return means no estimate sequence can be created.
+ virtual SDValue getRecipEstimate(SDValue Operand,
+ DAGCombinerInfo &DCI,
+ unsigned &RefinementSteps) const {
+ return SDValue();
+ }
//===--------------------------------------------------------------------===//
// Legalization utility functions
@@ -2589,6 +2800,12 @@ public:
/// ARM 's' setting instructions.
virtual void
AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const;
+
+ /// If this function returns true, SelectionDAGBuilder emits a
+ /// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector.
+ virtual bool useLoadStackGuardNode() const {
+ return false;
+ }
};
/// Given an LLVM IR type and return type attributes, compute the return value
diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h
index 7c32a5e3d0ca..73bf56f018e9 100644
--- a/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/include/llvm/Target/TargetLoweringObjectFile.h
@@ -151,16 +151,10 @@ public:
return nullptr;
}
- /// \brief True if the section is atomized using the symbols in it.
- /// This is false if the section is not atomized at all (most ELF sections) or
- /// if it is atomized based on its contents (MachO' __TEXT,__cstring for
- /// example).
- virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const;
-
protected:
virtual const MCSection *
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
- Mangler &Mang, const TargetMachine &TM) const;
+ Mangler &Mang, const TargetMachine &TM) const = 0;
};
} // end namespace llvm
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index b263c571d9e6..a4f95c061283 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -24,7 +24,6 @@
namespace llvm {
class InstrItineraryData;
-class JITCodeEmitter;
class GlobalValue;
class Mangler;
class MCAsmInfo;
@@ -35,9 +34,7 @@ class Target;
class DataLayout;
class TargetLibraryInfo;
class TargetFrameLowering;
-class TargetInstrInfo;
class TargetIntrinsicInfo;
-class TargetJITInfo;
class TargetLowering;
class TargetPassConfig;
class TargetRegisterInfo;
@@ -47,6 +44,7 @@ class ScalarTargetTransformInfo;
class VectorTargetTransformInfo;
class formatted_raw_ostream;
class raw_ostream;
+class TargetLoweringObjectFile;
// The old pass manager infrastructure is hidden in a legacy namespace now.
namespace legacy {
@@ -87,47 +85,27 @@ protected: // Can only create subclasses.
unsigned RequireStructuredCFG : 1;
public:
+ mutable TargetOptions Options;
+
virtual ~TargetMachine();
const Target &getTarget() const { return TheTarget; }
- const StringRef getTargetTriple() const { return TargetTriple; }
- const StringRef getTargetCPU() const { return TargetCPU; }
- const StringRef getTargetFeatureString() const { return TargetFS; }
+ StringRef getTargetTriple() const { return TargetTriple; }
+ StringRef getTargetCPU() const { return TargetCPU; }
+ StringRef getTargetFeatureString() const { return TargetFS; }
/// getSubtargetImpl - virtual method implemented by subclasses that returns
/// a reference to that target's TargetSubtargetInfo-derived member variable.
virtual const TargetSubtargetInfo *getSubtargetImpl() const {
return nullptr;
}
-
- mutable TargetOptions Options;
-
- /// \brief Reset the target options based on the function's attributes.
- void resetTargetOptions(const MachineFunction *MF) const;
-
- // Interfaces to the major aspects of target machine information:
- //
- // -- Instruction opcode and operand information
- // -- Pipelines and scheduling information
- // -- Stack frame information
- // -- Selection DAG lowering information
- //
- // N.B. These objects may change during compilation. It's not safe to cache
- // them between functions.
- virtual const TargetInstrInfo *getInstrInfo() const { return nullptr; }
- virtual const TargetFrameLowering *getFrameLowering() const {
- return nullptr;
+ virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const {
+ return getSubtargetImpl();
}
- virtual const TargetLowering *getTargetLowering() const { return nullptr; }
- virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const {
+ virtual TargetLoweringObjectFile *getObjFileLowering() const {
return nullptr;
}
- virtual const DataLayout *getDataLayout() const { return nullptr; }
-
- /// getMCAsmInfo - Return target specific asm information.
- ///
- const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; }
/// getSubtarget - This method returns a pointer to the specified type of
/// TargetSubtargetInfo. In debug builds, it verifies that the object being
@@ -135,27 +113,23 @@ public:
template<typename STC> const STC &getSubtarget() const {
return *static_cast<const STC*>(getSubtargetImpl());
}
+ template <typename STC> const STC &getSubtarget(const Function *) const {
+ return *static_cast<const STC*>(getSubtargetImpl());
+ }
+
+ /// \brief 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;
- /// getRegisterInfo - If register information is available, return it. If
- /// not, return null. This is kept separate from RegInfo until RegInfo has
- /// details of graph coloring register allocation removed from it.
+ /// getMCAsmInfo - Return target specific asm information.
///
- virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; }
+ const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; }
/// getIntrinsicInfo - If intrinsic information is available, return it. If
/// not, return null.
///
- virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr;}
-
- /// getJITInfo - If this target supports a JIT, return information for it,
- /// otherwise return null.
- ///
- virtual TargetJITInfo *getJITInfo() { return nullptr; }
-
- /// getInstrItineraryData - Returns instruction itinerary data for the target
- /// or specific subtarget.
- ///
- virtual const InstrItineraryData *getInstrItineraryData() const {
+ virtual const TargetIntrinsicInfo *getIntrinsicInfo() const {
return nullptr;
}
@@ -233,18 +207,6 @@ public:
return true;
}
- /// addPassesToEmitMachineCode - Add passes to the specified pass manager to
- /// get machine code emitted. This uses a JITCodeEmitter object to handle
- /// actually outputting the machine code and resolving things like the address
- /// of functions. This method returns true if machine code emission is
- /// not supported.
- ///
- virtual bool addPassesToEmitMachineCode(PassManagerBase &,
- JITCodeEmitter &,
- bool /*DisableVerify*/ = true) {
- return true;
- }
-
/// addPassesToEmitMC - Add passes to the specified pass manager to get
/// machine code emitted with the MCJIT. This method returns true if machine
/// code is not supported. It fills the MCContext Ctx pointer which can be
@@ -291,15 +253,6 @@ public:
AnalysisID StartAfter = nullptr,
AnalysisID StopAfter = nullptr) override;
- /// addPassesToEmitMachineCode - Add passes to the specified pass manager to
- /// get machine code emitted. This uses a JITCodeEmitter object to handle
- /// actually outputting the machine code and resolving things like the address
- /// of functions. This method returns true if machine code emission is
- /// not supported.
- ///
- bool addPassesToEmitMachineCode(PassManagerBase &PM, JITCodeEmitter &MCE,
- bool DisableVerify = true) override;
-
/// addPassesToEmitMC - Add passes to the specified pass manager to get
/// machine code emitted with the MCJIT. This method returns true if machine
/// code is not supported. It fills the MCContext Ctx pointer which can be
@@ -307,14 +260,6 @@ public:
///
bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
raw_ostream &OS, bool DisableVerify = true) override;
-
- /// addCodeEmitter - This pass should be overridden by the target to add a
- /// code emitter, if supported. If this is not supported, 'true' should be
- /// returned.
- virtual bool addCodeEmitter(PassManagerBase &,
- JITCodeEmitter &) {
- return true;
- }
};
} // End llvm namespace
diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h
index abb3ecacaefd..afc22365eba7 100644
--- a/include/llvm/Target/TargetOpcodes.h
+++ b/include/llvm/Target/TargetOpcodes.h
@@ -104,7 +104,24 @@ enum {
/// support optimizations for dynamic languages (such as javascript) that
/// rewrite calls to runtimes with more efficient code sequences.
/// This also implies a stack map.
- PATCHPOINT = 18
+ PATCHPOINT = 18,
+
+ /// This pseudo-instruction loads the stack guard value. Targets which need
+ /// to prevent the stack guard value or address from being spilled to the
+ /// stack should override TargetLowering::emitLoadStackGuardNode and
+ /// additionally expand this pseudo after register allocation.
+ LOAD_STACK_GUARD = 19,
+
+ /// Call instruction with associated vm state for deoptimization and list
+ /// of live pointers for relocation by the garbage collector. It is
+ /// intended to support garbage collection with fully precise relocating
+ /// collectors and deoptimizations in either the callee or caller.
+ STATEPOINT = 20,
+
+ /// Instruction that records the offset of a function's frame allocation in a
+ /// label. Created by the llvm.frameallocate intrinsic. It has two arguments:
+ /// the symbol for the label and the frame index of the stack allocation.
+ FRAME_ALLOC = 21,
};
} // end namespace TargetOpcode
} // end namespace llvm
diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h
index 922fae54bb80..9ab8242578fd 100644
--- a/include/llvm/Target/TargetOptions.h
+++ b/include/llvm/Target/TargetOptions.h
@@ -50,6 +50,21 @@ namespace llvm {
};
}
+ namespace ThreadModel {
+ enum Model {
+ POSIX, // POSIX Threads
+ Single // Single Threaded Environment
+ };
+ }
+
+ enum class CFIntegrity {
+ Sub, // Use subtraction-based checks.
+ Ror, // Use rotation-based checks.
+ Add // Use addition-based checks. This depends on having
+ // sufficient alignment in the code and is usually not
+ // feasible.
+ };
+
class TargetOptions {
public:
TargetOptions()
@@ -63,9 +78,11 @@ namespace llvm {
EnableFastISel(false), PositionIndependentExecutable(false),
UseInitArray(false), DisableIntegratedAS(false),
CompressDebugSections(false), FunctionSections(false),
- DataSections(false), TrapUnreachable(false), TrapFuncName(""),
+ DataSections(false), TrapUnreachable(false), TrapFuncName(),
FloatABIType(FloatABI::Default),
- AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single) {}
+ AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
+ FCFI(false), ThreadModel(ThreadModel::POSIX),
+ CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs
/// option is specified on the command line, and should enable debugging
@@ -220,6 +237,28 @@ namespace llvm {
/// create for functions that have the jumptable attribute.
JumpTable::JumpTableType JTType;
+ /// FCFI - This flags controls whether or not forward-edge control-flow
+ /// integrity is applied.
+ bool FCFI;
+
+ /// ThreadModel - This flag specifies the type of threading model to assume
+ /// for things like atomics
+ ThreadModel::Model ThreadModel;
+
+ /// CFIType - This flag specifies the type of control-flow integrity check
+ /// to add as a preamble to indirect calls.
+ CFIntegrity CFIType;
+
+ /// CFIEnforcing - This flags controls whether or not CFI violations cause
+ /// the program to halt.
+ bool CFIEnforcing;
+
+ /// getCFIFuncName - If this returns a non-empty string, then this is the
+ /// name of the function that will be called for each CFI violation in
+ /// non-enforcing mode.
+ std::string CFIFuncName;
+ StringRef getCFIFuncName() const;
+
/// Machine level options.
MCTargetOptions MCOptions;
};
@@ -249,6 +288,12 @@ inline bool operator==(const TargetOptions &LHS,
ARE_EQUAL(TrapFuncName) &&
ARE_EQUAL(FloatABIType) &&
ARE_EQUAL(AllowFPOpFusion) &&
+ ARE_EQUAL(JTType) &&
+ ARE_EQUAL(FCFI) &&
+ ARE_EQUAL(ThreadModel) &&
+ ARE_EQUAL(CFIType) &&
+ ARE_EQUAL(CFIEnforcing) &&
+ ARE_EQUAL(CFIFuncName) &&
ARE_EQUAL(MCOptions);
#undef ARE_EQUAL
}
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 5dda8bd4b938..a7552565c938 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -18,7 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/MC/MCRegisterInfo.h"
#include <cassert>
@@ -45,6 +45,7 @@ public:
const vt_iterator VTs;
const uint32_t *SubClassMask;
const uint16_t *SuperRegIndices;
+ const unsigned LaneMask;
const sc_iterator SuperClasses;
ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&);
@@ -52,10 +53,6 @@ public:
///
unsigned getID() const { return MC->getID(); }
- /// getName() - Return the register class name for debugging.
- ///
- const char *getName() const { return MC->getName(); }
-
/// begin/end - Return all of the registers in this class.
///
iterator begin() const { return MC->begin(); }
@@ -101,9 +98,9 @@ public:
/// hasType - return true if this TargetRegisterClass has the ValueType vt.
///
- bool hasType(EVT vt) const {
+ bool hasType(MVT vt) const {
for(int i = 0; VTs[i] != MVT::Other; ++i)
- if (EVT(VTs[i]) == vt)
+ if (MVT(VTs[i]) == vt)
return true;
return false;
}
@@ -194,6 +191,13 @@ public:
ArrayRef<MCPhysReg> getRawAllocationOrder(const MachineFunction &MF) const {
return OrderFunc ? OrderFunc(MF) : makeArrayRef(begin(), getNumRegs());
}
+
+ /// Returns the combination of all lane masks of register in this class.
+ /// The lane masks of the registers are the combination of all lane masks
+ /// of their subregisters.
+ unsigned getLaneMask() const {
+ return LaneMask;
+ }
};
/// TargetRegisterInfoDesc - Extra information, not in MCRegisterDesc, about
@@ -306,7 +310,7 @@ public:
/// register of the given type, picking the most sub register class of
/// the right type that contains this physreg.
const TargetRegisterClass *
- getMinimalPhysRegClass(unsigned Reg, EVT VT = MVT::Other) const;
+ getMinimalPhysRegClass(unsigned Reg, MVT VT = MVT::Other) const;
/// getAllocatableClass - Return the maximal subclass of the given register
/// class that is alloctable, or NULL.
@@ -452,6 +456,11 @@ public:
/// used by register scavenger to determine what registers are free.
virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0;
+ /// Prior to adding the live-out mask to a stackmap or patchpoint
+ /// instruction, provide the target the opportunity to adjust it (mainly to
+ /// remove pseudo-registers that should be ignored).
+ virtual void adjustStackMapLiveOutMask(uint32_t *Mask) const { }
+
/// getMatchingSuperReg - Return a super-register of the specified register
/// Reg so its sub-register of index SubIdx is Reg.
unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx,
@@ -506,12 +515,31 @@ public:
return composeSubRegIndicesImpl(a, b);
}
+ /// Transforms a LaneMask computed for one subregister to the lanemask that
+ /// would have been computed when composing the subsubregisters with IdxA
+ /// first. @sa composeSubRegIndices()
+ unsigned composeSubRegIndexLaneMask(unsigned IdxA, unsigned LaneMask) const {
+ if (!IdxA)
+ return LaneMask;
+ return composeSubRegIndexLaneMaskImpl(IdxA, LaneMask);
+ }
+
+ /// Debugging helper: dump register in human readable form to dbgs() stream.
+ static void dumpReg(unsigned Reg, unsigned SubRegIndex = 0,
+ const TargetRegisterInfo* TRI = nullptr);
+
protected:
/// Overridden by TableGen in targets that have sub-registers.
virtual unsigned composeSubRegIndicesImpl(unsigned, unsigned) const {
llvm_unreachable("Target has no sub-registers");
}
+ /// Overridden by TableGen in targets that have sub-registers.
+ virtual unsigned
+ composeSubRegIndexLaneMaskImpl(unsigned, unsigned) const {
+ llvm_unreachable("Target has no sub-registers");
+ }
+
public:
/// getCommonSuperRegClass - Find a common super-register class if it exists.
///
@@ -561,6 +589,11 @@ public:
return RegClassBegin[i];
}
+ /// getRegClassName - Returns the name of the register class.
+ const char *getRegClassName(const TargetRegisterClass *Class) const {
+ return MCRegisterInfo::getRegClassName(Class->MC);
+ }
+
/// getCommonSubClass - find the largest common subclass of A and B. Return
/// NULL if there is no common subclass.
const TargetRegisterClass *
@@ -683,12 +716,6 @@ public:
/// (3) Bottom-up allocation is no longer guaranteed to optimally color.
virtual bool reverseLocalAssignment() const { return false; }
- /// Allow the target to override register assignment heuristics based on the
- /// live range size. If this returns false, then local live ranges are always
- /// assigned in order regardless of their size. This is a temporary hook for
- /// debugging downstream codegen failures exposed by regalloc.
- virtual bool mayOverrideLocalAssignment() const { return true; }
-
/// Allow the target to override the cost of using a callee-saved register for
/// the first time. Default value of 0 means we will use a callee-saved
/// register if it is available.
diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td
index 2d822de4ad69..907baa1b9b1f 100644
--- a/include/llvm/Target/TargetSelectionDAG.td
+++ b/include/llvm/Target/TargetSelectionDAG.td
@@ -162,6 +162,10 @@ def SDTBr : SDTypeProfile<0, 1, [ // br
SDTCisVT<0, OtherVT>
]>;
+def SDTBrCC : SDTypeProfile<0, 4, [ // brcc
+ SDTCisVT<0, OtherVT>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT>
+]>;
+
def SDTBrcond : SDTypeProfile<0, 2, [ // brcond
SDTCisInt<0>, SDTCisVT<1, OtherVT>
]>;
@@ -184,6 +188,14 @@ def SDTIStore : SDTypeProfile<1, 3, [ // indexed store
SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3>
]>;
+def SDTMaskedStore: SDTypeProfile<0, 3, [ // masked store
+ SDTCisPtrTy<0>, SDTCisVec<1>, SDTCisVec<2>
+]>;
+
+def SDTMaskedLoad: SDTypeProfile<1, 3, [ // masked load
+ SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameAs<0, 3>
+]>;
+
def SDTVecShuffle : SDTypeProfile<1, 2, [
SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>
]>;
@@ -369,6 +381,8 @@ def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>;
def frem : SDNode<"ISD::FREM" , SDTFPBinOp>;
def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>;
def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>;
+def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp>;
+def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp>;
def fgetsign : SDNode<"ISD::FGETSIGN" , SDTFPToIntOp>;
def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>;
def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>;
@@ -400,6 +414,7 @@ def select : SDNode<"ISD::SELECT" , SDTSelect>;
def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>;
def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>;
+def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>;
def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>;
def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>;
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
@@ -447,6 +462,11 @@ def atomic_load : SDNode<"ISD::ATOMIC_LOAD", SDTAtomicLoad,
def atomic_store : SDNode<"ISD::ATOMIC_STORE", SDTAtomicStore,
[SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad,
+ [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
+
// Do not use ld, st directly. Use load, extload, sextload, zextload, store,
// and truncst (see below).
def ld : SDNode<"ISD::LOAD" , SDTLoad,
diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h
index 78a2db183fb1..d1a3fcf4a50e 100644
--- a/include/llvm/Target/TargetSelectionDAGInfo.h
+++ b/include/llvm/Target/TargetSelectionDAGInfo.h
@@ -46,7 +46,7 @@ public:
/// more efficient than using a library call. This function can return a null
/// SDValue if the target declines to use custom code and a different
/// lowering strategy should be used.
- ///
+ ///
/// If AlwaysInline is true, the size is constant and the target should not
/// emit any calls and is strongly encouraged to attempt to emit inline code
/// even if it is beyond the usual threshold because this intrinsic is being
diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h
index 86e303e18348..4ff88d07bf27 100644
--- a/include/llvm/Target/TargetSubtargetInfo.h
+++ b/include/llvm/Target/TargetSubtargetInfo.h
@@ -14,17 +14,24 @@
#ifndef LLVM_TARGET_TARGETSUBTARGETINFO_H
#define LLVM_TARGET_TARGETSUBTARGETINFO_H
+#include "llvm/CodeGen/PBQPRAConstraint.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/CodeGen.h"
namespace llvm {
+class DataLayout;
class MachineFunction;
class MachineInstr;
class SDep;
class SUnit;
+class TargetFrameLowering;
+class TargetInstrInfo;
+class TargetLowering;
class TargetRegisterClass;
+class TargetRegisterInfo;
class TargetSchedModel;
+class TargetSelectionDAGInfo;
struct MachineSchedPolicy;
template <typename T> class SmallVectorImpl;
@@ -47,6 +54,38 @@ public:
virtual ~TargetSubtargetInfo();
+ // Interfaces to the major aspects of target machine information:
+ //
+ // -- Instruction opcode and operand information
+ // -- Pipelines and scheduling information
+ // -- Stack frame information
+ // -- Selection DAG lowering information
+ //
+ // N.B. These objects may change during compilation. It's not safe to cache
+ // them between functions.
+ virtual const TargetInstrInfo *getInstrInfo() const { return nullptr; }
+ virtual const TargetFrameLowering *getFrameLowering() const {
+ return nullptr;
+ }
+ virtual const TargetLowering *getTargetLowering() const { return nullptr; }
+ virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const {
+ return nullptr;
+ }
+ virtual const DataLayout *getDataLayout() const { return nullptr; }
+
+ /// getRegisterInfo - If register information is available, return it. If
+ /// not, return null. This is kept separate from RegInfo until RegInfo has
+ /// details of graph coloring register allocation removed from it.
+ ///
+ virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; }
+
+ /// getInstrItineraryData - Returns instruction itinerary data for the target
+ /// or specific subtarget.
+ ///
+ virtual const InstrItineraryData *getInstrItineraryData() const {
+ return nullptr;
+ }
+
/// Resolve a SchedClass at runtime, where SchedClass identifies an
/// MCSchedClassDesc with the isVariant property. This may return the ID of
/// another variant SchedClass, but repeated invocation must quickly terminate
@@ -74,7 +113,7 @@ public:
virtual bool enablePostMachineScheduler() const;
/// \brief True if the subtarget should run the atomic expansion pass.
- virtual bool enableAtomicExpandLoadLinked() const;
+ virtual bool enableAtomicExpand() const;
/// \brief Override generic scheduling policy within a region.
///
@@ -90,26 +129,26 @@ public:
// dependency.
virtual void adjustSchedDependency(SUnit *def, SUnit *use,
SDep& dep) const { }
-
+
// For use with PostRAScheduling: get the anti-dependence breaking that should
// be performed before post-RA scheduling.
virtual AntiDepBreakMode getAntiDepBreakMode() const {
return ANTIDEP_NONE;
}
-
+
// For use with PostRAScheduling: in CriticalPathRCs, return any register
// classes that should only be considered for anti-dependence breaking if they
// are on the critical path.
virtual void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {
return CriticalPathRCs.clear();
}
-
+
// For use with PostRAScheduling: get the minimum optimization level needed
// to enable post-RA scheduling.
virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const {
return CodeGenOpt::Default;
}
-
+
/// \brief True if the subtarget should run the local reassignment
/// heuristic of the register allocator.
/// This heuristic may be compile time intensive, \p OptLevel provides
@@ -123,9 +162,17 @@ public:
/// \brief Enable the use of the early if conversion pass.
virtual bool enableEarlyIfConversion() const { return false; }
- /// \brief Reset the features for the subtarget.
- virtual void resetSubtargetFeatures(const MachineFunction *MF) { }
+ /// \brief Return PBQPConstraint(s) for the target.
+ ///
+ /// Override to provide custom PBQP constraints.
+ virtual std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const {
+ return nullptr;
+ }
+ /// Enable tracking of subregister liveness in register allocator.
+ virtual bool enableSubRegLiveness() const {
+ return false;
+ }
};
} // End llvm namespace
diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h
index 50877d013702..b1426b4f45ca 100644
--- a/include/llvm/Transforms/IPO/PassManagerBuilder.h
+++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h
@@ -18,16 +18,17 @@
#include <vector>
namespace llvm {
-class TargetLibraryInfo;
class Pass;
+class TargetLibraryInfo;
+class TargetMachine;
// The old pass manager infrastructure is hidden in a legacy namespace now.
namespace legacy {
-class PassManagerBase;
class FunctionPassManager;
+class PassManagerBase;
}
-using legacy::PassManagerBase;
using legacy::FunctionPassManager;
+using legacy::PassManagerBase;
/// PassManagerBuilder - This class is used to set up a standard optimization
/// sequence for languages like C and C++, allowing some APIs to customize the
@@ -118,6 +119,11 @@ public:
bool LoopVectorize;
bool RerollLoops;
bool LoadCombine;
+ bool DisableGVNLoadPRE;
+ bool VerifyInput;
+ bool VerifyOutput;
+ bool StripDebug;
+ bool MergeFunctions;
private:
/// ExtensionList - This is list of all of the extensions that are registered.
@@ -135,6 +141,7 @@ public:
private:
void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const;
void addInitialAliasAnalysisPasses(PassManagerBase &PM) const;
+ void addLTOOptimizationPasses(PassManagerBase &PM);
public:
/// populateFunctionPassManager - This fills in the function pass manager,
@@ -144,8 +151,7 @@ public:
/// populateModulePassManager - This sets up the primary pass manager.
void populateModulePassManager(PassManagerBase &MPM);
- void populateLTOPassManager(PassManagerBase &PM, bool Internalize,
- bool RunInliner, bool DisableGVNLoadPRE = false);
+ void populateLTOPassManager(PassManagerBase &PM, TargetMachine *TM = nullptr);
};
/// Registers a function for adding a standard set of passes. This should be
diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h
index c6a339b0fd22..24e3ef783ee6 100644
--- a/include/llvm/Transforms/Instrumentation.h
+++ b/include/llvm/Transforms/Instrumentation.h
@@ -63,6 +63,18 @@ struct GCOVOptions {
ModulePass *createGCOVProfilerPass(const GCOVOptions &Options =
GCOVOptions::getDefault());
+/// Options for the frontend instrumentation based profiling pass.
+struct InstrProfOptions {
+ InstrProfOptions() : NoRedZone(false) {}
+
+ // Add the 'noredzone' attribute to added runtime library calls.
+ bool NoRedZone;
+};
+
+/// Insert frontend instrumentation based profiling.
+ModulePass *createInstrProfilingPass(
+ const InstrProfOptions &Options = InstrProfOptions());
+
// Insert AddressSanitizer (address sanity checking) instrumentation
FunctionPass *createAddressSanitizerFunctionPass();
ModulePass *createAddressSanitizerModulePass();
@@ -78,6 +90,9 @@ ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(),
void *(*getArgTLS)() = nullptr,
void *(*getRetValTLS)() = nullptr);
+// Insert SanitizerCoverage instrumentation.
+ModulePass *createSanitizerCoverageModulePass(int CoverageLevel);
+
#if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID)
inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile =
StringRef()) {
@@ -90,37 +105,6 @@ inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile =
// checking on loads, stores, and other memory intrinsics.
FunctionPass *createBoundsCheckingPass();
-/// createDebugIRPass - Enable interactive stepping through LLVM IR in LLDB (or
-/// GDB) and generate a file with the LLVM IR to be
-/// displayed in the debugger.
-///
-/// Existing debug metadata is preserved (but may be modified) in order to allow
-/// accessing variables in the original source. The line table and file
-/// information is modified to correspond to the lines in the LLVM IR. If
-/// Filename and Directory are empty, a file name is generated based on existing
-/// debug information. If no debug information is available, a temporary file
-/// name is generated.
-///
-/// @param HideDebugIntrinsics Omit debug intrinsics in emitted IR source file.
-/// @param HideDebugMetadata Omit debug metadata in emitted IR source file.
-/// @param Directory Embed this directory in the debug information.
-/// @param Filename Embed this file name in the debug information.
-ModulePass *createDebugIRPass(bool HideDebugIntrinsics,
- bool HideDebugMetadata,
- StringRef Directory = StringRef(),
- StringRef Filename = StringRef());
-
-/// createDebugIRPass - Enable interactive stepping through LLVM IR in LLDB
-/// (or GDB) with an existing IR file on disk. When creating
-/// a DebugIR pass with this function, no source file is
-/// output to disk and the existing one is unmodified. Debug
-/// metadata in the Module is created/updated to point to
-/// the existing textual IR file on disk.
-/// NOTE: If the IR file to be debugged is not on disk, use the version of this
-/// function with parameters in order to generate the file that will be
-/// seen by the debugger.
-ModulePass *createDebugIRPass();
-
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index 413134e51c7a..5dcd89948759 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -36,6 +36,13 @@ FunctionPass *createConstantPropagationPass();
//===----------------------------------------------------------------------===//
//
+// AlignmentFromAssumptions - Use assume intrinsics to set load/store
+// alignments.
+//
+FunctionPass *createAlignmentFromAssumptionsPass();
+
+//===----------------------------------------------------------------------===//
+//
// SCCP - Sparse conditional constant propagation.
//
FunctionPass *createSCCPPass();
@@ -199,16 +206,17 @@ FunctionPass *createReassociatePass();
//===----------------------------------------------------------------------===//
//
// JumpThreading - Thread control through mult-pred/multi-succ blocks where some
-// preds always go to some succ.
+// preds always go to some succ. Thresholds other than minus one override the
+// internal BB duplication default threshold.
//
-FunctionPass *createJumpThreadingPass();
+FunctionPass *createJumpThreadingPass(int Threshold = -1);
//===----------------------------------------------------------------------===//
//
// CFGSimplification - Merge basic blocks, eliminate unreachable blocks,
// simplify terminator instructions, etc...
//
-FunctionPass *createCFGSimplificationPass();
+FunctionPass *createCFGSimplificationPass(int Threshold = -1);
//===----------------------------------------------------------------------===//
//
@@ -387,7 +395,9 @@ FunctionPass *createAddDiscriminatorsPass();
//
// SeparateConstOffsetFromGEP - Split GEPs for better CSE
//
-FunctionPass *createSeparateConstOffsetFromGEPPass();
+FunctionPass *
+createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr,
+ bool LowerGEP = false);
//===----------------------------------------------------------------------===//
//
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index bcafda657c2b..19acf5b2db83 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -133,6 +133,11 @@ inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst,
}
}
+// SplitAllCriticalEdges - Loop over all of the edges in the CFG,
+// breaking critical edges as they are found. Pass P must not be NULL.
+// Returns the number of broken edges.
+unsigned SplitAllCriticalEdges(Function &F, Pass *P);
+
/// SplitEdge - Split the edge connecting specified block. Pass P must
/// not be NULL.
BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P);
diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h
index 1e407fb468e1..6387c166ec71 100644
--- a/include/llvm/Transforms/Utils/BuildLibCalls.h
+++ b/include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -115,20 +115,6 @@ namespace llvm {
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
const DataLayout *TD, const TargetLibraryInfo *TLI);
-
- /// SimplifyFortifiedLibCalls - Helper class for folding checked library
- /// calls (e.g. __strcpy_chk) into their unchecked counterparts.
- class SimplifyFortifiedLibCalls {
- protected:
- CallInst *CI;
- virtual void replaceCall(Value *With) = 0;
- virtual bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp,
- bool isString) const = 0;
-
- public:
- virtual ~SimplifyFortifiedLibCalls();
- bool fold(CallInst *CI, const DataLayout *TD, const TargetLibraryInfo *TLI);
- };
}
#endif
diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h
index bdf50ddf5cc6..6584abe822d8 100644
--- a/include/llvm/Transforms/Utils/Cloning.h
+++ b/include/llvm/Transforms/Utils/Cloning.h
@@ -43,6 +43,8 @@ class DataLayout;
class Loop;
class LoopInfo;
class AllocaInst;
+class AliasAnalysis;
+class AssumptionCacheTracker;
/// CloneModule - Return an exact copy of the specified module
///
@@ -157,13 +159,18 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
/// InlineFunction call, and records the auxiliary results produced by it.
class InlineFunctionInfo {
public:
- explicit InlineFunctionInfo(CallGraph *cg = nullptr, const DataLayout *DL = nullptr)
- : CG(cg), DL(DL) {}
+ explicit InlineFunctionInfo(CallGraph *cg = nullptr,
+ const DataLayout *DL = nullptr,
+ AliasAnalysis *AA = nullptr,
+ AssumptionCacheTracker *ACT = nullptr)
+ : CG(cg), DL(DL), AA(AA), ACT(ACT) {}
/// CG - If non-null, InlineFunction will update the callgraph to reflect the
/// changes it makes.
CallGraph *CG;
const DataLayout *DL;
+ AliasAnalysis *AA;
+ AssumptionCacheTracker *ACT;
/// StaticAllocas - InlineFunction fills this in with all static allocas that
/// get copied into the caller.
diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h
index 6b41e82dac73..3a96d955cac2 100644
--- a/include/llvm/Transforms/Utils/CodeExtractor.h
+++ b/include/llvm/Transforms/Utils/CodeExtractor.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TRANSFORMS_UTILS_CODE_EXTRACTOR_H
-#define LLVM_TRANSFORMS_UTILS_CODE_EXTRACTOR_H
+#ifndef LLVM_TRANSFORMS_UTILS_CODEEXTRACTOR_H
+#define LLVM_TRANSFORMS_UTILS_CODEEXTRACTOR_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SetVector.h"
diff --git a/include/llvm/Transforms/Utils/CtorUtils.h b/include/llvm/Transforms/Utils/CtorUtils.h
index 81e7b951c252..63e564dcb87a 100644
--- a/include/llvm/Transforms/Utils/CtorUtils.h
+++ b/include/llvm/Transforms/Utils/CtorUtils.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H
-#define LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H
+#ifndef LLVM_TRANSFORMS_UTILS_CTORUTILS_H
+#define LLVM_TRANSFORMS_UTILS_CTORUTILS_H
#include "llvm/ADT/STLExtras.h"
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index c0c690664a9c..14844117f44f 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -34,12 +34,14 @@ class Value;
class Pass;
class PHINode;
class AllocaInst;
+class AssumptionCache;
class ConstantExpr;
class DataLayout;
class TargetLibraryInfo;
class TargetTransformInfo;
class DIBuilder;
class AliasAnalysis;
+class DominatorTree;
template<typename T> class SmallVectorImpl;
@@ -136,7 +138,8 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB);
/// the basic block that was pointed to.
///
bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
- const DataLayout *TD = nullptr);
+ unsigned BonusInstThreshold, const DataLayout *TD = nullptr,
+ AssumptionCache *AC = nullptr);
/// FlatternCFG - This function is used to flatten a CFG. For
/// example, it uses parallel-and and parallel-or mode to collapse
@@ -148,7 +151,8 @@ bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr);
/// and if a predecessor branches to us and one of our successors, fold the
/// setcc into the predecessor and use logical operations to pick the right
/// destination.
-bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr);
+bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr,
+ unsigned BonusInstThreshold = 1);
/// DemoteRegToStack - This function takes a virtual register computed by an
/// Instruction and replaces it with a slot in the stack frame, allocated via
@@ -170,12 +174,18 @@ AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = nullptr);
/// and it is more than the alignment of the ultimate object, see if we can
/// increase the alignment of the ultimate object, making this check succeed.
unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign,
- const DataLayout *TD = nullptr);
+ const DataLayout *TD = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
/// getKnownAlignment - Try to infer an alignment for the specified pointer.
static inline unsigned getKnownAlignment(Value *V,
- const DataLayout *TD = nullptr) {
- return getOrEnforceKnownAlignment(V, 0, TD);
+ const DataLayout *TD = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr) {
+ return getOrEnforceKnownAlignment(V, 0, TD, AC, CxtI, DT);
}
/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the
@@ -275,6 +285,11 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
/// Returns true if any basic block was removed.
bool removeUnreachableBlocks(Function &F);
+/// \brief Combine the metadata of two instructions so that K can replace J
+///
+/// Metadata not listed as known via KnownIDs is removed
+void combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsigned> KnownIDs);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h
index 7e3a74aae93c..f315adc49d15 100644
--- a/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/include/llvm/Transforms/Utils/LoopUtils.h
@@ -16,6 +16,7 @@
namespace llvm {
class AliasAnalysis;
+class AssumptionCache;
class BasicBlock;
class DataLayout;
class DominatorTree;
@@ -34,7 +35,8 @@ BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P);
/// passed into it.
bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP,
AliasAnalysis *AA = nullptr, ScalarEvolution *SE = nullptr,
- const DataLayout *DL = nullptr);
+ const DataLayout *DL = nullptr,
+ AssumptionCache *AC = nullptr);
/// \brief Put loop into LCSSA form.
///
@@ -47,7 +49,8 @@ bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP,
/// If ScalarEvolution is passed in, it will be preserved.
///
/// Returns true if any modifications are made to the loop.
-bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr);
+bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI,
+ ScalarEvolution *SE = nullptr);
/// \brief Put a loop nest into LCSSA form.
///
@@ -58,7 +61,7 @@ bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr);
/// If ScalarEvolution is passed in, it will be preserved.
///
/// Returns true if any modifications are made to the loop.
-bool formLCSSARecursively(Loop &L, DominatorTree &DT,
+bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI,
ScalarEvolution *SE = nullptr);
}
diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h
index 98a19ed426ac..16904f16e369 100644
--- a/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -20,7 +20,7 @@ class Module;
class Function;
class GlobalValue;
class GlobalVariable;
-template <class PtrType, unsigned SmallSize> class SmallPtrSet;
+template <class PtrType> class SmallPtrSetImpl;
/// Append F to the list of global ctors of module M with the given Priority.
/// This wraps the function in the appropriate structure and stores it along
@@ -34,7 +34,7 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority);
/// \brief 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(Module &M,
- SmallPtrSet<GlobalValue *, 8> &Set,
+ SmallPtrSetImpl<GlobalValue *> &Set,
bool CompilerUsed);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h
index c83fedb0e2ca..d0602bf47c92 100644
--- a/include/llvm/Transforms/Utils/PromoteMemToReg.h
+++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h
@@ -22,6 +22,7 @@ namespace llvm {
class AllocaInst;
class DominatorTree;
class AliasSetTracker;
+class AssumptionCache;
/// \brief Return true if this alloca is legal for promotion.
///
@@ -41,7 +42,8 @@ bool isAllocaPromotable(const AllocaInst *AI);
/// If AST is specified, the specified tracker is updated to reflect changes
/// made to the IR.
void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT,
- AliasSetTracker *AST = nullptr);
+ AliasSetTracker *AST = nullptr,
+ AssumptionCache *AC = nullptr);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index a2a5f9a45601..d2f096fd1efd 100644
--- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -15,40 +15,149 @@
#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
#define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/IRBuilder.h"
+
namespace llvm {
- class Value;
- class CallInst;
- class DataLayout;
- class Instruction;
- class TargetLibraryInfo;
- class LibCallSimplifierImpl;
-
- /// LibCallSimplifier - This class implements a collection of optimizations
- /// that replace well formed calls to library functions with a more optimal
- /// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'.
- class LibCallSimplifier {
- /// Impl - A pointer to the actual implementation of the library call
- /// simplifier.
- LibCallSimplifierImpl *Impl;
-
- public:
- LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI,
- bool UnsafeFPShrink);
- virtual ~LibCallSimplifier();
-
- /// optimizeCall - 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. Note that the returned value may
- /// be equal to the instruction being optimized. In this case all
- /// other instructions that use the given instruction were modified
- /// and the given instruction is dead.
- Value *optimizeCall(CallInst *CI);
-
- /// replaceAllUsesWith - This method is used when the library call
- /// simplifier needs to replace instructions other than the library
- /// call being modified.
- virtual void replaceAllUsesWith(Instruction *I, Value *With) const;
- };
+class Value;
+class CallInst;
+class DataLayout;
+class Instruction;
+class TargetLibraryInfo;
+class BasicBlock;
+class Function;
+
+/// \brief This class implements simplifications for calls to fortified library
+/// functions (__st*cpy_chk, __memcpy_chk, __memmove_chk, __memset_chk), to,
+/// when possible, replace them with their non-checking counterparts.
+/// Other optimizations can also be done, but it's possible to disable them and
+/// only simplify needless use of the checking versions (when the object size
+/// is unknown) by passing true for OnlyLowerUnknownSize.
+class FortifiedLibCallSimplifier {
+private:
+ const DataLayout *DL;
+ const TargetLibraryInfo *TLI;
+ bool OnlyLowerUnknownSize;
+
+public:
+ FortifiedLibCallSimplifier(const DataLayout *DL, const TargetLibraryInfo *TLI,
+ bool OnlyLowerUnknownSize = false);
+
+ /// \brief Take the given call instruction and return a more
+ /// optimal value to replace the instruction with or 0 if a more
+ /// optimal form can't be found.
+ /// The call must not be an indirect call.
+ Value *optimizeCall(CallInst *CI);
+
+private:
+ Value *optimizeMemCpyChk(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemMoveChk(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrCpyChk(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrNCpyChk(CallInst *CI, IRBuilder<> &B);
+
+ /// \brief Checks whether the call \p CI to a fortified libcall is foldable
+ /// to the non-fortified version.
+ bool isFortifiedCallFoldable(CallInst *CI, unsigned ObjSizeOp,
+ unsigned SizeOp, bool isString);
+};
+
+/// LibCallSimplifier - This class implements a collection of optimizations
+/// that replace well formed calls to library functions with a more optimal
+/// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'.
+class LibCallSimplifier {
+private:
+ FortifiedLibCallSimplifier FortifiedSimplifier;
+ const DataLayout *DL;
+ const TargetLibraryInfo *TLI;
+ bool UnsafeFPShrink;
+
+protected:
+ ~LibCallSimplifier() {}
+
+public:
+ LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI);
+
+ /// optimizeCall - 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. Note that the returned value may
+ /// be equal to the instruction being optimized. In this case all
+ /// other instructions that use the given instruction were modified
+ /// and the given instruction is dead.
+ /// The call must not be an indirect call.
+ Value *optimizeCall(CallInst *CI);
+
+ /// replaceAllUsesWith - This method is used when the library call
+ /// simplifier needs to replace instructions other than the library
+ /// call being modified.
+ virtual void replaceAllUsesWith(Instruction *I, Value *With) const;
+
+private:
+ // String and Memory Library Call Optimizations
+ Value *optimizeStrCat(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrNCat(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrChr(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrRChr(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrCmp(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrNCmp(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrCpy(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStpCpy(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrNCpy(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrLen(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrPBrk(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrTo(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrSpn(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrCSpn(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B);
+ // Wrapper for all String/Memory Library Call Optimizations
+ Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B);
+
+ // Math Library Optimizations
+ Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B, bool CheckRetType);
+ Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeCos(CallInst *CI, IRBuilder<> &B);
+ Value *optimizePow(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeExp2(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeFabs(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B);
+
+ // Integer Library Call Optimizations
+ Value *optimizeFFS(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeAbs(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeIsDigit(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeIsAscii(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeToAscii(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 *optimizeFPrintF(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B);
+ Value *optimizePuts(CallInst *CI, IRBuilder<> &B);
+
+ // Helper methods
+ Value *emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B);
+ void classifyArgUse(Value *Val, BasicBlock *BB, bool IsFloat,
+ SmallVectorImpl<CallInst *> &SinCalls,
+ SmallVectorImpl<CallInst *> &CosCalls,
+ SmallVectorImpl<CallInst *> &SinCosCalls);
+ void replaceTrigInsts(SmallVectorImpl<CallInst *> &Calls, Value *Res);
+ Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeSPrintFString(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeFPrintFString(CallInst *CI, IRBuilder<> &B);
+
+ /// hasFloatVersion - Checks if there is a float version of the specified
+ /// function by checking for an existing function with name FuncName + f
+ bool hasFloatVersion(StringRef FuncName);
+};
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h
new file mode 100644
index 000000000000..af7937265795
--- /dev/null
+++ b/include/llvm/Transforms/Utils/SymbolRewriter.h
@@ -0,0 +1,155 @@
+//===-- SymbolRewriter.h - Symbol Rewriting Pass ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the prototypes and definitions related to the Symbol
+// Rewriter pass.
+//
+// The Symbol Rewriter pass takes a set of rewrite descriptors which define
+// transformations for symbol names. These can be either single name to name
+// trnsformation or more broad regular expression based transformations.
+//
+// All the functions are re-written at the IR level. The Symbol Rewriter itself
+// is exposed as a module level pass. All symbols at the module level are
+// iterated. For any matching symbol, the requested transformation is applied,
+// updating references to it as well (a la RAUW). The resulting binary will
+// only contain the rewritten symbols.
+//
+// By performing this operation in the compiler, we are able to catch symbols
+// that would otherwise not be possible to catch (e.g. inlined symbols).
+//
+// This makes it possible to cleanly transform symbols without resorting to
+// overly-complex macro tricks and the pre-processor. An example of where this
+// is useful is the sanitizers where we would like to intercept a well-defined
+// set of functions across the module.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H
+#define LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H
+
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/IR/Module.h"
+
+namespace llvm {
+class MemoryBuffer;
+
+namespace yaml {
+class KeyValueNode;
+class MappingNode;
+class ScalarNode;
+class Stream;
+}
+
+namespace SymbolRewriter {
+/// The basic entity representing a rewrite operation. It serves as the base
+/// class for any rewrite descriptor. It has a certain set of specializations
+/// which describe a particular rewrite.
+///
+/// The RewriteMapParser can be used to parse a mapping file that provides the
+/// mapping for rewriting the symbols. The descriptors individually describe
+/// whether to rewrite a function, global variable, or global alias. Each of
+/// these can be selected either by explicitly providing a name for the ones to
+/// be rewritten or providing a (posix compatible) regular expression that will
+/// select the symbols to rewrite. This descriptor list is passed to the
+/// SymbolRewriter pass.
+class RewriteDescriptor : public ilist_node<RewriteDescriptor> {
+ RewriteDescriptor(const RewriteDescriptor &) LLVM_DELETED_FUNCTION;
+
+ const RewriteDescriptor &
+ operator=(const RewriteDescriptor &) LLVM_DELETED_FUNCTION;
+
+public:
+ enum class Type {
+ Invalid, /// invalid
+ Function, /// function - descriptor rewrites a function
+ GlobalVariable, /// global variable - descriptor rewrites a global variable
+ NamedAlias, /// named alias - descriptor rewrites a global alias
+ };
+
+ virtual ~RewriteDescriptor() {}
+
+ Type getType() const { return Kind; }
+
+ virtual bool performOnModule(Module &M) = 0;
+
+protected:
+ explicit RewriteDescriptor(Type T) : Kind(T) {}
+
+private:
+ const Type Kind;
+};
+
+typedef iplist<RewriteDescriptor> RewriteDescriptorList;
+
+class RewriteMapParser {
+public:
+ RewriteMapParser() {}
+ ~RewriteMapParser() {}
+
+ bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors);
+
+private:
+ bool parse(std::unique_ptr<MemoryBuffer> &MapFile, RewriteDescriptorList *DL);
+ bool parseEntry(yaml::Stream &Stream, yaml::KeyValueNode &Entry,
+ RewriteDescriptorList *DL);
+ bool parseRewriteFunctionDescriptor(yaml::Stream &Stream,
+ yaml::ScalarNode *Key,
+ yaml::MappingNode *Value,
+ RewriteDescriptorList *DL);
+ bool parseRewriteGlobalVariableDescriptor(yaml::Stream &Stream,
+ yaml::ScalarNode *Key,
+ yaml::MappingNode *Value,
+ RewriteDescriptorList *DL);
+ bool parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
+ yaml::MappingNode *V,
+ RewriteDescriptorList *DL);
+};
+}
+
+template <>
+struct ilist_traits<SymbolRewriter::RewriteDescriptor>
+ : public ilist_default_traits<SymbolRewriter::RewriteDescriptor> {
+ mutable ilist_half_node<SymbolRewriter::RewriteDescriptor> Sentinel;
+
+public:
+ // createSentinel is used to get a reference to a node marking the end of
+ // the list. Because the sentinel is relative to this instance, use a
+ // non-static method.
+ SymbolRewriter::RewriteDescriptor *createSentinel() const {
+ // since i[p] lists always publicly derive from the corresponding
+ // traits, placing a data member in this class will augment the
+ // i[p]list. Since the NodeTy is expected to publicly derive from
+ // ilist_node<NodeTy>, there is a legal viable downcast from it to
+ // NodeTy. We use this trick to superpose i[p]list with a "ghostly"
+ // NodeTy, which becomes the sentinel. Dereferencing the sentinel is
+ // forbidden (save the ilist_node<NodeTy>) so no one will ever notice
+ // the superposition.
+ return static_cast<SymbolRewriter::RewriteDescriptor *>(&Sentinel);
+ }
+ void destroySentinel(SymbolRewriter::RewriteDescriptor *) {}
+
+ SymbolRewriter::RewriteDescriptor *provideInitialHead() const {
+ return createSentinel();
+ }
+
+ SymbolRewriter::RewriteDescriptor *
+ ensureHead(SymbolRewriter::RewriteDescriptor *&) const {
+ return createSentinel();
+ }
+
+ static void noteHead(SymbolRewriter::RewriteDescriptor *,
+ SymbolRewriter::RewriteDescriptor *) {}
+};
+
+ModulePass *createRewriteSymbolsPass();
+ModulePass *createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &);
+}
+
+#endif
diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h
index 7ac2572f9af3..550292f6b7a3 100644
--- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h
+++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h
@@ -15,8 +15,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H
-#define LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H
+#ifndef LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H
+#define LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H
#include "llvm/Pass.h"
diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h
index aaadd7d48bdc..807367cd4b12 100644
--- a/include/llvm/Transforms/Utils/UnrollLoop.h
+++ b/include/llvm/Transforms/Utils/UnrollLoop.h
@@ -18,6 +18,7 @@
namespace llvm {
+class AssumptionCache;
class Loop;
class LoopInfo;
class LPPassManager;
@@ -25,7 +26,7 @@ class Pass;
bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime,
unsigned TripMultiple, LoopInfo *LI, Pass *PP,
- LPPassManager *LPM);
+ LPPassManager *LPM, AssumptionCache *AC);
bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,
LPPassManager* LPM);
diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h
index 5774763575d3..047ab818711b 100644
--- a/include/llvm/Transforms/Utils/ValueMapper.h
+++ b/include/llvm/Transforms/Utils/ValueMapper.h
@@ -71,20 +71,23 @@ namespace llvm {
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
+ Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+
+ /// MapMetadata - provide versions that preserve type safety for MDNodes.
+ MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
- /// MapValue - provide versions that preserve type safety for MDNode and
- /// Constants.
- inline MDNode *MapValue(const MDNode *V, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr) {
- return cast<MDNode>(MapValue((const Value*)V, VM, Flags, TypeMapper,
- Materializer));
- }
+ /// MapValue - provide versions that preserve type safety for Constants.
inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = nullptr,
diff --git a/include/llvm/Transforms/Utils/VectorUtils.h b/include/llvm/Transforms/Utils/VectorUtils.h
index 44a7149eee98..b47acf517b37 100644
--- a/include/llvm/Transforms/Utils/VectorUtils.h
+++ b/include/llvm/Transforms/Utils/VectorUtils.h
@@ -14,8 +14,8 @@
#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
-#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/Target/TargetLibraryInfo.h"
namespace llvm {
@@ -36,6 +36,8 @@ static inline bool isTriviallyVectorizable(Intrinsic::ID ID) {
case Intrinsic::log10:
case Intrinsic::log2:
case Intrinsic::fabs:
+ case Intrinsic::minnum:
+ case Intrinsic::maxnum:
case Intrinsic::copysign:
case Intrinsic::floor:
case Intrinsic::ceil:
@@ -99,7 +101,7 @@ getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) {
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
Intrinsic::ID ID = II->getIntrinsicID();
if (isTriviallyVectorizable(ID) || ID == Intrinsic::lifetime_start ||
- ID == Intrinsic::lifetime_end)
+ ID == Intrinsic::lifetime_end || ID == Intrinsic::assume)
return ID;
else
return Intrinsic::not_intrinsic;
@@ -153,6 +155,14 @@ getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) {
case LibFunc::fabsf:
case LibFunc::fabsl:
return checkUnaryFloatSignature(*CI, Intrinsic::fabs);
+ case LibFunc::fmin:
+ case LibFunc::fminf:
+ case LibFunc::fminl:
+ return checkBinaryFloatSignature(*CI, Intrinsic::minnum);
+ case LibFunc::fmax:
+ case LibFunc::fmaxf:
+ case LibFunc::fmaxl:
+ return checkBinaryFloatSignature(*CI, Intrinsic::maxnum);
case LibFunc::copysign:
case LibFunc::copysignf:
case LibFunc::copysignl:
diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap
index 1790a7242e5b..61f65510c4ea 100644
--- a/include/llvm/module.modulemap
+++ b/include/llvm/module.modulemap
@@ -75,8 +75,9 @@ module LLVM_IR {
exclude header "IR/PassManager.h"
exclude header "IR/LegacyPassManager.h"
- // Exclude this; it's intended for (repeated) textual inclusion.
- exclude header "IR/Instruction.def"
+ // These are intended for (repeated) textual inclusion.
+ textual header "IR/Instruction.def"
+ textual header "IR/Metadata.def"
}
module LLVM_LegacyPassManager {
@@ -112,7 +113,12 @@ module LLVM_MC {
exclude header "MC/MCTargetOptionsCommandFlags.h"
}
-module LLVM_Object { requires cplusplus umbrella "Object" module * { export * } }
+module LLVM_Object {
+ requires cplusplus
+ umbrella "Object"
+ module * { export * }
+}
+
module LLVM_Option { requires cplusplus umbrella "Option" module * { export * } }
module LLVM_TableGen { requires cplusplus umbrella "TableGen" module * { export * } }
@@ -148,9 +154,6 @@ module LLVM_Utils {
exclude header "Support/AIXDataTypesFix.h"
// Exclude this; it's fundamentally non-modular.
- exclude header "Support/Debug.h"
-
- // Exclude this; it's fundamentally non-modular.
exclude header "Support/PluginLoader.h"
// Exclude this; it's a weirdly-factored part of llvm-gcov and conflicts
@@ -159,6 +162,18 @@ module LLVM_Utils {
// FIXME: Mislayered?
exclude header "Support/TargetRegistry.h"
+
+ // These are intended for textual inclusion.
+ textual header "Support/ELFRelocs/AArch64.def"
+ textual header "Support/ELFRelocs/ARM.def"
+ textual header "Support/ELFRelocs/Hexagon.def"
+ textual header "Support/ELFRelocs/i386.def"
+ textual header "Support/ELFRelocs/Mips.def"
+ textual header "Support/ELFRelocs/PowerPC64.def"
+ textual header "Support/ELFRelocs/PowerPC.def"
+ textual header "Support/ELFRelocs/Sparc.def"
+ textual header "Support/ELFRelocs/SystemZ.def"
+ textual header "Support/ELFRelocs/x86_64.def"
}
}