aboutsummaryrefslogtreecommitdiff
path: root/include/llvm
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-05-27 18:44:32 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-05-27 18:44:32 +0000
commit5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch)
treea6140557876943cdd800ee997c9317283394b22c /include/llvm
parentf03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff)
downloadsrc-5a5ac124e1efaf208671f01c46edb15f29ed2a0b.tar.gz
src-5a5ac124e1efaf208671f01c46edb15f29ed2a0b.zip
Notes
Diffstat (limited to 'include/llvm')
-rw-r--r--include/llvm/ADT/APFloat.h10
-rw-r--r--include/llvm/ADT/APInt.h21
-rw-r--r--include/llvm/ADT/APSInt.h73
-rw-r--r--include/llvm/ADT/ArrayRef.h86
-rw-r--r--include/llvm/ADT/BitVector.h41
-rw-r--r--include/llvm/ADT/DeltaAlgorithm.h2
-rw-r--r--include/llvm/ADT/DenseMap.h107
-rw-r--r--include/llvm/ADT/DepthFirstIterator.h54
-rw-r--r--include/llvm/ADT/EpochTracker.h99
-rw-r--r--include/llvm/ADT/EquivalenceClasses.h3
-rw-r--r--include/llvm/ADT/FoldingSet.h88
-rw-r--r--include/llvm/ADT/Hashing.h106
-rw-r--r--include/llvm/ADT/ImmutableList.h4
-rw-r--r--include/llvm/ADT/ImmutableMap.h62
-rw-r--r--include/llvm/ADT/ImmutableSet.h174
-rw-r--r--include/llvm/ADT/IndexedMap.h7
-rw-r--r--include/llvm/ADT/IntervalMap.h20
-rw-r--r--include/llvm/ADT/IntrusiveRefCntPtr.h13
-rw-r--r--include/llvm/ADT/MapVector.h5
-rw-r--r--include/llvm/ADT/None.h5
-rw-r--r--include/llvm/ADT/Optional.h49
-rw-r--r--include/llvm/ADT/PointerUnion.h80
-rw-r--r--include/llvm/ADT/PostOrderIterator.h86
-rw-r--r--include/llvm/ADT/STLExtras.h367
-rw-r--r--include/llvm/ADT/ScopedHashTable.h4
-rw-r--r--include/llvm/ADT/SmallBitVector.h24
-rw-r--r--include/llvm/ADT/SmallPtrSet.h4
-rw-r--r--include/llvm/ADT/SmallVector.h98
-rw-r--r--include/llvm/ADT/SparseBitVector.h34
-rw-r--r--include/llvm/ADT/SparseMultiSet.h4
-rw-r--r--include/llvm/ADT/SparseSet.h4
-rw-r--r--include/llvm/ADT/StringMap.h2
-rw-r--r--include/llvm/ADT/StringRef.h9
-rw-r--r--include/llvm/ADT/TinyPtrVector.h23
-rw-r--r--include/llvm/ADT/Triple.h47
-rw-r--r--include/llvm/ADT/Twine.h104
-rw-r--r--include/llvm/ADT/edit_distance.h2
-rw-r--r--include/llvm/ADT/ilist.h12
-rw-r--r--include/llvm/ADT/iterator.h4
-rw-r--r--include/llvm/Analysis/AliasAnalysis.h50
-rw-r--r--include/llvm/Analysis/AliasSetTracker.h18
-rw-r--r--include/llvm/Analysis/AssumptionCache.h43
-rw-r--r--include/llvm/Analysis/BlockFrequencyInfo.h2
-rw-r--r--include/llvm/Analysis/BlockFrequencyInfoImpl.h3
-rw-r--r--include/llvm/Analysis/CGSCCPassManager.h5
-rw-r--r--include/llvm/Analysis/CallGraph.h6
-rw-r--r--include/llvm/Analysis/ConstantFolding.h30
-rw-r--r--include/llvm/Analysis/ConstantsScanner.h93
-rw-r--r--include/llvm/Analysis/DependenceAnalysis.h13
-rw-r--r--include/llvm/Analysis/DominanceFrontierImpl.h4
-rw-r--r--include/llvm/Analysis/FunctionTargetTransformInfo.h49
-rw-r--r--include/llvm/Analysis/IVUsers.h1
-rw-r--r--include/llvm/Analysis/InlineCost.h8
-rw-r--r--include/llvm/Analysis/InstructionSimplify.h80
-rw-r--r--include/llvm/Analysis/IntervalIterator.h33
-rw-r--r--include/llvm/Analysis/IteratedDominanceFrontier.h96
-rw-r--r--include/llvm/Analysis/JumpInstrTableInfo.h2
-rw-r--r--include/llvm/Analysis/LazyValueInfo.h7
-rw-r--r--include/llvm/Analysis/LibCallAliasAnalysis.h12
-rw-r--r--include/llvm/Analysis/LibCallSemantics.h47
-rw-r--r--include/llvm/Analysis/Loads.h3
-rw-r--r--include/llvm/Analysis/LoopAccessAnalysis.h552
-rw-r--r--include/llvm/Analysis/LoopInfo.h219
-rw-r--r--include/llvm/Analysis/LoopInfoImpl.h56
-rw-r--r--include/llvm/Analysis/MemoryBuiltins.h21
-rw-r--r--include/llvm/Analysis/MemoryDependenceAnalysis.h16
-rw-r--r--include/llvm/Analysis/PHITransAddr.h8
-rw-r--r--include/llvm/Analysis/Passes.h17
-rw-r--r--include/llvm/Analysis/PostDominators.h2
-rw-r--r--include/llvm/Analysis/RegionInfo.h18
-rw-r--r--include/llvm/Analysis/RegionInfoImpl.h8
-rw-r--r--include/llvm/Analysis/RegionIterator.h20
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h98
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpander.h129
-rw-r--r--include/llvm/Analysis/SparsePropagation.h4
-rw-r--r--include/llvm/Analysis/TargetFolder.h29
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.def1029
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.h328
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h670
-rw-r--r--include/llvm/Analysis/TargetTransformInfoImpl.h441
-rw-r--r--include/llvm/Analysis/ValueTracking.h157
-rw-r--r--include/llvm/Bitcode/BitCodes.h4
-rw-r--r--include/llvm/Bitcode/BitcodeWriterPass.h14
-rw-r--r--include/llvm/Bitcode/BitstreamReader.h26
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h41
-rw-r--r--include/llvm/Bitcode/ReaderWriter.h21
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h117
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h767
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h33
-rw-r--r--include/llvm/CodeGen/CommandFlags.h114
-rw-r--r--include/llvm/CodeGen/DIE.h201
-rw-r--r--include/llvm/CodeGen/DwarfStringPoolEntry.h51
-rw-r--r--include/llvm/CodeGen/ForwardControlFlowIntegrity.h122
-rw-r--r--include/llvm/CodeGen/FunctionLoweringInfo.h18
-rw-r--r--include/llvm/CodeGen/GCMetadata.h325
-rw-r--r--include/llvm/CodeGen/GCMetadataPrinter.h56
-rw-r--r--include/llvm/CodeGen/GCStrategy.h265
-rw-r--r--include/llvm/CodeGen/GCs.h35
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h37
-rw-r--r--include/llvm/CodeGen/JumpInstrTables.h105
-rw-r--r--include/llvm/CodeGen/LatencyPriorityQueue.h2
-rw-r--r--include/llvm/CodeGen/LexicalScopes.h58
-rw-r--r--include/llvm/CodeGen/LinkAllCodegenComponents.h1
-rw-r--r--include/llvm/CodeGen/LiveInterval.h52
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h23
-rw-r--r--include/llvm/CodeGen/LiveIntervalUnion.h4
-rw-r--r--include/llvm/CodeGen/LivePhysRegs.h19
-rw-r--r--include/llvm/CodeGen/LiveRangeEdit.h2
-rw-r--r--include/llvm/CodeGen/LiveStackAnalysis.h3
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h32
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequencyInfo.h2
-rw-r--r--include/llvm/CodeGen/MachineDominanceFrontier.h4
-rw-r--r--include/llvm/CodeGen/MachineDominators.h76
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h34
-rw-r--r--include/llvm/CodeGen/MachineFunction.h11
-rw-r--r--include/llvm/CodeGen/MachineFunctionAnalysis.h2
-rw-r--r--include/llvm/CodeGen/MachineInstr.h356
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h15
-rw-r--r--include/llvm/CodeGen/MachineLoopInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineMemOperand.h18
-rw-r--r--include/llvm/CodeGen/MachineModuleInfo.h69
-rw-r--r--include/llvm/CodeGen/MachineModuleInfoImpls.h16
-rw-r--r--include/llvm/CodeGen/MachineOperand.h10
-rw-r--r--include/llvm/CodeGen/MachinePassRegistry.h9
-rw-r--r--include/llvm/CodeGen/MachinePostDominators.h2
-rw-r--r--include/llvm/CodeGen/MachineRegionInfo.h6
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h38
-rw-r--r--include/llvm/CodeGen/MachineSSAUpdater.h4
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h4
-rw-r--r--include/llvm/CodeGen/MachineValueType.h71
-rw-r--r--include/llvm/CodeGen/PBQP/Graph.h74
-rw-r--r--include/llvm/CodeGen/PBQP/ReductionRules.h32
-rw-r--r--include/llvm/CodeGen/Passes.h58
-rw-r--r--include/llvm/CodeGen/RegAllocPBQP.h126
-rw-r--r--include/llvm/CodeGen/RegisterPressure.h15
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h39
-rw-r--r--include/llvm/CodeGen/ResourcePriorityQueue.h8
-rw-r--r--include/llvm/CodeGen/RuntimeLibcalls.h4
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h6
-rw-r--r--include/llvm/CodeGen/ScheduleDAGInstrs.h2
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h422
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h13
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h615
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h2
-rw-r--r--include/llvm/CodeGen/StackMapLivenessAnalysis.h64
-rw-r--r--include/llvm/CodeGen/StackMaps.h41
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h93
-rw-r--r--include/llvm/CodeGen/TargetSchedule.h3
-rw-r--r--include/llvm/CodeGen/ValueTypes.h7
-rw-r--r--include/llvm/CodeGen/ValueTypes.td36
-rw-r--r--include/llvm/CodeGen/VirtRegMap.h4
-rw-r--r--include/llvm/CodeGen/WinEHFuncInfo.h157
-rw-r--r--include/llvm/Config/config.h.cmake66
-rw-r--r--include/llvm/Config/config.h.in66
-rw-r--r--include/llvm/Config/llvm-config.h.cmake4
-rw-r--r--include/llvm/Config/llvm-config.h.in3
-rw-r--r--include/llvm/DebugInfo/DIContext.h52
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h (renamed from include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h)14
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h (renamed from include/llvm/DebugInfo/DWARFAcceleratorTable.h)9
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h (renamed from include/llvm/DebugInfo/DWARFCompileUnit.h)2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h (renamed from include/llvm/DebugInfo/DWARFContext.h)30
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h (renamed from include/llvm/DebugInfo/DWARFDebugAbbrev.h)2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h (renamed from include/llvm/DebugInfo/DWARFDebugArangeSet.h)0
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h (renamed from include/llvm/DebugInfo/DWARFDebugAranges.h)0
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h (renamed from include/llvm/DebugInfo/DWARFDebugFrame.h)0
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h (renamed from include/llvm/DebugInfo/DWARFDebugInfoEntry.h)4
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLine.h (renamed from include/llvm/DebugInfo/DWARFDebugLine.h)2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h (renamed from include/llvm/DebugInfo/DWARFDebugLoc.h)2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h (renamed from include/llvm/DebugInfo/DWARFDebugRangeList.h)2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFFormValue.h (renamed from include/llvm/DebugInfo/DWARFFormValue.h)5
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFRelocMap.h (renamed from include/llvm/DebugInfo/DWARFRelocMap.h)0
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFSection.h (renamed from include/llvm/DebugInfo/DWARFSection.h)3
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h (renamed from include/llvm/DebugInfo/DWARFTypeUnit.h)2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h (renamed from include/llvm/DebugInfo/DWARFUnit.h)57
-rw-r--r--include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h59
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIADataStream.h33
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h35
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h35
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h37
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h37
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h39
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h206
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASession.h51
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h36
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASupport.h33
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBDataStream.h37
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBEnumChildren.h33
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBLineNumber.h36
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBRawSymbol.h211
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBSession.h61
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBSourceFile.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDB.h26
-rw-r--r--include/llvm/DebugInfo/PDB/PDBContext.h60
-rw-r--r--include/llvm/DebugInfo/PDB/PDBExtras.h38
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymDumper.h61
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbol.h97
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h39
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolBlock.h41
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h38
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h55
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCustom.h39
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolData.h61
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolExe.h46
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFunc.h80
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h49
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h49
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolLabel.h49
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h47
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolThunk.h57
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h45
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h60
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h40
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h36
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h36
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h55
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h50
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h35
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h43
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h54
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h52
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h40
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h39
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h34
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h36
-rw-r--r--include/llvm/DebugInfo/PDB/PDBTypes.h516
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h82
-rw-r--r--include/llvm/ExecutionEngine/JITSymbolFlags.h81
-rw-r--r--include/llvm/ExecutionEngine/ObjectMemoryBuffer.h63
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h547
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileUtils.h62
-rw-r--r--include/llvm/ExecutionEngine/Orc/ExecutionUtils.h182
-rw-r--r--include/llvm/ExecutionEngine/Orc/IRCompileLayer.h148
-rw-r--r--include/llvm/ExecutionEngine/Orc/IRTransformLayer.h101
-rw-r--r--include/llvm/ExecutionEngine/Orc/IndirectionUtils.h295
-rw-r--r--include/llvm/ExecutionEngine/Orc/JITSymbol.h77
-rw-r--r--include/llvm/ExecutionEngine/Orc/LambdaResolver.h62
-rw-r--r--include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h304
-rw-r--r--include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h284
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h53
-rw-r--r--include/llvm/ExecutionEngine/OrcMCJITReplacement.h38
-rw-r--r--include/llvm/ExecutionEngine/RTDyldMemoryManager.h133
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyld.h151
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyldChecker.h7
-rw-r--r--include/llvm/ExecutionEngine/SectionMemoryManager.h8
-rw-r--r--include/llvm/IR/Argument.h5
-rw-r--r--include/llvm/IR/Attributes.h71
-rw-r--r--include/llvm/IR/BasicBlock.h75
-rw-r--r--include/llvm/IR/CFG.h30
-rw-r--r--include/llvm/IR/CallSite.h51
-rw-r--r--include/llvm/IR/Comdat.h2
-rw-r--r--include/llvm/IR/Constant.h4
-rw-r--r--include/llvm/IR/ConstantFolder.h25
-rw-r--r--include/llvm/IR/ConstantRange.h33
-rw-r--r--include/llvm/IR/Constants.h94
-rw-r--r--include/llvm/IR/DIBuilder.h474
-rw-r--r--include/llvm/IR/DataLayout.h52
-rw-r--r--include/llvm/IR/DebugInfo.h1021
-rw-r--r--include/llvm/IR/DebugInfoFlags.def36
-rw-r--r--include/llvm/IR/DebugInfoMetadata.h2227
-rw-r--r--include/llvm/IR/DebugLoc.h117
-rw-r--r--include/llvm/IR/DerivedTypes.h27
-rw-r--r--include/llvm/IR/DiagnosticInfo.h1
-rw-r--r--include/llvm/IR/Function.h139
-rw-r--r--include/llvm/IR/GVMaterializer.h7
-rw-r--r--include/llvm/IR/GetElementPtrTypeIterator.h50
-rw-r--r--include/llvm/IR/GlobalAlias.h24
-rw-r--r--include/llvm/IR/GlobalObject.h4
-rw-r--r--include/llvm/IR/GlobalValue.h37
-rw-r--r--include/llvm/IR/GlobalVariable.h8
-rw-r--r--include/llvm/IR/IRBuilder.h217
-rw-r--r--include/llvm/IR/IRPrintingPasses.h7
-rw-r--r--include/llvm/IR/InlineAsm.h60
-rw-r--r--include/llvm/IR/InstIterator.h29
-rw-r--r--include/llvm/IR/InstVisitor.h2
-rw-r--r--include/llvm/IR/InstrTypes.h25
-rw-r--r--include/llvm/IR/Instruction.h64
-rw-r--r--include/llvm/IR/Instructions.h345
-rw-r--r--include/llvm/IR/IntrinsicInst.h42
-rw-r--r--include/llvm/IR/Intrinsics.h29
-rw-r--r--include/llvm/IR/Intrinsics.td62
-rw-r--r--include/llvm/IR/IntrinsicsBPF.td24
-rw-r--r--include/llvm/IR/IntrinsicsHexagon.td463
-rw-r--r--include/llvm/IR/IntrinsicsPowerPC.td387
-rw-r--r--include/llvm/IR/IntrinsicsSystemZ.td376
-rw-r--r--include/llvm/IR/IntrinsicsX86.td707
-rw-r--r--include/llvm/IR/LLVMContext.h8
-rw-r--r--include/llvm/IR/LegacyPassManager.h4
-rw-r--r--include/llvm/IR/LegacyPassNameParser.h12
-rw-r--r--include/llvm/IR/MDBuilder.h6
-rw-r--r--include/llvm/IR/Metadata.def73
-rw-r--r--include/llvm/IR/Metadata.h658
-rw-r--r--include/llvm/IR/Module.h42
-rw-r--r--include/llvm/IR/NoFolder.h25
-rw-r--r--include/llvm/IR/Operator.h70
-rw-r--r--include/llvm/IR/PassManager.h34
-rw-r--r--include/llvm/IR/PassManagerInternal.h1
-rw-r--r--include/llvm/IR/PatternMatch.h49
-rw-r--r--include/llvm/IR/PredIteratorCache.h87
-rw-r--r--include/llvm/IR/Statepoint.h255
-rw-r--r--include/llvm/IR/Type.h7
-rw-r--r--include/llvm/IR/TypeBuilder.h10
-rw-r--r--include/llvm/IR/Use.h2
-rw-r--r--include/llvm/IR/UseListOrder.h10
-rw-r--r--include/llvm/IR/User.h8
-rw-r--r--include/llvm/IR/Value.h33
-rw-r--r--include/llvm/IR/ValueHandle.h2
-rw-r--r--include/llvm/IR/ValueMap.h21
-rw-r--r--include/llvm/IR/Verifier.h13
-rw-r--r--include/llvm/InitializePasses.h38
-rw-r--r--include/llvm/LTO/LTOCodeGenerator.h44
-rw-r--r--include/llvm/LineEditor/LineEditor.h2
-rw-r--r--include/llvm/LinkAllPasses.h15
-rw-r--r--include/llvm/Linker/Linker.h8
-rw-r--r--include/llvm/MC/ConstantPools.h9
-rw-r--r--include/llvm/MC/MCAsmBackend.h71
-rw-r--r--include/llvm/MC/MCAsmInfo.h49
-rw-r--r--include/llvm/MC/MCAsmInfoELF.h3
-rw-r--r--include/llvm/MC/MCAsmLayout.h40
-rw-r--r--include/llvm/MC/MCAssembler.h631
-rw-r--r--include/llvm/MC/MCCodeEmitter.h9
-rw-r--r--include/llvm/MC/MCCodeGenInfo.h40
-rw-r--r--include/llvm/MC/MCContext.h348
-rw-r--r--include/llvm/MC/MCDisassembler.h13
-rw-r--r--include/llvm/MC/MCDwarf.h55
-rw-r--r--include/llvm/MC/MCELF.h2
-rw-r--r--include/llvm/MC/MCELFObjectWriter.h24
-rw-r--r--include/llvm/MC/MCELFStreamer.h41
-rw-r--r--include/llvm/MC/MCExpr.h142
-rw-r--r--include/llvm/MC/MCFixup.h10
-rw-r--r--include/llvm/MC/MCFixupKindInfo.h2
-rw-r--r--include/llvm/MC/MCInst.h31
-rw-r--r--include/llvm/MC/MCInstBuilder.h16
-rw-r--r--include/llvm/MC/MCInstPrinter.h42
-rw-r--r--include/llvm/MC/MCInstrAnalysis.h4
-rw-r--r--include/llvm/MC/MCInstrDesc.h521
-rw-r--r--include/llvm/MC/MCInstrInfo.h13
-rw-r--r--include/llvm/MC/MCInstrItineraries.h45
-rw-r--r--include/llvm/MC/MCLabel.h19
-rw-r--r--include/llvm/MC/MCLinkerOptimizationHint.h14
-rw-r--r--include/llvm/MC/MCMachObjectWriter.h82
-rw-r--r--include/llvm/MC/MCObjectFileInfo.h290
-rw-r--r--include/llvm/MC/MCObjectStreamer.h51
-rw-r--r--include/llvm/MC/MCObjectWriter.h66
-rw-r--r--include/llvm/MC/MCParser/AsmLexer.h6
-rw-r--r--include/llvm/MC/MCParser/MCAsmLexer.h12
-rw-r--r--include/llvm/MC/MCParser/MCAsmParser.h74
-rw-r--r--include/llvm/MC/MCParser/MCAsmParserExtension.h6
-rw-r--r--include/llvm/MC/MCParser/MCParsedAsmOperand.h5
-rw-r--r--include/llvm/MC/MCRelocationInfo.h4
-rw-r--r--include/llvm/MC/MCSection.h203
-rw-r--r--include/llvm/MC/MCSectionCOFF.h13
-rw-r--r--include/llvm/MC/MCSectionELF.h40
-rw-r--r--include/llvm/MC/MCSectionMachO.h12
-rw-r--r--include/llvm/MC/MCStreamer.h382
-rw-r--r--include/llvm/MC/MCSubtargetInfo.h22
-rw-r--r--include/llvm/MC/MCSymbol.h404
-rw-r--r--include/llvm/MC/MCSymbolizer.h20
-rw-r--r--include/llvm/MC/MCTargetAsmParser.h8
-rw-r--r--include/llvm/MC/MCValue.h17
-rw-r--r--include/llvm/MC/MCWinCOFFObjectWriter.h18
-rw-r--r--include/llvm/MC/MCWinCOFFStreamer.h7
-rw-r--r--include/llvm/MC/MCWinEH.h8
-rw-r--r--include/llvm/MC/SectionKind.h6
-rw-r--r--include/llvm/MC/SubtargetFeature.h28
-rw-r--r--include/llvm/Object/Archive.h20
-rw-r--r--include/llvm/Object/Binary.h4
-rw-r--r--include/llvm/Object/COFF.h30
-rw-r--r--include/llvm/Object/ELF.h24
-rw-r--r--include/llvm/Object/ELFObjectFile.h62
-rw-r--r--include/llvm/Object/ELFTypes.h113
-rw-r--r--include/llvm/Object/ELFYAML.h88
-rw-r--r--include/llvm/Object/IRObjectFile.h2
-rw-r--r--include/llvm/Object/MachO.h5
-rw-r--r--include/llvm/Object/MachOUniversal.h10
-rw-r--r--include/llvm/Object/ObjectFile.h14
-rw-r--r--include/llvm/Object/SymbolicFile.h12
-rw-r--r--include/llvm/Option/Arg.h8
-rw-r--r--include/llvm/Option/ArgList.h39
-rw-r--r--include/llvm/Option/OptSpecifier.h4
-rw-r--r--include/llvm/Option/OptTable.h5
-rw-r--r--include/llvm/Option/Option.h1
-rw-r--r--include/llvm/Pass.h8
-rw-r--r--include/llvm/PassAnalysisSupport.h2
-rw-r--r--include/llvm/PassInfo.h4
-rw-r--r--include/llvm/PassManager.h39
-rw-r--r--include/llvm/Passes/PassBuilder.h105
-rw-r--r--include/llvm/ProfileData/CoverageMapping.h109
-rw-r--r--include/llvm/ProfileData/CoverageMappingReader.h80
-rw-r--r--include/llvm/ProfileData/InstrProfReader.h25
-rw-r--r--include/llvm/ProfileData/InstrProfWriter.h8
-rw-r--r--include/llvm/ProfileData/SampleProf.h34
-rw-r--r--include/llvm/Support/ARMBuildAttributes.h7
-rw-r--r--include/llvm/Support/AlignOf.h14
-rw-r--r--include/llvm/Support/Allocator.h26
-rw-r--r--include/llvm/Support/BranchProbability.h2
-rw-r--r--include/llvm/Support/COFF.h12
-rw-r--r--include/llvm/Support/COM.h36
-rw-r--r--include/llvm/Support/CommandLine.h507
-rw-r--r--include/llvm/Support/Compiler.h144
-rw-r--r--include/llvm/Support/Compression.h4
-rw-r--r--include/llvm/Support/ConvertUTF.h8
-rw-r--r--include/llvm/Support/CrashRecoveryContext.h2
-rw-r--r--include/llvm/Support/DataExtractor.h1
-rw-r--r--include/llvm/Support/Debug.h3
-rw-r--r--include/llvm/Support/Dwarf.def350
-rw-r--r--include/llvm/Support/Dwarf.h339
-rw-r--r--include/llvm/Support/ELF.h79
-rw-r--r--include/llvm/Support/ELFRelocs/Mips.def5
-rw-r--r--include/llvm/Support/Endian.h23
-rw-r--r--include/llvm/Support/EndianStream.h25
-rw-r--r--include/llvm/Support/ErrorOr.h6
-rw-r--r--include/llvm/Support/FileOutputBuffer.h4
-rw-r--r--include/llvm/Support/FileSystem.h9
-rw-r--r--include/llvm/Support/FileUtilities.h4
-rw-r--r--include/llvm/Support/Format.h192
-rw-r--r--include/llvm/Support/FormattedStream.h72
-rw-r--r--include/llvm/Support/GCOV.h147
-rw-r--r--include/llvm/Support/GenericDomTree.h95
-rw-r--r--include/llvm/Support/GenericDomTreeConstruction.h20
-rw-r--r--include/llvm/Support/GraphWriter.h3
-rw-r--r--include/llvm/Support/LockFileManager.h8
-rw-r--r--include/llvm/Support/MathExtras.h378
-rw-r--r--include/llvm/Support/MemoryBuffer.h6
-rw-r--r--include/llvm/Support/MipsABIFlags.h102
-rw-r--r--include/llvm/Support/Mutex.h6
-rw-r--r--include/llvm/Support/MutexGuard.h4
-rw-r--r--include/llvm/Support/OnDiskHashTable.h7
-rw-r--r--include/llvm/Support/Options.h2
-rw-r--r--include/llvm/Support/PrettyStackTrace.h4
-rw-r--r--include/llvm/Support/Program.h3
-rw-r--r--include/llvm/Support/RWMutex.h6
-rw-r--r--include/llvm/Support/RandomNumberGenerator.h6
-rw-r--r--include/llvm/Support/Regex.h3
-rw-r--r--include/llvm/Support/Registry.h9
-rw-r--r--include/llvm/Support/ScaledNumber.h25
-rw-r--r--include/llvm/Support/Signals.h15
-rw-r--r--include/llvm/Support/SourceMgr.h4
-rw-r--r--include/llvm/Support/SpecialCaseList.h30
-rw-r--r--include/llvm/Support/StreamingMemoryObject.h39
-rw-r--r--include/llvm/Support/StringPool.h4
-rw-r--r--include/llvm/Support/SwapByteOrder.h20
-rw-r--r--include/llvm/Support/SystemUtils.h2
-rw-r--r--include/llvm/Support/TargetParser.h155
-rw-r--r--include/llvm/Support/TargetRegistry.h2170
-rw-r--r--include/llvm/Support/Timer.h7
-rw-r--r--include/llvm/Support/ToolOutputFile.h21
-rw-r--r--include/llvm/Support/UnicodeCharRanges.h4
-rw-r--r--include/llvm/Support/UniqueLock.h4
-rw-r--r--include/llvm/Support/Watchdog.h4
-rw-r--r--include/llvm/Support/YAMLParser.h57
-rw-r--r--include/llvm/Support/YAMLTraits.h169
-rw-r--r--include/llvm/Support/circular_raw_ostream.h23
-rw-r--r--include/llvm/Support/raw_os_ostream.h2
-rw-r--r--include/llvm/Support/raw_ostream.h253
-rw-r--r--include/llvm/Support/type_traits.h10
-rw-r--r--include/llvm/TableGen/Record.h190
-rw-r--r--include/llvm/TableGen/SetTheory.h8
-rw-r--r--include/llvm/TableGen/TableGenBackend.h3
-rw-r--r--include/llvm/Target/Target.td20
-rw-r--r--include/llvm/Target/TargetCallingConv.h1
-rw-r--r--include/llvm/Target/TargetFrameLowering.h45
-rw-r--r--include/llvm/Target/TargetInstrInfo.h396
-rw-r--r--include/llvm/Target/TargetIntrinsicInfo.h4
-rw-r--r--include/llvm/Target/TargetLibraryInfo.h802
-rw-r--r--include/llvm/Target/TargetLowering.h348
-rw-r--r--include/llvm/Target/TargetLoweringObjectFile.h77
-rw-r--r--include/llvm/Target/TargetMachine.h204
-rw-r--r--include/llvm/Target/TargetOptions.h84
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h42
-rw-r--r--include/llvm/Target/TargetSelectionDAG.td32
-rw-r--r--include/llvm/Target/TargetSelectionDAGInfo.h5
-rw-r--r--include/llvm/Target/TargetSubtargetInfo.h44
-rw-r--r--include/llvm/Transforms/IPO.h4
-rw-r--r--include/llvm/Transforms/IPO/LowerBitSets.h198
-rw-r--r--include/llvm/Transforms/IPO/PassManagerBuilder.h23
-rw-r--r--include/llvm/Transforms/InstCombine/InstCombine.h46
-rw-r--r--include/llvm/Transforms/InstCombine/InstCombineWorklist.h116
-rw-r--r--include/llvm/Transforms/Instrumentation.h41
-rw-r--r--include/llvm/Transforms/Scalar.h73
-rw-r--r--include/llvm/Transforms/Scalar/EarlyCSE.h39
-rw-r--r--include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h40
-rw-r--r--include/llvm/Transforms/Scalar/SimplifyCFG.h46
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h158
-rw-r--r--include/llvm/Transforms/Utils/BuildLibCalls.h32
-rw-r--r--include/llvm/Transforms/Utils/Cloning.h65
-rw-r--r--include/llvm/Transforms/Utils/Local.h47
-rw-r--r--include/llvm/Transforms/Utils/LoopUtils.h194
-rw-r--r--include/llvm/Transforms/Utils/ModuleUtils.h21
-rw-r--r--include/llvm/Transforms/Utils/SSAUpdater.h7
-rw-r--r--include/llvm/Transforms/Utils/SimplifyLibCalls.h29
-rw-r--r--include/llvm/Transforms/Utils/SymbolRewriter.h7
-rw-r--r--include/llvm/Transforms/Utils/UnrollLoop.h15
-rw-r--r--include/llvm/Transforms/Utils/VectorUtils.h4
-rw-r--r--include/llvm/module.modulemap69
497 files changed, 27346 insertions, 13474 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index 26aae773624c..958e3fdaea14 100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -282,12 +282,6 @@ public:
/// into FoldingSets.
void Profile(FoldingSetNodeID &NID) const;
- /// \brief Used by the Bitcode serializer to emit APInts to Bitcode.
- void Emit(Serializer &S) const;
-
- /// \brief Used by the Bitcode deserializer to deserialize APInts.
- static APFloat ReadVal(Deserializer &D);
-
/// \name Arithmetic
/// @{
@@ -349,7 +343,7 @@ public:
/// copied from some other APFloat.
static APFloat copySign(APFloat Value, const APFloat &Sign) {
Value.copySign(Sign);
- return std::move(Value);
+ return Value;
}
/// @}
@@ -376,7 +370,7 @@ public:
/// The definition of equality is not straightforward for floating point, so
/// we won't use operator==. Use one of the following, or write whatever it
/// is you really mean.
- bool operator==(const APFloat &) const LLVM_DELETED_FUNCTION;
+ bool operator==(const APFloat &) const = delete;
/// IEEE comparison with another floating point number (NaNs compare
/// unordered, 0==-0).
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index 025397d9ce45..36d8159d21ba 100644
--- a/include/llvm/ADT/APInt.h
+++ b/include/llvm/ADT/APInt.h
@@ -25,9 +25,7 @@
#include <string>
namespace llvm {
-class Deserializer;
class FoldingSetNodeID;
-class Serializer;
class StringRef;
class hash_code;
class raw_ostream;
@@ -409,6 +407,13 @@ public:
: getZExtValue();
}
+ /// \brief Check if the APInt consists of a repeated bit pattern.
+ ///
+ /// e.g. 0x01010101 satisfies isSplat(8).
+ /// \param SplatSizeInBits The size of the pattern in bits. Must divide bit
+ /// width without remainder.
+ bool isSplat(unsigned SplatSizeInBits) const;
+
/// @}
/// \name Value Generators
/// @{
@@ -1356,7 +1361,7 @@ public:
/// \brief Count the number of leading one bits.
///
- /// This function is an APInt version of the countLeadingOnes_{32,64}
+ /// This function is an APInt version of the countLeadingOnes
/// functions in MathExtras.h. It counts the number of ones from the most
/// significant bit to the first zero bit.
///
@@ -1372,7 +1377,7 @@ public:
/// \brief Count the number of trailing zero bits.
///
- /// This function is an APInt version of the countTrailingZeros_{32,64}
+ /// This function is an APInt version of the countTrailingZeros
/// functions in MathExtras.h. It counts the number of zeros from the least
/// significant bit to the first set bit.
///
@@ -1382,7 +1387,7 @@ public:
/// \brief Count the number of trailing one bits.
///
- /// This function is an APInt version of the countTrailingOnes_{32,64}
+ /// This function is an APInt version of the countTrailingOnes
/// functions in MathExtras.h. It counts the number of ones from the least
/// significant bit to the first zero bit.
///
@@ -1390,19 +1395,19 @@ public:
/// of ones from the least significant bit to the first zero bit.
unsigned countTrailingOnes() const {
if (isSingleWord())
- return CountTrailingOnes_64(VAL);
+ return llvm::countTrailingOnes(VAL);
return countTrailingOnesSlowCase();
}
/// \brief Count the number of bits set.
///
- /// This function is an APInt version of the countPopulation_{32,64} functions
+ /// This function is an APInt version of the countPopulation functions
/// in MathExtras.h. It counts the number of 1 bits in the APInt value.
///
/// \returns 0 if the value is zero, otherwise returns the number of set bits.
unsigned countPopulation() const {
if (isSingleWord())
- return CountPopulation_64(VAL);
+ return llvm::countPopulation(VAL);
return countPopulationSlowCase();
}
diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h
index a6693f7992cd..91ccda22f2f0 100644
--- a/include/llvm/ADT/APSInt.h
+++ b/include/llvm/ADT/APSInt.h
@@ -62,6 +62,12 @@ public:
}
using APInt::toString;
+ /// \brief Get the correctly-extended \c int64_t value.
+ int64_t getExtValue() const {
+ assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
+ return isSigned() ? getSExtValue() : getZExtValue();
+ }
+
APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const {
return APSInt(APInt::trunc(width), IsUnsigned);
}
@@ -133,14 +139,27 @@ public:
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
return eq(RHS);
}
- inline bool operator==(int64_t RHS) const {
- return isSameValue(*this, APSInt(APInt(64, RHS), true));
- }
inline bool operator!=(const APSInt& RHS) const {
return !((*this) == RHS);
}
- inline bool operator!=(int64_t RHS) const {
- return !((*this) == RHS);
+
+ bool operator==(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) == 0;
+ }
+ bool operator!=(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) != 0;
+ }
+ bool operator<=(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) <= 0;
+ }
+ bool operator>=(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) >= 0;
+ }
+ bool operator<(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) < 0;
+ }
+ bool operator>(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) > 0;
}
// The remaining operators just wrap the logic of APInt, but retain the
@@ -260,37 +279,49 @@ public:
/// \brief Determine if two APSInts have the same value, zero- or
/// sign-extending as needed.
static bool isSameValue(const APSInt &I1, const APSInt &I2) {
+ return !compareValues(I1, I2);
+ }
+
+ /// \brief Compare underlying values of two numbers.
+ static int compareValues(const APSInt &I1, const APSInt &I2) {
if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
- return I1 == I2;
+ return I1 == I2 ? 0 : I1 > I2 ? 1 : -1;
// Check for a bit-width mismatch.
if (I1.getBitWidth() > I2.getBitWidth())
- return isSameValue(I1, I2.extend(I1.getBitWidth()));
+ return compareValues(I1, I2.extend(I1.getBitWidth()));
else if (I2.getBitWidth() > I1.getBitWidth())
- return isSameValue(I1.extend(I2.getBitWidth()), I2);
-
- assert(I1.isSigned() != I2.isSigned());
+ return compareValues(I1.extend(I2.getBitWidth()), I2);
// We have a signedness mismatch. Check for negative values and do an
- // unsigned compare if signs match.
- if ((I1.isSigned() && I1.isNegative()) ||
- (!I1.isSigned() && I2.isNegative()))
- return false;
+ // unsigned compare if both are positive.
+ if (I1.isSigned()) {
+ assert(!I2.isSigned() && "Expected signed mismatch");
+ if (I1.isNegative())
+ return -1;
+ } else {
+ assert(I2.isSigned() && "Expected signed mismatch");
+ if (I2.isNegative())
+ return 1;
+ }
- return I1.eq(I2);
+ return I1.eq(I2) ? 0 : I1.ugt(I2) ? 1 : -1;
}
+ static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
+ static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
+
/// Profile - Used to insert APSInt objects, or objects that contain APSInt
/// objects, into FoldingSets.
void Profile(FoldingSetNodeID& ID) const;
};
-inline bool operator==(int64_t V1, const APSInt& V2) {
- return V2 == V1;
-}
-inline bool operator!=(int64_t V1, const APSInt& V2) {
- return V2 != V1;
-}
+inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
+inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
+inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
+inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
+inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
+inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
I.print(OS, I.isSigned());
diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h
index 8c14a423c8f5..1b2bdffc8335 100644
--- a/include/llvm/ADT/ArrayRef.h
+++ b/include/llvm/ADT/ArrayRef.h
@@ -11,7 +11,6 @@
#define LLVM_ADT_ARRAYREF_H
#include "llvm/ADT/None.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
@@ -44,19 +43,6 @@ 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
/// @{
@@ -97,12 +83,10 @@ namespace llvm {
/*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N])
: Data(Arr), Length(N) {}
-#if LLVM_HAS_INITIALIZER_LISTS
/// Construct an ArrayRef from a std::initializer_list.
/*implicit*/ ArrayRef(const std::initializer_list<T> &Vec)
: Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()),
Length(Vec.size()) {}
-#endif
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
/// ensure that only ArrayRefs of pointers can be converted.
@@ -112,6 +96,25 @@ namespace llvm {
std::is_convertible<U *const *, T const *>::value>::type* = 0)
: Data(A.data()), Length(A.size()) {}
+ /// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is
+ /// templated in order to avoid instantiating SmallVectorTemplateCommon<T>
+ /// whenever we copy-construct an ArrayRef.
+ template<typename U, typename DummyT>
+ /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<U*, DummyT> &Vec,
+ typename std::enable_if<
+ std::is_convertible<U *const *,
+ T const *>::value>::type* = 0)
+ : Data(Vec.data()), Length(Vec.size()) {
+ }
+
+ /// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE
+ /// to ensure that only vectors of pointers can be converted.
+ template<typename U, typename A>
+ ArrayRef(const std::vector<U *, A> &Vec,
+ typename std::enable_if<
+ std::is_convertible<U *const *, T const *>::value>::type* = 0)
+ : Data(Vec.data()), Length(Vec.size()) {}
+
/// @}
/// @name Simple Operations
/// @{
@@ -153,13 +156,9 @@ namespace llvm {
bool equals(ArrayRef RHS) const {
if (Length != RHS.Length)
return false;
- // 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;
+ if (Length == 0)
+ return true;
+ return std::equal(begin(), end(), RHS.begin());
}
/// slice(n) - Chop off the first N elements of the array.
@@ -204,47 +203,6 @@ 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 a40f694485bf..f58dd7356c7d 100644
--- a/include/llvm/ADT/BitVector.h
+++ b/include/llvm/ADT/BitVector.h
@@ -29,6 +29,9 @@ class BitVector {
enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT };
+ static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32,
+ "Unsupported word size");
+
BitWord *Bits; // Actual bits.
unsigned Size; // Size of bitvector in bits.
unsigned Capacity; // Size of allocated memory in BitWord.
@@ -50,7 +53,7 @@ public:
BitPos = Idx % BITWORD_SIZE;
}
- ~reference() {}
+ reference(const reference&) = default;
reference &operator=(reference t) {
*this = bool(t);
@@ -118,12 +121,7 @@ public:
size_type count() const {
unsigned NumBits = 0;
for (unsigned i = 0; i < NumBitWords(size()); ++i)
- if (sizeof(BitWord) == 4)
- NumBits += CountPopulation_32((uint32_t)Bits[i]);
- else if (sizeof(BitWord) == 8)
- NumBits += CountPopulation_64(Bits[i]);
- else
- llvm_unreachable("Unsupported!");
+ NumBits += countPopulation(Bits[i]);
return NumBits;
}
@@ -157,13 +155,8 @@ public:
/// of the bits are set.
int find_first() const {
for (unsigned i = 0; i < NumBitWords(size()); ++i)
- if (Bits[i] != 0) {
- if (sizeof(BitWord) == 4)
- return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]);
- if (sizeof(BitWord) == 8)
- return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
- llvm_unreachable("Unsupported!");
- }
+ if (Bits[i] != 0)
+ return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
}
@@ -180,23 +173,13 @@ public:
// Mask off previous bits.
Copy &= ~0UL << BitPos;
- if (Copy != 0) {
- if (sizeof(BitWord) == 4)
- return WordPos * BITWORD_SIZE + countTrailingZeros((uint32_t)Copy);
- if (sizeof(BitWord) == 8)
- return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
- llvm_unreachable("Unsupported!");
- }
+ if (Copy != 0)
+ return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
// Check subsequent words.
for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
- if (Bits[i] != 0) {
- if (sizeof(BitWord) == 4)
- return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]);
- if (sizeof(BitWord) == 8)
- return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
- llvm_unreachable("Unsupported!");
- }
+ if (Bits[i] != 0)
+ return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
}
@@ -559,7 +542,7 @@ private:
template<bool AddBits, bool InvertMask>
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
- assert(BITWORD_SIZE % 32 == 0 && "Unsupported BitWord size.");
+ static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size.");
MaskWords = std::min(MaskWords, (size() + 31) / 32);
const unsigned Scale = BITWORD_SIZE / 32;
unsigned i;
diff --git a/include/llvm/ADT/DeltaAlgorithm.h b/include/llvm/ADT/DeltaAlgorithm.h
index 4d07e044781f..21bc1e80c9d8 100644
--- a/include/llvm/ADT/DeltaAlgorithm.h
+++ b/include/llvm/ADT/DeltaAlgorithm.h
@@ -77,6 +77,8 @@ protected:
/// ExecuteOneTest - Execute a single test predicate on the change set \p S.
virtual bool ExecuteOneTest(const changeset_ty &S) = 0;
+ DeltaAlgorithm& operator=(const DeltaAlgorithm&) = default;
+
public:
virtual ~DeltaAlgorithm();
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h
index 050f8ac150dd..27f73157a29f 100644
--- a/include/llvm/ADT/DenseMap.h
+++ b/include/llvm/ADT/DenseMap.h
@@ -15,6 +15,7 @@
#define LLVM_ADT_DENSEMAP_H
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/EpochTracker.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
@@ -50,7 +51,7 @@ class DenseMapIterator;
template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
typename BucketT>
-class DenseMapBase {
+class DenseMapBase : public DebugEpochBase {
public:
typedef unsigned size_type;
typedef KeyT key_type;
@@ -62,16 +63,17 @@ public:
const_iterator;
inline iterator begin() {
// When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
- return empty() ? end() : iterator(getBuckets(), getBucketsEnd());
+ return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this);
}
inline iterator end() {
- return iterator(getBucketsEnd(), getBucketsEnd(), true);
+ return iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
}
inline const_iterator begin() const {
- return empty() ? end() : const_iterator(getBuckets(), getBucketsEnd());
+ return empty() ? end()
+ : const_iterator(getBuckets(), getBucketsEnd(), *this);
}
inline const_iterator end() const {
- return const_iterator(getBucketsEnd(), getBucketsEnd(), true);
+ return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
}
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const {
@@ -81,11 +83,13 @@ public:
/// Grow the densemap so that it has at least Size buckets. Does not shrink
void resize(size_type Size) {
+ incrementEpoch();
if (Size > getNumBuckets())
grow(Size);
}
void clear() {
+ incrementEpoch();
if (getNumEntries() == 0 && getNumTombstones() == 0) return;
// If the capacity of the array is huge, and the # elements used is small,
@@ -96,16 +100,18 @@ public:
}
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
+ unsigned NumEntries = getNumEntries();
for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
P->getSecond().~ValueT();
- decrementNumEntries();
+ --NumEntries;
}
P->getFirst() = EmptyKey;
}
}
- assert(getNumEntries() == 0 && "Node count imbalance!");
+ assert(NumEntries == 0 && "Node count imbalance!");
+ setNumEntries(0);
setNumTombstones(0);
}
@@ -118,13 +124,13 @@ public:
iterator find(const KeyT &Val) {
BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
- return iterator(TheBucket, getBucketsEnd(), true);
+ return iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
const_iterator find(const KeyT &Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
- return const_iterator(TheBucket, getBucketsEnd(), true);
+ return const_iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
@@ -137,14 +143,14 @@ public:
iterator find_as(const LookupKeyT &Val) {
BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
- return iterator(TheBucket, getBucketsEnd(), true);
+ return iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
template<class LookupKeyT>
const_iterator find_as(const LookupKeyT &Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
- return const_iterator(TheBucket, getBucketsEnd(), true);
+ return const_iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
@@ -163,12 +169,13 @@ public:
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
BucketT *TheBucket;
if (LookupBucketFor(KV.first, TheBucket))
- return std::make_pair(iterator(TheBucket, getBucketsEnd(), true),
+ return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
false); // Already in map.
// Otherwise, insert the new element.
TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket);
- return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
+ return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+ true);
}
// Inserts key,value pair into the map if the key isn't already in the map.
@@ -177,14 +184,15 @@ public:
std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
BucketT *TheBucket;
if (LookupBucketFor(KV.first, TheBucket))
- return std::make_pair(iterator(TheBucket, getBucketsEnd(), true),
+ return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
false); // Already in map.
-
+
// Otherwise, insert the new element.
TheBucket = InsertIntoBucket(std::move(KV.first),
std::move(KV.second),
TheBucket);
- return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
+ return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+ true);
}
/// insert - Range insertion of pairs.
@@ -251,7 +259,7 @@ public:
const void *getPointerIntoBucketsArray() const { return getBuckets(); }
protected:
- DenseMapBase() {}
+ DenseMapBase() = default;
void destroyAll() {
if (getNumBuckets() == 0) // Nothing to do.
@@ -264,10 +272,6 @@ protected:
P->getSecond().~ValueT();
P->getFirst().~KeyT();
}
-
-#ifndef NDEBUG
- memset((void*)getBuckets(), 0x5a, sizeof(BucketT)*getNumBuckets());
-#endif
}
void initEmpty() {
@@ -304,12 +308,6 @@ protected:
}
B->getFirst().~KeyT();
}
-
-#ifndef NDEBUG
- if (OldBucketsBegin != OldBucketsEnd)
- memset((void*)OldBucketsBegin, 0x5a,
- sizeof(BucketT) * (OldBucketsEnd - OldBucketsBegin));
-#endif
}
template <typename OtherBaseT>
@@ -335,11 +333,6 @@ protected:
}
}
- void swap(DenseMapBase& RHS) {
- std::swap(getNumEntries(), RHS.getNumEntries());
- std::swap(getNumTombstones(), RHS.getNumTombstones());
- }
-
static unsigned getHashValue(const KeyT &Val) {
return KeyInfoT::getHashValue(Val);
}
@@ -431,6 +424,8 @@ private:
}
BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) {
+ incrementEpoch();
+
// If the load of the hash table is more than 3/4, or if fewer than 1/8 of
// the buckets are empty (meaning that many are filled with tombstones),
// grow the table.
@@ -442,11 +437,12 @@ private:
// causing infinite loops in lookup.
unsigned NewNumEntries = getNumEntries() + 1;
unsigned NumBuckets = getNumBuckets();
- if (NewNumEntries*4 >= NumBuckets*3) {
+ if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
this->grow(NumBuckets * 2);
LookupBucketFor(Key, TheBucket);
NumBuckets = getNumBuckets();
- } else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) {
+ } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
+ NumBuckets/8)) {
this->grow(NumBuckets);
LookupBucketFor(Key, TheBucket);
}
@@ -492,14 +488,14 @@ private:
while (1) {
const BucketT *ThisBucket = BucketsPtr + BucketNo;
// Found Val's bucket? If so, return it.
- if (KeyInfoT::isEqual(Val, ThisBucket->getFirst())) {
+ if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
FoundBucket = ThisBucket;
return true;
}
// If we found an empty bucket, the key doesn't exist in the set.
// Insert it and return the default value.
- if (KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey)) {
+ if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
// If we've already seen a tombstone while probing, fill it in instead
// of the empty bucket we eventually probed to.
FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
@@ -580,6 +576,8 @@ public:
}
void swap(DenseMap& RHS) {
+ this->incrementEpoch();
+ RHS.incrementEpoch();
std::swap(Buckets, RHS.Buckets);
std::swap(NumEntries, RHS.NumEntries);
std::swap(NumTombstones, RHS.NumTombstones);
@@ -986,9 +984,10 @@ private:
template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
bool IsConst>
-class DenseMapIterator {
+class DenseMapIterator : DebugEpochBase::HandleBase {
typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator;
friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
+ friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
public:
typedef ptrdiff_t difference_type;
@@ -1002,38 +1001,54 @@ private:
public:
DenseMapIterator() : Ptr(nullptr), End(nullptr) {}
- DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false)
- : Ptr(Pos), End(E) {
+ DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch,
+ bool NoAdvance = false)
+ : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
+ assert(isHandleInSync() && "invalid construction!");
if (!NoAdvance) AdvancePastEmptyBuckets();
}
- // 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.
+ // Converting ctor from non-const iterators to const iterators. SFINAE'd out
+ // for const iterator destinations so it doesn't end up as a user defined copy
+ // constructor.
+ template <bool IsConstSrc,
+ typename = typename std::enable_if<!IsConstSrc && IsConst>::type>
DenseMapIterator(
- const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false> &I)
- : Ptr(I.Ptr), End(I.End) {}
+ const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
+ : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
reference operator*() const {
+ assert(isHandleInSync() && "invalid iterator access!");
return *Ptr;
}
pointer operator->() const {
+ assert(isHandleInSync() && "invalid iterator access!");
return Ptr;
}
bool operator==(const ConstIterator &RHS) const {
- return Ptr == RHS.operator->();
+ assert((!Ptr || isHandleInSync()) && "handle not in sync!");
+ assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
+ assert(getEpochAddress() == RHS.getEpochAddress() &&
+ "comparing incomparable iterators!");
+ return Ptr == RHS.Ptr;
}
bool operator!=(const ConstIterator &RHS) const {
- return Ptr != RHS.operator->();
+ assert((!Ptr || isHandleInSync()) && "handle not in sync!");
+ assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
+ assert(getEpochAddress() == RHS.getEpochAddress() &&
+ "comparing incomparable iterators!");
+ return Ptr != RHS.Ptr;
}
inline DenseMapIterator& operator++() { // Preincrement
+ assert(isHandleInSync() && "invalid iterator access!");
++Ptr;
AdvancePastEmptyBuckets();
return *this;
}
DenseMapIterator operator++(int) { // Postincrement
+ assert(isHandleInSync() && "invalid iterator access!");
DenseMapIterator tmp = *this; ++*this; return tmp;
}
diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h
index 6cd9e68aea56..d79b9acacfa9 100644
--- a/include/llvm/ADT/DepthFirstIterator.h
+++ b/include/llvm/ADT/DepthFirstIterator.h
@@ -113,9 +113,8 @@ private:
while (It != GT::child_end(Node)) {
NodeType *Next = *It++;
// Has our next sibling been visited?
- if (Next && !this->Visited.count(Next)) {
+ if (Next && this->Visited.insert(Next).second) {
// No, do it now.
- this->Visited.insert(Next);
VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0),
GT::child_begin(Next)));
return;
@@ -129,58 +128,59 @@ private:
public:
typedef typename super::pointer pointer;
- typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self;
// Provide static begin and end methods as our public "constructors"
- static inline _Self begin(const GraphT& G) {
- return _Self(GT::getEntryNode(G));
+ static df_iterator begin(const GraphT &G) {
+ return df_iterator(GT::getEntryNode(G));
}
- static inline _Self end(const GraphT& G) { return _Self(); }
+ static df_iterator end(const GraphT &G) { return df_iterator(); }
// Static begin and end methods as our public ctors for external iterators
- static inline _Self begin(const GraphT& G, SetType &S) {
- return _Self(GT::getEntryNode(G), S);
+ static df_iterator begin(const GraphT &G, SetType &S) {
+ return df_iterator(GT::getEntryNode(G), S);
}
- static inline _Self end(const GraphT& G, SetType &S) { return _Self(S); }
+ static df_iterator end(const GraphT &G, SetType &S) { return df_iterator(S); }
- inline bool operator==(const _Self& x) const {
+ bool operator==(const df_iterator &x) const {
return VisitStack == x.VisitStack;
}
- inline bool operator!=(const _Self& x) const { return !operator==(x); }
+ bool operator!=(const df_iterator &x) const { return !(*this == x); }
- inline pointer operator*() const {
- return VisitStack.back().first.getPointer();
- }
+ pointer operator*() const { return VisitStack.back().first.getPointer(); }
// This is a nonstandard operator-> that dereferences the pointer an extra
// time... so that you can actually call methods ON the Node, because
// the contained type is a pointer. This allows BBIt->getTerminator() f.e.
//
- inline NodeType *operator->() const { return operator*(); }
+ NodeType *operator->() const { return **this; }
- inline _Self& operator++() { // Preincrement
+ df_iterator &operator++() { // Preincrement
toNext();
return *this;
}
- // skips all children of the current node and traverses to next node
- //
- inline _Self& skipChildren() {
+ /// \brief Skips all children of the current node and traverses to next node
+ ///
+ /// Note: This function takes care of incrementing the iterator. If you
+ /// always increment and call this function, you risk walking off the end.
+ df_iterator &skipChildren() {
VisitStack.pop_back();
if (!VisitStack.empty())
toNext();
return *this;
}
- inline _Self operator++(int) { // Postincrement
- _Self tmp = *this; ++*this; return tmp;
+ df_iterator operator++(int) { // Postincrement
+ df_iterator tmp = *this;
+ ++*this;
+ return tmp;
}
// nodeVisited - return true if this iterator has already visited the
// specified node. This is public, and will probably be used to iterate over
// nodes that a depth first iteration did not find: ie unreachable nodes.
//
- inline bool nodeVisited(NodeType *Node) const {
+ bool nodeVisited(NodeType *Node) const {
return this->Visited.count(Node) != 0;
}
@@ -211,7 +211,7 @@ df_iterator<T> df_end(const T& G) {
// Provide an accessor method to use them in range-based patterns.
template <class T>
iterator_range<df_iterator<T>> depth_first(const T& G) {
- return iterator_range<df_iterator<T>>(df_begin(G), df_end(G));
+ return make_range(df_begin(G), df_end(G));
}
// Provide global definitions of external depth first iterators...
@@ -234,8 +234,7 @@ df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &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));
+ return make_range(df_ext_begin(G, S), df_ext_end(G, S));
}
@@ -261,7 +260,7 @@ idf_iterator<T> idf_end(const T& G){
// Provide an accessor method to use them in range-based patterns.
template <class T>
iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) {
- return iterator_range<idf_iterator<T>>(idf_begin(G), idf_end(G));
+ return make_range(idf_begin(G), idf_end(G));
}
// Provide global definitions of external inverse depth first iterators...
@@ -286,8 +285,7 @@ idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &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));
+ return make_range(idf_ext_begin(G, S), idf_ext_end(G, S));
}
} // End llvm namespace
diff --git a/include/llvm/ADT/EpochTracker.h b/include/llvm/ADT/EpochTracker.h
new file mode 100644
index 000000000000..582d58179d13
--- /dev/null
+++ b/include/llvm/ADT/EpochTracker.h
@@ -0,0 +1,99 @@
+//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- 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 DebugEpochBase and DebugEpochBase::HandleBase classes.
+// These can be used to write iterators that are fail-fast when LLVM is built
+// with asserts enabled.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_EPOCH_TRACKER_H
+#define LLVM_ADT_EPOCH_TRACKER_H
+
+#include "llvm/Config/llvm-config.h"
+
+#include <cstdint>
+
+namespace llvm {
+
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+
+class DebugEpochBase {
+public:
+ void incrementEpoch() {}
+
+ class HandleBase {
+ public:
+ HandleBase() = default;
+ explicit HandleBase(const DebugEpochBase *) {}
+ bool isHandleInSync() const { return true; }
+ const void *getEpochAddress() const { return nullptr; }
+ };
+};
+
+#else
+
+/// \brief A base class for data structure classes wishing to make iterators
+/// ("handles") pointing into themselves fail-fast. When building without
+/// asserts, this class is empty and does nothing.
+///
+/// DebugEpochBase does not by itself track handles pointing into itself. The
+/// expectation is that routines touching the handles will poll on
+/// isHandleInSync at appropriate points to assert that the handle they're using
+/// is still valid.
+///
+class DebugEpochBase {
+ uint64_t Epoch;
+
+public:
+ DebugEpochBase() : Epoch(0) {}
+
+ /// \brief Calling incrementEpoch invalidates all handles pointing into the
+ /// calling instance.
+ void incrementEpoch() { ++Epoch; }
+
+ /// \brief The destructor calls incrementEpoch to make use-after-free bugs
+ /// more likely to crash deterministically.
+ ~DebugEpochBase() { incrementEpoch(); }
+
+ /// \brief A base class for iterator classes ("handles") that wish to poll for
+ /// iterator invalidating modifications in the underlying data structure.
+ /// When LLVM is built without asserts, this class is empty and does nothing.
+ ///
+ /// HandleBase does not track the parent data structure by itself. It expects
+ /// the routines modifying the data structure to call incrementEpoch when they
+ /// make an iterator-invalidating modification.
+ ///
+ class HandleBase {
+ const uint64_t *EpochAddress;
+ uint64_t EpochAtCreation;
+
+ public:
+ HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
+
+ explicit HandleBase(const DebugEpochBase *Parent)
+ : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
+
+ /// \brief Returns true if the DebugEpochBase this Handle is linked to has
+ /// not called incrementEpoch on itself since the creation of this
+ /// HandleBase instance.
+ bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
+
+ /// \brief Returns a pointer to the epoch word stored in the data structure
+ /// this handle points into. Can be used to check if two iterators point
+ /// into the same data structure.
+ const void *getEpochAddress() const { return EpochAddress; }
+ };
+};
+
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h
index e0396c7e7914..d6a26f88e67d 100644
--- a/include/llvm/ADT/EquivalenceClasses.h
+++ b/include/llvm/ADT/EquivalenceClasses.h
@@ -17,6 +17,7 @@
#include "llvm/Support/DataTypes.h"
#include <cassert>
+#include <cstddef>
#include <set>
namespace llvm {
@@ -254,7 +255,7 @@ public:
assert(Node != nullptr && "Dereferencing end()!");
return Node->getData();
}
- reference operator->() const { return operator*(); }
+ pointer operator->() const { return &operator*(); }
member_iterator &operator++() {
assert(Node != nullptr && "++'d off the end of the list!");
diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h
index 14c5933d388a..52d10c1c1245 100644
--- a/include/llvm/ADT/FoldingSet.h
+++ b/include/llvm/ADT/FoldingSet.h
@@ -18,13 +18,11 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
- class APFloat;
- class APInt;
-
/// This folding set used for two purposes:
/// 1. Given information about a node we want to create, look up the unique
/// instance of the node in the set. If the node already exists, return
@@ -109,6 +107,8 @@ class FoldingSetNodeID;
/// back to the bucket to facilitate node removal.
///
class FoldingSetImpl {
+ virtual void anchor(); // Out of line virtual method.
+
protected:
/// Buckets - Array of bucket chains.
///
@@ -122,10 +122,11 @@ protected:
/// is greater than twice the number of buckets.
unsigned NumNodes;
-public:
+ ~FoldingSetImpl();
+
explicit FoldingSetImpl(unsigned Log2InitSize = 6);
- virtual ~FoldingSetImpl();
+public:
//===--------------------------------------------------------------------===//
/// Node - This class is used to maintain the singly linked bucket list in
/// a folding set.
@@ -392,7 +393,7 @@ DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
/// implementation of the folding set to the node class T. T must be a
/// subclass of FoldingSetNode and implement a Profile function.
///
-template<class T> class FoldingSet : public FoldingSetImpl {
+template <class T> class FoldingSet final : public FoldingSetImpl {
private:
/// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
/// way to convert nodes into a unique specifier.
@@ -462,7 +463,7 @@ public:
/// function with signature
/// void Profile(llvm::FoldingSetNodeID &, Ctx);
template <class T, class Ctx>
-class ContextualFoldingSet : public FoldingSetImpl {
+class ContextualFoldingSet final : public FoldingSetImpl {
// Unfortunately, this can't derive from FoldingSet<T> because the
// construction vtable for FoldingSet<T> requires
// FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
@@ -532,46 +533,6 @@ public:
};
//===----------------------------------------------------------------------===//
-/// FoldingSetVectorIterator - This implements an iterator for
-/// FoldingSetVector. It is only necessary because FoldingSetIterator provides
-/// a value_type of T, while the vector in FoldingSetVector exposes
-/// a value_type of T*. Fortunately, FoldingSetIterator doesn't expose very
-/// much besides operator* and operator->, so we just wrap the inner vector
-/// iterator and perform the extra dereference.
-template <class T, class VectorIteratorT>
-class FoldingSetVectorIterator {
- // Provide a typedef to workaround the lack of correct injected class name
- // support in older GCCs.
- typedef FoldingSetVectorIterator<T, VectorIteratorT> SelfT;
-
- VectorIteratorT Iterator;
-
-public:
- FoldingSetVectorIterator(VectorIteratorT I) : Iterator(I) {}
-
- bool operator==(const SelfT &RHS) const {
- return Iterator == RHS.Iterator;
- }
- bool operator!=(const SelfT &RHS) const {
- return Iterator != RHS.Iterator;
- }
-
- T &operator*() const { return **Iterator; }
-
- T *operator->() const { return *Iterator; }
-
- inline SelfT &operator++() {
- ++Iterator;
- return *this;
- }
- SelfT operator++(int) {
- SelfT tmp = *this;
- ++*this;
- return tmp;
- }
-};
-
-//===----------------------------------------------------------------------===//
/// FoldingSetVector - This template class combines a FoldingSet and a vector
/// to provide the interface of FoldingSet but with deterministic iteration
/// order based on the insertion order. T must be a subclass of FoldingSetNode
@@ -586,12 +547,11 @@ public:
: Set(Log2InitSize) {
}
- typedef FoldingSetVectorIterator<T, typename VectorT::iterator> iterator;
+ typedef pointee_iterator<typename VectorT::iterator> iterator;
iterator begin() { return Vector.begin(); }
iterator end() { return Vector.end(); }
- typedef FoldingSetVectorIterator<const T, typename VectorT::const_iterator>
- const_iterator;
+ typedef pointee_iterator<typename VectorT::const_iterator> const_iterator;
const_iterator begin() const { return Vector.begin(); }
const_iterator end() const { return Vector.end(); }
@@ -735,31 +695,9 @@ template <typename T>
class FoldingSetNodeWrapper : public FoldingSetNode {
T data;
public:
- explicit FoldingSetNodeWrapper(const T &x) : data(x) {}
- virtual ~FoldingSetNodeWrapper() {}
-
- template<typename A1>
- explicit FoldingSetNodeWrapper(const A1 &a1)
- : data(a1) {}
-
- template <typename A1, typename A2>
- explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2)
- : data(a1,a2) {}
-
- template <typename A1, typename A2, typename A3>
- explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3)
- : data(a1,a2,a3) {}
-
- template <typename A1, typename A2, typename A3, typename A4>
- explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3,
- const A4 &a4)
- : data(a1,a2,a3,a4) {}
-
- template <typename A1, typename A2, typename A3, typename A4, typename A5>
- explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3,
- const A4 &a4, const A5 &a5)
- : data(a1,a2,a3,a4,a5) {}
-
+ template <typename... Ts>
+ explicit FoldingSetNodeWrapper(Ts &&... Args)
+ : data(std::forward<Ts>(Args)...) {}
void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); }
diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h
index abf02b8cc9d5..77e6d77b1b8e 100644
--- a/include/llvm/ADT/Hashing.h
+++ b/include/llvm/ADT/Hashing.h
@@ -55,12 +55,6 @@
#include <iterator>
#include <utility>
-// Allow detecting C++11 feature availability when building with Clang without
-// breaking other compilers.
-#ifndef __has_feature
-# define __has_feature(x) 0
-#endif
-
namespace llvm {
/// \brief An opaque object representing a hash code.
@@ -81,7 +75,7 @@ class hash_code {
public:
/// \brief Default construct a hash_code.
/// Note that this leaves the value uninitialized.
- hash_code() {}
+ hash_code() = default;
/// \brief Form a hash code directly from a numerical value.
hash_code(size_t value) : value(value) {}
@@ -553,8 +547,6 @@ public:
return buffer_ptr;
}
-#if defined(__has_feature) && __has_feature(__cxx_variadic_templates__)
-
/// \brief Recursive, variadic combining method.
///
/// This function recurses through each argument, combining that argument
@@ -568,53 +560,6 @@ public:
return combine(length, buffer_ptr, buffer_end, args...);
}
-#else
- // Manually expanded recursive combining methods. See variadic above for
- // documentation.
-
- template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
- hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
- const T1 &arg1, const T2 &arg2, const T3 &arg3,
- const T4 &arg4, const T5 &arg5, const T6 &arg6) {
- buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
- return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5, arg6);
- }
- template <typename T1, typename T2, typename T3, typename T4, typename T5>
- hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
- const T1 &arg1, const T2 &arg2, const T3 &arg3,
- const T4 &arg4, const T5 &arg5) {
- buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
- return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5);
- }
- template <typename T1, typename T2, typename T3, typename T4>
- hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
- const T1 &arg1, const T2 &arg2, const T3 &arg3,
- const T4 &arg4) {
- buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
- return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4);
- }
- template <typename T1, typename T2, typename T3>
- hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
- const T1 &arg1, const T2 &arg2, const T3 &arg3) {
- buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
- return combine(length, buffer_ptr, buffer_end, arg2, arg3);
- }
- template <typename T1, typename T2>
- hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
- const T1 &arg1, const T2 &arg2) {
- buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
- return combine(length, buffer_ptr, buffer_end, arg2);
- }
- template <typename T1>
- hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
- const T1 &arg1) {
- buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
- return combine(length, buffer_ptr, buffer_end);
- }
-
-#endif
-
/// \brief Base case for recursive, variadic combining.
///
/// The base case when combining arguments recursively is reached when all
@@ -643,9 +588,6 @@ public:
} // namespace detail
} // namespace hashing
-
-#if __has_feature(__cxx_variadic_templates__)
-
/// \brief Combine values into a single hash_code.
///
/// This routine accepts a varying number of arguments of any type. It will
@@ -663,52 +605,6 @@ template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
return helper.combine(0, helper.buffer, helper.buffer + 64, args...);
}
-#else
-
-// What follows are manually exploded overloads for each argument width. See
-// the above variadic definition for documentation and specification.
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
-hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
- const T4 &arg4, const T5 &arg5, const T6 &arg6) {
- ::llvm::hashing::detail::hash_combine_recursive_helper helper;
- return helper.combine(0, helper.buffer, helper.buffer + 64,
- arg1, arg2, arg3, arg4, arg5, arg6);
-}
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
- const T4 &arg4, const T5 &arg5) {
- ::llvm::hashing::detail::hash_combine_recursive_helper helper;
- return helper.combine(0, helper.buffer, helper.buffer + 64,
- arg1, arg2, arg3, arg4, arg5);
-}
-template <typename T1, typename T2, typename T3, typename T4>
-hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
- const T4 &arg4) {
- ::llvm::hashing::detail::hash_combine_recursive_helper helper;
- return helper.combine(0, helper.buffer, helper.buffer + 64,
- arg1, arg2, arg3, arg4);
-}
-template <typename T1, typename T2, typename T3>
-hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) {
- ::llvm::hashing::detail::hash_combine_recursive_helper helper;
- return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2, arg3);
-}
-template <typename T1, typename T2>
-hash_code hash_combine(const T1 &arg1, const T2 &arg2) {
- ::llvm::hashing::detail::hash_combine_recursive_helper helper;
- return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2);
-}
-template <typename T1>
-hash_code hash_combine(const T1 &arg1) {
- ::llvm::hashing::detail::hash_combine_recursive_helper helper;
- return helper.combine(0, helper.buffer, helper.buffer + 64, arg1);
-}
-
-#endif
-
-
// Implementation details for implementations of hash_value overloads provided
// here.
namespace hashing {
diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h
index 7f0c239423bd..748d3e4bf9ff 100644
--- a/include/llvm/ADT/ImmutableList.h
+++ b/include/llvm/ADT/ImmutableList.h
@@ -33,8 +33,8 @@ class ImmutableListImpl : public FoldingSetNode {
friend class ImmutableListFactory<T>;
- void operator=(const ImmutableListImpl&) LLVM_DELETED_FUNCTION;
- ImmutableListImpl(const ImmutableListImpl&) LLVM_DELETED_FUNCTION;
+ void operator=(const ImmutableListImpl&) = delete;
+ ImmutableListImpl(const ImmutableListImpl&) = delete;
public:
const T& getHead() const { return Head; }
diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h
index 11f281be3d23..438dec2333c5 100644
--- a/include/llvm/ADT/ImmutableMap.h
+++ b/include/llvm/ADT/ImmutableMap.h
@@ -122,8 +122,8 @@ public:
}
private:
- Factory(const Factory& RHS) LLVM_DELETED_FUNCTION;
- void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION;
+ Factory(const Factory& RHS) = delete;
+ void operator=(const Factory& RHS) = delete;
};
bool contains(key_type_ref K) const {
@@ -203,33 +203,14 @@ public:
// Iterators.
//===--------------------------------------------------===//
- class iterator {
- typename TreeTy::iterator itr;
-
- iterator() {}
- iterator(TreeTy* t) : itr(t) {}
+ class iterator : public ImutAVLValueIterator<ImmutableMap> {
+ iterator() = default;
+ explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
friend class ImmutableMap;
public:
- typedef ptrdiff_t difference_type;
- typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type value_type;
- typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type_ref reference;
- typedef typename iterator::value_type *pointer;
- typedef std::bidirectional_iterator_tag iterator_category;
-
- typename iterator::reference operator*() const { return itr->getValue(); }
- typename iterator::pointer operator->() const { return &itr->getValue(); }
-
- key_type_ref getKey() const { return itr->getValue().first; }
- data_type_ref getData() const { return itr->getValue().second; }
-
- iterator& operator++() { ++itr; return *this; }
- iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
- iterator& operator--() { --itr; return *this; }
- iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
-
- bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
- bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
+ key_type_ref getKey() const { return (*this)->first; }
+ data_type_ref getData() const { return (*this)->second; }
};
iterator begin() const { return iterator(Root); }
@@ -376,30 +357,17 @@ public:
//===--------------------------------------------------===//
// Iterators.
//===--------------------------------------------------===//
-
- class iterator {
- typename TreeTy::iterator itr;
-
- iterator() {}
- iterator(TreeTy* t) : itr(t) {}
+
+ class iterator : public ImutAVLValueIterator<ImmutableMapRef> {
+ iterator() = default;
+ explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
friend class ImmutableMapRef;
-
+
public:
- value_type_ref operator*() const { return itr->getValue(); }
- value_type* operator->() const { return &itr->getValue(); }
-
- key_type_ref getKey() const { return itr->getValue().first; }
- data_type_ref getData() const { return itr->getValue().second; }
-
-
- iterator& operator++() { ++itr; return *this; }
- iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
- iterator& operator--() { --itr; return *this; }
- iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
- bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
- bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
+ key_type_ref getKey() const { return (*this)->first; }
+ data_type_ref getData() const { return (*this)->second; }
};
-
+
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h
index 5a3d8ad21f92..87026f019fec 100644
--- a/include/llvm/ADT/ImmutableSet.h
+++ b/include/llvm/ADT/ImmutableSet.h
@@ -142,13 +142,13 @@ public:
iterator RItr = RHS.begin(), REnd = RHS.end();
while (LItr != LEnd && RItr != REnd) {
- if (*LItr == *RItr) {
+ if (&*LItr == &*RItr) {
LItr.skipSubTree();
RItr.skipSubTree();
continue;
}
- if (!LItr->isElementEqual(*RItr))
+ if (!LItr->isElementEqual(&*RItr))
return false;
++LItr;
@@ -293,8 +293,8 @@ private:
height = h;
}
- static inline
- uint32_t computeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) {
+ static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
+ value_type_ref V) {
uint32_t digest = 0;
if (L)
@@ -311,7 +311,7 @@ private:
return digest;
}
- inline uint32_t computeDigest() {
+ uint32_t computeDigest() {
// Check the lowest bit to determine if digest has actually been
// pre-computed.
if (hasCachedDigest())
@@ -429,9 +429,7 @@ protected:
value_type_ref getValue(TreeTy* T) const { return T->value; }
// Make sure the index is not the Tombstone or Entry key of the DenseMap.
- static inline unsigned maskCacheIndex(unsigned I) {
- return (I & ~0x02);
- }
+ static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
unsigned hl = getHeight(L);
@@ -444,7 +442,7 @@ protected:
typename TreeTy::iterator& TE) {
typename TreeTy::iterator I = T->begin(), E = T->end();
for ( ; I!=E ; ++I, ++TI) {
- if (TI == TE || !I->isElementEqual(*TI))
+ if (TI == TE || !I->isElementEqual(&*TI))
return false;
}
return true;
@@ -647,24 +645,26 @@ public:
//===----------------------------------------------------------------------===//
template <typename ImutInfo>
-class ImutAVLTreeGenericIterator {
+class ImutAVLTreeGenericIterator
+ : public std::iterator<std::bidirectional_iterator_tag,
+ ImutAVLTree<ImutInfo>> {
SmallVector<uintptr_t,20> stack;
public:
enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
Flags=0x3 };
typedef ImutAVLTree<ImutInfo> TreeTy;
- typedef ImutAVLTreeGenericIterator<ImutInfo> _Self;
- inline ImutAVLTreeGenericIterator() {}
- inline ImutAVLTreeGenericIterator(const TreeTy* Root) {
+ ImutAVLTreeGenericIterator() {}
+ ImutAVLTreeGenericIterator(const TreeTy *Root) {
if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
}
- TreeTy* operator*() const {
+ TreeTy &operator*() const {
assert(!stack.empty());
- return reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
+ return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags);
}
+ TreeTy *operator->() const { return &*this; }
uintptr_t getVisitState() const {
assert(!stack.empty());
@@ -695,13 +695,15 @@ public:
}
}
- inline bool operator==(const _Self& x) const {
+ bool operator==(const ImutAVLTreeGenericIterator &x) const {
return stack == x.stack;
}
- inline bool operator!=(const _Self& x) const { return !operator==(x); }
+ bool operator!=(const ImutAVLTreeGenericIterator &x) const {
+ return !(*this == x);
+ }
- _Self& operator++() {
+ ImutAVLTreeGenericIterator &operator++() {
assert(!stack.empty());
TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
assert(Current);
@@ -727,7 +729,7 @@ public:
return *this;
}
- _Self& operator--() {
+ ImutAVLTreeGenericIterator &operator--() {
assert(!stack.empty());
TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
assert(Current);
@@ -754,30 +756,34 @@ public:
};
template <typename ImutInfo>
-class ImutAVLTreeInOrderIterator {
+class ImutAVLTreeInOrderIterator
+ : public std::iterator<std::bidirectional_iterator_tag,
+ ImutAVLTree<ImutInfo>> {
typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy;
InternalIteratorTy InternalItr;
public:
typedef ImutAVLTree<ImutInfo> TreeTy;
- typedef ImutAVLTreeInOrderIterator<ImutInfo> _Self;
ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
- if (Root) operator++(); // Advance to first element.
+ if (Root)
+ ++*this; // Advance to first element.
}
ImutAVLTreeInOrderIterator() : InternalItr() {}
- inline bool operator==(const _Self& x) const {
+ bool operator==(const ImutAVLTreeInOrderIterator &x) const {
return InternalItr == x.InternalItr;
}
- inline bool operator!=(const _Self& x) const { return !operator==(x); }
+ bool operator!=(const ImutAVLTreeInOrderIterator &x) const {
+ return !(*this == x);
+ }
- inline TreeTy* operator*() const { return *InternalItr; }
- inline TreeTy* operator->() const { return *InternalItr; }
+ TreeTy &operator*() const { return *InternalItr; }
+ TreeTy *operator->() const { return &*InternalItr; }
- inline _Self& operator++() {
+ ImutAVLTreeInOrderIterator &operator++() {
do ++InternalItr;
while (!InternalItr.atEnd() &&
InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
@@ -785,7 +791,7 @@ public:
return *this;
}
- inline _Self& operator--() {
+ ImutAVLTreeInOrderIterator &operator--() {
do --InternalItr;
while (!InternalItr.atBeginning() &&
InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
@@ -793,7 +799,7 @@ public:
return *this;
}
- inline void skipSubTree() {
+ void skipSubTree() {
InternalItr.skipToParent();
while (!InternalItr.atEnd() &&
@@ -802,6 +808,24 @@ public:
}
};
+/// Generic iterator that wraps a T::TreeTy::iterator and exposes
+/// iterator::getValue() on dereference.
+template <typename T>
+struct ImutAVLValueIterator
+ : iterator_adaptor_base<
+ ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
+ typename std::iterator_traits<
+ typename T::TreeTy::iterator>::iterator_category,
+ const typename T::value_type> {
+ ImutAVLValueIterator() = default;
+ explicit ImutAVLValueIterator(typename T::TreeTy *Tree)
+ : ImutAVLValueIterator::iterator_adaptor_base(Tree) {}
+
+ typename ImutAVLValueIterator::reference operator*() const {
+ return this->I->getValue();
+ }
+};
+
//===----------------------------------------------------------------------===//
// Trait classes for Profile information.
//===----------------------------------------------------------------------===//
@@ -814,7 +838,7 @@ struct ImutProfileInfo {
typedef const T value_type;
typedef const T& value_type_ref;
- static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
+ static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
FoldingSetTrait<T>::Profile(X,ID);
}
};
@@ -825,7 +849,7 @@ struct ImutProfileInteger {
typedef const T value_type;
typedef const T& value_type_ref;
- static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
+ static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddInteger(X);
}
};
@@ -852,7 +876,7 @@ struct ImutProfileInfo<bool> {
typedef const bool value_type;
typedef const bool& value_type_ref;
- static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
+ static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddBoolean(X);
}
};
@@ -865,7 +889,7 @@ struct ImutProfileInfo<T*> {
typedef const T* value_type;
typedef value_type value_type_ref;
- static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) {
+ static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddPointer(X);
}
};
@@ -890,18 +914,18 @@ struct ImutContainerInfo : public ImutProfileInfo<T> {
typedef bool data_type;
typedef bool data_type_ref;
- static inline key_type_ref KeyOfValue(value_type_ref D) { return D; }
- static inline data_type_ref DataOfValue(value_type_ref) { return true; }
+ static key_type_ref KeyOfValue(value_type_ref D) { return D; }
+ static data_type_ref DataOfValue(value_type_ref) { return true; }
- static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) {
+ static bool isEqual(key_type_ref LHS, key_type_ref RHS) {
return std::equal_to<key_type>()(LHS,RHS);
}
- static inline bool isLess(key_type_ref LHS, key_type_ref RHS) {
+ static bool isLess(key_type_ref LHS, key_type_ref RHS) {
return std::less<key_type>()(LHS,RHS);
}
- static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; }
+ static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
};
/// ImutContainerInfo - Specialization for pointer values to treat pointers
@@ -916,18 +940,14 @@ struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
typedef bool data_type;
typedef bool data_type_ref;
- static inline key_type_ref KeyOfValue(value_type_ref D) { return D; }
- static inline data_type_ref DataOfValue(value_type_ref) { return true; }
+ static key_type_ref KeyOfValue(value_type_ref D) { return D; }
+ static data_type_ref DataOfValue(value_type_ref) { return true; }
- static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) {
- return LHS == RHS;
- }
+ static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
- static inline bool isLess(key_type_ref LHS, key_type_ref RHS) {
- return LHS < RHS;
- }
+ static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
- static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; }
+ static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
};
//===----------------------------------------------------------------------===//
@@ -1014,8 +1034,8 @@ public:
}
private:
- Factory(const Factory& RHS) LLVM_DELETED_FUNCTION;
- void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION;
+ Factory(const Factory& RHS) = delete;
+ void operator=(const Factory& RHS) = delete;
};
friend class Factory;
@@ -1059,31 +1079,7 @@ public:
// Iterators.
//===--------------------------------------------------===//
- class iterator {
- typename TreeTy::iterator itr;
-
- iterator() {}
- iterator(TreeTy* t) : itr(t) {}
- friend class ImmutableSet<ValT,ValInfo>;
-
- public:
- typedef ptrdiff_t difference_type;
- typedef typename ImmutableSet<ValT,ValInfo>::value_type value_type;
- typedef typename ImmutableSet<ValT,ValInfo>::value_type_ref reference;
- typedef typename iterator::value_type *pointer;
- typedef std::bidirectional_iterator_tag iterator_category;
-
- typename iterator::reference operator*() const { return itr->getValue(); }
- typename iterator::pointer operator->() const { return &(operator*()); }
-
- iterator& operator++() { ++itr; return *this; }
- iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
- iterator& operator--() { --itr; return *this; }
- iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
-
- bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
- bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
- };
+ typedef ImutAVLValueIterator<ImmutableSet> iterator;
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
@@ -1094,13 +1090,11 @@ public:
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
- static inline void Profile(FoldingSetNodeID& ID, const ImmutableSet& S) {
+ static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
ID.AddPointer(S.Root);
}
- inline void Profile(FoldingSetNodeID& ID) const {
- return Profile(ID,*this);
- }
+ void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
//===--------------------------------------------------===//
// For testing.
@@ -1150,7 +1144,7 @@ public:
if (Root) { Root->release(); }
}
- static inline ImmutableSetRef getEmptySet(FactoryTy *F) {
+ static ImmutableSetRef getEmptySet(FactoryTy *F) {
return ImmutableSetRef(0, F);
}
@@ -1195,21 +1189,7 @@ public:
// Iterators.
//===--------------------------------------------------===//
- class iterator {
- typename TreeTy::iterator itr;
- iterator(TreeTy* t) : itr(t) {}
- friend class ImmutableSetRef<ValT,ValInfo>;
- public:
- iterator() {}
- inline value_type_ref operator*() const { return itr->getValue(); }
- inline iterator& operator++() { ++itr; return *this; }
- inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
- inline iterator& operator--() { --itr; return *this; }
- inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
- inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
- inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
- inline value_type *operator->() const { return &(operator*()); }
- };
+ typedef ImutAVLValueIterator<ImmutableSetRef> iterator;
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
@@ -1220,13 +1200,11 @@ public:
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
- static inline void Profile(FoldingSetNodeID& ID, const ImmutableSetRef& S) {
+ static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
ID.AddPointer(S.Root);
}
- inline void Profile(FoldingSetNodeID& ID) const {
- return Profile(ID,*this);
- }
+ void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
//===--------------------------------------------------===//
// For testing.
diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h
index 2ffb5058e5bb..5ba85c027920 100644
--- a/include/llvm/ADT/IndexedMap.h
+++ b/include/llvm/ADT/IndexedMap.h
@@ -21,16 +21,19 @@
#define LLVM_ADT_INDEXEDMAP_H
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <functional>
-#include <vector>
namespace llvm {
template <typename T, typename ToIndexT = llvm::identity<unsigned> >
class IndexedMap {
typedef typename ToIndexT::argument_type IndexT;
- typedef std::vector<T> StorageT;
+ // Prefer SmallVector with zero inline storage over std::vector. IndexedMaps
+ // can grow very large and SmallVector grows more efficiently as long as T
+ // is trivially copyable.
+ typedef SmallVector<T, 0> StorageT;
StorageT storage_;
T nullVal_;
ToIndexT toIndex_;
diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h
index 46549eed9939..f8843b2a4e50 100644
--- a/include/llvm/ADT/IntervalMap.h
+++ b/include/llvm/ADT/IntervalMap.h
@@ -101,6 +101,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/RecyclingAllocator.h"
#include <iterator>
@@ -496,7 +497,7 @@ public:
NodeRef() {}
/// operator bool - Detect a null ref.
- LLVM_EXPLICIT operator bool() const { return pip.getOpaqueValue(); }
+ explicit operator bool() const { return pip.getOpaqueValue(); }
/// NodeRef - Create a reference to the node p with n elements.
template <typename NodeT>
@@ -953,11 +954,6 @@ class IntervalMap {
RootBranch node;
};
- enum {
- RootDataSize = sizeof(RootBranchData) > sizeof(RootLeaf) ?
- sizeof(RootBranchData) : sizeof(RootLeaf)
- };
-
public:
typedef typename Sizer::Allocator Allocator;
typedef KeyT KeyType;
@@ -966,13 +962,7 @@ public:
private:
// The root data is either a RootLeaf or a RootBranchData instance.
- // We can't put them in a union since C++03 doesn't allow non-trivial
- // constructors in unions.
- // Instead, we use a char array with pointer alignment. The alignment is
- // ensured by the allocator member in the class, but still verified in the
- // constructor. We don't support keys or values that are more aligned than a
- // pointer.
- char data[RootDataSize];
+ AlignedCharArrayUnion<RootLeaf, RootBranchData> data;
// Tree height.
// 0: Leaves in root.
@@ -993,7 +983,7 @@ private:
const char *d;
T *t;
} u;
- u.d = data;
+ u.d = data.buffer;
return *u.t;
}
@@ -1051,7 +1041,7 @@ private:
public:
explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) {
- assert((uintptr_t(data) & (alignOf<RootLeaf>() - 1)) == 0 &&
+ assert((uintptr_t(data.buffer) & (alignOf<RootLeaf>() - 1)) == 0 &&
"Insufficient alignment");
new(&rootLeaf()) RootLeaf();
}
diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h
index c859c98d06b2..65b2da793d7c 100644
--- a/include/llvm/ADT/IntrusiveRefCntPtr.h
+++ b/include/llvm/ADT/IntrusiveRefCntPtr.h
@@ -21,10 +21,9 @@
#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
#define LLVM_ADT_INTRUSIVEREFCNTPTR_H
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
#include <atomic>
-#include <memory>
+#include <cassert>
+#include <cstddef>
namespace llvm {
@@ -84,7 +83,7 @@ namespace llvm {
friend struct IntrusiveRefCntPtrInfo;
};
-
+
template <typename T> struct IntrusiveRefCntPtrInfo {
static void retain(T *obj) { obj->Retain(); }
static void release(T *obj) { obj->Release(); }
@@ -114,7 +113,7 @@ public:
delete static_cast<const Derived*>(this);
}
};
-
+
//===----------------------------------------------------------------------===//
/// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
/// that assumes the wrapped object has a reference count associated
@@ -177,7 +176,7 @@ public:
T* get() const { return Obj; }
- LLVM_EXPLICIT operator bool() const { return Obj; }
+ explicit operator bool() const { return Obj; }
void swap(IntrusiveRefCntPtr& other) {
T* tmp = other.Obj;
@@ -268,6 +267,8 @@ public:
// LLVM-style downcasting support for IntrusiveRefCntPtr objects
//===----------------------------------------------------------------------===//
+ template <typename From> struct simplify_type;
+
template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
typedef T* SimpleType;
static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h
index 1331b15b2d29..f19a50b7ba84 100644
--- a/include/llvm/ADT/MapVector.h
+++ b/include/llvm/ADT/MapVector.h
@@ -67,6 +67,11 @@ public:
Vector.clear();
}
+ void swap(MapVector &RHS) {
+ std::swap(Map, RHS.Map);
+ std::swap(Vector, RHS.Vector);
+ }
+
ValueT &operator[](const KeyT &Key) {
std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0);
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
diff --git a/include/llvm/ADT/None.h b/include/llvm/ADT/None.h
index 5793bd2faef4..d69ec17c15f9 100644
--- a/include/llvm/ADT/None.h
+++ b/include/llvm/ADT/None.h
@@ -19,9 +19,8 @@
namespace llvm {
/// \brief A simple null object to allow implicit construction of Optional<T>
/// and similar types without having to spell out the specialization's name.
-enum NoneType {
- None
-};
+enum class NoneType { None };
+const NoneType None = None;
}
#endif
diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h
index 591872e6591a..855ab890392e 100644
--- a/include/llvm/ADT/Optional.h
+++ b/include/llvm/ADT/Optional.h
@@ -70,8 +70,6 @@ public:
return *this;
}
-#if LLVM_HAS_VARIADIC_TEMPLATES
-
/// Create a new object by constructing it in place with the given arguments.
template<typename ...ArgTypes>
void emplace(ArgTypes &&...Args) {
@@ -80,51 +78,6 @@ public:
new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
}
-#else
-
- /// Create a new object by default-constructing it in place.
- void emplace() {
- reset();
- hasVal = true;
- new (storage.buffer) T();
- }
-
- /// Create a new object by constructing it in place with the given arguments.
- template<typename T1>
- void emplace(T1 &&A1) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<T1>(A1));
- }
-
- /// Create a new object by constructing it in place with the given arguments.
- template<typename T1, typename T2>
- void emplace(T1 &&A1, T2 &&A2) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2));
- }
-
- /// Create a new object by constructing it in place with the given arguments.
- template<typename T1, typename T2, typename T3>
- void emplace(T1 &&A1, T2 &&A2, T3 &&A3) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
- std::forward<T3>(A3));
- }
-
- /// Create a new object by constructing it in place with the given arguments.
- template<typename T1, typename T2, typename T3, typename T4>
- void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
- std::forward<T3>(A3), std::forward<T4>(A4));
- }
-
-#endif // LLVM_HAS_VARIADIC_TEMPLATES
-
static inline Optional create(const T* y) {
return y ? Optional(*y) : Optional();
}
@@ -168,7 +121,7 @@ public:
const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
- LLVM_EXPLICIT operator bool() const { return hasVal; }
+ explicit operator bool() const { return hasVal; }
bool hasValue() const { return hasVal; }
const T* operator->() const { return getPointer(); }
T* operator->() { return getPointer(); }
diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h
index a6dddd277621..f27b81113ec5 100644
--- a/include/llvm/ADT/PointerUnion.h
+++ b/include/llvm/ADT/PointerUnion.h
@@ -61,7 +61,7 @@ namespace llvm {
NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
};
};
-
+
/// PointerUnion - This implements a discriminated union of two pointer types,
/// and keeps the discriminator bit-mangled into the low bits of the pointer.
/// This allows the implementation to be extremely efficient in space, but
@@ -80,7 +80,7 @@ namespace llvm {
template <typename PT1, typename PT2>
class PointerUnion {
public:
- typedef PointerIntPair<void*, 1, bool,
+ typedef PointerIntPair<void*, 1, bool,
PointerUnionUIntTraits<PT1,PT2> > ValTy;
private:
ValTy Val;
@@ -96,14 +96,14 @@ namespace llvm {
public:
PointerUnion() {}
-
+
PointerUnion(PT1 V) : Val(
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
}
PointerUnion(PT2 V) : Val(
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
}
-
+
/// isNull - Return true if the pointer held in the union is null,
/// regardless of which type it is.
bool isNull() const {
@@ -111,7 +111,7 @@ namespace llvm {
// we recursively strip off low bits if we have a nested PointerUnion.
return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
}
- LLVM_EXPLICIT operator bool() const { return !isNull(); }
+ explicit operator bool() const { return !isNull(); }
/// is<T>() return true if the Union currently holds the type matching T.
template<typename T>
@@ -123,7 +123,7 @@ namespace llvm {
int TyNo = Ty::Num;
return static_cast<int>(Val.getInt()) == TyNo;
}
-
+
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@@ -131,7 +131,7 @@ namespace llvm {
assert(is<T>() && "Invalid accessor called");
return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
}
-
+
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@@ -160,7 +160,7 @@ namespace llvm {
Val.initWithPointer(nullptr);
return *this;
}
-
+
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
const PointerUnion &operator=(const PT1 &RHS) {
@@ -174,7 +174,7 @@ namespace llvm {
1);
return *this;
}
-
+
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
static inline PointerUnion getFromOpaqueValue(void *VP) {
PointerUnion V;
@@ -195,6 +195,12 @@ namespace llvm {
return lhs.getOpaqueValue() != rhs.getOpaqueValue();
}
+ template<typename PT1, typename PT2>
+ static bool operator<(PointerUnion<PT1, PT2> lhs,
+ PointerUnion<PT1, PT2> rhs) {
+ return lhs.getOpaqueValue() < rhs.getOpaqueValue();
+ }
+
// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
// # low bits available = min(PT1bits,PT2bits)-1.
template<typename PT1, typename PT2>
@@ -208,16 +214,16 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
}
-
+
// The number of bits available are the min of the two pointer types.
enum {
- NumLowBitsAvailable =
+ NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
::NumLowBitsAvailable
};
};
-
-
+
+
/// PointerUnion3 - This is a pointer union of three pointer types. See
/// documentation for PointerUnion for usage.
template <typename PT1, typename PT2, typename PT3>
@@ -233,7 +239,7 @@ namespace llvm {
IsInnerUnion(ValTy val) : Val(val) { }
template<typename T>
int is() const {
- return Val.template is<InnerUnion>() &&
+ return Val.template is<InnerUnion>() &&
Val.template get<InnerUnion>().template is<T>();
}
template<typename T>
@@ -257,7 +263,7 @@ namespace llvm {
public:
PointerUnion3() {}
-
+
PointerUnion3(PT1 V) {
Val = InnerUnion(V);
}
@@ -267,12 +273,12 @@ namespace llvm {
PointerUnion3(PT3 V) {
Val = V;
}
-
+
/// isNull - Return true if the pointer held in the union is null,
/// regardless of which type it is.
bool isNull() const { return Val.isNull(); }
- LLVM_EXPLICIT operator bool() const { return !isNull(); }
-
+ explicit operator bool() const { return !isNull(); }
+
/// is<T>() return true if the Union currently holds the type matching T.
template<typename T>
int is() const {
@@ -283,7 +289,7 @@ namespace llvm {
>::Return Ty;
return Ty(Val).template is<T>();
}
-
+
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@@ -296,7 +302,7 @@ namespace llvm {
>::Return Ty;
return Ty(Val).template get<T>();
}
-
+
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@@ -310,7 +316,7 @@ namespace llvm {
Val = nullptr;
return *this;
}
-
+
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
const PointerUnion3 &operator=(const PT1 &RHS) {
@@ -325,7 +331,7 @@ namespace llvm {
Val = RHS;
return *this;
}
-
+
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
static inline PointerUnion3 getFromOpaqueValue(void *VP) {
PointerUnion3 V;
@@ -333,7 +339,7 @@ namespace llvm {
return V;
}
};
-
+
// Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
template<typename PT1, typename PT2, typename PT3>
@@ -347,10 +353,10 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
}
-
+
// The number of bits available are the min of the two pointer types.
enum {
- NumLowBitsAvailable =
+ NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
::NumLowBitsAvailable
};
@@ -368,7 +374,7 @@ namespace llvm {
ValTy Val;
public:
PointerUnion4() {}
-
+
PointerUnion4(PT1 V) {
Val = InnerUnion1(V);
}
@@ -381,12 +387,12 @@ namespace llvm {
PointerUnion4(PT4 V) {
Val = InnerUnion2(V);
}
-
+
/// isNull - Return true if the pointer held in the union is null,
/// regardless of which type it is.
bool isNull() const { return Val.isNull(); }
- LLVM_EXPLICIT operator bool() const { return !isNull(); }
-
+ explicit operator bool() const { return !isNull(); }
+
/// is<T>() return true if the Union currently holds the type matching T.
template<typename T>
int is() const {
@@ -395,10 +401,10 @@ namespace llvm {
::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
>::Return Ty;
- return Val.template is<Ty>() &&
+ return Val.template is<Ty>() &&
Val.template get<Ty>().template is<T>();
}
-
+
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@@ -411,7 +417,7 @@ namespace llvm {
>::Return Ty;
return Val.template get<Ty>().template get<T>();
}
-
+
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@@ -425,7 +431,7 @@ namespace llvm {
Val = nullptr;
return *this;
}
-
+
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
const PointerUnion4 &operator=(const PT1 &RHS) {
@@ -444,7 +450,7 @@ namespace llvm {
Val = InnerUnion2(RHS);
return *this;
}
-
+
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
static inline PointerUnion4 getFromOpaqueValue(void *VP) {
PointerUnion4 V;
@@ -452,7 +458,7 @@ namespace llvm {
return V;
}
};
-
+
// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
template<typename PT1, typename PT2, typename PT3, typename PT4>
@@ -466,10 +472,10 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
}
-
+
// The number of bits available are the min of the two pointer types.
enum {
- NumLowBitsAvailable =
+ NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
::NumLowBitsAvailable
};
diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h
index dfadc3b85db6..759a2db24f2a 100644
--- a/include/llvm/ADT/PostOrderIterator.h
+++ b/include/llvm/ADT/PostOrderIterator.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/iterator_range.h"
#include <set>
#include <vector>
@@ -111,53 +112,52 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
}
}
- inline po_iterator(NodeType *BB) {
+ po_iterator(NodeType *BB) {
this->insertEdge((NodeType*)nullptr, BB);
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
traverseChild();
}
- inline po_iterator() {} // End is when stack is empty.
+ po_iterator() {} // End is when stack is empty.
- inline po_iterator(NodeType *BB, SetType &S) :
- po_iterator_storage<SetType, ExtStorage>(S) {
+ po_iterator(NodeType *BB, SetType &S)
+ : po_iterator_storage<SetType, ExtStorage>(S) {
if (this->insertEdge((NodeType*)nullptr, BB)) {
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
traverseChild();
}
}
- inline po_iterator(SetType &S) :
- po_iterator_storage<SetType, ExtStorage>(S) {
+ po_iterator(SetType &S)
+ : po_iterator_storage<SetType, ExtStorage>(S) {
} // End is when stack is empty.
public:
typedef typename super::pointer pointer;
- typedef po_iterator<GraphT, SetType, ExtStorage, GT> _Self;
// Provide static "constructors"...
- static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); }
- static inline _Self end (GraphT G) { return _Self(); }
+ static po_iterator begin(GraphT G) {
+ return po_iterator(GT::getEntryNode(G));
+ }
+ static po_iterator end(GraphT G) { return po_iterator(); }
- static inline _Self begin(GraphT G, SetType &S) {
- return _Self(GT::getEntryNode(G), S);
+ static po_iterator begin(GraphT G, SetType &S) {
+ return po_iterator(GT::getEntryNode(G), S);
}
- static inline _Self end (GraphT G, SetType &S) { return _Self(S); }
+ static po_iterator end(GraphT G, SetType &S) { return po_iterator(S); }
- inline bool operator==(const _Self& x) const {
+ bool operator==(const po_iterator &x) const {
return VisitStack == x.VisitStack;
}
- inline bool operator!=(const _Self& x) const { return !operator==(x); }
+ bool operator!=(const po_iterator &x) const { return !(*this == x); }
- inline pointer operator*() const {
- return VisitStack.back().first;
- }
+ pointer operator*() const { return VisitStack.back().first; }
// This is a nonstandard operator-> that dereferences the pointer an extra
// time... so that you can actually call methods ON the BasicBlock, because
// the contained type is a pointer. This allows BBIt->getTerminator() f.e.
//
- inline NodeType *operator->() const { return operator*(); }
+ NodeType *operator->() const { return **this; }
- inline _Self& operator++() { // Preincrement
+ po_iterator &operator++() { // Preincrement
this->finishPostorder(VisitStack.back().first);
VisitStack.pop_back();
if (!VisitStack.empty())
@@ -165,17 +165,23 @@ public:
return *this;
}
- inline _Self operator++(int) { // Postincrement
- _Self tmp = *this; ++*this; return tmp;
+ po_iterator operator++(int) { // Postincrement
+ po_iterator tmp = *this;
+ ++*this;
+ return tmp;
}
};
// Provide global constructors that automatically figure out correct types...
//
template <class T>
-po_iterator<T> po_begin(T G) { return po_iterator<T>::begin(G); }
+po_iterator<T> po_begin(const T &G) { return po_iterator<T>::begin(G); }
template <class T>
-po_iterator<T> po_end (T G) { return po_iterator<T>::end(G); }
+po_iterator<T> po_end (const T &G) { return po_iterator<T>::end(G); }
+
+template <class T> iterator_range<po_iterator<T>> post_order(const T &G) {
+ return make_range(po_begin(G), po_end(G));
+}
// Provide global definitions of external postorder iterators...
template<class T, class SetType=std::set<typename GraphTraits<T>::NodeType*> >
@@ -194,6 +200,11 @@ po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) {
return po_ext_iterator<T, SetType>::end(G, S);
}
+template <class T, class SetType>
+iterator_range<po_ext_iterator<T, SetType>> post_order_ext(const T &G, SetType &S) {
+ return make_range(po_ext_begin(G, S), po_ext_end(G, S));
+}
+
// Provide global definitions of inverse post order iterators...
template <class T,
class SetType = std::set<typename GraphTraits<T>::NodeType*>,
@@ -204,15 +215,20 @@ struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External > {
};
template <class T>
-ipo_iterator<T> ipo_begin(T G, bool Reverse = false) {
+ipo_iterator<T> ipo_begin(const T &G, bool Reverse = false) {
return ipo_iterator<T>::begin(G, Reverse);
}
template <class T>
-ipo_iterator<T> ipo_end(T G){
+ipo_iterator<T> ipo_end(const T &G){
return ipo_iterator<T>::end(G);
}
+template <class T>
+iterator_range<ipo_iterator<T>> inverse_post_order(const T &G, bool Reverse = false) {
+ return make_range(ipo_begin(G, Reverse), ipo_end(G));
+}
+
// Provide global definitions of external inverse postorder iterators...
template <class T,
class SetType = std::set<typename GraphTraits<T>::NodeType*> >
@@ -224,15 +240,21 @@ struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> {
};
template <class T, class SetType>
-ipo_ext_iterator<T, SetType> ipo_ext_begin(T G, SetType &S) {
+ipo_ext_iterator<T, SetType> ipo_ext_begin(const T &G, SetType &S) {
return ipo_ext_iterator<T, SetType>::begin(G, S);
}
template <class T, class SetType>
-ipo_ext_iterator<T, SetType> ipo_ext_end(T G, SetType &S) {
+ipo_ext_iterator<T, SetType> ipo_ext_end(const T &G, SetType &S) {
return ipo_ext_iterator<T, SetType>::end(G, S);
}
+template <class T, class SetType>
+iterator_range<ipo_ext_iterator<T, SetType>>
+inverse_post_order_ext(const T &G, SetType &S) {
+ return make_range(ipo_ext_begin(G, S), ipo_ext_end(G, S));
+}
+
//===--------------------------------------------------------------------===//
// Reverse Post Order CFG iterator code
//===--------------------------------------------------------------------===//
@@ -260,19 +282,17 @@ template<class GraphT, class GT = GraphTraits<GraphT> >
class ReversePostOrderTraversal {
typedef typename GT::NodeType NodeType;
std::vector<NodeType*> Blocks; // Block list in normal PO order
- inline void Initialize(NodeType *BB) {
+ void Initialize(NodeType *BB) {
std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks));
}
public:
typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator;
- inline ReversePostOrderTraversal(GraphT G) {
- Initialize(GT::getEntryNode(G));
- }
+ ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); }
// Because we want a reverse post order, use reverse iterators from the vector
- inline rpo_iterator begin() { return Blocks.rbegin(); }
- inline rpo_iterator end() { return Blocks.rend(); }
+ rpo_iterator begin() { return Blocks.rbegin(); }
+ rpo_iterator end() { return Blocks.rend(); }
};
} // End llvm namespace
diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h
index 4e56e4d74470..b68345a1dcf6 100644
--- a/include/llvm/ADT/STLExtras.h
+++ b/include/llvm/ADT/STLExtras.h
@@ -18,6 +18,8 @@
#define LLVM_ADT_STLEXTRAS_H
#include "llvm/Support/Compiler.h"
+#include <algorithm> // for std::all_of
+#include <cassert>
#include <cstddef> // for std::size_t
#include <cstdlib> // for qsort
#include <functional>
@@ -63,8 +65,6 @@ struct greater_ptr : public std::binary_function<Ty, Ty, bool> {
/// a function_ref.
template<typename Fn> class function_ref;
-#if LLVM_HAS_VARIADIC_TEMPLATES
-
template<typename Ret, typename ...Params>
class function_ref<Ret(Params...)> {
Ret (*callback)(intptr_t callable, Params ...params);
@@ -89,112 +89,6 @@ public:
}
};
-#else
-
-template<typename Ret>
-class function_ref<Ret()> {
- Ret (*callback)(intptr_t callable);
- intptr_t callable;
-
- template<typename Callable>
- static Ret callback_fn(intptr_t callable) {
- return (*reinterpret_cast<Callable*>(callable))();
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable,
- typename std::enable_if<
- !std::is_same<typename std::remove_reference<Callable>::type,
- function_ref>::value>::type * = nullptr)
- : callback(callback_fn<typename std::remove_reference<Callable>::type>),
- callable(reinterpret_cast<intptr_t>(&callable)) {}
- Ret operator()() const { return callback(callable); }
-};
-
-template<typename Ret, typename Param1>
-class function_ref<Ret(Param1)> {
- Ret (*callback)(intptr_t callable, Param1 param1);
- intptr_t callable;
-
- template<typename Callable>
- static Ret callback_fn(intptr_t callable, Param1 param1) {
- return (*reinterpret_cast<Callable*>(callable))(
- std::forward<Param1>(param1));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable,
- typename std::enable_if<
- !std::is_same<typename std::remove_reference<Callable>::type,
- function_ref>::value>::type * = nullptr)
- : callback(callback_fn<typename std::remove_reference<Callable>::type>),
- callable(reinterpret_cast<intptr_t>(&callable)) {}
- Ret operator()(Param1 param1) {
- return callback(callable, std::forward<Param1>(param1));
- }
-};
-
-template<typename Ret, typename Param1, typename Param2>
-class function_ref<Ret(Param1, Param2)> {
- Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2);
- intptr_t callable;
-
- template<typename Callable>
- static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) {
- return (*reinterpret_cast<Callable*>(callable))(
- std::forward<Param1>(param1),
- std::forward<Param2>(param2));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable,
- typename std::enable_if<
- !std::is_same<typename std::remove_reference<Callable>::type,
- function_ref>::value>::type * = nullptr)
- : callback(callback_fn<typename std::remove_reference<Callable>::type>),
- callable(reinterpret_cast<intptr_t>(&callable)) {}
- Ret operator()(Param1 param1, Param2 param2) {
- return callback(callable,
- std::forward<Param1>(param1),
- std::forward<Param2>(param2));
- }
-};
-
-template<typename Ret, typename Param1, typename Param2, typename Param3>
-class function_ref<Ret(Param1, Param2, Param3)> {
- Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3);
- intptr_t callable;
-
- template<typename Callable>
- static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2,
- Param3 param3) {
- return (*reinterpret_cast<Callable*>(callable))(
- std::forward<Param1>(param1),
- std::forward<Param2>(param2),
- std::forward<Param3>(param3));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable,
- typename std::enable_if<
- !std::is_same<typename std::remove_reference<Callable>::type,
- function_ref>::value>::type * = nullptr)
- : callback(callback_fn<typename std::remove_reference<Callable>::type>),
- callable(reinterpret_cast<intptr_t>(&callable)) {}
- Ret operator()(Param1 param1, Param2 param2, Param3 param3) {
- return callback(callable,
- std::forward<Param1>(param1),
- std::forward<Param2>(param2),
- std::forward<Param3>(param3));
- }
-};
-
-#endif
-
// deleter - Very very very simple method that is used to invoke operator
// delete on something. It is used like this:
//
@@ -230,7 +124,6 @@ public:
typedef void reference; // Can't modify value returned by fn
typedef RootIt iterator_type;
- typedef mapped_iterator<RootIt, UnaryFunc> _Self;
inline const RootIt &getCurrent() const { return current; }
inline const UnaryFunc &getFunc() const { return Fn; }
@@ -242,34 +135,56 @@ public:
return Fn(*current); // little change
}
- _Self& operator++() { ++current; return *this; }
- _Self& operator--() { --current; return *this; }
- _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; }
- _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; }
- _Self operator+ (difference_type n) const {
- return _Self(current + n, Fn);
+ mapped_iterator &operator++() {
+ ++current;
+ return *this;
}
- _Self& operator+= (difference_type n) { current += n; return *this; }
- _Self operator- (difference_type n) const {
- return _Self(current - n, Fn);
+ mapped_iterator &operator--() {
+ --current;
+ return *this;
+ }
+ mapped_iterator operator++(int) {
+ mapped_iterator __tmp = *this;
+ ++current;
+ return __tmp;
+ }
+ mapped_iterator operator--(int) {
+ mapped_iterator __tmp = *this;
+ --current;
+ return __tmp;
+ }
+ mapped_iterator operator+(difference_type n) const {
+ return mapped_iterator(current + n, Fn);
+ }
+ mapped_iterator &operator+=(difference_type n) {
+ current += n;
+ return *this;
+ }
+ mapped_iterator operator-(difference_type n) const {
+ return mapped_iterator(current - n, Fn);
+ }
+ mapped_iterator &operator-=(difference_type n) {
+ current -= n;
+ return *this;
}
- _Self& operator-= (difference_type n) { current -= n; return *this; }
reference operator[](difference_type n) const { return *(*this + n); }
- inline bool operator!=(const _Self &X) const { return !operator==(X); }
- inline bool operator==(const _Self &X) const { return current == X.current; }
- inline bool operator< (const _Self &X) const { return current < X.current; }
+ bool operator!=(const mapped_iterator &X) const { return !operator==(X); }
+ bool operator==(const mapped_iterator &X) const {
+ return current == X.current;
+ }
+ bool operator<(const mapped_iterator &X) const { return current < X.current; }
- inline difference_type operator-(const _Self &X) const {
+ difference_type operator-(const mapped_iterator &X) const {
return current - X.current;
}
};
-template <class _Iterator, class Func>
-inline mapped_iterator<_Iterator, Func>
-operator+(typename mapped_iterator<_Iterator, Func>::difference_type N,
- const mapped_iterator<_Iterator, Func>& X) {
- return mapped_iterator<_Iterator, Func>(X.getCurrent() - N, X.getFunc());
+template <class Iterator, class Func>
+inline mapped_iterator<Iterator, Func>
+operator+(typename mapped_iterator<Iterator, Func>::difference_type N,
+ const mapped_iterator<Iterator, Func> &X) {
+ return mapped_iterator<Iterator, Func>(X.getCurrent() - N, X.getFunc());
}
@@ -301,6 +216,28 @@ struct less_second {
}
};
+// A subset of N3658. More stuff can be added as-needed.
+
+/// \brief Represents a compile-time sequence of integers.
+template <class T, T... I> struct integer_sequence {
+ typedef T value_type;
+
+ static LLVM_CONSTEXPR size_t size() { return sizeof...(I); }
+};
+
+/// \brief Alias for the common case of a sequence of size_ts.
+template <size_t... I>
+struct index_sequence : integer_sequence<std::size_t, I...> {};
+
+template <std::size_t N, std::size_t... I>
+struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {};
+template <std::size_t... I>
+struct build_index_impl<0, I...> : index_sequence<I...> {};
+
+/// \brief Creates a compile-time integer sequence for a parameter pack.
+template <class... Ts>
+struct index_sequence_for : build_index_impl<sizeof...(Ts)> {};
+
//===----------------------------------------------------------------------===//
// Extra additions for arrays
//===----------------------------------------------------------------------===//
@@ -348,10 +285,11 @@ inline int (*get_array_pod_sort_comparator(const T &))
/// default to std::less.
template<class IteratorTy>
inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
- // Don't dereference start iterator of empty sequence.
- if (Start == End) return;
- qsort(&*Start, End-Start, sizeof(*Start),
- get_array_pod_sort_comparator(*Start));
+ // Don't inefficiently call qsort with one element or trigger undefined
+ // behavior with an empty sequence.
+ auto NElts = End - Start;
+ if (NElts <= 1) return;
+ qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
}
template <class IteratorTy>
@@ -360,9 +298,11 @@ inline void array_pod_sort(
int (*Compare)(
const typename std::iterator_traits<IteratorTy>::value_type *,
const typename std::iterator_traits<IteratorTy>::value_type *)) {
- // Don't dereference start iterator of empty sequence.
- if (Start == End) return;
- qsort(&*Start, End - Start, sizeof(*Start),
+ // Don't inefficiently call qsort with one element or trigger undefined
+ // behavior with an empty sequence.
+ auto NElts = End - Start;
+ if (NElts <= 1) return;
+ qsort(&*Start, NElts, sizeof(*Start),
reinterpret_cast<int (*)(const void *, const void *)>(Compare));
}
@@ -388,12 +328,18 @@ void DeleteContainerSeconds(Container &C) {
C.clear();
}
+/// Provide wrappers to std::all_of which take ranges instead of having to pass
+/// being/end explicitly.
+template<typename R, class UnaryPredicate>
+bool all_of(R &&Range, UnaryPredicate &&P) {
+ return std::all_of(Range.begin(), Range.end(),
+ std::forward<UnaryPredicate>(P));
+}
+
//===----------------------------------------------------------------------===//
// Extra additions to <memory>
//===----------------------------------------------------------------------===//
-#if LLVM_HAS_VARIADIC_TEMPLATES
-
// Implement make_unique according to N3656.
/// \brief Constructs a `new T()` with the given args and returns a
@@ -427,123 +373,7 @@ make_unique(size_t n) {
/// This function isn't used and is only here to provide better compile errors.
template <class T, class... Args>
typename std::enable_if<std::extent<T>::value != 0>::type
-make_unique(Args &&...) LLVM_DELETED_FUNCTION;
-
-#else
-
-template <class T>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique() {
- return std::unique_ptr<T>(new T());
-}
-
-template <class T, class Arg1>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1) {
- return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1)));
-}
-
-template <class T, class Arg1, class Arg2>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) {
- return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1),
- std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
- Arg6 &&arg6) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6, class Arg7>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
- Arg6 &&arg6, Arg7 &&arg7) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
- std::forward<Arg7>(arg7)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6, class Arg7, class Arg8>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
- Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
- std::forward<Arg7>(arg7), std::forward<Arg8>(arg8)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6, class Arg7, class Arg8, class Arg9>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
- Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
- std::forward<Arg7>(arg7), std::forward<Arg8>(arg8),
- std::forward<Arg9>(arg9)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6, class Arg7, class Arg8, class Arg9, class Arg10>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
- Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
- std::forward<Arg7>(arg7), std::forward<Arg8>(arg8),
- std::forward<Arg9>(arg9), std::forward<Arg10>(arg10)));
-}
-
-template <class T>
-typename std::enable_if<std::is_array<T>::value &&std::extent<T>::value == 0,
- std::unique_ptr<T>>::type
-make_unique(size_t n) {
- return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
-}
-
-#endif
+make_unique(Args &&...) = delete;
struct FreeDeleter {
void operator()(void* v) {
@@ -558,6 +388,35 @@ struct pair_hash {
}
};
+/// A functor like C++14's std::less<void> in its absence.
+struct less {
+ template <typename A, typename B> bool operator()(A &&a, B &&b) const {
+ return std::forward<A>(a) < std::forward<B>(b);
+ }
+};
+
+/// A functor like C++14's std::equal<void> in its absence.
+struct equal {
+ template <typename A, typename B> bool operator()(A &&a, B &&b) const {
+ return std::forward<A>(a) == std::forward<B>(b);
+ }
+};
+
+/// Binary functor that adapts to any other binary functor after dereferencing
+/// operands.
+template <typename T> struct deref {
+ T func;
+ // Could be further improved to cope with non-derivable functors and
+ // non-binary functors (should be a variadic template member function
+ // operator()).
+ template <typename A, typename B>
+ auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) {
+ assert(lhs);
+ assert(rhs);
+ return func(*lhs, *rhs);
+ }
+};
+
} // End llvm namespace
#endif
diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h
index 2f60ecc92043..5abe76c12259 100644
--- a/include/llvm/ADT/ScopedHashTable.h
+++ b/include/llvm/ADT/ScopedHashTable.h
@@ -90,8 +90,8 @@ class ScopedHashTableScope {
/// LastValInScope - This is the last value that was inserted for this scope
/// or null if none have been inserted yet.
ScopedHashTableVal<K, V> *LastValInScope;
- void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION;
- ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION;
+ void operator=(ScopedHashTableScope&) = delete;
+ ScopedHashTableScope(ScopedHashTableScope&) = delete;
public:
ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT);
~ScopedHashTableScope();
diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h
index 1e2f365b1040..ae3d645396fd 100644
--- a/include/llvm/ADT/SmallBitVector.h
+++ b/include/llvm/ADT/SmallBitVector.h
@@ -53,6 +53,9 @@ class SmallBitVector {
SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits
};
+ static_assert(NumBaseBits == 64 || NumBaseBits == 32,
+ "Unsupported word size");
+
public:
typedef unsigned size_type;
// Encapsulation of a single bit.
@@ -63,6 +66,8 @@ public:
public:
reference(SmallBitVector &b, unsigned Idx) : TheVector(b), BitPos(Idx) {}
+ reference(const reference&) = default;
+
reference& operator=(reference t) {
*this = bool(t);
return *this;
@@ -177,11 +182,7 @@ public:
size_type count() const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
- if (NumBaseBits == 32)
- return CountPopulation_32(Bits);
- if (NumBaseBits == 64)
- return CountPopulation_64(Bits);
- llvm_unreachable("Unsupported!");
+ return countPopulation(Bits);
}
return getPointer()->count();
}
@@ -214,11 +215,7 @@ public:
uintptr_t Bits = getSmallBits();
if (Bits == 0)
return -1;
- if (NumBaseBits == 32)
- return countTrailingZeros(Bits);
- if (NumBaseBits == 64)
- return countTrailingZeros(Bits);
- llvm_unreachable("Unsupported!");
+ return countTrailingZeros(Bits);
}
return getPointer()->find_first();
}
@@ -232,11 +229,7 @@ public:
Bits &= ~uintptr_t(0) << (Prev + 1);
if (Bits == 0 || Prev + 1 >= getSmallSize())
return -1;
- if (NumBaseBits == 32)
- return countTrailingZeros(Bits);
- if (NumBaseBits == 64)
- return countTrailingZeros(Bits);
- llvm_unreachable("Unsupported!");
+ return countTrailingZeros(Bits);
}
return getPointer()->find_next(Prev);
}
@@ -560,7 +553,6 @@ public:
private:
template<bool AddBits, bool InvertMask>
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
- assert((NumBaseBits == 64 || NumBaseBits == 32) && "Unsupported word size");
if (NumBaseBits == 64 && MaskWords >= 2) {
uint64_t M = Mask[0] | (uint64_t(Mask[1]) << 32);
if (InvertMask) M = ~M;
diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h
index cb1c5e1fa96a..3e3c9c154ef4 100644
--- a/include/llvm/ADT/SmallPtrSet.h
+++ b/include/llvm/ADT/SmallPtrSet.h
@@ -132,7 +132,7 @@ private:
/// Grow - Allocate a larger backing store for the buckets and move it over.
void Grow(unsigned NewSize);
- void operator=(const SmallPtrSetImplBase &RHS) LLVM_DELETED_FUNCTION;
+ void operator=(const SmallPtrSetImplBase &RHS) = delete;
protected:
/// swap - Swaps the elements of two sets.
/// Note: This method assumes that both sets have the same small size.
@@ -242,7 +242,7 @@ template <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
- SmallPtrSetImpl(const SmallPtrSetImpl&) LLVM_DELETED_FUNCTION;
+ SmallPtrSetImpl(const SmallPtrSetImpl&) = delete;
protected:
// Constructors that forward to the base.
SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)
diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h
index 44a352119b09..5b208b76a21f 100644
--- a/include/llvm/ADT/SmallVector.h
+++ b/include/llvm/ADT/SmallVector.h
@@ -24,6 +24,7 @@
#include <cstddef>
#include <cstdlib>
#include <cstring>
+#include <initializer_list>
#include <iterator>
#include <memory>
@@ -236,51 +237,6 @@ 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.
@@ -352,8 +308,11 @@ protected:
/// Copy the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
- template<typename T1, typename T2>
- static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) {
+ template <typename T1, typename T2>
+ static void uninitialized_copy(
+ T1 *I, T1 *E, T2 *Dest,
+ typename std::enable_if<std::is_same<typename std::remove_const<T1>::type,
+ T2>::value>::type * = nullptr) {
// Use memcpy for PODs iterated by pointers (which includes SmallVector
// iterators): std::uninitialized_copy optimizes to memmove, but we can
// use memcpy here.
@@ -385,7 +344,7 @@ template <typename T>
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
- SmallVectorImpl(const SmallVectorImpl&) LLVM_DELETED_FUNCTION;
+ SmallVectorImpl(const SmallVectorImpl&) = delete;
public:
typedef typename SuperClass::iterator iterator;
typedef typename SuperClass::size_type size_type;
@@ -459,9 +418,7 @@ public:
this->grow(this->size()+NumInputs);
// Copy the new elements over.
- // TODO: NEED To compile time dispatch on whether in_iter is a random access
- // iterator to use the fast uninitialized_copy.
- std::uninitialized_copy(in_start, in_end, this->end());
+ this->uninitialized_copy(in_start, in_end, this->end());
this->setEnd(this->end() + NumInputs);
}
@@ -476,6 +433,10 @@ public:
this->setEnd(this->end() + NumInputs);
}
+ void append(std::initializer_list<T> IL) {
+ append(IL.begin(), IL.end());
+ }
+
void assign(size_type NumElts, const T &Elt) {
clear();
if (this->capacity() < NumElts)
@@ -484,6 +445,11 @@ public:
std::uninitialized_fill(this->begin(), this->end(), Elt);
}
+ void assign(std::initializer_list<T> IL) {
+ clear();
+ append(IL);
+ }
+
iterator erase(iterator I) {
assert(I >= this->begin() && "Iterator to erase is out of bounds.");
assert(I < this->end() && "Erasing at past-the-end iterator.");
@@ -677,6 +643,17 @@ public:
return I;
}
+ void insert(iterator I, std::initializer_list<T> IL) {
+ insert(I, IL.begin(), IL.end());
+ }
+
+ template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
+ if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+ this->grow();
+ ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
+ this->setEnd(this->end() + 1);
+ }
+
SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
@@ -902,6 +879,10 @@ public:
this->append(R.begin(), R.end());
}
+ SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
+ this->assign(IL);
+ }
+
SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
if (!RHS.empty())
SmallVectorImpl<T>::operator=(RHS);
@@ -921,6 +902,21 @@ public:
SmallVectorImpl<T>::operator=(::std::move(RHS));
return *this;
}
+
+ SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
+ if (!RHS.empty())
+ SmallVectorImpl<T>::operator=(::std::move(RHS));
+ }
+
+ const SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
+ SmallVectorImpl<T>::operator=(::std::move(RHS));
+ return *this;
+ }
+
+ const SmallVector &operator=(std::initializer_list<T> IL) {
+ this->assign(IL);
+ return *this;
+ }
};
template<typename T, unsigned N>
diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h
index d5bde2963fbd..20cbe2cddfc2 100644
--- a/include/llvm/ADT/SparseBitVector.h
+++ b/include/llvm/ADT/SparseBitVector.h
@@ -124,25 +124,15 @@ public:
size_type count() const {
unsigned NumBits = 0;
for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
- if (sizeof(BitWord) == 4)
- NumBits += CountPopulation_32(Bits[i]);
- else if (sizeof(BitWord) == 8)
- NumBits += CountPopulation_64(Bits[i]);
- else
- llvm_unreachable("Unsupported!");
+ NumBits += countPopulation(Bits[i]);
return NumBits;
}
/// find_first - Returns the index of the first set bit.
int find_first() const {
for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
- if (Bits[i] != 0) {
- if (sizeof(BitWord) == 4)
- return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
- if (sizeof(BitWord) == 8)
- return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
- llvm_unreachable("Unsupported!");
- }
+ if (Bits[i] != 0)
+ return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
llvm_unreachable("Illegal empty element");
}
@@ -161,23 +151,13 @@ public:
// Mask off previous bits.
Copy &= ~0UL << BitPos;
- if (Copy != 0) {
- if (sizeof(BitWord) == 4)
- return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
- if (sizeof(BitWord) == 8)
- return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
- llvm_unreachable("Unsupported!");
- }
+ if (Copy != 0)
+ return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
// Check subsequent words.
for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i)
- if (Bits[i] != 0) {
- if (sizeof(BitWord) == 4)
- return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
- if (sizeof(BitWord) == 8)
- return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
- llvm_unreachable("Unsupported!");
- }
+ if (Bits[i] != 0)
+ return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
}
diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h
index f858536b6ed8..e3aa2589b79f 100644
--- a/include/llvm/ADT/SparseMultiSet.h
+++ b/include/llvm/ADT/SparseMultiSet.h
@@ -133,8 +133,8 @@ class SparseMultiSet {
// Disable copy construction and assignment.
// This data structure is not meant to be used that way.
- SparseMultiSet(const SparseMultiSet&) LLVM_DELETED_FUNCTION;
- SparseMultiSet &operator=(const SparseMultiSet&) LLVM_DELETED_FUNCTION;
+ SparseMultiSet(const SparseMultiSet&) = delete;
+ SparseMultiSet &operator=(const SparseMultiSet&) = delete;
/// Whether the given entry is the head of the list. List heads's previous
/// pointers are to the tail of the list, allowing for efficient access to the
diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h
index 9a13440000ac..a45d1c8d6b8a 100644
--- a/include/llvm/ADT/SparseSet.h
+++ b/include/llvm/ADT/SparseSet.h
@@ -133,8 +133,8 @@ class SparseSet {
// Disable copy construction and assignment.
// This data structure is not meant to be used that way.
- SparseSet(const SparseSet&) LLVM_DELETED_FUNCTION;
- SparseSet &operator=(const SparseSet&) LLVM_DELETED_FUNCTION;
+ SparseSet(const SparseSet&) = delete;
+ SparseSet &operator=(const SparseSet&) = delete;
public:
typedef ValueT value_type;
diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h
index 3437607a0bd0..8721c73b95b1 100644
--- a/include/llvm/ADT/StringMap.h
+++ b/include/llvm/ADT/StringMap.h
@@ -111,7 +111,7 @@ public:
/// and data.
template<typename ValueTy>
class StringMapEntry : public StringMapEntryBase {
- StringMapEntry(StringMapEntry &E) LLVM_DELETED_FUNCTION;
+ StringMapEntry(StringMapEntry &E) = delete;
public:
ValueTy second;
diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h
index 6111c42da9dc..95660a49f1f1 100644
--- a/include/llvm/ADT/StringRef.h
+++ b/include/llvm/ADT/StringRef.h
@@ -238,9 +238,12 @@ 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 = std::min(From, Length), e = Length; i != e; ++i)
- if (Data[i] == C)
- return i;
+ size_t FindBegin = std::min(From, Length);
+ if (FindBegin < Length) { // Avoid calling memchr with nullptr.
+ // Just forward to memchr, which is faster than a hand-rolled loop.
+ if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin))
+ return static_cast<const char *>(P) - Data;
+ }
return npos;
}
diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h
index 15137f5ebf8c..f29608f3d3d1 100644
--- a/include/llvm/ADT/TinyPtrVector.h
+++ b/include/llvm/ADT/TinyPtrVector.h
@@ -27,9 +27,12 @@ class TinyPtrVector {
public:
typedef llvm::SmallVector<EltTy, 4> VecTy;
typedef typename VecTy::value_type value_type;
+ typedef llvm::PointerUnion<EltTy, VecTy *> PtrUnion;
- llvm::PointerUnion<EltTy, VecTy*> Val;
+private:
+ PtrUnion Val;
+public:
TinyPtrVector() {}
~TinyPtrVector() {
if (VecTy *V = Val.template dyn_cast<VecTy*>())
@@ -96,12 +99,13 @@ public:
return *this;
}
- /// Constructor from a single element.
- explicit TinyPtrVector(EltTy Elt) : Val(Elt) {}
-
/// Constructor from an ArrayRef.
+ ///
+ /// This also is a constructor for individual array elements due to the single
+ /// element constructor for ArrayRef.
explicit TinyPtrVector(ArrayRef<EltTy> Elts)
- : Val(new VecTy(Elts.begin(), Elts.end())) {}
+ : Val(Elts.size() == 1 ? PtrUnion(Elts[0])
+ : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
// implicit conversion operator to ArrayRef.
operator ArrayRef<EltTy>() const {
@@ -112,6 +116,15 @@ public:
return *Val.template get<VecTy*>();
}
+ // implicit conversion operator to MutableArrayRef.
+ operator MutableArrayRef<EltTy>() {
+ if (Val.isNull())
+ return None;
+ if (Val.template is<EltTy>())
+ return *Val.getAddrOfPtr1();
+ return *Val.template get<VecTy*>();
+ }
+
bool empty() const {
// This vector can be empty if it contains no element, or if it
// contains a pointer to an empty vector.
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index 8a685995256b..2416ce342c9b 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -50,6 +50,7 @@ public:
armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
+ bpf, // eBPF or extended BPF or 64-bit BPF (little endian)
hexagon, // Hexagon: hexagon
mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel
@@ -63,6 +64,7 @@ public:
amdgcn, // AMDGCN: AMD GCN GPUs
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
+ sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
systemz, // SystemZ: s390x
tce, // TCE (http://tce.cs.tut.fi/): tce
thumb, // Thumb (little endian): thumb, thumbv.*
@@ -80,11 +82,13 @@ public:
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
+ kalimba, // Kalimba: generic kalimba
+ LastArchType = kalimba
};
enum SubArchType {
NoSubArch,
+ ARMSubArch_v8_1a,
ARMSubArch_v8,
ARMSubArch_v7,
ARMSubArch_v7em,
@@ -92,6 +96,7 @@ public:
ARMSubArch_v7s,
ARMSubArch_v6,
ARMSubArch_v6m,
+ ARMSubArch_v6k,
ARMSubArch_v6t2,
ARMSubArch_v5,
ARMSubArch_v5te,
@@ -114,11 +119,13 @@ public:
ImaginationTechnologies,
MipsTechnologies,
NVIDIA,
- CSR
+ CSR,
+ LastVendorType = CSR
};
enum OSType {
UnknownOS,
+ CloudABI,
Darwin,
DragonFly,
FreeBSD,
@@ -140,7 +147,9 @@ public:
AIX,
CUDA, // NVIDIA CUDA
NVCL, // NVIDIA OpenCL
- AMDHSA // AMD HSA Runtime
+ AMDHSA, // AMD HSA Runtime
+ PS4,
+ LastOSType = PS4
};
enum EnvironmentType {
UnknownEnvironment,
@@ -157,6 +166,7 @@ public:
MSVC,
Itanium,
Cygnus,
+ LastEnvironmentType = Cygnus
};
enum ObjectFormatType {
UnknownObjectFormat,
@@ -200,6 +210,13 @@ public:
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
const Twine &EnvironmentStr);
+ bool operator==(const Triple &Other) const {
+ return Arch == Other.Arch && SubArch == Other.SubArch &&
+ Vendor == Other.Vendor && OS == Other.OS &&
+ Environment == Other.Environment &&
+ ObjectFormat == Other.ObjectFormat;
+ }
+
/// @}
/// @name Normalization
/// @{
@@ -210,6 +227,9 @@ public:
/// common case in which otherwise valid components are in the wrong order.
static std::string normalize(StringRef Str);
+ /// \brief Return the normalized form of this triple's string.
+ std::string normalize() const { return normalize(Data); }
+
/// @}
/// @name Typed Component Access
/// @{
@@ -334,6 +354,12 @@ public:
return false;
}
+ bool isOSVersionLT(const Triple &Other) const {
+ unsigned RHS[3];
+ Other.getOSVersion(RHS[0], RHS[1], RHS[2]);
+ return isOSVersionLT(RHS[0], RHS[1], RHS[2]);
+ }
+
/// isMacOSXVersionLT - Comparison function for checking OS X version
/// compatibility, which handles supporting skewed version numbering schemes
/// used by the "darwin" triples.
@@ -423,7 +449,7 @@ public:
/// \brief Tests whether the OS is Windows.
bool isOSWindows() const {
- return getOS() == Triple::Win32 || isOSCygMing();
+ return getOS() == Triple::Win32;
}
/// \brief Tests whether the OS is NaCl (Native Client)
@@ -451,6 +477,19 @@ public:
return getObjectFormat() == Triple::MachO;
}
+ /// \brief Tests whether the target is the PS4 CPU
+ bool isPS4CPU() const {
+ return getArch() == Triple::x86_64 &&
+ getVendor() == Triple::SCEI &&
+ getOS() == Triple::PS4;
+ }
+
+ /// \brief Tests whether the target is the PS4 platform
+ bool isPS4() const {
+ return getVendor() == Triple::SCEI &&
+ getOS() == Triple::PS4;
+ }
+
/// @}
/// @name Mutators
/// @{
diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h
index 05d2fea117cf..db0bf4b68de8 100644
--- a/include/llvm/ADT/Twine.h
+++ b/include/llvm/ADT/Twine.h
@@ -10,6 +10,7 @@
#ifndef LLVM_ADT_TWINE_H
#define LLVM_ADT_TWINE_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
@@ -17,9 +18,6 @@
#include <string>
namespace llvm {
- template <typename T>
- class SmallVectorImpl;
- class StringRef;
class raw_ostream;
/// Twine - A lightweight data structure for efficiently representing the
@@ -100,6 +98,9 @@ namespace llvm {
/// A pointer to a StringRef instance.
StringRefKind,
+ /// A pointer to a SmallString instance.
+ SmallStringKind,
+
/// A char value reinterpreted as a pointer, to render as a character.
CharKind,
@@ -136,6 +137,7 @@ namespace llvm {
const char *cString;
const std::string *stdString;
const StringRef *stringRef;
+ const SmallVectorImpl<char> *smallString;
char character;
unsigned int decUI;
int decI;
@@ -166,50 +168,49 @@ namespace llvm {
}
/// Construct a binary twine.
- explicit Twine(const Twine &_LHS, const Twine &_RHS)
- : LHSKind(TwineKind), RHSKind(TwineKind) {
- LHS.twine = &_LHS;
- RHS.twine = &_RHS;
+ explicit Twine(const Twine &LHS, const Twine &RHS)
+ : LHSKind(TwineKind), RHSKind(TwineKind) {
+ this->LHS.twine = &LHS;
+ this->RHS.twine = &RHS;
assert(isValid() && "Invalid twine!");
}
/// Construct a twine from explicit values.
- explicit Twine(Child _LHS, NodeKind _LHSKind,
- Child _RHS, NodeKind _RHSKind)
- : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) {
+ explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind)
+ : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) {
assert(isValid() && "Invalid twine!");
}
/// Since the intended use of twines is as temporary objects, assignments
/// when concatenating might cause undefined behavior or stack corruptions
- Twine &operator=(const Twine &Other) LLVM_DELETED_FUNCTION;
+ Twine &operator=(const Twine &Other) = delete;
- /// isNull - Check for the null twine.
+ /// Check for the null twine.
bool isNull() const {
return getLHSKind() == NullKind;
}
- /// isEmpty - Check for the empty twine.
+ /// Check for the empty twine.
bool isEmpty() const {
return getLHSKind() == EmptyKind;
}
- /// isNullary - Check if this is a nullary twine (null or empty).
+ /// Check if this is a nullary twine (null or empty).
bool isNullary() const {
return isNull() || isEmpty();
}
- /// isUnary - Check if this is a unary twine.
+ /// Check if this is a unary twine.
bool isUnary() const {
return getRHSKind() == EmptyKind && !isNullary();
}
- /// isBinary - Check if this is a binary twine.
+ /// Check if this is a binary twine.
bool isBinary() const {
return getLHSKind() != NullKind && getRHSKind() != EmptyKind;
}
- /// isValid - Check if this is a valid twine (satisfying the invariants on
+ /// Check if this is a valid twine (satisfying the invariants on
/// order and number of arguments).
bool isValid() const {
// Nullary twines always have Empty on the RHS.
@@ -235,16 +236,16 @@ namespace llvm {
return true;
}
- /// getLHSKind - Get the NodeKind of the left-hand side.
+ /// Get the NodeKind of the left-hand side.
NodeKind getLHSKind() const { return LHSKind; }
- /// getRHSKind - Get the NodeKind of the right-hand side.
+ /// Get the NodeKind of the right-hand side.
NodeKind getRHSKind() const { return RHSKind; }
- /// printOneChild - Print one child from a twine.
+ /// Print one child from a twine.
void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
- /// printOneChildRepr - Print the representation of one child from a twine.
+ /// Print the representation of one child from a twine.
void printOneChildRepr(raw_ostream &OS, Child Ptr,
NodeKind Kind) const;
@@ -257,6 +258,8 @@ namespace llvm {
assert(isValid() && "Invalid twine!");
}
+ Twine(const Twine &) = default;
+
/// Construct from a C string.
///
/// We take care here to optimize "" into the empty twine -- this will be
@@ -287,6 +290,13 @@ namespace llvm {
assert(isValid() && "Invalid twine!");
}
+ /// Construct from a SmallString.
+ /*implicit*/ Twine(const SmallVectorImpl<char> &Str)
+ : LHSKind(SmallStringKind), RHSKind(EmptyKind) {
+ LHS.smallString = &Str;
+ assert(isValid() && "Invalid twine!");
+ }
+
/// Construct from a char.
explicit Twine(char Val)
: LHSKind(CharKind), RHSKind(EmptyKind) {
@@ -347,18 +357,18 @@ namespace llvm {
// right thing. Yet.
/// Construct as the concatenation of a C string and a StringRef.
- /*implicit*/ Twine(const char *_LHS, const StringRef &_RHS)
- : LHSKind(CStringKind), RHSKind(StringRefKind) {
- LHS.cString = _LHS;
- RHS.stringRef = &_RHS;
+ /*implicit*/ Twine(const char *LHS, const StringRef &RHS)
+ : LHSKind(CStringKind), RHSKind(StringRefKind) {
+ this->LHS.cString = LHS;
+ this->RHS.stringRef = &RHS;
assert(isValid() && "Invalid twine!");
}
/// Construct as the concatenation of a StringRef and a C string.
- /*implicit*/ Twine(const StringRef &_LHS, const char *_RHS)
- : LHSKind(StringRefKind), RHSKind(CStringKind) {
- LHS.stringRef = &_LHS;
- RHS.cString = _RHS;
+ /*implicit*/ Twine(const StringRef &LHS, const char *RHS)
+ : LHSKind(StringRefKind), RHSKind(CStringKind) {
+ this->LHS.stringRef = &LHS;
+ this->RHS.cString = RHS;
assert(isValid() && "Invalid twine!");
}
@@ -384,14 +394,14 @@ namespace llvm {
/// @name Predicate Operations
/// @{
- /// isTriviallyEmpty - Check if this twine is trivially empty; a false
- /// return value does not necessarily mean the twine is empty.
+ /// Check if this twine is trivially empty; a false return value does not
+ /// necessarily mean the twine is empty.
bool isTriviallyEmpty() const {
return isNullary();
}
- /// isSingleStringRef - Return true if this twine can be dynamically
- /// accessed as a single StringRef value with getSingleStringRef().
+ /// Return true if this twine can be dynamically accessed as a single
+ /// StringRef value with getSingleStringRef().
bool isSingleStringRef() const {
if (getRHSKind() != EmptyKind) return false;
@@ -400,6 +410,7 @@ namespace llvm {
case CStringKind:
case StdStringKind:
case StringRefKind:
+ case SmallStringKind:
return true;
default:
return false;
@@ -416,15 +427,14 @@ namespace llvm {
/// @name Output & Conversion.
/// @{
- /// str - Return the twine contents as a std::string.
+ /// Return the twine contents as a std::string.
std::string str() const;
- /// toVector - Write the concatenated string into the given SmallString or
- /// SmallVector.
+ /// Append the concatenated string into the given SmallString or SmallVector.
void toVector(SmallVectorImpl<char> &Out) const;
- /// getSingleStringRef - This returns the twine as a single StringRef. This
- /// method is only valid if isSingleStringRef() is true.
+ /// This returns the twine as a single StringRef. This method is only valid
+ /// if isSingleStringRef() is true.
StringRef getSingleStringRef() const {
assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
switch (getLHSKind()) {
@@ -433,18 +443,24 @@ namespace llvm {
case CStringKind: return StringRef(LHS.cString);
case StdStringKind: return StringRef(*LHS.stdString);
case StringRefKind: return *LHS.stringRef;
+ case SmallStringKind:
+ return StringRef(LHS.smallString->data(), LHS.smallString->size());
}
}
- /// toStringRef - This returns the twine as a single StringRef if it can be
+ /// This returns the twine as a single StringRef if it can be
/// represented as such. Otherwise the twine is written into the given
/// SmallVector and a StringRef to the SmallVector's data is returned.
- StringRef toStringRef(SmallVectorImpl<char> &Out) const;
+ StringRef toStringRef(SmallVectorImpl<char> &Out) const {
+ if (isSingleStringRef())
+ return getSingleStringRef();
+ toVector(Out);
+ return StringRef(Out.data(), Out.size());
+ }
- /// toNullTerminatedStringRef - This returns the twine as a single null
- /// terminated StringRef if it can be represented as such. Otherwise the
- /// twine is written into the given SmallVector and a StringRef to the
- /// SmallVector's data is returned.
+ /// This returns the twine as a single null terminated StringRef if it
+ /// can be represented as such. Otherwise the twine is written into the
+ /// given SmallVector and a StringRef to the SmallVector's data is returned.
///
/// The returned StringRef's size does not include the null terminator.
StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const;
diff --git a/include/llvm/ADT/edit_distance.h b/include/llvm/ADT/edit_distance.h
index 9ee1edc54e05..c2b2041242aa 100644
--- a/include/llvm/ADT/edit_distance.h
+++ b/include/llvm/ADT/edit_distance.h
@@ -50,7 +50,7 @@ unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
// http://en.wikipedia.org/wiki/Levenshtein_distance
//
// Although the algorithm is typically described using an m x n
- // array, only two rows are used at a time, so this implemenation
+ // array, only two rows are used at a time, so this implementation
// just keeps two separate vectors for those two rows.
typename ArrayRef<T>::size_type m = FromArray.size();
typename ArrayRef<T>::size_type n = ToArray.size();
diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h
index 8c19a6f4547a..a7b9306b3a73 100644
--- a/include/llvm/ADT/ilist.h
+++ b/include/llvm/ADT/ilist.h
@@ -237,14 +237,14 @@ public:
// These are to catch errors when people try to use them as random access
// iterators.
template<typename T>
-void operator-(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION;
+void operator-(int, ilist_iterator<T>) = delete;
template<typename T>
-void operator-(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION;
+void operator-(ilist_iterator<T>,int) = delete;
template<typename T>
-void operator+(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION;
+void operator+(int, ilist_iterator<T>) = delete;
template<typename T>
-void operator+(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION;
+void operator+(ilist_iterator<T>,int) = delete;
// operator!=/operator== - Allow mixed comparisons without dereferencing
// the iterator, which could very likely be pointing to end().
@@ -332,8 +332,8 @@ class iplist : public Traits {
// No fundamental reason why iplist can't be copyable, but the default
// copy/copy-assign won't do.
- iplist(const iplist &) LLVM_DELETED_FUNCTION;
- void operator=(const iplist &) LLVM_DELETED_FUNCTION;
+ iplist(const iplist &) = delete;
+ void operator=(const iplist &) = delete;
public:
typedef NodeTy *pointer;
diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h
index e2c9e5ea6bda..54a288df0173 100644
--- a/include/llvm/ADT/iterator.h
+++ b/include/llvm/ADT/iterator.h
@@ -150,7 +150,7 @@ class iterator_adaptor_base
protected:
WrappedIteratorT I;
- iterator_adaptor_base() {}
+ iterator_adaptor_base() = default;
template <typename U>
explicit iterator_adaptor_base(
@@ -231,7 +231,7 @@ struct pointee_iterator
pointee_iterator<WrappedIteratorT>, WrappedIteratorT,
typename std::iterator_traits<WrappedIteratorT>::iterator_category,
T> {
- pointee_iterator() {}
+ pointee_iterator() = default;
template <typename U>
pointee_iterator(U &&u)
: pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {}
diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h
index 763f37298811..ac9d21c590a4 100644
--- a/include/llvm/Analysis/AliasAnalysis.h
+++ b/include/llvm/Analysis/AliasAnalysis.h
@@ -68,7 +68,7 @@ protected:
/// typically called by the run* methods of these subclasses. This may be
/// called multiple times.
///
- void InitializeAliasAnalysis(Pass *P);
+ void InitializeAliasAnalysis(Pass *P, const DataLayout *DL);
/// getAnalysisUsage - All alias analysis implementations should invoke this
/// directly (using AliasAnalysis::getAnalysisUsage(AU)).
@@ -84,11 +84,6 @@ public:
/// know the sizes of the potential memory references.
static uint64_t const UnknownSize = ~UINT64_C(0);
- /// getDataLayout - Return a pointer to the current DataLayout object, or
- /// null if no DataLayout object is available.
- ///
- const DataLayout *getDataLayout() const { return DL; }
-
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
/// object, or null if no TargetLibraryInfo object is available.
///
@@ -139,6 +134,10 @@ public:
Copy.AATags = AAMDNodes();
return Copy;
}
+
+ bool operator==(const AliasAnalysis::Location &Other) const {
+ return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags;
+ }
};
/// getLocation - Fill in Loc with information about the memory reference by
@@ -150,6 +149,19 @@ public:
Location getLocation(const AtomicRMWInst *RMWI);
static Location getLocationForSource(const MemTransferInst *MTI);
static Location getLocationForDest(const MemIntrinsic *MI);
+ Location getLocation(const Instruction *Inst) {
+ if (auto *I = dyn_cast<LoadInst>(Inst))
+ return getLocation(I);
+ else if (auto *I = dyn_cast<StoreInst>(Inst))
+ return getLocation(I);
+ else if (auto *I = dyn_cast<VAArgInst>(Inst))
+ return getLocation(I);
+ else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst))
+ return getLocation(I);
+ else if (auto *I = dyn_cast<AtomicRMWInst>(Inst))
+ return getLocation(I);
+ llvm_unreachable("unsupported memory instruction");
+ }
/// Alias analysis result - Either we know for sure that it does not alias, we
/// know for sure it must alias, or we don't know anything: The two pointers
@@ -357,6 +369,24 @@ public:
return (MRB & ModRef) && (MRB & ArgumentPointees);
}
+ /// getModRefInfo - Return information about whether or not an
+ /// instruction may read or write memory (without regard to a
+ /// specific location)
+ ModRefResult getModRefInfo(const Instruction *I) {
+ if (auto CS = ImmutableCallSite(I)) {
+ auto MRB = getModRefBehavior(CS);
+ if (MRB & ModRef)
+ return ModRef;
+ else if (MRB & Ref)
+ return Ref;
+ else if (MRB & Mod)
+ return Mod;
+ return NoModRef;
+ }
+
+ return getModRefInfo(I, Location());
+ }
+
/// getModRefInfo - Return information about whether or not an instruction may
/// read or write the specified memory location. An instruction
/// that doesn't read or write memory may be trivially LICM'd for example.
@@ -477,6 +507,10 @@ public:
ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){
return getModRefInfo(I, Location(P, Size));
}
+ /// getModRefInfo - Return information about whether a call and an instruction
+ /// may refer to the same memory locations.
+ ModRefResult getModRefInfo(Instruction *I,
+ ImmutableCallSite Call);
/// getModRefInfo - Return information about whether two call sites may refer
/// to the same set of memory locations. See
@@ -585,9 +619,7 @@ struct DenseMapInfo<AliasAnalysis::Location> {
}
static bool isEqual(const AliasAnalysis::Location &LHS,
const AliasAnalysis::Location &RHS) {
- return LHS.Ptr == RHS.Ptr &&
- LHS.Size == RHS.Size &&
- LHS.AATags == RHS.AATags;
+ return LHS == RHS;
}
};
diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h
index 036d58dfa810..18f95b401e6a 100644
--- a/include/llvm/Analysis/AliasSetTracker.h
+++ b/include/llvm/Analysis/AliasSetTracker.h
@@ -192,11 +192,6 @@ public:
}
bool operator!=(const iterator& x) const { return !operator==(x); }
- const iterator &operator=(const iterator &I) {
- CurNode = I.CurNode;
- return *this;
- }
-
value_type &operator*() const {
assert(CurNode && "Dereferencing AliasSet.end()!");
return *CurNode;
@@ -226,8 +221,8 @@ private:
AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
}
- AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION;
- void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION;
+ AliasSet(const AliasSet &AS) = delete;
+ void operator=(const AliasSet &AS) = delete;
PointerRec *getSomePointer() const {
return PtrList;
@@ -273,7 +268,7 @@ public:
///
bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo,
AliasAnalysis &AA) const;
- bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const;
+ bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const;
};
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
@@ -363,7 +358,7 @@ public:
/// getAliasSetForPointerIfExists - Return the alias set containing the
/// location specified if one exists, otherwise return null.
- AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size,
+ AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size,
const AAMDNodes &AAInfo) {
return findAliasSetForPointer(P, Size, AAInfo);
}
@@ -371,11 +366,12 @@ public:
/// 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 AAMDNodes &AAInfo) const;
+ bool containsPointer(const 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;
+ bool containsUnknown(const Instruction *I) const;
/// getAliasAnalysis - Return the underlying alias analysis object used by
/// this tracker.
diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h
index b129e6796328..1f00b691b305 100644
--- a/include/llvm/Analysis/AssumptionCache.h
+++ b/include/llvm/Analysis/AssumptionCache.h
@@ -27,6 +27,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;
+
/// \brief A cache of @llvm.assume calls within a function.
///
/// This cache provides fast lookup of assumptions within a function by caching
@@ -88,6 +93,42 @@ public:
}
};
+/// \brief A function analysis which provides an \c AssumptionCache.
+///
+/// This analysis is intended for use with the new pass manager and will vend
+/// assumption caches for a given function.
+class AssumptionAnalysis {
+ static char PassID;
+
+public:
+ typedef AssumptionCache Result;
+
+ /// \brief Opaque, unique identifier for this analysis pass.
+ static void *ID() { return (void *)&PassID; }
+
+ /// \brief Provide a name for the analysis for debugging and logging.
+ static StringRef name() { return "AssumptionAnalysis"; }
+
+ AssumptionAnalysis() {}
+ AssumptionAnalysis(const AssumptionAnalysis &Arg) {}
+ AssumptionAnalysis(AssumptionAnalysis &&Arg) {}
+ AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; }
+ AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; }
+
+ AssumptionCache run(Function &F) { return AssumptionCache(F); }
+};
+
+/// \brief Printer pass for the \c AssumptionAnalysis results.
+class AssumptionPrinterPass {
+ raw_ostream &OS;
+
+public:
+ explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+
+ static StringRef name() { return "AssumptionPrinterPass"; }
+};
+
/// \brief An immutable pass that tracks lazily created \c AssumptionCache
/// objects.
///
@@ -124,7 +165,7 @@ public:
AssumptionCache &getAssumptionCache(Function &F);
AssumptionCacheTracker();
- ~AssumptionCacheTracker();
+ ~AssumptionCacheTracker() override;
void releaseMemory() override { AssumptionCaches.shrink_and_clear(); }
diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h
index 3289a2823c0c..f27c32df9283 100644
--- a/include/llvm/Analysis/BlockFrequencyInfo.h
+++ b/include/llvm/Analysis/BlockFrequencyInfo.h
@@ -34,7 +34,7 @@ public:
BlockFrequencyInfo();
- ~BlockFrequencyInfo();
+ ~BlockFrequencyInfo() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h
index 57b515420925..9acc863a7382 100644
--- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h
+++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -718,9 +718,6 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
///
/// It has some known flaws.
///
-/// - Loop scale is limited to 4096 per loop (2^12) to avoid exhausting
-/// BlockFrequency's 64-bit integer precision.
-///
/// - The model of irreducible control flow is a rough approximation.
///
/// Modelling irreducible control flow exactly involves setting up and
diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h
index 0d4fe932481b..6a406cd24402 100644
--- a/include/llvm/Analysis/CGSCCPassManager.h
+++ b/include/llvm/Analysis/CGSCCPassManager.h
@@ -263,8 +263,7 @@ private:
template <typename CGSCCPassT>
ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
- return std::move(
- ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass)));
+ return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass));
}
/// \brief A CGSCC analysis which acts as a proxy for a function analysis
@@ -484,7 +483,7 @@ private:
template <typename FunctionPassT>
CGSCCToFunctionPassAdaptor<FunctionPassT>
createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
- return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
+ return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
}
}
diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h
index 76d9073799f8..14b88220202a 100644
--- a/include/llvm/Analysis/CallGraph.h
+++ b/include/llvm/Analysis/CallGraph.h
@@ -273,8 +273,8 @@ private:
/// CalledFunctions array of this or other CallGraphNodes.
unsigned NumReferences;
- CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION;
- void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION;
+ CallGraphNode(const CallGraphNode &) = delete;
+ void operator=(const CallGraphNode &) = delete;
void DropRef() { --NumReferences; }
void AddRef() { ++NumReferences; }
@@ -318,7 +318,7 @@ public:
static char ID; // Class identification, replacement for typeinfo
CallGraphWrapperPass();
- virtual ~CallGraphWrapperPass();
+ ~CallGraphWrapperPass() override;
/// \brief The internal \c CallGraph around which the rest of this interface
/// is wrapped.
diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h
index 09d45ca2b486..541a2109af6c 100644
--- a/include/llvm/Analysis/ConstantFolding.h
+++ b/include/llvm/Analysis/ConstantFolding.h
@@ -36,16 +36,15 @@ namespace llvm {
/// Note that this fails if not all of the operands are constant. Otherwise,
/// this function can only fail when attempting to fold instructions like loads
/// and stores, which have no constant expression form.
-Constant *ConstantFoldInstruction(Instruction *I,
- const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI = nullptr);
+ Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldConstantExpression - Attempt to fold the constant expression
/// using the specified DataLayout. If successful, the constant result is
/// result is returned, if not, null is returned.
-Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
- const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI =nullptr);
+ Constant *
+ ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
/// specified operands. If successful, the constant result is returned, if not,
@@ -53,19 +52,19 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
/// fold instructions like loads and stores, which have no constant expression
/// form.
///
-Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
- ArrayRef<Constant *> Ops,
- const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI = nullptr);
+ Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
+ ArrayRef<Constant *> Ops,
+ const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
/// instruction (icmp/fcmp) with the specified operands. If it fails, it
/// returns a constant expression of the specified operands.
///
-Constant *ConstantFoldCompareInstOperands(unsigned Predicate,
- Constant *LHS, Constant *RHS,
- const DataLayout *TD = nullptr,
- const TargetLibraryInfo *TLI=nullptr);
+ Constant *
+ ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
+ Constant *RHS, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue
/// instruction with the specified operands and indices. The constant result is
@@ -76,8 +75,7 @@ Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
/// produce if it is constant and determinable. If this is not determinable,
/// return null.
-Constant *ConstantFoldLoadFromConstPtr(Constant *C,
- const DataLayout *TD = nullptr);
+Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout &DL);
/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
/// getelementptr constantexpr, return the constant value being addressed by the
diff --git a/include/llvm/Analysis/ConstantsScanner.h b/include/llvm/Analysis/ConstantsScanner.h
deleted file mode 100644
index d3d0a44bd6d4..000000000000
--- a/include/llvm/Analysis/ConstantsScanner.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements an iterator to walk through the constants referenced by
-// a method. This is used by the Bitcode & Assembly writers to build constant
-// pools.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H
-#define LLVM_ANALYSIS_CONSTANTSSCANNER_H
-
-#include "llvm/IR/InstIterator.h"
-
-namespace llvm {
-
-class Constant;
-
-class constant_iterator : public std::iterator<std::forward_iterator_tag,
- const Constant, ptrdiff_t> {
- const_inst_iterator InstI; // Method instruction iterator
- unsigned OpIdx; // Operand index
-
- typedef constant_iterator _Self;
-
- inline bool isAtConstant() const {
- assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() &&
- "isAtConstant called with invalid arguments!");
- return isa<Constant>(InstI->getOperand(OpIdx));
- }
-
-public:
- inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) {
- // Advance to first constant... if we are not already at constant or end
- if (InstI != inst_end(F) && // InstI is valid?
- (InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant?
- operator++();
- }
-
- inline constant_iterator(const Function *F, bool) // end ctor
- : InstI(inst_end(F)), OpIdx(0) {
- }
-
- inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx &&
- InstI == x.InstI; }
- inline bool operator!=(const _Self& x) const { return !operator==(x); }
-
- inline pointer operator*() const {
- assert(isAtConstant() && "Dereferenced an iterator at the end!");
- return cast<Constant>(InstI->getOperand(OpIdx));
- }
- inline pointer operator->() const { return operator*(); }
-
- inline _Self& operator++() { // Preincrement implementation
- ++OpIdx;
- do {
- unsigned NumOperands = InstI->getNumOperands();
- while (OpIdx < NumOperands && !isAtConstant()) {
- ++OpIdx;
- }
-
- if (OpIdx < NumOperands) return *this; // Found a constant!
- ++InstI;
- OpIdx = 0;
- } while (!InstI.atEnd());
-
- return *this; // At the end of the method
- }
-
- inline _Self operator++(int) { // Postincrement
- _Self tmp = *this; ++*this; return tmp;
- }
-
- inline bool atEnd() const { return InstI.atEnd(); }
-};
-
-inline constant_iterator constant_begin(const Function *F) {
- return constant_iterator(F);
-}
-
-inline constant_iterator constant_end(const Function *F) {
- return constant_iterator(F, true);
-}
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h
index 1041e3f0a4a9..0b3b2ea42813 100644
--- a/include/llvm/Analysis/DependenceAnalysis.h
+++ b/include/llvm/Analysis/DependenceAnalysis.h
@@ -217,13 +217,9 @@ namespace llvm {
/// input dependences are unordered.
class FullDependence : public Dependence {
public:
- FullDependence(Instruction *Src,
- Instruction *Dst,
- bool LoopIndependent,
+ FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent,
unsigned Levels);
- ~FullDependence() {
- delete[] DV;
- }
+ ~FullDependence() override { delete[] DV; }
/// isLoopIndependent - Returns true if this is a loop-independent
/// dependence.
@@ -266,6 +262,7 @@ namespace llvm {
/// if no subscript in the source or destination mention the induction
/// variable associated with the loop at this level.
bool isScalar(unsigned Level) const override;
+
private:
unsigned short Levels;
bool LoopIndependent;
@@ -278,8 +275,8 @@ namespace llvm {
/// DependenceAnalysis - This class is the main dependence-analysis driver.
///
class DependenceAnalysis : public FunctionPass {
- void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION;
- DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION;
+ void operator=(const DependenceAnalysis &) = delete;
+ DependenceAnalysis(const DependenceAnalysis &) = delete;
public:
/// depends - Tests for a dependence between the Src and Dst instructions.
/// Returns NULL if no dependence; otherwise, returns a Dependence (or a
diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h
index 735bfb83671d..629ae3809045 100644
--- a/include/llvm/Analysis/DominanceFrontierImpl.h
+++ b/include/llvm/Analysis/DominanceFrontierImpl.h
@@ -19,11 +19,12 @@
#define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/DominanceFrontier.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/GenericDomTree.h"
namespace llvm {
-namespace {
template <class BlockT>
class DFCalculateWorkObject {
public:
@@ -37,7 +38,6 @@ public:
const DomTreeNodeT *Node;
const DomTreeNodeT *parentNode;
};
-}
template <class BlockT>
void DominanceFrontierBase<BlockT>::removeBlock(BlockT *BB) {
diff --git a/include/llvm/Analysis/FunctionTargetTransformInfo.h b/include/llvm/Analysis/FunctionTargetTransformInfo.h
deleted file mode 100644
index fce5a1a92bd9..000000000000
--- a/include/llvm/Analysis/FunctionTargetTransformInfo.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass wraps a TargetTransformInfo in a FunctionPass so that it can
-// forward along the current Function so that we can make target specific
-// decisions based on the particular subtarget specified for each Function.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H
-#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H
-
-#include "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 d1f037021773..ae9c1f5bd9ac 100644
--- a/include/llvm/Analysis/IVUsers.h
+++ b/include/llvm/Analysis/IVUsers.h
@@ -122,7 +122,6 @@ class IVUsers : public LoopPass {
LoopInfo *LI;
DominatorTree *DT;
ScalarEvolution *SE;
- const DataLayout *DL;
SmallPtrSet<Instruction*,16> Processed;
/// IVUses - A list of all tracked IV uses of induction variable expressions
diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h
index a064cfc897b0..79ed74d82411 100644
--- a/include/llvm/Analysis/InlineCost.h
+++ b/include/llvm/Analysis/InlineCost.h
@@ -23,7 +23,7 @@ class AssumptionCacheTracker;
class CallSite;
class DataLayout;
class Function;
-class TargetTransformInfo;
+class TargetTransformInfoWrapperPass;
namespace InlineConstants {
// Various magic constants used to adjust heuristics.
@@ -77,7 +77,7 @@ public:
}
/// \brief Test whether the inline cost is low enough for inlining.
- LLVM_EXPLICIT operator bool() const {
+ explicit operator bool() const {
return Cost < Threshold;
}
@@ -100,14 +100,14 @@ public:
/// \brief Cost analyzer used by inliner.
class InlineCostAnalysis : public CallGraphSCCPass {
- const TargetTransformInfo *TTI;
+ TargetTransformInfoWrapperPass *TTIWP;
AssumptionCacheTracker *ACT;
public:
static char ID;
InlineCostAnalysis();
- ~InlineCostAnalysis();
+ ~InlineCostAnalysis() override;
// Pass interface implementation.
void getAnalysisUsage(AnalysisUsage &AU) const override;
diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h
index b88e0899f19a..706bd8000d3a 100644
--- a/include/llvm/Analysis/InstructionSimplify.h
+++ b/include/llvm/Analysis/InstructionSimplify.h
@@ -49,7 +49,7 @@ namespace llvm {
/// SimplifyAddInst - Given operands for an Add, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
- const DataLayout *TD = nullptr,
+ const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -58,7 +58,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -67,7 +67,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -76,7 +76,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -85,7 +85,7 @@ namespace llvm {
/// 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,
- const DataLayout *TD = nullptr,
+ const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -93,7 +93,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -101,8 +101,7 @@ namespace llvm {
/// 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,
+ Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -110,8 +109,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -119,8 +117,8 @@ namespace llvm {
/// 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,
+ Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+ const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -128,8 +126,7 @@ namespace llvm {
/// 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,
+ Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -137,8 +134,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -146,8 +142,8 @@ namespace llvm {
/// 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,
+ Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+ const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -156,7 +152,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -165,7 +161,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -174,7 +170,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -182,7 +178,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -190,7 +186,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -198,7 +194,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -207,7 +203,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -216,7 +212,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -225,7 +221,7 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -233,7 +229,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -242,8 +238,7 @@ namespace llvm {
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
/// can fold the result. If not, this returns null.
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
- ArrayRef<unsigned> Idxs,
- const DataLayout *TD = nullptr,
+ ArrayRef<unsigned> Idxs, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -251,7 +246,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -263,7 +258,7 @@ namespace llvm {
/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
- const DataLayout *TD = nullptr,
+ const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -272,18 +267,28 @@ namespace llvm {
/// 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 DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
+ /// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can
+ /// fold the result. If not, this returns null.
+ /// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the
+ /// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp.
+ Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
+ const FastMathFlags &FMF, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr,
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
/// \brief Given a function and iterators over arguments, see if we can fold
/// the result.
///
/// If this call could not be simplified returns null.
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
- User::op_iterator ArgEnd, const DataLayout *TD = nullptr,
+ User::op_iterator ArgEnd, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -293,8 +298,7 @@ namespace llvm {
/// result.
///
/// If this call could not be simplified returns null.
- Value *SimplifyCall(Value *V, ArrayRef<Value *> Args,
- const DataLayout *TD = nullptr,
+ Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@@ -302,7 +306,7 @@ namespace llvm {
/// 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,
+ Value *SimplifyInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
@@ -316,7 +320,6 @@ namespace llvm {
///
/// The function returns true if any simplifications were performed.
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
- const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
@@ -328,7 +331,6 @@ namespace llvm {
/// of the users impacted. It returns true if any simplifications were
/// performed.
bool recursivelySimplifyInstruction(Instruction *I,
- const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h
index 3b51d44099fa..655ce2dab413 100644
--- a/include/llvm/Analysis/IntervalIterator.h
+++ b/include/llvm/Analysis/IntervalIterator.h
@@ -78,7 +78,7 @@ inline void addNodeToInterval(Interval *Int, BasicBlock *BB) {
//
inline void addNodeToInterval(Interval *Int, Interval *I) {
// Add all of the nodes in I as new nodes in Int.
- copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes));
+ Int->Nodes.insert(Int->Nodes.end(), I->Nodes.begin(), I->Nodes.end());
}
@@ -94,7 +94,6 @@ class IntervalIterator {
bool IOwnMem; // If True, delete intervals when done with them
// See file header for conditions of use
public:
- typedef IntervalIterator<NodeTy, OrigContainer_t> _Self;
typedef std::forward_iterator_tag iterator_category;
IntervalIterator() {} // End iterator, empty stack
@@ -105,6 +104,12 @@ public:
}
}
+ IntervalIterator(IntervalIterator &&x)
+ : IntStack(std::move(x.IntStack)), Visited(std::move(x.Visited)),
+ OrigContainer(x.OrigContainer), IOwnMem(x.IOwnMem) {
+ x.IOwnMem = false;
+ }
+
IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) {
OrigContainer = &IP;
if (!ProcessInterval(IP.getRootInterval())) {
@@ -112,7 +117,7 @@ public:
}
}
- inline ~IntervalIterator() {
+ ~IntervalIterator() {
if (IOwnMem)
while (!IntStack.empty()) {
delete operator*();
@@ -120,15 +125,17 @@ public:
}
}
- inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;}
- inline bool operator!=(const _Self& x) const { return !operator==(x); }
+ bool operator==(const IntervalIterator &x) const {
+ return IntStack == x.IntStack;
+ }
+ bool operator!=(const IntervalIterator &x) const { return !(*this == x); }
- inline const Interval *operator*() const { return IntStack.back().first; }
- inline Interval *operator*() { return IntStack.back().first; }
- inline const Interval *operator->() const { return operator*(); }
- inline Interval *operator->() { return operator*(); }
+ const Interval *operator*() const { return IntStack.back().first; }
+ Interval *operator*() { return IntStack.back().first; }
+ const Interval *operator->() const { return operator*(); }
+ Interval *operator->() { return operator*(); }
- _Self& operator++() { // Preincrement
+ IntervalIterator &operator++() { // Preincrement
assert(!IntStack.empty() && "Attempting to use interval iterator at end!");
do {
// All of the intervals on the stack have been visited. Try visiting
@@ -150,8 +157,10 @@ public:
return *this;
}
- inline _Self operator++(int) { // Postincrement
- _Self tmp = *this; ++*this; return tmp;
+ IntervalIterator operator++(int) { // Postincrement
+ IntervalIterator tmp = *this;
+ ++*this;
+ return tmp;
}
private:
diff --git a/include/llvm/Analysis/IteratedDominanceFrontier.h b/include/llvm/Analysis/IteratedDominanceFrontier.h
new file mode 100644
index 000000000000..5a339f10f50f
--- /dev/null
+++ b/include/llvm/Analysis/IteratedDominanceFrontier.h
@@ -0,0 +1,96 @@
+//===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \brief Compute iterated dominance frontiers using a linear time algorithm.
+///
+/// The algorithm used here is based on:
+///
+/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes.
+/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of
+/// Programming Languages
+/// POPL '95. ACM, New York, NY, 62-73.
+///
+/// It has been modified to not explicitly use the DJ graph data structure and
+/// to directly compute pruned SSA using per-variable liveness information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_IDF_H
+#define LLVM_ANALYSIS_IDF_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+class BasicBlock;
+template <class T> class DomTreeNodeBase;
+typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
+class DominatorTree;
+
+/// \brief Determine the iterated dominance frontier, given a set of defining
+/// blocks, and optionally, a set of live-in blocks.
+///
+/// In turn, the results can be used to place phi nodes.
+///
+/// This algorithm is a linear time computation of Iterated Dominance Frontiers,
+/// pruned using the live-in set.
+/// By default, liveness is not used to prune the IDF computation.
+class IDFCalculator {
+
+public:
+ IDFCalculator(DominatorTree &DT) : DT(DT), useLiveIn(false) {}
+
+ /// \brief Give the IDF calculator the set of blocks in which the value is
+ /// defined. This is equivalent to the set of starting blocks it should be
+ /// calculating the IDF for (though later gets pruned based on liveness).
+ ///
+ /// Note: This set *must* live for the entire lifetime of the IDF calculator.
+ void setDefiningBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) {
+ DefBlocks = &Blocks;
+ }
+
+ /// \brief Give the IDF calculator the set of blocks in which the value is
+ /// live on entry to the block. This is used to prune the IDF calculation to
+ /// not include blocks where any phi insertion would be dead.
+ ///
+ /// Note: This set *must* live for the entire lifetime of the IDF calculator.
+
+ void setLiveInBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) {
+ LiveInBlocks = &Blocks;
+ useLiveIn = true;
+ }
+
+ /// \brief Reset the live-in block set to be empty, and tell the IDF
+ /// calculator to not use liveness anymore.
+ void resetLiveInBlocks() {
+ LiveInBlocks = nullptr;
+ useLiveIn = false;
+ }
+
+ /// \brief Calculate iterated dominance frontiers
+ ///
+ /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in
+ /// the file-level comment. It performs DF->IDF pruning using the live-in
+ /// set, to avoid computing the IDF for blocks where an inserted PHI node
+ /// would be dead.
+ void calculate(SmallVectorImpl<BasicBlock *> &IDFBlocks);
+
+private:
+ DominatorTree &DT;
+ bool useLiveIn;
+ DenseMap<DomTreeNode *, unsigned> DomLevels;
+ const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks;
+ const SmallPtrSetImpl<BasicBlock *> *DefBlocks;
+ SmallVector<BasicBlock *, 32> PHIBlocks;
+};
+}
+#endif
diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h
index 591e794a3901..b6dad478cdf2 100644
--- a/include/llvm/Analysis/JumpInstrTableInfo.h
+++ b/include/llvm/Analysis/JumpInstrTableInfo.h
@@ -39,7 +39,7 @@ public:
/// The default byte alignment for jump tables is 16, which is large but
/// usually safe.
JumpInstrTableInfo(uint64_t ByteAlign = 16);
- virtual ~JumpInstrTableInfo();
+ ~JumpInstrTableInfo() override;
const char *getPassName() const override {
return "Jump-Instruction Table Info";
}
diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h
index 9a67d52c3696..1051cff5efb7 100644
--- a/include/llvm/Analysis/LazyValueInfo.h
+++ b/include/llvm/Analysis/LazyValueInfo.h
@@ -29,18 +29,17 @@ namespace llvm {
/// 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;
+ LazyValueInfo(const LazyValueInfo&) = delete;
+ void operator=(const LazyValueInfo&) = delete;
public:
static char ID;
LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) {
initializeLazyValueInfoPass(*PassRegistry::getPassRegistry());
}
- ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); }
+ ~LazyValueInfo() override { assert(!PImpl && "releaseMemory not called"); }
/// This is used to return true/false/dunno results.
enum Tristate {
diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h
index 4c03c922447c..df95e0e6fdc2 100644
--- a/include/llvm/Analysis/LibCallAliasAnalysis.h
+++ b/include/llvm/Analysis/LibCallAliasAnalysis.h
@@ -15,6 +15,7 @@
#define LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H
#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
namespace llvm {
@@ -35,8 +36,8 @@ namespace llvm {
: FunctionPass(ID), LCI(LC) {
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
}
- ~LibCallAliasAnalysis();
-
+ ~LibCallAliasAnalysis() override;
+
ModRefResult getModRefInfo(ImmutableCallSite CS,
const Location &Loc) override;
@@ -48,11 +49,8 @@ namespace llvm {
void getAnalysisUsage(AnalysisUsage &AU) const override;
- bool runOnFunction(Function &F) override {
- InitializeAliasAnalysis(this); // set up super class
- return false;
- }
-
+ bool runOnFunction(Function &F) override;
+
/// getAdjustedAnalysisPointer - This method is used when a pass implements
/// an analysis interface through multiple inheritance. If needed, it
/// should override this to adjust the this pointer as needed for the
diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h
index 8bd747f03970..34831b2849dd 100644
--- a/include/llvm/Analysis/LibCallSemantics.h
+++ b/include/llvm/Analysis/LibCallSemantics.h
@@ -18,6 +18,7 @@
#include "llvm/Analysis/AliasAnalysis.h"
namespace llvm {
+class InvokeInst;
/// LibCallLocationInfo - This struct describes a set of memory locations that
/// are accessed by libcalls. Identification of a location is doing with a
@@ -162,6 +163,52 @@ namespace llvm {
virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0;
};
+ enum class EHPersonality {
+ Unknown,
+ GNU_Ada,
+ GNU_C,
+ GNU_CXX,
+ GNU_ObjC,
+ MSVC_X86SEH,
+ MSVC_Win64SEH,
+ MSVC_CXX,
+ };
+
+ /// \brief See if the given exception handling personality function is one
+ /// that we understand. If so, return a description of it; otherwise return
+ /// Unknown.
+ EHPersonality classifyEHPersonality(const Value *Pers);
+
+ /// \brief Returns true if this personality function catches asynchronous
+ /// exceptions.
+ inline bool isAsynchronousEHPersonality(EHPersonality Pers) {
+ // The two SEH personality functions can catch asynch exceptions. We assume
+ // unknown personalities don't catch asynch exceptions.
+ switch (Pers) {
+ case EHPersonality::MSVC_X86SEH:
+ case EHPersonality::MSVC_Win64SEH:
+ return true;
+ default: return false;
+ }
+ llvm_unreachable("invalid enum");
+ }
+
+ /// \brief Returns true if this is an MSVC personality function.
+ inline bool isMSVCEHPersonality(EHPersonality Pers) {
+ // The two SEH personality functions can catch asynch exceptions. We assume
+ // unknown personalities don't catch asynch exceptions.
+ switch (Pers) {
+ case EHPersonality::MSVC_CXX:
+ case EHPersonality::MSVC_X86SEH:
+ case EHPersonality::MSVC_Win64SEH:
+ return true;
+ default: return false;
+ }
+ llvm_unreachable("invalid enum");
+ }
+
+ bool canSimplifyInvokeNoUnwind(const InvokeInst *II);
+
} // end namespace llvm
#endif
diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h
index 0fe34539f8f7..42667d2af14a 100644
--- a/include/llvm/Analysis/Loads.h
+++ b/include/llvm/Analysis/Loads.h
@@ -27,8 +27,7 @@ class MDNode;
/// specified pointer, we do a quick local scan of the basic block containing
/// ScanFrom, to determine if the address is already accessed.
bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
- unsigned Align,
- const DataLayout *TD = nullptr);
+ unsigned Align);
/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at
/// the instruction before ScanFrom) checking to see if we have the value at
diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h
new file mode 100644
index 000000000000..c14e1451f338
--- /dev/null
+++ b/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -0,0 +1,552 @@
+//===- llvm/Analysis/LoopAccessAnalysis.h -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for the loop memory dependence framework that
+// was originally developed for the Loop Vectorizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H
+#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H
+
+#include "llvm/ADT/EquivalenceClasses.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/AliasSetTracker.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+class Value;
+class DataLayout;
+class AliasAnalysis;
+class ScalarEvolution;
+class Loop;
+class SCEV;
+
+/// Optimization analysis message produced during vectorization. Messages inform
+/// the user why vectorization did not occur.
+class LoopAccessReport {
+ std::string Message;
+ const Instruction *Instr;
+
+protected:
+ LoopAccessReport(const Twine &Message, const Instruction *I)
+ : Message(Message.str()), Instr(I) {}
+
+public:
+ LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {}
+
+ template <typename A> LoopAccessReport &operator<<(const A &Value) {
+ raw_string_ostream Out(Message);
+ Out << Value;
+ return *this;
+ }
+
+ const Instruction *getInstr() const { return Instr; }
+
+ std::string &str() { return Message; }
+ const std::string &str() const { return Message; }
+ operator Twine() { return Message; }
+
+ /// \brief Emit an analysis note for \p PassName with the debug location from
+ /// the instruction in \p Message if available. Otherwise use the location of
+ /// \p TheLoop.
+ static void emitAnalysis(const LoopAccessReport &Message,
+ const Function *TheFunction,
+ const Loop *TheLoop,
+ const char *PassName);
+};
+
+/// \brief Collection of parameters shared beetween the Loop Vectorizer and the
+/// Loop Access Analysis.
+struct VectorizerParams {
+ /// \brief Maximum SIMD width.
+ static const unsigned MaxVectorWidth;
+
+ /// \brief VF as overridden by the user.
+ static unsigned VectorizationFactor;
+ /// \brief Interleave factor as overridden by the user.
+ static unsigned VectorizationInterleave;
+ /// \brief True if force-vector-interleave was specified by the user.
+ static bool isInterleaveForced();
+
+ /// \\brief When performing memory disambiguation checks at runtime do not
+ /// make more than this number of comparisons.
+ static unsigned RuntimeMemoryCheckThreshold;
+};
+
+/// \brief Checks memory dependences among accesses to the same underlying
+/// object to determine whether there vectorization is legal or not (and at
+/// which vectorization factor).
+///
+/// Note: This class will compute a conservative dependence for access to
+/// different underlying pointers. Clients, such as the loop vectorizer, will
+/// sometimes deal these potential dependencies by emitting runtime checks.
+///
+/// We use the ScalarEvolution framework to symbolically evalutate access
+/// functions pairs. Since we currently don't restructure the loop we can rely
+/// on the program order of memory accesses to determine their safety.
+/// At the moment we will only deem accesses as safe for:
+/// * A negative constant distance assuming program order.
+///
+/// Safe: tmp = a[i + 1]; OR a[i + 1] = x;
+/// a[i] = tmp; y = a[i];
+///
+/// The latter case is safe because later checks guarantuee that there can't
+/// be a cycle through a phi node (that is, we check that "x" and "y" is not
+/// the same variable: a header phi can only be an induction or a reduction, a
+/// reduction can't have a memory sink, an induction can't have a memory
+/// source). This is important and must not be violated (or we have to
+/// resort to checking for cycles through memory).
+///
+/// * A positive constant distance assuming program order that is bigger
+/// than the biggest memory access.
+///
+/// tmp = a[i] OR b[i] = x
+/// a[i+2] = tmp y = b[i+2];
+///
+/// Safe distance: 2 x sizeof(a[0]), and 2 x sizeof(b[0]), respectively.
+///
+/// * Zero distances and all accesses have the same size.
+///
+class MemoryDepChecker {
+public:
+ typedef PointerIntPair<Value *, 1, bool> MemAccessInfo;
+ typedef SmallPtrSet<MemAccessInfo, 8> MemAccessInfoSet;
+ /// \brief Set of potential dependent memory accesses.
+ typedef EquivalenceClasses<MemAccessInfo> DepCandidates;
+
+ /// \brief Dependece between memory access instructions.
+ struct Dependence {
+ /// \brief The type of the dependence.
+ enum DepType {
+ // No dependence.
+ NoDep,
+ // We couldn't determine the direction or the distance.
+ Unknown,
+ // Lexically forward.
+ Forward,
+ // Forward, but if vectorized, is likely to prevent store-to-load
+ // forwarding.
+ ForwardButPreventsForwarding,
+ // Lexically backward.
+ Backward,
+ // Backward, but the distance allows a vectorization factor of
+ // MaxSafeDepDistBytes.
+ BackwardVectorizable,
+ // Same, but may prevent store-to-load forwarding.
+ BackwardVectorizableButPreventsForwarding
+ };
+
+ /// \brief String version of the types.
+ static const char *DepName[];
+
+ /// \brief Index of the source of the dependence in the InstMap vector.
+ unsigned Source;
+ /// \brief Index of the destination of the dependence in the InstMap vector.
+ unsigned Destination;
+ /// \brief The type of the dependence.
+ DepType Type;
+
+ Dependence(unsigned Source, unsigned Destination, DepType Type)
+ : Source(Source), Destination(Destination), Type(Type) {}
+
+ /// \brief Dependence types that don't prevent vectorization.
+ static bool isSafeForVectorization(DepType Type);
+
+ /// \brief Dependence types that can be queried from the analysis.
+ static bool isInterestingDependence(DepType Type);
+
+ /// \brief Lexically backward dependence types.
+ bool isPossiblyBackward() const;
+
+ /// \brief Print the dependence. \p Instr is used to map the instruction
+ /// indices to instructions.
+ void print(raw_ostream &OS, unsigned Depth,
+ const SmallVectorImpl<Instruction *> &Instrs) const;
+ };
+
+ MemoryDepChecker(ScalarEvolution *Se, const Loop *L)
+ : SE(Se), InnermostLoop(L), AccessIdx(0),
+ ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true),
+ RecordInterestingDependences(true) {}
+
+ /// \brief Register the location (instructions are given increasing numbers)
+ /// of a write access.
+ void addAccess(StoreInst *SI) {
+ Value *Ptr = SI->getPointerOperand();
+ Accesses[MemAccessInfo(Ptr, true)].push_back(AccessIdx);
+ InstMap.push_back(SI);
+ ++AccessIdx;
+ }
+
+ /// \brief Register the location (instructions are given increasing numbers)
+ /// of a write access.
+ void addAccess(LoadInst *LI) {
+ Value *Ptr = LI->getPointerOperand();
+ Accesses[MemAccessInfo(Ptr, false)].push_back(AccessIdx);
+ InstMap.push_back(LI);
+ ++AccessIdx;
+ }
+
+ /// \brief Check whether the dependencies between the accesses are safe.
+ ///
+ /// Only checks sets with elements in \p CheckDeps.
+ bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoSet &CheckDeps,
+ const ValueToValueMap &Strides);
+
+ /// \brief No memory dependence was encountered that would inhibit
+ /// vectorization.
+ bool isSafeForVectorization() const { return SafeForVectorization; }
+
+ /// \brief The maximum number of bytes of a vector register we can vectorize
+ /// the accesses safely with.
+ unsigned getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
+
+ /// \brief In same cases when the dependency check fails we can still
+ /// vectorize the loop with a dynamic array access check.
+ bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; }
+
+ /// \brief Returns the interesting dependences. If null is returned we
+ /// exceeded the MaxInterestingDependence threshold and this information is
+ /// not available.
+ const SmallVectorImpl<Dependence> *getInterestingDependences() const {
+ return RecordInterestingDependences ? &InterestingDependences : nullptr;
+ }
+
+ void clearInterestingDependences() { InterestingDependences.clear(); }
+
+ /// \brief The vector of memory access instructions. The indices are used as
+ /// instruction identifiers in the Dependence class.
+ const SmallVectorImpl<Instruction *> &getMemoryInstructions() const {
+ return InstMap;
+ }
+
+ /// \brief Find the set of instructions that read or write via \p Ptr.
+ SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
+ bool isWrite) const;
+
+private:
+ ScalarEvolution *SE;
+ const Loop *InnermostLoop;
+
+ /// \brief Maps access locations (ptr, read/write) to program order.
+ DenseMap<MemAccessInfo, std::vector<unsigned> > Accesses;
+
+ /// \brief Memory access instructions in program order.
+ SmallVector<Instruction *, 16> InstMap;
+
+ /// \brief The program order index to be used for the next instruction.
+ unsigned AccessIdx;
+
+ // We can access this many bytes in parallel safely.
+ unsigned MaxSafeDepDistBytes;
+
+ /// \brief If we see a non-constant dependence distance we can still try to
+ /// vectorize this loop with runtime checks.
+ bool ShouldRetryWithRuntimeCheck;
+
+ /// \brief No memory dependence was encountered that would inhibit
+ /// vectorization.
+ bool SafeForVectorization;
+
+ //// \brief True if InterestingDependences reflects the dependences in the
+ //// loop. If false we exceeded MaxInterestingDependence and
+ //// InterestingDependences is invalid.
+ bool RecordInterestingDependences;
+
+ /// \brief Interesting memory dependences collected during the analysis as
+ /// defined by isInterestingDependence. Only valid if
+ /// RecordInterestingDependences is true.
+ SmallVector<Dependence, 8> InterestingDependences;
+
+ /// \brief Check whether there is a plausible dependence between the two
+ /// accesses.
+ ///
+ /// Access \p A must happen before \p B in program order. The two indices
+ /// identify the index into the program order map.
+ ///
+ /// This function checks whether there is a plausible dependence (or the
+ /// absence of such can't be proved) between the two accesses. If there is a
+ /// plausible dependence but the dependence distance is bigger than one
+ /// element access it records this distance in \p MaxSafeDepDistBytes (if this
+ /// distance is smaller than any other distance encountered so far).
+ /// Otherwise, this function returns true signaling a possible dependence.
+ Dependence::DepType isDependent(const MemAccessInfo &A, unsigned AIdx,
+ const MemAccessInfo &B, unsigned BIdx,
+ const ValueToValueMap &Strides);
+
+ /// \brief Check whether the data dependence could prevent store-load
+ /// forwarding.
+ bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize);
+};
+
+/// \brief Drive the analysis of memory accesses in the loop
+///
+/// This class is responsible for analyzing the memory accesses of a loop. It
+/// collects the accesses and then its main helper the AccessAnalysis class
+/// finds and categorizes the dependences in buildDependenceSets.
+///
+/// For memory dependences that can be analyzed at compile time, it determines
+/// whether the dependence is part of cycle inhibiting vectorization. This work
+/// is delegated to the MemoryDepChecker class.
+///
+/// For memory dependences that cannot be determined at compile time, it
+/// generates run-time checks to prove independence. This is done by
+/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the
+/// RuntimePointerCheck class.
+class LoopAccessInfo {
+public:
+ /// This struct holds information about the memory runtime legality check that
+ /// a group of pointers do not overlap.
+ struct RuntimePointerCheck {
+ RuntimePointerCheck() : Need(false) {}
+
+ /// Reset the state of the pointer runtime information.
+ void reset() {
+ Need = false;
+ Pointers.clear();
+ Starts.clear();
+ Ends.clear();
+ IsWritePtr.clear();
+ DependencySetId.clear();
+ AliasSetId.clear();
+ }
+
+ /// Insert a pointer and calculate the start and end SCEVs.
+ void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr,
+ unsigned DepSetId, unsigned ASId,
+ const ValueToValueMap &Strides);
+
+ /// \brief No run-time memory checking is necessary.
+ bool empty() const { return Pointers.empty(); }
+
+ /// \brief Decide whether we need to issue a run-time check for pointer at
+ /// index \p I and \p J to prove their independence.
+ ///
+ /// If \p PtrPartition is set, it contains the partition number for
+ /// pointers (-1 if the pointer belongs to multiple partitions). In this
+ /// case omit checks between pointers belonging to the same partition.
+ bool needsChecking(unsigned I, unsigned J,
+ const SmallVectorImpl<int> *PtrPartition) const;
+
+ /// \brief Return true if any pointer requires run-time checking according
+ /// to needsChecking.
+ bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
+
+ /// \brief Print the list run-time memory checks necessary.
+ ///
+ /// If \p PtrPartition is set, it contains the partition number for
+ /// pointers (-1 if the pointer belongs to multiple partitions). In this
+ /// case omit checks between pointers belonging to the same partition.
+ void print(raw_ostream &OS, unsigned Depth = 0,
+ const SmallVectorImpl<int> *PtrPartition = nullptr) const;
+
+ /// This flag indicates if we need to add the runtime check.
+ bool Need;
+ /// Holds the pointers that we need to check.
+ SmallVector<TrackingVH<Value>, 2> Pointers;
+ /// Holds the pointer value at the beginning of the loop.
+ SmallVector<const SCEV*, 2> Starts;
+ /// Holds the pointer value at the end of the loop.
+ SmallVector<const SCEV*, 2> Ends;
+ /// Holds the information if this pointer is used for writing to memory.
+ SmallVector<bool, 2> IsWritePtr;
+ /// Holds the id of the set of pointers that could be dependent because of a
+ /// shared underlying object.
+ SmallVector<unsigned, 2> DependencySetId;
+ /// Holds the id of the disjoint alias set to which this pointer belongs.
+ SmallVector<unsigned, 2> AliasSetId;
+ };
+
+ LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,
+ const TargetLibraryInfo *TLI, AliasAnalysis *AA,
+ DominatorTree *DT, LoopInfo *LI,
+ const ValueToValueMap &Strides);
+
+ /// Return true we can analyze the memory accesses in the loop and there are
+ /// no memory dependence cycles.
+ bool canVectorizeMemory() const { return CanVecMem; }
+
+ const RuntimePointerCheck *getRuntimePointerCheck() const {
+ return &PtrRtCheck;
+ }
+
+ /// \brief Number of memchecks required to prove independence of otherwise
+ /// may-alias pointers.
+ unsigned getNumRuntimePointerChecks() const { return NumComparisons; }
+
+ /// Return true if the block BB needs to be predicated in order for the loop
+ /// to be vectorized.
+ static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop,
+ DominatorTree *DT);
+
+ /// Returns true if the value V is uniform within the loop.
+ bool isUniform(Value *V) const;
+
+ unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; }
+ unsigned getNumStores() const { return NumStores; }
+ unsigned getNumLoads() const { return NumLoads;}
+
+ /// \brief Add code that checks at runtime if the accessed arrays overlap.
+ ///
+ /// Returns a pair of instructions where the first element is the first
+ /// instruction generated in possibly a sequence of instructions and the
+ /// second value is the final comparator value or NULL if no check is needed.
+ ///
+ /// If \p PtrPartition is set, it contains the partition number for pointers
+ /// (-1 if the pointer belongs to multiple partitions). In this case omit
+ /// checks between pointers belonging to the same partition.
+ std::pair<Instruction *, Instruction *>
+ addRuntimeCheck(Instruction *Loc,
+ const SmallVectorImpl<int> *PtrPartition = nullptr) const;
+
+ /// \brief The diagnostics report generated for the analysis. E.g. why we
+ /// couldn't analyze the loop.
+ const Optional<LoopAccessReport> &getReport() const { return Report; }
+
+ /// \brief the Memory Dependence Checker which can determine the
+ /// loop-independent and loop-carried dependences between memory accesses.
+ const MemoryDepChecker &getDepChecker() const { return DepChecker; }
+
+ /// \brief Return the list of instructions that use \p Ptr to read or write
+ /// memory.
+ SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
+ bool isWrite) const {
+ return DepChecker.getInstructionsForAccess(Ptr, isWrite);
+ }
+
+ /// \brief Print the information about the memory accesses in the loop.
+ void print(raw_ostream &OS, unsigned Depth = 0) const;
+
+ /// \brief Used to ensure that if the analysis was run with speculating the
+ /// value of symbolic strides, the client queries it with the same assumption.
+ /// Only used in DEBUG build but we don't want NDEBUG-dependent ABI.
+ unsigned NumSymbolicStrides;
+
+ /// \brief Checks existence of store to invariant address inside loop.
+ /// If the loop has any store to invariant address, then it returns true,
+ /// else returns false.
+ bool hasStoreToLoopInvariantAddress() const {
+ return StoreToLoopInvariantAddress;
+ }
+
+private:
+ /// \brief Analyze the loop. Substitute symbolic strides using Strides.
+ void analyzeLoop(const ValueToValueMap &Strides);
+
+ /// \brief Check if the structure of the loop allows it to be analyzed by this
+ /// pass.
+ bool canAnalyzeLoop();
+
+ void emitAnalysis(LoopAccessReport &Message);
+
+ /// We need to check that all of the pointers in this list are disjoint
+ /// at runtime.
+ RuntimePointerCheck PtrRtCheck;
+
+ /// \brief the Memory Dependence Checker which can determine the
+ /// loop-independent and loop-carried dependences between memory accesses.
+ MemoryDepChecker DepChecker;
+
+ /// \brief Number of memchecks required to prove independence of otherwise
+ /// may-alias pointers
+ unsigned NumComparisons;
+
+ Loop *TheLoop;
+ ScalarEvolution *SE;
+ const DataLayout &DL;
+ const TargetLibraryInfo *TLI;
+ AliasAnalysis *AA;
+ DominatorTree *DT;
+ LoopInfo *LI;
+
+ unsigned NumLoads;
+ unsigned NumStores;
+
+ unsigned MaxSafeDepDistBytes;
+
+ /// \brief Cache the result of analyzeLoop.
+ bool CanVecMem;
+
+ /// \brief Indicator for storing to uniform addresses.
+ /// If a loop has write to a loop invariant address then it should be true.
+ bool StoreToLoopInvariantAddress;
+
+ /// \brief The diagnostics report generated for the analysis. E.g. why we
+ /// couldn't analyze the loop.
+ Optional<LoopAccessReport> Report;
+};
+
+Value *stripIntegerCast(Value *V);
+
+///\brief Return the SCEV corresponding to a pointer with the symbolic stride
+///replaced with constant one.
+///
+/// If \p OrigPtr is not null, use it to look up the stride value instead of \p
+/// Ptr. \p PtrToStride provides the mapping between the pointer value and its
+/// stride as collected by LoopVectorizationLegality::collectStridedAccess.
+const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE,
+ const ValueToValueMap &PtrToStride,
+ Value *Ptr, Value *OrigPtr = nullptr);
+
+/// \brief This analysis provides dependence information for the memory accesses
+/// of a loop.
+///
+/// It runs the analysis for a loop on demand. This can be initiated by
+/// querying the loop access info via LAA::getInfo. getInfo return a
+/// LoopAccessInfo object. See this class for the specifics of what information
+/// is provided.
+class LoopAccessAnalysis : public FunctionPass {
+public:
+ static char ID;
+
+ LoopAccessAnalysis() : FunctionPass(ID) {
+ initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry());
+ }
+
+ bool runOnFunction(Function &F) override;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ /// \brief Query the result of the loop access information for the loop \p L.
+ ///
+ /// If the client speculates (and then issues run-time checks) for the values
+ /// of symbolic strides, \p Strides provides the mapping (see
+ /// replaceSymbolicStrideSCEV). If there is no cached result available run
+ /// the analysis.
+ const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides);
+
+ void releaseMemory() override {
+ // Invalidate the cache when the pass is freed.
+ LoopAccessInfoMap.clear();
+ }
+
+ /// \brief Print the result of the analysis when invoked with -analyze.
+ void print(raw_ostream &OS, const Module *M = nullptr) const override;
+
+private:
+ /// \brief The cache.
+ DenseMap<Loop *, std::unique_ptr<LoopAccessInfo>> LoopAccessInfoMap;
+
+ // The used analysis passes.
+ ScalarEvolution *SE;
+ const TargetLibraryInfo *TLI;
+ AliasAnalysis *AA;
+ DominatorTree *DT;
+ LoopInfo *LI;
+};
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h
index bef03e91bbbd..be78c15e7224 100644
--- a/include/llvm/Analysis/LoopInfo.h
+++ b/include/llvm/Analysis/LoopInfo.h
@@ -42,6 +42,11 @@
namespace llvm {
+// FIXME: Replace this brittle forward declaration with the include of the new
+// PassManager.h when doing so doesn't break the PassManagerBuilder.
+template <typename IRUnitT> class AnalysisManager;
+class PreservedAnalyses;
+
template<typename T>
inline void RemoveFromVector(std::vector<T*> &V, T *N) {
typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N);
@@ -74,9 +79,9 @@ class LoopBase {
SmallPtrSet<const BlockT*, 8> DenseBlockSet;
- LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
+ LoopBase(const LoopBase<BlockT, LoopT> &) = delete;
const LoopBase<BlockT, LoopT>&
- operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
+ operator=(const LoopBase<BlockT, LoopT> &) = delete;
public:
/// Loop ctor - This creates an empty loop.
LoopBase() : ParentLoop(nullptr) {}
@@ -356,11 +361,11 @@ public:
/// isLoopInvariant - Return true if the specified value is loop invariant
///
- bool isLoopInvariant(Value *V) const;
+ bool isLoopInvariant(const Value *V) const;
/// hasLoopInvariantOperands - Return true if all the operands of the
/// specified instruction are loop invariant.
- bool hasLoopInvariantOperands(Instruction *I) const;
+ bool hasLoopInvariantOperands(const Instruction *I) const;
/// makeLoopInvariant - If the given value is an instruction inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
@@ -459,23 +464,20 @@ public:
/// cannot find a terminating instruction with location information,
/// it returns an unknown location.
DebugLoc getStartLoc() const {
- DebugLoc StartLoc;
BasicBlock *HeadBB;
// Try the pre-header first.
- if ((HeadBB = getLoopPreheader()) != nullptr) {
- StartLoc = HeadBB->getTerminator()->getDebugLoc();
- if (!StartLoc.isUnknown())
- return StartLoc;
- }
+ if ((HeadBB = getLoopPreheader()) != nullptr)
+ if (DebugLoc DL = HeadBB->getTerminator()->getDebugLoc())
+ return DL;
// If we have no pre-header or there are no instructions with debug
// info in it, try the header.
HeadBB = getHeader();
if (HeadBB)
- StartLoc = HeadBB->getTerminator()->getDebugLoc();
+ return HeadBB->getTerminator()->getDebugLoc();
- return StartLoc;
+ return DebugLoc();
}
private:
@@ -496,18 +498,33 @@ class LoopInfoBase {
friend class LoopBase<BlockT, LoopT>;
friend class LoopInfo;
- void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION;
- LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION;
+ void operator=(const LoopInfoBase &) = delete;
+ LoopInfoBase(const LoopInfoBase &) = delete;
public:
LoopInfoBase() { }
~LoopInfoBase() { releaseMemory(); }
+ LoopInfoBase(LoopInfoBase &&Arg)
+ : BBMap(std::move(Arg.BBMap)),
+ TopLevelLoops(std::move(Arg.TopLevelLoops)) {
+ // We have to clear the arguments top level loops as we've taken ownership.
+ Arg.TopLevelLoops.clear();
+ }
+ LoopInfoBase &operator=(LoopInfoBase &&RHS) {
+ BBMap = std::move(RHS.BBMap);
+
+ for (auto *L : TopLevelLoops)
+ delete L;
+ TopLevelLoops = std::move(RHS.TopLevelLoops);
+ RHS.TopLevelLoops.clear();
+ return *this;
+ }
+
void releaseMemory() {
- for (typename std::vector<LoopT *>::iterator I =
- TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I)
- delete *I; // Delete all of the loops...
+ BBMap.clear();
- BBMap.clear(); // Reset internal state of analysis
+ for (auto *L : TopLevelLoops)
+ delete L;
TopLevelLoops.clear();
}
@@ -576,8 +593,7 @@ public:
/// list with the indicated loop.
void changeTopLevelLoop(LoopT *OldLoop,
LoopT *NewLoop) {
- typename std::vector<LoopT *>::iterator I =
- std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop);
+ auto I = std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop);
assert(I != TopLevelLoops.end() && "Old loop not at top level!");
*I = NewLoop;
assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop &&
@@ -595,7 +611,7 @@ public:
/// including all of the Loop objects it is nested in and our mapping from
/// BasicBlocks to loops.
void removeBlock(BlockT *BB) {
- typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
+ auto I = BBMap.find(BB);
if (I != BBMap.end()) {
for (LoopT *L = I->second; L; L = L->getParentLoop())
L->removeBlockFromLoop(BB);
@@ -617,8 +633,9 @@ public:
void Analyze(DominatorTreeBase<BlockT> &DomTree);
// Debugging
-
void print(raw_ostream &OS) const;
+
+ void verify() const;
};
// Implementation in LoopInfoImpl.h
@@ -626,99 +643,23 @@ public:
__extension__ extern template class LoopInfoBase<BasicBlock, Loop>;
#endif
-class LoopInfo : public FunctionPass {
- LoopInfoBase<BasicBlock, Loop> LI;
+class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
+ typedef LoopInfoBase<BasicBlock, Loop> BaseT;
+
friend class LoopBase<BasicBlock, Loop>;
- void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION;
- LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION;
+ void operator=(const LoopInfo &) = delete;
+ LoopInfo(const LoopInfo &) = delete;
public:
- static char ID; // Pass identification, replacement for typeid
-
- LoopInfo() : FunctionPass(ID) {
- initializeLoopInfoPass(*PassRegistry::getPassRegistry());
- }
-
- LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; }
-
- /// iterator/begin/end - The interface to the top-level loops in the current
- /// function.
- ///
- typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator;
- typedef LoopInfoBase<BasicBlock, Loop>::reverse_iterator reverse_iterator;
- inline iterator begin() const { return LI.begin(); }
- inline iterator end() const { return LI.end(); }
- inline reverse_iterator rbegin() const { return LI.rbegin(); }
- inline reverse_iterator rend() const { return LI.rend(); }
- bool empty() const { return LI.empty(); }
-
- /// getLoopFor - Return the inner most loop that BB lives in. If a basic
- /// block is in no loop (for example the entry node), null is returned.
- ///
- inline Loop *getLoopFor(const BasicBlock *BB) const {
- return LI.getLoopFor(BB);
- }
-
- /// operator[] - same as getLoopFor...
- ///
- inline const Loop *operator[](const BasicBlock *BB) const {
- return LI.getLoopFor(BB);
- }
-
- /// getLoopDepth - Return the loop nesting level of the specified block. A
- /// depth of 0 means the block is not inside any loop.
- ///
- inline unsigned getLoopDepth(const BasicBlock *BB) const {
- return LI.getLoopDepth(BB);
- }
-
- // isLoopHeader - True if the block is a loop header node
- inline bool isLoopHeader(BasicBlock *BB) const {
- return LI.isLoopHeader(BB);
- }
-
- /// runOnFunction - Calculate the natural loop information.
- ///
- bool runOnFunction(Function &F) override;
-
- void verifyAnalysis() const override;
-
- void releaseMemory() override { LI.releaseMemory(); }
-
- void print(raw_ostream &O, const Module* M = nullptr) const override;
-
- void getAnalysisUsage(AnalysisUsage &AU) const override;
-
- /// removeLoop - This removes the specified top-level loop from this loop info
- /// object. The loop is not deleted, as it will presumably be inserted into
- /// another loop.
- inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); }
-
- /// changeLoopFor - Change the top-level loop that contains BB to the
- /// specified loop. This should be used by transformations that restructure
- /// the loop hierarchy tree.
- inline void changeLoopFor(BasicBlock *BB, Loop *L) {
- LI.changeLoopFor(BB, L);
- }
+ LoopInfo() {}
- /// changeTopLevelLoop - Replace the specified loop in the top-level loops
- /// list with the indicated loop.
- inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) {
- LI.changeTopLevelLoop(OldLoop, NewLoop);
- }
-
- /// addTopLevelLoop - This adds the specified loop to the collection of
- /// top-level loops.
- inline void addTopLevelLoop(Loop *New) {
- LI.addTopLevelLoop(New);
+ LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
+ LoopInfo &operator=(LoopInfo &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
+ return *this;
}
- /// removeBlock - This method completely removes BB from all data structures,
- /// including all of the Loop objects it is nested in and our mapping from
- /// BasicBlocks to loops.
- void removeBlock(BasicBlock *BB) {
- LI.removeBlock(BB);
- }
+ // Most of the public interface is provided via LoopInfoBase.
/// updateUnloop - Update LoopInfo after removing the last backedge from a
/// loop--now the "unloop". This updates the loop forest and parent loops for
@@ -748,7 +689,6 @@ public:
}
};
-
// Allow clients to walk the list of nested loops...
template <> struct GraphTraits<const Loop*> {
typedef const Loop NodeType;
@@ -776,6 +716,65 @@ template <> struct GraphTraits<Loop*> {
}
};
+/// \brief Analysis pass that exposes the \c LoopInfo for a function.
+class LoopAnalysis {
+ static char PassID;
+
+public:
+ typedef LoopInfo Result;
+
+ /// \brief Opaque, unique identifier for this analysis pass.
+ static void *ID() { return (void *)&PassID; }
+
+ /// \brief Provide a name for the analysis for debugging and logging.
+ static StringRef name() { return "LoopAnalysis"; }
+
+ LoopAnalysis() {}
+ LoopAnalysis(const LoopAnalysis &Arg) {}
+ LoopAnalysis(LoopAnalysis &&Arg) {}
+ LoopAnalysis &operator=(const LoopAnalysis &RHS) { return *this; }
+ LoopAnalysis &operator=(LoopAnalysis &&RHS) { return *this; }
+
+ LoopInfo run(Function &F, AnalysisManager<Function> *AM);
+};
+
+/// \brief Printer pass for the \c LoopAnalysis results.
+class LoopPrinterPass {
+ raw_ostream &OS;
+
+public:
+ explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+
+ static StringRef name() { return "LoopPrinterPass"; }
+};
+
+/// \brief The legacy pass manager's analysis pass to compute loop information.
+class LoopInfoWrapperPass : public FunctionPass {
+ LoopInfo LI;
+
+public:
+ static char ID; // Pass identification, replacement for typeid
+
+ LoopInfoWrapperPass() : FunctionPass(ID) {
+ initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ LoopInfo &getLoopInfo() { return LI; }
+ const LoopInfo &getLoopInfo() const { return LI; }
+
+ /// \brief Calculate the natural loop information for a given function.
+ bool runOnFunction(Function &F) override;
+
+ void verifyAnalysis() const override;
+
+ void releaseMemory() override { LI.releaseMemory(); }
+
+ void print(raw_ostream &O, const Module *M = nullptr) const override;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+};
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h
index 948be0f5ee1e..0490bb1d761a 100644
--- a/include/llvm/Analysis/LoopInfoImpl.h
+++ b/include/llvm/Analysis/LoopInfoImpl.h
@@ -402,7 +402,6 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
L->reserveBlocks(NumBlocks);
}
-namespace {
/// Populate all loop data in a stable order during a single forward DFS.
template<class BlockT, class LoopT>
class PopulateLoopsDFS {
@@ -410,9 +409,6 @@ class PopulateLoopsDFS {
typedef typename BlockTraits::ChildIteratorType SuccIterTy;
LoopInfoBase<BlockT, LoopT> *LI;
- DenseSet<const BlockT *> VisitedBlocks;
- std::vector<std::pair<BlockT*, SuccIterTy> > DFSStack;
-
public:
PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li):
LI(li) {}
@@ -421,37 +417,13 @@ public:
protected:
void insertIntoLoop(BlockT *Block);
-
- BlockT *dfsSource() { return DFSStack.back().first; }
- SuccIterTy &dfsSucc() { return DFSStack.back().second; }
- SuccIterTy dfsSuccEnd() { return BlockTraits::child_end(dfsSource()); }
-
- void pushBlock(BlockT *Block) {
- DFSStack.push_back(std::make_pair(Block, BlockTraits::child_begin(Block)));
- }
};
-} // anonymous
/// Top-level driver for the forward DFS within the loop.
template<class BlockT, class LoopT>
void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) {
- pushBlock(EntryBlock);
- VisitedBlocks.insert(EntryBlock);
- while (!DFSStack.empty()) {
- // Traverse the leftmost path as far as possible.
- while (dfsSucc() != dfsSuccEnd()) {
- BlockT *BB = *dfsSucc();
- ++dfsSucc();
- if (!VisitedBlocks.insert(BB).second)
- continue;
-
- // Push the next DFS successor onto the stack.
- pushBlock(BB);
- }
- // Visit the top of the stack in postorder and backtrack.
- insertIntoLoop(dfsSource());
- DFSStack.pop_back();
- }
+ for (BlockT *BB : post_order(EntryBlock))
+ insertIntoLoop(BB);
}
/// Add a single Block to its ancestor loops in PostOrder. If the block is a
@@ -500,10 +472,9 @@ Analyze(DominatorTreeBase<BlockT> &DomTree) {
// Postorder traversal of the dominator tree.
DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode();
- for (po_iterator<DomTreeNodeBase<BlockT>*> DomIter = po_begin(DomRoot),
- DomEnd = po_end(DomRoot); DomIter != DomEnd; ++DomIter) {
+ for (auto DomNode : post_order(DomRoot)) {
- BlockT *Header = DomIter->getBlock();
+ BlockT *Header = DomNode->getBlock();
SmallVector<BlockT *, 4> Backedges;
// Check each predecessor of the potential loop header.
@@ -545,6 +516,25 @@ void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
#endif
}
+template<class BlockT, class LoopT>
+void LoopInfoBase<BlockT, LoopT>::verify() const {
+ DenseSet<const LoopT*> Loops;
+ for (iterator I = begin(), E = end(); I != E; ++I) {
+ assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
+ (*I)->verifyLoopNest(&Loops);
+ }
+
+ // Verify that blocks are mapped to valid loops.
+#ifndef NDEBUG
+ for (auto &Entry : BBMap) {
+ BlockT *BB = Entry.first;
+ LoopT *L = Entry.second;
+ assert(Loops.count(L) && "orphaned loop");
+ assert(L->contains(BB) && "orphaned block");
+ }
+#endif
+}
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h
index d414680b519d..805a43dfb070 100644
--- a/include/llvm/Analysis/MemoryBuiltins.h
+++ b/include/llvm/Analysis/MemoryBuiltins.h
@@ -82,12 +82,6 @@ static inline CallInst *extractMallocCall(Value *I,
return const_cast<CallInst*>(extractMallocCall((const Value*)I, TLI));
}
-/// isArrayMalloc - Returns the corresponding CallInst if the instruction
-/// is a call to malloc whose array size can be determined and the array size
-/// is not constant 1. Otherwise, return NULL.
-const CallInst *isArrayMalloc(const Value *I, const DataLayout *DL,
- const TargetLibraryInfo *TLI);
-
/// getMallocType - Returns the PointerType resulting from the malloc call.
/// The PointerType depends on the number of bitcast uses of the malloc call:
/// 0: PointerType is the malloc calls' return type.
@@ -107,11 +101,10 @@ Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI);
/// then return that multiple. For non-array mallocs, the multiple is
/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be
/// determined.
-Value *getMallocArraySize(CallInst *CI, const DataLayout *DL,
+Value *getMallocArraySize(CallInst *CI, const DataLayout &DL,
const TargetLibraryInfo *TLI,
bool LookThroughSExt = false);
-
//===----------------------------------------------------------------------===//
// calloc Call Utility Functions.
//
@@ -147,11 +140,9 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
/// underlying object pointed to by Ptr.
/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
/// byval arguments, and global variables.
-bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *DL,
+bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
const TargetLibraryInfo *TLI, bool RoundToAlign = false);
-
-
typedef std::pair<APInt, APInt> SizeOffsetType;
/// \brief Evaluate the size and offset of an object pointed to by a Value*
@@ -159,7 +150,7 @@ typedef std::pair<APInt, APInt> SizeOffsetType;
class ObjectSizeOffsetVisitor
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
- const DataLayout *DL;
+ const DataLayout &DL;
const TargetLibraryInfo *TLI;
bool RoundToAlign;
unsigned IntTyBits;
@@ -173,7 +164,7 @@ class ObjectSizeOffsetVisitor
}
public:
- ObjectSizeOffsetVisitor(const DataLayout *DL, const TargetLibraryInfo *TLI,
+ ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
LLVMContext &Context, bool RoundToAlign = false);
SizeOffsetType compute(Value *V);
@@ -222,7 +213,7 @@ class ObjectSizeOffsetEvaluator
typedef DenseMap<const Value*, WeakEvalType> CacheMapTy;
typedef SmallPtrSet<const Value*, 8> PtrSetTy;
- const DataLayout *DL;
+ const DataLayout &DL;
const TargetLibraryInfo *TLI;
LLVMContext &Context;
BuilderTy Builder;
@@ -238,7 +229,7 @@ class ObjectSizeOffsetEvaluator
SizeOffsetEvalType compute_(Value *V);
public:
- ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI,
+ ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI,
LLVMContext &Context, bool RoundToAlign = false);
SizeOffsetEvalType compute(Value *V);
diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h
index 67fd70a4561f..cf51dd62388f 100644
--- a/include/llvm/Analysis/MemoryDependenceAnalysis.h
+++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/PredIteratorCache.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
@@ -29,7 +30,6 @@ namespace llvm {
class CallSite;
class AliasAnalysis;
class AssumptionCache;
- class DataLayout;
class MemoryDependenceAnalysis;
class PredIteratorCache;
class DominatorTree;
@@ -324,14 +324,13 @@ namespace llvm {
/// Current AA implementation, just a cache.
AliasAnalysis *AA;
- const DataLayout *DL;
DominatorTree *DT;
AssumptionCache *AC;
- std::unique_ptr<PredIteratorCache> PredCache;
+ PredIteratorCache PredCache;
public:
MemoryDependenceAnalysis();
- ~MemoryDependenceAnalysis();
+ ~MemoryDependenceAnalysis() override;
static char ID;
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
@@ -421,20 +420,21 @@ namespace llvm {
static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase,
int64_t MemLocOffs,
unsigned MemLocSize,
- const LoadInst *LI,
- const DataLayout &DL);
+ const LoadInst *LI);
private:
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
- bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer,
+ bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
+ const PHITransAddr &Pointer,
const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
SmallVectorImpl<NonLocalDepResult> &Result,
DenseMap<BasicBlock*, Value*> &Visited,
bool SkipFirstBlock = false);
- MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc,
+ MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst,
+ const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
NonLocalDepInfo *Cache,
unsigned NumSortedEntries);
diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h
index 38730d8ea4f3..84bb9d8008b5 100644
--- a/include/llvm/Analysis/PHITransAddr.h
+++ b/include/llvm/Analysis/PHITransAddr.h
@@ -36,9 +36,9 @@ namespace llvm {
class PHITransAddr {
/// Addr - The actual address we're analyzing.
Value *Addr;
-
- /// The DataLayout we are playing with if known, otherwise null.
- const DataLayout *DL;
+
+ /// The DataLayout we are playing with.
+ const DataLayout &DL;
/// TLI - The target library info if known, otherwise null.
const TargetLibraryInfo *TLI;
@@ -49,7 +49,7 @@ class PHITransAddr {
/// InstInputs - The inputs for our symbolic address.
SmallVector<Instruction*, 4> InstInputs;
public:
- PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC)
+ 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))
diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h
index 10a56059ae10..d112ab1823b4 100644
--- a/include/llvm/Analysis/Passes.h
+++ b/include/llvm/Analysis/Passes.h
@@ -138,6 +138,13 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
+ // createDivergenceAnalysisPass - This pass determines which branches in a GPU
+ // program are divergent.
+ //
+ FunctionPass *createDivergenceAnalysisPass();
+
+ //===--------------------------------------------------------------------===//
+ //
// Minor pass prototypes, allowing us to expose them through bugpoint and
// analyze.
FunctionPass *createInstCountPass();
@@ -159,9 +166,13 @@ namespace llvm {
//
FunctionPass *createMemDepPrinter();
- // createJumpInstrTableInfoPass - This creates a pass that stores information
- // about the jump tables created by JumpInstrTables
- ImmutablePass *createJumpInstrTableInfoPass();
+ //===--------------------------------------------------------------------===//
+ //
+ // createMemDerefPrinter - This pass collects memory dereferenceability
+ // information and prints it with -analyze.
+ //
+ FunctionPass *createMemDerefPrinter();
+
}
#endif
diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h
index 72cd35754c8a..0f7e2b88d2d7 100644
--- a/include/llvm/Analysis/PostDominators.h
+++ b/include/llvm/Analysis/PostDominators.h
@@ -30,7 +30,7 @@ struct PostDominatorTree : public FunctionPass {
DT = new DominatorTreeBase<BasicBlock>(true);
}
- ~PostDominatorTree();
+ ~PostDominatorTree() override;
bool runOnFunction(Function &F) override;
diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h
index 6ff7f97d01f5..7ceb086ee0a1 100644
--- a/include/llvm/Analysis/RegionInfo.h
+++ b/include/llvm/Analysis/RegionInfo.h
@@ -115,8 +115,8 @@ public:
typedef typename Tr::RegionT RegionT;
private:
- RegionNodeBase(const RegionNodeBase &) LLVM_DELETED_FUNCTION;
- const RegionNodeBase &operator=(const RegionNodeBase &) LLVM_DELETED_FUNCTION;
+ RegionNodeBase(const RegionNodeBase &) = delete;
+ const RegionNodeBase &operator=(const RegionNodeBase &) = delete;
/// This is the entry basic block that starts this region node. If this is a
/// BasicBlock RegionNode, then entry is just the basic block, that this
@@ -261,8 +261,8 @@ class RegionBase : public RegionNodeBase<Tr> {
typedef typename InvBlockTraits::ChildIteratorType PredIterTy;
friend class RegionInfoBase<Tr>;
- RegionBase(const RegionBase &) LLVM_DELETED_FUNCTION;
- const RegionBase &operator=(const RegionBase &) LLVM_DELETED_FUNCTION;
+ RegionBase(const RegionBase &) = delete;
+ const RegionBase &operator=(const RegionBase &) = delete;
// Information necessary to manage this Region.
RegionInfoT *RI;
@@ -674,8 +674,8 @@ class RegionInfoBase {
RegionInfoBase();
virtual ~RegionInfoBase();
- RegionInfoBase(const RegionInfoBase &) LLVM_DELETED_FUNCTION;
- const RegionInfoBase &operator=(const RegionInfoBase &) LLVM_DELETED_FUNCTION;
+ RegionInfoBase(const RegionInfoBase &) = delete;
+ const RegionInfoBase &operator=(const RegionInfoBase &) = delete;
DomTreeT *DT;
PostDomTreeT *PDT;
@@ -820,8 +820,6 @@ public:
inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false)
: RegionNodeBase<RegionTraits<Function>>(Parent, Entry, isSubRegion) {}
- ~RegionNode() {}
-
bool operator==(const Region &RN) const {
return this == reinterpret_cast<const RegionNode *>(&RN);
}
@@ -842,7 +840,7 @@ class RegionInfo : public RegionInfoBase<RegionTraits<Function>> {
public:
explicit RegionInfo();
- virtual ~RegionInfo();
+ ~RegionInfo() override;
// updateStatistics - Update statistic about created regions.
void updateStatistics(Region *R) final;
@@ -858,7 +856,7 @@ public:
static char ID;
explicit RegionInfoPass();
- ~RegionInfoPass();
+ ~RegionInfoPass() override;
RegionInfo &getRegionInfo() { return RI; }
diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h
index b0dc26312aaa..b31eefc15f78 100644
--- a/include/llvm/Analysis/RegionInfoImpl.h
+++ b/include/llvm/Analysis/RegionInfoImpl.h
@@ -487,7 +487,7 @@ void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level,
OS.indent(level * 2 + 2);
if (Style == PrintBB) {
- for (const auto &BB : blocks())
+ for (const auto *BB : blocks())
OS << BB->getName() << ", "; // TODO: remove the last ","
} else if (Style == PrintRN) {
for (const_element_iterator I = element_begin(), E = element_end();
@@ -714,10 +714,8 @@ void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) {
// regions from the bottom of the dominance tree. If the small regions are
// detected first, detection of bigger regions is faster, as we can jump
// over the small regions.
- for (po_iterator<DomTreeNodeT *> FI = po_begin(N), FE = po_end(N); FI != FE;
- ++FI) {
- findRegionsWithEntry(FI->getBlock(), ShortCut);
- }
+ for (auto DomNode : post_order(N))
+ findRegionsWithEntry(DomNode->getBlock(), ShortCut);
}
template <class Tr>
diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h
index 0daff58475dd..ced58dfabdd5 100644
--- a/include/llvm/Analysis/RegionIterator.h
+++ b/include/llvm/Analysis/RegionIterator.h
@@ -145,16 +145,6 @@ public:
++*this;
return tmp;
}
-
- inline const Self &operator=(const Self &I) {
- if (this != &I) {
- assert(getNode()->getParent() == I.getNode()->getParent()
- && "Cannot assign iterators of two different regions!");
- Node = I.Node;
- BItor = I.BItor;
- }
- return *this;
- }
};
@@ -240,16 +230,6 @@ public:
++*this;
return tmp;
}
-
- inline const Self &operator=(const Self &I) {
- if (this != &I) {
- assert(Node->getParent() == I.Node->getParent()
- && "Cannot assign iterators to two different regions!");
- Node = I.Node;
- Itor = I.Itor;
- }
- return *this;
- }
};
template<class NodeType, class BlockT, class RegionT>
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index f394e335257f..1d1bd67b61ff 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -71,8 +71,8 @@ namespace llvm {
unsigned short SubclassData;
private:
- SCEV(const SCEV &) LLVM_DELETED_FUNCTION;
- void operator=(const SCEV &) LLVM_DELETED_FUNCTION;
+ SCEV(const SCEV &) = delete;
+ void operator=(const SCEV &) = delete;
public:
/// NoWrapFlags are bitfield indices into SubclassData.
@@ -82,12 +82,13 @@ namespace llvm {
/// operator. NSW is a misnomer that we use to mean no signed overflow or
/// underflow.
///
- /// AddRec expression may have a no-self-wraparound <NW> property if the
- /// result can never reach the start value. This property is independent of
- /// the actual start value and step direction. Self-wraparound is defined
- /// purely in terms of the recurrence's loop, step size, and
- /// bitwidth. Formally, a recurrence with no self-wraparound satisfies:
- /// abs(step) * max-iteration(loop) <= unsigned-max(bitwidth).
+ /// AddRec expressions may have a no-self-wraparound <NW> property if, in
+ /// the integer domain, abs(step) * max-iteration(loop) <=
+ /// unsigned-max(bitwidth). This means that the recurrence will never reach
+ /// its start value if the step is non-zero. Computing the same value on
+ /// each iteration is not considered wrapping, and recurrences with step = 0
+ /// are trivially <NW>. <NW> is independent of the sign of step and the
+ /// value the add recurrence starts with.
///
/// Note that NUW and NSW are also valid properties of a recurrence, and
/// either implies NW. For convenience, NW will be set for a recurrence
@@ -231,10 +232,6 @@ namespace llvm {
///
LoopInfo *LI;
- /// The DataLayout information for the target we are targeting.
- ///
- const DataLayout *DL;
-
/// TLI - The target library information for the target we are targeting.
///
TargetLibraryInfo *TLI;
@@ -259,6 +256,10 @@ namespace llvm {
/// Mark predicate values currently being processed by isImpliedCond.
DenseSet<Value*> PendingLoopPredicates;
+ /// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of
+ /// conditions dominating the backedge of a loop.
+ bool WalkingBEDominatingConds;
+
/// ExitLimit - Information about the number of loop iterations for which a
/// loop exit's branch condition evaluates to the not-taken path. This is a
/// temporary pair of exact and max expressions that are eventually
@@ -372,44 +373,46 @@ namespace llvm {
/// LoopDispositions - Memoized computeLoopDisposition results.
DenseMap<const SCEV *,
- SmallVector<std::pair<const Loop *, LoopDisposition>, 2> > LoopDispositions;
+ SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>>
+ LoopDispositions;
/// computeLoopDisposition - Compute a LoopDisposition value.
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
/// BlockDispositions - Memoized computeBlockDisposition results.
- DenseMap<const SCEV *,
- SmallVector<std::pair<const BasicBlock *, BlockDisposition>, 2> > BlockDispositions;
+ DenseMap<
+ const SCEV *,
+ SmallVector<PointerIntPair<const BasicBlock *, 2, BlockDisposition>, 2>>
+ BlockDispositions;
/// computeBlockDisposition - Compute a BlockDisposition value.
BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB);
- /// UnsignedRanges - Memoized results from getUnsignedRange
+ /// UnsignedRanges - Memoized results from getRange
DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
- /// SignedRanges - Memoized results from getSignedRange
+ /// SignedRanges - Memoized results from getRange
DenseMap<const SCEV *, ConstantRange> SignedRanges;
- /// setUnsignedRange - Set the memoized unsigned range for the given SCEV.
- const ConstantRange &setUnsignedRange(const SCEV *S,
- const ConstantRange &CR) {
- std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
- UnsignedRanges.insert(std::make_pair(S, CR));
- if (!Pair.second)
- Pair.first->second = CR;
- return Pair.first->second;
- }
+ /// RangeSignHint - Used to parameterize getRange
+ enum RangeSignHint { HINT_RANGE_UNSIGNED, HINT_RANGE_SIGNED };
+
+ /// setRange - Set the memoized range for the given SCEV.
+ const ConstantRange &setRange(const SCEV *S, RangeSignHint Hint,
+ const ConstantRange &CR) {
+ DenseMap<const SCEV *, ConstantRange> &Cache =
+ Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges;
- /// setUnsignedRange - Set the memoized signed range for the given SCEV.
- const ConstantRange &setSignedRange(const SCEV *S,
- const ConstantRange &CR) {
std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
- SignedRanges.insert(std::make_pair(S, CR));
+ Cache.insert(std::make_pair(S, CR));
if (!Pair.second)
Pair.first->second = CR;
return Pair.first->second;
}
+ /// getRange - Determine the range for a particular SCEV.
+ ConstantRange getRange(const SCEV *S, RangeSignHint Hint);
+
/// createSCEV - We know that there is no SCEV for the specified value.
/// Analyze the expression.
const SCEV *createSCEV(Value *V);
@@ -536,6 +539,15 @@ namespace llvm {
const SCEV *FoundLHS,
const SCEV *FoundRHS);
+ /// isImpliedCondOperandsViaRanges - Test whether the condition described by
+ /// Pred, LHS, and RHS is true whenever the condition described by Pred,
+ /// FoundLHS, and FoundRHS is true. Utility function used by
+ /// isImpliedCondOperands.
+ bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
+ const SCEV *LHS, const SCEV *RHS,
+ const SCEV *FoundLHS,
+ const SCEV *FoundRHS);
+
/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is
/// in the header of its containing loop, we know the loop executes a
/// constant number of times, and the PHI node is just a recurrence
@@ -557,6 +569,15 @@ namespace llvm {
/// pointer.
bool checkValidity(const SCEV *S) const;
+ // Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be equal
+ // to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is equivalent to
+ // proving no signed (resp. unsigned) wrap in {`Start`,+,`Step`} if
+ // `ExtendOpTy` is `SCEVSignExtendExpr` (resp. `SCEVZeroExtendExpr`).
+ //
+ template<typename ExtendOpTy>
+ bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
+ const Loop *L);
+
public:
static char ID; // Pass identification, replacement for typeid
ScalarEvolution();
@@ -636,6 +657,15 @@ namespace llvm {
SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end());
return getAddRecExpr(NewOp, L, Flags);
}
+ /// \brief Returns an expression for a GEP
+ ///
+ /// \p PointeeType The type used as the basis for the pointer arithmetics
+ /// \p BaseExpr The expression for the pointer operand.
+ /// \p IndexExprs The expressions for the indices.
+ /// \p InBounds Whether the GEP is in bounds.
+ const SCEV *getGEPExpr(Type *PointeeType, const SCEV *BaseExpr,
+ const SmallVectorImpl<const SCEV *> &IndexExprs,
+ bool InBounds = false);
const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS);
const SCEV *getSMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS);
@@ -830,11 +860,15 @@ namespace llvm {
/// getUnsignedRange - Determine the unsigned range for a particular SCEV.
///
- ConstantRange getUnsignedRange(const SCEV *S);
+ ConstantRange getUnsignedRange(const SCEV *S) {
+ return getRange(S, HINT_RANGE_UNSIGNED);
+ }
/// getSignedRange - Determine the signed range for a particular SCEV.
///
- ConstantRange getSignedRange(const SCEV *S);
+ ConstantRange getSignedRange(const SCEV *S) {
+ return getRange(S, HINT_RANGE_SIGNED);
+ }
/// isKnownNegative - Test if the given expression is known to be negative.
///
diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h
index b9bef970b5d3..8ec2078258d1 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpander.h
+++ b/include/llvm/Analysis/ScalarEvolutionExpander.h
@@ -28,7 +28,7 @@ namespace llvm {
/// all materialized values are safe to speculate.
bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE);
- /// SCEVExpander - This class uses information about analyze scalars to
+ /// This class uses information about analyze scalars to
/// rewrite expressions in canonical form.
///
/// Clients should create an instance of this class when rewriting is needed,
@@ -36,6 +36,7 @@ namespace llvm {
/// memory.
class SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> {
ScalarEvolution &SE;
+ const DataLayout &DL;
// New instructions receive a name to identifies them with the current pass.
const char* IVName;
@@ -47,37 +48,36 @@ namespace llvm {
std::set<AssertingVH<Value> > InsertedValues;
std::set<AssertingVH<Value> > InsertedPostIncValues;
- /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV.
+ /// A memoization of the "relevant" loop for a given SCEV.
DenseMap<const SCEV *, const Loop *> RelevantLoops;
- /// PostIncLoops - Addrecs referring to any of the given loops are expanded
+ /// \brief Addrecs referring to any of the given loops are expanded
/// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode
/// returns the add instruction that adds one to the phi for {0,+,1}<L>,
/// as opposed to a new phi starting at 1. This is only supported in
/// non-canonical mode.
PostIncLoopSet PostIncLoops;
- /// IVIncInsertPos - When this is non-null, addrecs expanded in the
- /// loop it indicates should be inserted with increments at
- /// IVIncInsertPos.
+ /// \brief When this is non-null, addrecs expanded in the loop it indicates
+ /// should be inserted with increments at IVIncInsertPos.
const Loop *IVIncInsertLoop;
- /// IVIncInsertPos - When expanding addrecs in the IVIncInsertLoop loop,
- /// insert the IV increment at this position.
+ /// \brief When expanding addrecs in the IVIncInsertLoop loop, insert the IV
+ /// increment at this position.
Instruction *IVIncInsertPos;
- /// Phis that complete an IV chain. Reuse
+ /// \brief Phis that complete an IV chain. Reuse
std::set<AssertingVH<PHINode> > ChainedPhis;
- /// CanonicalMode - When true, expressions are expanded in "canonical"
- /// form. In particular, addrecs are expanded as arithmetic based on
- /// a canonical induction variable. When false, expression are expanded
- /// in a more literal form.
+ /// \brief When true, expressions are expanded in "canonical" form. In
+ /// particular, addrecs are expanded as arithmetic based on a canonical
+ /// induction variable. When false, expression are expanded in a more
+ /// literal form.
bool CanonicalMode;
- /// When invoked from LSR, the expander is in "strength reduction" mode. The
- /// only difference is that phi's are only reused if they are already in
- /// "expanded" form.
+ /// \brief When invoked from LSR, the expander is in "strength reduction"
+ /// mode. The only difference is that phi's are only reused if they are
+ /// already in "expanded" form.
bool LSRMode;
typedef IRBuilder<true, TargetFolder> BuilderType;
@@ -90,11 +90,12 @@ namespace llvm {
friend struct SCEVVisitor<SCEVExpander, Value*>;
public:
- /// SCEVExpander - Construct a SCEVExpander in "canonical" mode.
- explicit SCEVExpander(ScalarEvolution &se, const char *name)
- : SE(se), IVName(name), IVIncInsertLoop(nullptr), IVIncInsertPos(nullptr),
- CanonicalMode(true), LSRMode(false),
- Builder(se.getContext(), TargetFolder(se.DL)) {
+ /// \brief Construct a SCEVExpander in "canonical" mode.
+ explicit SCEVExpander(ScalarEvolution &se, const DataLayout &DL,
+ const char *name)
+ : SE(se), DL(DL), IVName(name), IVIncInsertLoop(nullptr),
+ IVIncInsertPos(nullptr), CanonicalMode(true), LSRMode(false),
+ Builder(se.getContext(), TargetFolder(DL)) {
#ifndef NDEBUG
DebugType = "";
#endif
@@ -104,7 +105,7 @@ namespace llvm {
void setDebugType(const char* s) { DebugType = s; }
#endif
- /// clear - Erase the contents of the InsertedExpressions map so that users
+ /// \brief Erase the contents of the InsertedExpressions map so that users
/// trying to expand the same expression into multiple BasicBlocks or
/// different places within the same BasicBlock can do so.
void clear() {
@@ -114,31 +115,38 @@ namespace llvm {
ChainedPhis.clear();
}
- /// getOrInsertCanonicalInductionVariable - This method returns the
- /// canonical induction variable of the specified type for the specified
- /// loop (inserting one if there is none). A canonical induction variable
- /// starts at zero and steps by one on each iteration.
+ /// \brief Return true for expressions that may incur non-trivial cost to
+ /// evaluate at runtime.
+ bool isHighCostExpansion(const SCEV *Expr, Loop *L) {
+ SmallPtrSet<const SCEV *, 8> Processed;
+ return isHighCostExpansionHelper(Expr, L, Processed);
+ }
+
+ /// \brief This method returns the canonical induction variable of the
+ /// specified type for the specified loop (inserting one if there is none).
+ /// A canonical induction variable starts at zero and steps by one on each
+ /// iteration.
PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty);
- /// getIVIncOperand - Return the induction variable increment's IV operand.
+ /// \brief Return the induction variable increment's IV operand.
Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos,
bool allowScale);
- /// hoistIVInc - Utility for hoisting an IV increment.
+ /// \brief Utility for hoisting an IV increment.
bool hoistIVInc(Instruction *IncV, Instruction *InsertPos);
- /// replaceCongruentIVs - replace congruent phis with their most canonical
+ /// \brief replace congruent phis with their most canonical
/// representative. Return the number of phis eliminated.
unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT,
SmallVectorImpl<WeakVH> &DeadInsts,
const TargetTransformInfo *TTI = nullptr);
- /// expandCodeFor - Insert code to directly compute the specified SCEV
- /// expression into the program. The inserted code is inserted into the
- /// specified block.
+ /// \brief Insert code to directly compute the specified SCEV expression
+ /// into the program. The inserted code is inserted into the specified
+ /// block.
Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I);
- /// setIVIncInsertPos - Set the current IV increment loop and position.
+ /// \brief Set the current IV increment loop and position.
void setIVIncInsertPos(const Loop *L, Instruction *Pos) {
assert(!CanonicalMode &&
"IV increment positions are not supported in CanonicalMode");
@@ -146,16 +154,15 @@ namespace llvm {
IVIncInsertPos = Pos;
}
- /// setPostInc - Enable post-inc expansion for addrecs referring to the
- /// given loops. Post-inc expansion is only supported in non-canonical
- /// mode.
+ /// \brief Enable post-inc expansion for addrecs referring to the given
+ /// loops. Post-inc expansion is only supported in non-canonical mode.
void setPostInc(const PostIncLoopSet &L) {
assert(!CanonicalMode &&
"Post-inc expansion is not supported in CanonicalMode");
PostIncLoops = L;
}
- /// clearPostInc - Disable all post-inc expansion.
+ /// \brief Disable all post-inc expansion.
void clearPostInc() {
PostIncLoops.clear();
@@ -164,23 +171,22 @@ namespace llvm {
InsertedPostIncValues.clear();
}
- /// disableCanonicalMode - Disable the behavior of expanding expressions in
- /// canonical form rather than in a more literal form. Non-canonical mode
- /// is useful for late optimization passes.
+ /// \brief Disable the behavior of expanding expressions in canonical form
+ /// rather than in a more literal form. Non-canonical mode is useful for
+ /// late optimization passes.
void disableCanonicalMode() { CanonicalMode = false; }
void enableLSRMode() { LSRMode = true; }
- /// clearInsertPoint - Clear the current insertion point. This is useful
- /// if the instruction that had been serving as the insertion point may
- /// have been deleted.
+ /// \brief Clear the current insertion point. This is useful if the
+ /// instruction that had been serving as the insertion point may have been
+ /// deleted.
void clearInsertPoint() {
Builder.ClearInsertionPoint();
}
- /// isInsertedInstruction - Return true if the specified instruction was
- /// inserted by the code rewriter. If so, the client should not modify the
- /// instruction.
+ /// \brief Return true if the specified instruction was inserted by the code
+ /// rewriter. If so, the client should not modify the instruction.
bool isInsertedInstruction(Instruction *I) const {
return InsertedValues.count(I) || InsertedPostIncValues.count(I);
}
@@ -190,24 +196,27 @@ namespace llvm {
private:
LLVMContext &getContext() const { return SE.getContext(); }
- /// InsertBinop - Insert the specified binary operator, doing a small amount
+ /// \brief Recursive helper function for isHighCostExpansion.
+ bool isHighCostExpansionHelper(const SCEV *S, Loop *L,
+ SmallPtrSetImpl<const SCEV *> &Processed);
+
+ /// \brief Insert the specified binary operator, doing a small amount
/// of work to avoid inserting an obviously redundant operation.
Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS);
- /// ReuseOrCreateCast - Arange for there to be a cast of V to Ty at IP,
- /// reusing an existing cast if a suitable one exists, moving an existing
- /// cast if a suitable one exists but isn't in the right place, or
- /// or creating a new one.
+ /// \brief Arrange for there to be a cast of V to Ty at IP, reusing an
+ /// existing cast if a suitable one exists, moving an existing cast if a
+ /// suitable one exists but isn't in the right place, or or creating a new
+ /// one.
Value *ReuseOrCreateCast(Value *V, Type *Ty,
Instruction::CastOps Op,
BasicBlock::iterator IP);
- /// InsertNoopCastOfTo - Insert a cast of V to the specified type,
- /// which must be possible with a noop cast, doing what we can to
- /// share the casts.
+ /// \brief Insert a cast of V to the specified type, which must be possible
+ /// with a noop cast, doing what we can to share the casts.
Value *InsertNoopCastOfTo(Value *V, Type *Ty);
- /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP
+ /// \brief Expand a SCEVAddExpr with a pointer type into a GEP
/// instead of using ptrtoint+arithmetic+inttoptr.
Value *expandAddToGEP(const SCEV *const *op_begin,
const SCEV *const *op_end,
@@ -215,13 +224,13 @@ namespace llvm {
Value *expand(const SCEV *S);
- /// expandCodeFor - Insert code to directly compute the specified SCEV
- /// expression into the program. The inserted code is inserted into the
- /// SCEVExpander's current insertion point. If a type is specified, the
- /// result will be expanded to have that type, with a cast if necessary.
+ /// \brief Insert code to directly compute the specified SCEV expression
+ /// into the program. The inserted code is inserted into the SCEVExpander's
+ /// current insertion point. If a type is specified, the result will be
+ /// expanded to have that type, with a cast if necessary.
Value *expandCodeFor(const SCEV *SH, Type *Ty = nullptr);
- /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV.
+ /// \brief Determine the most "relevant" loop for the given SCEV.
const Loop *getRelevantLoop(const SCEV *);
Value *visitConstant(const SCEVConstant *S) {
diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h
index 65ff2f643192..9ccae5ff89b7 100644
--- a/include/llvm/Analysis/SparsePropagation.h
+++ b/include/llvm/Analysis/SparsePropagation.h
@@ -131,8 +131,8 @@ class SparseSolver {
typedef std::pair<BasicBlock*,BasicBlock*> Edge;
std::set<Edge> KnownFeasibleEdges;
- SparseSolver(const SparseSolver&) LLVM_DELETED_FUNCTION;
- void operator=(const SparseSolver&) LLVM_DELETED_FUNCTION;
+ SparseSolver(const SparseSolver&) = delete;
+ void operator=(const SparseSolver&) = delete;
public:
explicit SparseSolver(AbstractLatticeFunction *Lattice)
: LatticeFunc(Lattice) {}
diff --git a/include/llvm/Analysis/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h
index 587a7ef5410a..12bf9fe78a47 100644
--- a/include/llvm/Analysis/TargetFolder.h
+++ b/include/llvm/Analysis/TargetFolder.h
@@ -30,7 +30,7 @@ class DataLayout;
/// TargetFolder - Create constants with target dependent folding.
class TargetFolder {
- const DataLayout *DL;
+ const DataLayout &DL;
/// Fold - Fold the constant using target specific information.
Constant *Fold(Constant *C) const {
@@ -41,7 +41,7 @@ class TargetFolder {
}
public:
- explicit TargetFolder(const DataLayout *DL) : DL(DL) {}
+ explicit TargetFolder(const DataLayout &DL) : DL(DL) {}
//===--------------------------------------------------------------------===//
// Binary Operators
@@ -130,34 +130,35 @@ public:
// Memory Instructions
//===--------------------------------------------------------------------===//
- Constant *CreateGetElementPtr(Constant *C,
+ Constant *CreateGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) const {
- return Fold(ConstantExpr::getGetElementPtr(C, IdxList));
+ return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList));
}
- Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const {
+ Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
- return Fold(ConstantExpr::getGetElementPtr(C, Idx));
+ return Fold(ConstantExpr::getGetElementPtr(Ty, C, Idx));
}
- Constant *CreateGetElementPtr(Constant *C,
+ Constant *CreateGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) const {
- return Fold(ConstantExpr::getGetElementPtr(C, IdxList));
+ return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList));
}
- Constant *CreateInBoundsGetElementPtr(Constant *C,
+ Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) const {
- return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList));
+ return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList));
}
- Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const {
+ Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
+ Constant *Idx) const {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
- return Fold(ConstantExpr::getInBoundsGetElementPtr(C, Idx));
+ return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx));
}
- Constant *CreateInBoundsGetElementPtr(Constant *C,
+ Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) const {
- return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList));
+ return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList));
}
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def
new file mode 100644
index 000000000000..1c1fdfef980d
--- /dev/null
+++ b/include/llvm/Analysis/TargetLibraryInfo.def
@@ -0,0 +1,1029 @@
+//===-- TargetLibraryInfo.def - Library information -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This .def file will either fill in the enum definition or fill in the
+// string representation array definition for TargetLibraryInfo.
+// Which is defined depends on whether TLI_DEFINE_ENUM is defined or
+// TLI_DEFINE_STRING is defined. Only one should be defined at a time.
+
+#if !(defined(TLI_DEFINE_ENUM) || defined(TLI_DEFINE_STRING))
+#error "Must define TLI_DEFINE_ENUM or TLI_DEFINE_STRING for TLI .def."
+#elif defined(TLI_DEFINE_ENUM) && defined(TLI_DEFINE_STRING)
+#error "Can only define one of TLI_DEFINE_ENUM or TLI_DEFINE_STRING at a time."
+#else
+// One of TLI_DEFINE_ENUM/STRING are defined.
+
+#if defined(TLI_DEFINE_ENUM)
+#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) enum_variant,
+#define TLI_DEFINE_STRING_INTERNAL(string_repr)
+#else
+#define TLI_DEFINE_ENUM_INTERNAL(enum_variant)
+#define TLI_DEFINE_STRING_INTERNAL(string_repr) string_repr,
+#endif
+
+/// int _IO_getc(_IO_FILE * __fp);
+TLI_DEFINE_ENUM_INTERNAL(under_IO_getc)
+TLI_DEFINE_STRING_INTERNAL("_IO_getc")
+/// int _IO_putc(int __c, _IO_FILE * __fp);
+TLI_DEFINE_ENUM_INTERNAL(under_IO_putc)
+TLI_DEFINE_STRING_INTERNAL("_IO_putc")
+/// void operator delete[](void*);
+TLI_DEFINE_ENUM_INTERNAL(ZdaPv)
+TLI_DEFINE_STRING_INTERNAL("_ZdaPv")
+/// void operator delete[](void*, nothrow);
+TLI_DEFINE_ENUM_INTERNAL(ZdaPvRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZdaPvRKSt9nothrow_t")
+/// void operator delete[](void*, unsigned int);
+TLI_DEFINE_ENUM_INTERNAL(ZdaPvj)
+TLI_DEFINE_STRING_INTERNAL("_ZdaPvj")
+/// void operator delete[](void*, unsigned long);
+TLI_DEFINE_ENUM_INTERNAL(ZdaPvm)
+TLI_DEFINE_STRING_INTERNAL("_ZdaPvm")
+/// void operator delete(void*);
+TLI_DEFINE_ENUM_INTERNAL(ZdlPv)
+TLI_DEFINE_STRING_INTERNAL("_ZdlPv")
+/// void operator delete(void*, nothrow);
+TLI_DEFINE_ENUM_INTERNAL(ZdlPvRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZdlPvRKSt9nothrow_t")
+/// void operator delete(void*, unsigned int);
+TLI_DEFINE_ENUM_INTERNAL(ZdlPvj)
+TLI_DEFINE_STRING_INTERNAL("_ZdlPvj")
+/// void operator delete(void*, unsigned long);
+TLI_DEFINE_ENUM_INTERNAL(ZdlPvm)
+TLI_DEFINE_STRING_INTERNAL("_ZdlPvm")
+/// void *new[](unsigned int);
+TLI_DEFINE_ENUM_INTERNAL(Znaj)
+TLI_DEFINE_STRING_INTERNAL("_Znaj")
+/// void *new[](unsigned int, nothrow);
+TLI_DEFINE_ENUM_INTERNAL(ZnajRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnajRKSt9nothrow_t")
+/// void *new[](unsigned long);
+TLI_DEFINE_ENUM_INTERNAL(Znam)
+TLI_DEFINE_STRING_INTERNAL("_Znam")
+/// void *new[](unsigned long, nothrow);
+TLI_DEFINE_ENUM_INTERNAL(ZnamRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnamRKSt9nothrow_t")
+/// void *new(unsigned int);
+TLI_DEFINE_ENUM_INTERNAL(Znwj)
+TLI_DEFINE_STRING_INTERNAL("_Znwj")
+/// void *new(unsigned int, nothrow);
+TLI_DEFINE_ENUM_INTERNAL(ZnwjRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnwjRKSt9nothrow_t")
+/// void *new(unsigned long);
+TLI_DEFINE_ENUM_INTERNAL(Znwm)
+TLI_DEFINE_STRING_INTERNAL("_Znwm")
+/// void *new(unsigned long, nothrow);
+TLI_DEFINE_ENUM_INTERNAL(ZnwmRKSt9nothrow_t)
+TLI_DEFINE_STRING_INTERNAL("_ZnwmRKSt9nothrow_t")
+/// double __cospi(double x);
+TLI_DEFINE_ENUM_INTERNAL(cospi)
+TLI_DEFINE_STRING_INTERNAL("__cospi")
+/// float __cospif(float x);
+TLI_DEFINE_ENUM_INTERNAL(cospif)
+TLI_DEFINE_STRING_INTERNAL("__cospif")
+/// int __cxa_atexit(void (*f)(void *), void *p, void *d);
+TLI_DEFINE_ENUM_INTERNAL(cxa_atexit)
+TLI_DEFINE_STRING_INTERNAL("__cxa_atexit")
+/// void __cxa_guard_abort(guard_t *guard);
+/// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi.
+TLI_DEFINE_ENUM_INTERNAL(cxa_guard_abort)
+TLI_DEFINE_STRING_INTERNAL("__cxa_guard_abort")
+/// int __cxa_guard_acquire(guard_t *guard);
+TLI_DEFINE_ENUM_INTERNAL(cxa_guard_acquire)
+TLI_DEFINE_STRING_INTERNAL("__cxa_guard_acquire")
+/// void __cxa_guard_release(guard_t *guard);
+TLI_DEFINE_ENUM_INTERNAL(cxa_guard_release)
+TLI_DEFINE_STRING_INTERNAL("__cxa_guard_release")
+/// int __isoc99_scanf (const char *format, ...)
+TLI_DEFINE_ENUM_INTERNAL(dunder_isoc99_scanf)
+TLI_DEFINE_STRING_INTERNAL("__isoc99_scanf")
+/// int __isoc99_sscanf(const char *s, const char *format, ...)
+TLI_DEFINE_ENUM_INTERNAL(dunder_isoc99_sscanf)
+TLI_DEFINE_STRING_INTERNAL("__isoc99_sscanf")
+/// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(memcpy_chk)
+TLI_DEFINE_STRING_INTERNAL("__memcpy_chk")
+/// void *__memmove_chk(void *s1, const void *s2, size_t n, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(memmove_chk)
+TLI_DEFINE_STRING_INTERNAL("__memmove_chk")
+/// void *__memset_chk(void *s, char v, size_t n, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(memset_chk)
+TLI_DEFINE_STRING_INTERNAL("__memset_chk")
+/// double __sincospi_stret(double x);
+TLI_DEFINE_ENUM_INTERNAL(sincospi_stret)
+TLI_DEFINE_STRING_INTERNAL("__sincospi_stret")
+/// float __sincospif_stret(float x);
+TLI_DEFINE_ENUM_INTERNAL(sincospif_stret)
+TLI_DEFINE_STRING_INTERNAL("__sincospif_stret")
+/// double __sinpi(double x);
+TLI_DEFINE_ENUM_INTERNAL(sinpi)
+TLI_DEFINE_STRING_INTERNAL("__sinpi")
+/// float __sinpif(float x);
+TLI_DEFINE_ENUM_INTERNAL(sinpif)
+TLI_DEFINE_STRING_INTERNAL("__sinpif")
+/// double __sqrt_finite(double x);
+TLI_DEFINE_ENUM_INTERNAL(sqrt_finite)
+TLI_DEFINE_STRING_INTERNAL("__sqrt_finite")
+/// float __sqrt_finite(float x);
+TLI_DEFINE_ENUM_INTERNAL(sqrtf_finite)
+TLI_DEFINE_STRING_INTERNAL("__sqrtf_finite")
+/// long double __sqrt_finite(long double x);
+TLI_DEFINE_ENUM_INTERNAL(sqrtl_finite)
+TLI_DEFINE_STRING_INTERNAL("__sqrtl_finite")
+/// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(stpcpy_chk)
+TLI_DEFINE_STRING_INTERNAL("__stpcpy_chk")
+/// char *__stpncpy_chk(char *s1, const char *s2, size_t n, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(stpncpy_chk)
+TLI_DEFINE_STRING_INTERNAL("__stpncpy_chk")
+/// char *__strcpy_chk(char *s1, const char *s2, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(strcpy_chk)
+TLI_DEFINE_STRING_INTERNAL("__strcpy_chk")
+/// char * __strdup(const char *s);
+TLI_DEFINE_ENUM_INTERNAL(dunder_strdup)
+TLI_DEFINE_STRING_INTERNAL("__strdup")
+/// char *__strncpy_chk(char *s1, const char *s2, size_t n, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(strncpy_chk)
+TLI_DEFINE_STRING_INTERNAL("__strncpy_chk")
+/// char *__strndup(const char *s, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(dunder_strndup)
+TLI_DEFINE_STRING_INTERNAL("__strndup")
+/// char * __strtok_r(char *s, const char *delim, char **save_ptr);
+TLI_DEFINE_ENUM_INTERNAL(dunder_strtok_r)
+TLI_DEFINE_STRING_INTERNAL("__strtok_r")
+/// int abs(int j);
+TLI_DEFINE_ENUM_INTERNAL(abs)
+TLI_DEFINE_STRING_INTERNAL("abs")
+/// int access(const char *path, int amode);
+TLI_DEFINE_ENUM_INTERNAL(access)
+TLI_DEFINE_STRING_INTERNAL("access")
+/// double acos(double x);
+TLI_DEFINE_ENUM_INTERNAL(acos)
+TLI_DEFINE_STRING_INTERNAL("acos")
+/// float acosf(float x);
+TLI_DEFINE_ENUM_INTERNAL(acosf)
+TLI_DEFINE_STRING_INTERNAL("acosf")
+/// double acosh(double x);
+TLI_DEFINE_ENUM_INTERNAL(acosh)
+TLI_DEFINE_STRING_INTERNAL("acosh")
+/// float acoshf(float x);
+TLI_DEFINE_ENUM_INTERNAL(acoshf)
+TLI_DEFINE_STRING_INTERNAL("acoshf")
+/// long double acoshl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(acoshl)
+TLI_DEFINE_STRING_INTERNAL("acoshl")
+/// long double acosl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(acosl)
+TLI_DEFINE_STRING_INTERNAL("acosl")
+/// double asin(double x);
+TLI_DEFINE_ENUM_INTERNAL(asin)
+TLI_DEFINE_STRING_INTERNAL("asin")
+/// float asinf(float x);
+TLI_DEFINE_ENUM_INTERNAL(asinf)
+TLI_DEFINE_STRING_INTERNAL("asinf")
+/// double asinh(double x);
+TLI_DEFINE_ENUM_INTERNAL(asinh)
+TLI_DEFINE_STRING_INTERNAL("asinh")
+/// float asinhf(float x);
+TLI_DEFINE_ENUM_INTERNAL(asinhf)
+TLI_DEFINE_STRING_INTERNAL("asinhf")
+/// long double asinhl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(asinhl)
+TLI_DEFINE_STRING_INTERNAL("asinhl")
+/// long double asinl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(asinl)
+TLI_DEFINE_STRING_INTERNAL("asinl")
+/// double atan(double x);
+TLI_DEFINE_ENUM_INTERNAL(atan)
+TLI_DEFINE_STRING_INTERNAL("atan")
+/// double atan2(double y, double x);
+TLI_DEFINE_ENUM_INTERNAL(atan2)
+TLI_DEFINE_STRING_INTERNAL("atan2")
+/// float atan2f(float y, float x);
+TLI_DEFINE_ENUM_INTERNAL(atan2f)
+TLI_DEFINE_STRING_INTERNAL("atan2f")
+/// long double atan2l(long double y, long double x);
+TLI_DEFINE_ENUM_INTERNAL(atan2l)
+TLI_DEFINE_STRING_INTERNAL("atan2l")
+/// float atanf(float x);
+TLI_DEFINE_ENUM_INTERNAL(atanf)
+TLI_DEFINE_STRING_INTERNAL("atanf")
+/// double atanh(double x);
+TLI_DEFINE_ENUM_INTERNAL(atanh)
+TLI_DEFINE_STRING_INTERNAL("atanh")
+/// float atanhf(float x);
+TLI_DEFINE_ENUM_INTERNAL(atanhf)
+TLI_DEFINE_STRING_INTERNAL("atanhf")
+/// long double atanhl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(atanhl)
+TLI_DEFINE_STRING_INTERNAL("atanhl")
+/// long double atanl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(atanl)
+TLI_DEFINE_STRING_INTERNAL("atanl")
+/// double atof(const char *str);
+TLI_DEFINE_ENUM_INTERNAL(atof)
+TLI_DEFINE_STRING_INTERNAL("atof")
+/// int atoi(const char *str);
+TLI_DEFINE_ENUM_INTERNAL(atoi)
+TLI_DEFINE_STRING_INTERNAL("atoi")
+/// long atol(const char *str);
+TLI_DEFINE_ENUM_INTERNAL(atol)
+TLI_DEFINE_STRING_INTERNAL("atol")
+/// long long atoll(const char *nptr);
+TLI_DEFINE_ENUM_INTERNAL(atoll)
+TLI_DEFINE_STRING_INTERNAL("atoll")
+/// int bcmp(const void *s1, const void *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(bcmp)
+TLI_DEFINE_STRING_INTERNAL("bcmp")
+/// void bcopy(const void *s1, void *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(bcopy)
+TLI_DEFINE_STRING_INTERNAL("bcopy")
+/// void bzero(void *s, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(bzero)
+TLI_DEFINE_STRING_INTERNAL("bzero")
+/// void *calloc(size_t count, size_t size);
+TLI_DEFINE_ENUM_INTERNAL(calloc)
+TLI_DEFINE_STRING_INTERNAL("calloc")
+/// double cbrt(double x);
+TLI_DEFINE_ENUM_INTERNAL(cbrt)
+TLI_DEFINE_STRING_INTERNAL("cbrt")
+/// float cbrtf(float x);
+TLI_DEFINE_ENUM_INTERNAL(cbrtf)
+TLI_DEFINE_STRING_INTERNAL("cbrtf")
+/// long double cbrtl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(cbrtl)
+TLI_DEFINE_STRING_INTERNAL("cbrtl")
+/// double ceil(double x);
+TLI_DEFINE_ENUM_INTERNAL(ceil)
+TLI_DEFINE_STRING_INTERNAL("ceil")
+/// float ceilf(float x);
+TLI_DEFINE_ENUM_INTERNAL(ceilf)
+TLI_DEFINE_STRING_INTERNAL("ceilf")
+/// long double ceill(long double x);
+TLI_DEFINE_ENUM_INTERNAL(ceill)
+TLI_DEFINE_STRING_INTERNAL("ceill")
+/// int chmod(const char *path, mode_t mode);
+TLI_DEFINE_ENUM_INTERNAL(chmod)
+TLI_DEFINE_STRING_INTERNAL("chmod")
+/// int chown(const char *path, uid_t owner, gid_t group);
+TLI_DEFINE_ENUM_INTERNAL(chown)
+TLI_DEFINE_STRING_INTERNAL("chown")
+/// void clearerr(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(clearerr)
+TLI_DEFINE_STRING_INTERNAL("clearerr")
+/// int closedir(DIR *dirp);
+TLI_DEFINE_ENUM_INTERNAL(closedir)
+TLI_DEFINE_STRING_INTERNAL("closedir")
+/// double copysign(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(copysign)
+TLI_DEFINE_STRING_INTERNAL("copysign")
+/// float copysignf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(copysignf)
+TLI_DEFINE_STRING_INTERNAL("copysignf")
+/// long double copysignl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(copysignl)
+TLI_DEFINE_STRING_INTERNAL("copysignl")
+/// double cos(double x);
+TLI_DEFINE_ENUM_INTERNAL(cos)
+TLI_DEFINE_STRING_INTERNAL("cos")
+/// float cosf(float x);
+TLI_DEFINE_ENUM_INTERNAL(cosf)
+TLI_DEFINE_STRING_INTERNAL("cosf")
+/// double cosh(double x);
+TLI_DEFINE_ENUM_INTERNAL(cosh)
+TLI_DEFINE_STRING_INTERNAL("cosh")
+/// float coshf(float x);
+TLI_DEFINE_ENUM_INTERNAL(coshf)
+TLI_DEFINE_STRING_INTERNAL("coshf")
+/// long double coshl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(coshl)
+TLI_DEFINE_STRING_INTERNAL("coshl")
+/// long double cosl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(cosl)
+TLI_DEFINE_STRING_INTERNAL("cosl")
+/// char *ctermid(char *s);
+TLI_DEFINE_ENUM_INTERNAL(ctermid)
+TLI_DEFINE_STRING_INTERNAL("ctermid")
+/// double exp(double x);
+TLI_DEFINE_ENUM_INTERNAL(exp)
+TLI_DEFINE_STRING_INTERNAL("exp")
+/// double exp10(double x);
+TLI_DEFINE_ENUM_INTERNAL(exp10)
+TLI_DEFINE_STRING_INTERNAL("exp10")
+/// float exp10f(float x);
+TLI_DEFINE_ENUM_INTERNAL(exp10f)
+TLI_DEFINE_STRING_INTERNAL("exp10f")
+/// long double exp10l(long double x);
+TLI_DEFINE_ENUM_INTERNAL(exp10l)
+TLI_DEFINE_STRING_INTERNAL("exp10l")
+/// double exp2(double x);
+TLI_DEFINE_ENUM_INTERNAL(exp2)
+TLI_DEFINE_STRING_INTERNAL("exp2")
+/// float exp2f(float x);
+TLI_DEFINE_ENUM_INTERNAL(exp2f)
+TLI_DEFINE_STRING_INTERNAL("exp2f")
+/// long double exp2l(long double x);
+TLI_DEFINE_ENUM_INTERNAL(exp2l)
+TLI_DEFINE_STRING_INTERNAL("exp2l")
+/// float expf(float x);
+TLI_DEFINE_ENUM_INTERNAL(expf)
+TLI_DEFINE_STRING_INTERNAL("expf")
+/// long double expl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(expl)
+TLI_DEFINE_STRING_INTERNAL("expl")
+/// double expm1(double x);
+TLI_DEFINE_ENUM_INTERNAL(expm1)
+TLI_DEFINE_STRING_INTERNAL("expm1")
+/// float expm1f(float x);
+TLI_DEFINE_ENUM_INTERNAL(expm1f)
+TLI_DEFINE_STRING_INTERNAL("expm1f")
+/// long double expm1l(long double x);
+TLI_DEFINE_ENUM_INTERNAL(expm1l)
+TLI_DEFINE_STRING_INTERNAL("expm1l")
+/// double fabs(double x);
+TLI_DEFINE_ENUM_INTERNAL(fabs)
+TLI_DEFINE_STRING_INTERNAL("fabs")
+/// float fabsf(float x);
+TLI_DEFINE_ENUM_INTERNAL(fabsf)
+TLI_DEFINE_STRING_INTERNAL("fabsf")
+/// long double fabsl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(fabsl)
+TLI_DEFINE_STRING_INTERNAL("fabsl")
+/// int fclose(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fclose)
+TLI_DEFINE_STRING_INTERNAL("fclose")
+/// FILE *fdopen(int fildes, const char *mode);
+TLI_DEFINE_ENUM_INTERNAL(fdopen)
+TLI_DEFINE_STRING_INTERNAL("fdopen")
+/// int feof(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(feof)
+TLI_DEFINE_STRING_INTERNAL("feof")
+/// int ferror(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(ferror)
+TLI_DEFINE_STRING_INTERNAL("ferror")
+/// int fflush(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fflush)
+TLI_DEFINE_STRING_INTERNAL("fflush")
+/// int ffs(int i);
+TLI_DEFINE_ENUM_INTERNAL(ffs)
+TLI_DEFINE_STRING_INTERNAL("ffs")
+/// int ffsl(long int i);
+TLI_DEFINE_ENUM_INTERNAL(ffsl)
+TLI_DEFINE_STRING_INTERNAL("ffsl")
+/// int ffsll(long long int i);
+TLI_DEFINE_ENUM_INTERNAL(ffsll)
+TLI_DEFINE_STRING_INTERNAL("ffsll")
+/// int fgetc(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fgetc)
+TLI_DEFINE_STRING_INTERNAL("fgetc")
+/// int fgetpos(FILE *stream, fpos_t *pos);
+TLI_DEFINE_ENUM_INTERNAL(fgetpos)
+TLI_DEFINE_STRING_INTERNAL("fgetpos")
+/// char *fgets(char *s, int n, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fgets)
+TLI_DEFINE_STRING_INTERNAL("fgets")
+/// int fileno(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fileno)
+TLI_DEFINE_STRING_INTERNAL("fileno")
+/// int fiprintf(FILE *stream, const char *format, ...);
+TLI_DEFINE_ENUM_INTERNAL(fiprintf)
+TLI_DEFINE_STRING_INTERNAL("fiprintf")
+/// void flockfile(FILE *file);
+TLI_DEFINE_ENUM_INTERNAL(flockfile)
+TLI_DEFINE_STRING_INTERNAL("flockfile")
+/// double floor(double x);
+TLI_DEFINE_ENUM_INTERNAL(floor)
+TLI_DEFINE_STRING_INTERNAL("floor")
+/// float floorf(float x);
+TLI_DEFINE_ENUM_INTERNAL(floorf)
+TLI_DEFINE_STRING_INTERNAL("floorf")
+/// long double floorl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(floorl)
+TLI_DEFINE_STRING_INTERNAL("floorl")
+/// double fmax(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fmax)
+TLI_DEFINE_STRING_INTERNAL("fmax")
+/// float fmaxf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fmaxf)
+TLI_DEFINE_STRING_INTERNAL("fmaxf")
+/// long double fmaxl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaxl)
+TLI_DEFINE_STRING_INTERNAL("fmaxl")
+/// double fmin(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fmin)
+TLI_DEFINE_STRING_INTERNAL("fmin")
+/// float fminf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fminf)
+TLI_DEFINE_STRING_INTERNAL("fminf")
+/// long double fminl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fminl)
+TLI_DEFINE_STRING_INTERNAL("fminl")
+/// double fmod(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fmod)
+TLI_DEFINE_STRING_INTERNAL("fmod")
+/// float fmodf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fmodf)
+TLI_DEFINE_STRING_INTERNAL("fmodf")
+/// long double fmodl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fmodl)
+TLI_DEFINE_STRING_INTERNAL("fmodl")
+/// FILE *fopen(const char *filename, const char *mode);
+TLI_DEFINE_ENUM_INTERNAL(fopen)
+TLI_DEFINE_STRING_INTERNAL("fopen")
+/// FILE *fopen64(const char *filename, const char *opentype)
+TLI_DEFINE_ENUM_INTERNAL(fopen64)
+TLI_DEFINE_STRING_INTERNAL("fopen64")
+/// int fprintf(FILE *stream, const char *format, ...);
+TLI_DEFINE_ENUM_INTERNAL(fprintf)
+TLI_DEFINE_STRING_INTERNAL("fprintf")
+/// int fputc(int c, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fputc)
+TLI_DEFINE_STRING_INTERNAL("fputc")
+/// int fputs(const char *s, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fputs)
+TLI_DEFINE_STRING_INTERNAL("fputs")
+/// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fread)
+TLI_DEFINE_STRING_INTERNAL("fread")
+/// void free(void *ptr);
+TLI_DEFINE_ENUM_INTERNAL(free)
+TLI_DEFINE_STRING_INTERNAL("free")
+/// double frexp(double num, int *exp);
+TLI_DEFINE_ENUM_INTERNAL(frexp)
+TLI_DEFINE_STRING_INTERNAL("frexp")
+/// float frexpf(float num, int *exp);
+TLI_DEFINE_ENUM_INTERNAL(frexpf)
+TLI_DEFINE_STRING_INTERNAL("frexpf")
+/// long double frexpl(long double num, int *exp);
+TLI_DEFINE_ENUM_INTERNAL(frexpl)
+TLI_DEFINE_STRING_INTERNAL("frexpl")
+/// int fscanf(FILE *stream, const char *format, ... );
+TLI_DEFINE_ENUM_INTERNAL(fscanf)
+TLI_DEFINE_STRING_INTERNAL("fscanf")
+/// int fseek(FILE *stream, long offset, int whence);
+TLI_DEFINE_ENUM_INTERNAL(fseek)
+TLI_DEFINE_STRING_INTERNAL("fseek")
+/// int fseeko(FILE *stream, off_t offset, int whence);
+TLI_DEFINE_ENUM_INTERNAL(fseeko)
+TLI_DEFINE_STRING_INTERNAL("fseeko")
+/// int fseeko64(FILE *stream, off64_t offset, int whence)
+TLI_DEFINE_ENUM_INTERNAL(fseeko64)
+TLI_DEFINE_STRING_INTERNAL("fseeko64")
+/// int fsetpos(FILE *stream, const fpos_t *pos);
+TLI_DEFINE_ENUM_INTERNAL(fsetpos)
+TLI_DEFINE_STRING_INTERNAL("fsetpos")
+/// int fstat(int fildes, struct stat *buf);
+TLI_DEFINE_ENUM_INTERNAL(fstat)
+TLI_DEFINE_STRING_INTERNAL("fstat")
+/// int fstat64(int filedes, struct stat64 *buf)
+TLI_DEFINE_ENUM_INTERNAL(fstat64)
+TLI_DEFINE_STRING_INTERNAL("fstat64")
+/// int fstatvfs(int fildes, struct statvfs *buf);
+TLI_DEFINE_ENUM_INTERNAL(fstatvfs)
+TLI_DEFINE_STRING_INTERNAL("fstatvfs")
+/// int fstatvfs64(int fildes, struct statvfs64 *buf);
+TLI_DEFINE_ENUM_INTERNAL(fstatvfs64)
+TLI_DEFINE_STRING_INTERNAL("fstatvfs64")
+/// long ftell(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(ftell)
+TLI_DEFINE_STRING_INTERNAL("ftell")
+/// off_t ftello(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(ftello)
+TLI_DEFINE_STRING_INTERNAL("ftello")
+/// off64_t ftello64(FILE *stream)
+TLI_DEFINE_ENUM_INTERNAL(ftello64)
+TLI_DEFINE_STRING_INTERNAL("ftello64")
+/// int ftrylockfile(FILE *file);
+TLI_DEFINE_ENUM_INTERNAL(ftrylockfile)
+TLI_DEFINE_STRING_INTERNAL("ftrylockfile")
+/// void funlockfile(FILE *file);
+TLI_DEFINE_ENUM_INTERNAL(funlockfile)
+TLI_DEFINE_STRING_INTERNAL("funlockfile")
+/// size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(fwrite)
+TLI_DEFINE_STRING_INTERNAL("fwrite")
+/// int getc(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(getc)
+TLI_DEFINE_STRING_INTERNAL("getc")
+/// int getc_unlocked(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(getc_unlocked)
+TLI_DEFINE_STRING_INTERNAL("getc_unlocked")
+/// int getchar(void);
+TLI_DEFINE_ENUM_INTERNAL(getchar)
+TLI_DEFINE_STRING_INTERNAL("getchar")
+/// char *getenv(const char *name);
+TLI_DEFINE_ENUM_INTERNAL(getenv)
+TLI_DEFINE_STRING_INTERNAL("getenv")
+/// int getitimer(int which, struct itimerval *value);
+TLI_DEFINE_ENUM_INTERNAL(getitimer)
+TLI_DEFINE_STRING_INTERNAL("getitimer")
+/// int getlogin_r(char *name, size_t namesize);
+TLI_DEFINE_ENUM_INTERNAL(getlogin_r)
+TLI_DEFINE_STRING_INTERNAL("getlogin_r")
+/// struct passwd *getpwnam(const char *name);
+TLI_DEFINE_ENUM_INTERNAL(getpwnam)
+TLI_DEFINE_STRING_INTERNAL("getpwnam")
+/// char *gets(char *s);
+TLI_DEFINE_ENUM_INTERNAL(gets)
+TLI_DEFINE_STRING_INTERNAL("gets")
+/// int gettimeofday(struct timeval *tp, void *tzp);
+TLI_DEFINE_ENUM_INTERNAL(gettimeofday)
+TLI_DEFINE_STRING_INTERNAL("gettimeofday")
+/// uint32_t htonl(uint32_t hostlong);
+TLI_DEFINE_ENUM_INTERNAL(htonl)
+TLI_DEFINE_STRING_INTERNAL("htonl")
+/// uint16_t htons(uint16_t hostshort);
+TLI_DEFINE_ENUM_INTERNAL(htons)
+TLI_DEFINE_STRING_INTERNAL("htons")
+/// int iprintf(const char *format, ...);
+TLI_DEFINE_ENUM_INTERNAL(iprintf)
+TLI_DEFINE_STRING_INTERNAL("iprintf")
+/// int isascii(int c);
+TLI_DEFINE_ENUM_INTERNAL(isascii)
+TLI_DEFINE_STRING_INTERNAL("isascii")
+/// int isdigit(int c);
+TLI_DEFINE_ENUM_INTERNAL(isdigit)
+TLI_DEFINE_STRING_INTERNAL("isdigit")
+/// long int labs(long int j);
+TLI_DEFINE_ENUM_INTERNAL(labs)
+TLI_DEFINE_STRING_INTERNAL("labs")
+/// int lchown(const char *path, uid_t owner, gid_t group);
+TLI_DEFINE_ENUM_INTERNAL(lchown)
+TLI_DEFINE_STRING_INTERNAL("lchown")
+/// double ldexp(double x, int n);
+TLI_DEFINE_ENUM_INTERNAL(ldexp)
+TLI_DEFINE_STRING_INTERNAL("ldexp")
+/// float ldexpf(float x, int n);
+TLI_DEFINE_ENUM_INTERNAL(ldexpf)
+TLI_DEFINE_STRING_INTERNAL("ldexpf")
+/// long double ldexpl(long double x, int n);
+TLI_DEFINE_ENUM_INTERNAL(ldexpl)
+TLI_DEFINE_STRING_INTERNAL("ldexpl")
+/// long long int llabs(long long int j);
+TLI_DEFINE_ENUM_INTERNAL(llabs)
+TLI_DEFINE_STRING_INTERNAL("llabs")
+/// double log(double x);
+TLI_DEFINE_ENUM_INTERNAL(log)
+TLI_DEFINE_STRING_INTERNAL("log")
+/// double log10(double x);
+TLI_DEFINE_ENUM_INTERNAL(log10)
+TLI_DEFINE_STRING_INTERNAL("log10")
+/// float log10f(float x);
+TLI_DEFINE_ENUM_INTERNAL(log10f)
+TLI_DEFINE_STRING_INTERNAL("log10f")
+/// long double log10l(long double x);
+TLI_DEFINE_ENUM_INTERNAL(log10l)
+TLI_DEFINE_STRING_INTERNAL("log10l")
+/// double log1p(double x);
+TLI_DEFINE_ENUM_INTERNAL(log1p)
+TLI_DEFINE_STRING_INTERNAL("log1p")
+/// float log1pf(float x);
+TLI_DEFINE_ENUM_INTERNAL(log1pf)
+TLI_DEFINE_STRING_INTERNAL("log1pf")
+/// long double log1pl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(log1pl)
+TLI_DEFINE_STRING_INTERNAL("log1pl")
+/// double log2(double x);
+TLI_DEFINE_ENUM_INTERNAL(log2)
+TLI_DEFINE_STRING_INTERNAL("log2")
+/// float log2f(float x);
+TLI_DEFINE_ENUM_INTERNAL(log2f)
+TLI_DEFINE_STRING_INTERNAL("log2f")
+/// double long double log2l(long double x);
+TLI_DEFINE_ENUM_INTERNAL(log2l)
+TLI_DEFINE_STRING_INTERNAL("log2l")
+/// double logb(double x);
+TLI_DEFINE_ENUM_INTERNAL(logb)
+TLI_DEFINE_STRING_INTERNAL("logb")
+/// float logbf(float x);
+TLI_DEFINE_ENUM_INTERNAL(logbf)
+TLI_DEFINE_STRING_INTERNAL("logbf")
+/// long double logbl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(logbl)
+TLI_DEFINE_STRING_INTERNAL("logbl")
+/// float logf(float x);
+TLI_DEFINE_ENUM_INTERNAL(logf)
+TLI_DEFINE_STRING_INTERNAL("logf")
+/// long double logl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(logl)
+TLI_DEFINE_STRING_INTERNAL("logl")
+/// int lstat(const char *path, struct stat *buf);
+TLI_DEFINE_ENUM_INTERNAL(lstat)
+TLI_DEFINE_STRING_INTERNAL("lstat")
+/// int lstat64(const char *path, struct stat64 *buf);
+TLI_DEFINE_ENUM_INTERNAL(lstat64)
+TLI_DEFINE_STRING_INTERNAL("lstat64")
+/// void *malloc(size_t size);
+TLI_DEFINE_ENUM_INTERNAL(malloc)
+TLI_DEFINE_STRING_INTERNAL("malloc")
+/// void *memalign(size_t boundary, size_t size);
+TLI_DEFINE_ENUM_INTERNAL(memalign)
+TLI_DEFINE_STRING_INTERNAL("memalign")
+/// void *memccpy(void *s1, const void *s2, int c, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(memccpy)
+TLI_DEFINE_STRING_INTERNAL("memccpy")
+/// void *memchr(const void *s, int c, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(memchr)
+TLI_DEFINE_STRING_INTERNAL("memchr")
+/// int memcmp(const void *s1, const void *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(memcmp)
+TLI_DEFINE_STRING_INTERNAL("memcmp")
+/// void *memcpy(void *s1, const void *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(memcpy)
+TLI_DEFINE_STRING_INTERNAL("memcpy")
+/// void *memmove(void *s1, const void *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(memmove)
+TLI_DEFINE_STRING_INTERNAL("memmove")
+// void *memrchr(const void *s, int c, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(memrchr)
+TLI_DEFINE_STRING_INTERNAL("memrchr")
+/// void *memset(void *b, int c, size_t len);
+TLI_DEFINE_ENUM_INTERNAL(memset)
+TLI_DEFINE_STRING_INTERNAL("memset")
+/// void memset_pattern16(void *b, const void *pattern16, size_t len);
+TLI_DEFINE_ENUM_INTERNAL(memset_pattern16)
+TLI_DEFINE_STRING_INTERNAL("memset_pattern16")
+/// int mkdir(const char *path, mode_t mode);
+TLI_DEFINE_ENUM_INTERNAL(mkdir)
+TLI_DEFINE_STRING_INTERNAL("mkdir")
+/// time_t mktime(struct tm *timeptr);
+TLI_DEFINE_ENUM_INTERNAL(mktime)
+TLI_DEFINE_STRING_INTERNAL("mktime")
+/// double modf(double x, double *iptr);
+TLI_DEFINE_ENUM_INTERNAL(modf)
+TLI_DEFINE_STRING_INTERNAL("modf")
+/// float modff(float, float *iptr);
+TLI_DEFINE_ENUM_INTERNAL(modff)
+TLI_DEFINE_STRING_INTERNAL("modff")
+/// long double modfl(long double value, long double *iptr);
+TLI_DEFINE_ENUM_INTERNAL(modfl)
+TLI_DEFINE_STRING_INTERNAL("modfl")
+/// double nearbyint(double x);
+TLI_DEFINE_ENUM_INTERNAL(nearbyint)
+TLI_DEFINE_STRING_INTERNAL("nearbyint")
+/// float nearbyintf(float x);
+TLI_DEFINE_ENUM_INTERNAL(nearbyintf)
+TLI_DEFINE_STRING_INTERNAL("nearbyintf")
+/// long double nearbyintl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(nearbyintl)
+TLI_DEFINE_STRING_INTERNAL("nearbyintl")
+/// uint32_t ntohl(uint32_t netlong);
+TLI_DEFINE_ENUM_INTERNAL(ntohl)
+TLI_DEFINE_STRING_INTERNAL("ntohl")
+/// uint16_t ntohs(uint16_t netshort);
+TLI_DEFINE_ENUM_INTERNAL(ntohs)
+TLI_DEFINE_STRING_INTERNAL("ntohs")
+/// int open(const char *path, int oflag, ... );
+TLI_DEFINE_ENUM_INTERNAL(open)
+TLI_DEFINE_STRING_INTERNAL("open")
+/// int open64(const char *filename, int flags[, mode_t mode])
+TLI_DEFINE_ENUM_INTERNAL(open64)
+TLI_DEFINE_STRING_INTERNAL("open64")
+/// DIR *opendir(const char *dirname);
+TLI_DEFINE_ENUM_INTERNAL(opendir)
+TLI_DEFINE_STRING_INTERNAL("opendir")
+/// int pclose(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(pclose)
+TLI_DEFINE_STRING_INTERNAL("pclose")
+/// void perror(const char *s);
+TLI_DEFINE_ENUM_INTERNAL(perror)
+TLI_DEFINE_STRING_INTERNAL("perror")
+/// FILE *popen(const char *command, const char *mode);
+TLI_DEFINE_ENUM_INTERNAL(popen)
+TLI_DEFINE_STRING_INTERNAL("popen")
+/// int posix_memalign(void **memptr, size_t alignment, size_t size);
+TLI_DEFINE_ENUM_INTERNAL(posix_memalign)
+TLI_DEFINE_STRING_INTERNAL("posix_memalign")
+/// double pow(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(pow)
+TLI_DEFINE_STRING_INTERNAL("pow")
+/// float powf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(powf)
+TLI_DEFINE_STRING_INTERNAL("powf")
+/// long double powl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(powl)
+TLI_DEFINE_STRING_INTERNAL("powl")
+/// ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
+TLI_DEFINE_ENUM_INTERNAL(pread)
+TLI_DEFINE_STRING_INTERNAL("pread")
+/// int printf(const char *format, ...);
+TLI_DEFINE_ENUM_INTERNAL(printf)
+TLI_DEFINE_STRING_INTERNAL("printf")
+/// int putc(int c, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(putc)
+TLI_DEFINE_STRING_INTERNAL("putc")
+/// int putchar(int c);
+TLI_DEFINE_ENUM_INTERNAL(putchar)
+TLI_DEFINE_STRING_INTERNAL("putchar")
+/// int puts(const char *s);
+TLI_DEFINE_ENUM_INTERNAL(puts)
+TLI_DEFINE_STRING_INTERNAL("puts")
+/// ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset);
+TLI_DEFINE_ENUM_INTERNAL(pwrite)
+TLI_DEFINE_STRING_INTERNAL("pwrite")
+/// void qsort(void *base, size_t nel, size_t width,
+/// int (*compar)(const void *, const void *));
+TLI_DEFINE_ENUM_INTERNAL(qsort)
+TLI_DEFINE_STRING_INTERNAL("qsort")
+/// ssize_t read(int fildes, void *buf, size_t nbyte);
+TLI_DEFINE_ENUM_INTERNAL(read)
+TLI_DEFINE_STRING_INTERNAL("read")
+/// ssize_t readlink(const char *path, char *buf, size_t bufsize);
+TLI_DEFINE_ENUM_INTERNAL(readlink)
+TLI_DEFINE_STRING_INTERNAL("readlink")
+/// void *realloc(void *ptr, size_t size);
+TLI_DEFINE_ENUM_INTERNAL(realloc)
+TLI_DEFINE_STRING_INTERNAL("realloc")
+/// void *reallocf(void *ptr, size_t size);
+TLI_DEFINE_ENUM_INTERNAL(reallocf)
+TLI_DEFINE_STRING_INTERNAL("reallocf")
+/// char *realpath(const char *file_name, char *resolved_name);
+TLI_DEFINE_ENUM_INTERNAL(realpath)
+TLI_DEFINE_STRING_INTERNAL("realpath")
+/// int remove(const char *path);
+TLI_DEFINE_ENUM_INTERNAL(remove)
+TLI_DEFINE_STRING_INTERNAL("remove")
+/// int rename(const char *old, const char *new);
+TLI_DEFINE_ENUM_INTERNAL(rename)
+TLI_DEFINE_STRING_INTERNAL("rename")
+/// void rewind(FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(rewind)
+TLI_DEFINE_STRING_INTERNAL("rewind")
+/// double rint(double x);
+TLI_DEFINE_ENUM_INTERNAL(rint)
+TLI_DEFINE_STRING_INTERNAL("rint")
+/// float rintf(float x);
+TLI_DEFINE_ENUM_INTERNAL(rintf)
+TLI_DEFINE_STRING_INTERNAL("rintf")
+/// long double rintl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(rintl)
+TLI_DEFINE_STRING_INTERNAL("rintl")
+/// int rmdir(const char *path);
+TLI_DEFINE_ENUM_INTERNAL(rmdir)
+TLI_DEFINE_STRING_INTERNAL("rmdir")
+/// double round(double x);
+TLI_DEFINE_ENUM_INTERNAL(round)
+TLI_DEFINE_STRING_INTERNAL("round")
+/// float roundf(float x);
+TLI_DEFINE_ENUM_INTERNAL(roundf)
+TLI_DEFINE_STRING_INTERNAL("roundf")
+/// long double roundl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(roundl)
+TLI_DEFINE_STRING_INTERNAL("roundl")
+/// int scanf(const char *restrict format, ... );
+TLI_DEFINE_ENUM_INTERNAL(scanf)
+TLI_DEFINE_STRING_INTERNAL("scanf")
+/// void setbuf(FILE *stream, char *buf);
+TLI_DEFINE_ENUM_INTERNAL(setbuf)
+TLI_DEFINE_STRING_INTERNAL("setbuf")
+/// int setitimer(int which, const struct itimerval *value,
+/// struct itimerval *ovalue);
+TLI_DEFINE_ENUM_INTERNAL(setitimer)
+TLI_DEFINE_STRING_INTERNAL("setitimer")
+/// int setvbuf(FILE *stream, char *buf, int type, size_t size);
+TLI_DEFINE_ENUM_INTERNAL(setvbuf)
+TLI_DEFINE_STRING_INTERNAL("setvbuf")
+/// double sin(double x);
+TLI_DEFINE_ENUM_INTERNAL(sin)
+TLI_DEFINE_STRING_INTERNAL("sin")
+/// float sinf(float x);
+TLI_DEFINE_ENUM_INTERNAL(sinf)
+TLI_DEFINE_STRING_INTERNAL("sinf")
+/// double sinh(double x);
+TLI_DEFINE_ENUM_INTERNAL(sinh)
+TLI_DEFINE_STRING_INTERNAL("sinh")
+/// float sinhf(float x);
+TLI_DEFINE_ENUM_INTERNAL(sinhf)
+TLI_DEFINE_STRING_INTERNAL("sinhf")
+/// long double sinhl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(sinhl)
+TLI_DEFINE_STRING_INTERNAL("sinhl")
+/// long double sinl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(sinl)
+TLI_DEFINE_STRING_INTERNAL("sinl")
+/// int siprintf(char *str, const char *format, ...);
+TLI_DEFINE_ENUM_INTERNAL(siprintf)
+TLI_DEFINE_STRING_INTERNAL("siprintf")
+/// int snprintf(char *s, size_t n, const char *format, ...);
+TLI_DEFINE_ENUM_INTERNAL(snprintf)
+TLI_DEFINE_STRING_INTERNAL("snprintf")
+/// int sprintf(char *str, const char *format, ...);
+TLI_DEFINE_ENUM_INTERNAL(sprintf)
+TLI_DEFINE_STRING_INTERNAL("sprintf")
+/// double sqrt(double x);
+TLI_DEFINE_ENUM_INTERNAL(sqrt)
+TLI_DEFINE_STRING_INTERNAL("sqrt")
+/// float sqrtf(float x);
+TLI_DEFINE_ENUM_INTERNAL(sqrtf)
+TLI_DEFINE_STRING_INTERNAL("sqrtf")
+/// long double sqrtl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(sqrtl)
+TLI_DEFINE_STRING_INTERNAL("sqrtl")
+/// int sscanf(const char *s, const char *format, ... );
+TLI_DEFINE_ENUM_INTERNAL(sscanf)
+TLI_DEFINE_STRING_INTERNAL("sscanf")
+/// int stat(const char *path, struct stat *buf);
+TLI_DEFINE_ENUM_INTERNAL(stat)
+TLI_DEFINE_STRING_INTERNAL("stat")
+/// int stat64(const char *path, struct stat64 *buf);
+TLI_DEFINE_ENUM_INTERNAL(stat64)
+TLI_DEFINE_STRING_INTERNAL("stat64")
+/// int statvfs(const char *path, struct statvfs *buf);
+TLI_DEFINE_ENUM_INTERNAL(statvfs)
+TLI_DEFINE_STRING_INTERNAL("statvfs")
+/// int statvfs64(const char *path, struct statvfs64 *buf)
+TLI_DEFINE_ENUM_INTERNAL(statvfs64)
+TLI_DEFINE_STRING_INTERNAL("statvfs64")
+/// char *stpcpy(char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(stpcpy)
+TLI_DEFINE_STRING_INTERNAL("stpcpy")
+/// char *stpncpy(char *s1, const char *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(stpncpy)
+TLI_DEFINE_STRING_INTERNAL("stpncpy")
+/// int strcasecmp(const char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strcasecmp)
+TLI_DEFINE_STRING_INTERNAL("strcasecmp")
+/// char *strcat(char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strcat)
+TLI_DEFINE_STRING_INTERNAL("strcat")
+/// char *strchr(const char *s, int c);
+TLI_DEFINE_ENUM_INTERNAL(strchr)
+TLI_DEFINE_STRING_INTERNAL("strchr")
+/// int strcmp(const char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strcmp)
+TLI_DEFINE_STRING_INTERNAL("strcmp")
+/// int strcoll(const char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strcoll)
+TLI_DEFINE_STRING_INTERNAL("strcoll")
+/// char *strcpy(char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strcpy)
+TLI_DEFINE_STRING_INTERNAL("strcpy")
+/// size_t strcspn(const char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strcspn)
+TLI_DEFINE_STRING_INTERNAL("strcspn")
+/// char *strdup(const char *s1);
+TLI_DEFINE_ENUM_INTERNAL(strdup)
+TLI_DEFINE_STRING_INTERNAL("strdup")
+/// size_t strlen(const char *s);
+TLI_DEFINE_ENUM_INTERNAL(strlen)
+TLI_DEFINE_STRING_INTERNAL("strlen")
+/// int strncasecmp(const char *s1, const char *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(strncasecmp)
+TLI_DEFINE_STRING_INTERNAL("strncasecmp")
+/// char *strncat(char *s1, const char *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(strncat)
+TLI_DEFINE_STRING_INTERNAL("strncat")
+/// int strncmp(const char *s1, const char *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(strncmp)
+TLI_DEFINE_STRING_INTERNAL("strncmp")
+/// char *strncpy(char *s1, const char *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(strncpy)
+TLI_DEFINE_STRING_INTERNAL("strncpy")
+/// char *strndup(const char *s1, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(strndup)
+TLI_DEFINE_STRING_INTERNAL("strndup")
+/// size_t strnlen(const char *s, size_t maxlen);
+TLI_DEFINE_ENUM_INTERNAL(strnlen)
+TLI_DEFINE_STRING_INTERNAL("strnlen")
+/// char *strpbrk(const char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strpbrk)
+TLI_DEFINE_STRING_INTERNAL("strpbrk")
+/// char *strrchr(const char *s, int c);
+TLI_DEFINE_ENUM_INTERNAL(strrchr)
+TLI_DEFINE_STRING_INTERNAL("strrchr")
+/// size_t strspn(const char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strspn)
+TLI_DEFINE_STRING_INTERNAL("strspn")
+/// char *strstr(const char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strstr)
+TLI_DEFINE_STRING_INTERNAL("strstr")
+/// double strtod(const char *nptr, char **endptr);
+TLI_DEFINE_ENUM_INTERNAL(strtod)
+TLI_DEFINE_STRING_INTERNAL("strtod")
+/// float strtof(const char *nptr, char **endptr);
+TLI_DEFINE_ENUM_INTERNAL(strtof)
+TLI_DEFINE_STRING_INTERNAL("strtof")
+// char *strtok(char *s1, const char *s2);
+TLI_DEFINE_ENUM_INTERNAL(strtok)
+TLI_DEFINE_STRING_INTERNAL("strtok")
+// char *strtok_r(char *s, const char *sep, char **lasts);
+TLI_DEFINE_ENUM_INTERNAL(strtok_r)
+TLI_DEFINE_STRING_INTERNAL("strtok_r")
+/// long int strtol(const char *nptr, char **endptr, int base);
+TLI_DEFINE_ENUM_INTERNAL(strtol)
+TLI_DEFINE_STRING_INTERNAL("strtol")
+/// long double strtold(const char *nptr, char **endptr);
+TLI_DEFINE_ENUM_INTERNAL(strtold)
+TLI_DEFINE_STRING_INTERNAL("strtold")
+/// long long int strtoll(const char *nptr, char **endptr, int base);
+TLI_DEFINE_ENUM_INTERNAL(strtoll)
+TLI_DEFINE_STRING_INTERNAL("strtoll")
+/// unsigned long int strtoul(const char *nptr, char **endptr, int base);
+TLI_DEFINE_ENUM_INTERNAL(strtoul)
+TLI_DEFINE_STRING_INTERNAL("strtoul")
+/// unsigned long long int strtoull(const char *nptr, char **endptr, int base);
+TLI_DEFINE_ENUM_INTERNAL(strtoull)
+TLI_DEFINE_STRING_INTERNAL("strtoull")
+/// size_t strxfrm(char *s1, const char *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(strxfrm)
+TLI_DEFINE_STRING_INTERNAL("strxfrm")
+/// int system(const char *command);
+TLI_DEFINE_ENUM_INTERNAL(system)
+TLI_DEFINE_STRING_INTERNAL("system")
+/// double tan(double x);
+TLI_DEFINE_ENUM_INTERNAL(tan)
+TLI_DEFINE_STRING_INTERNAL("tan")
+/// float tanf(float x);
+TLI_DEFINE_ENUM_INTERNAL(tanf)
+TLI_DEFINE_STRING_INTERNAL("tanf")
+/// double tanh(double x);
+TLI_DEFINE_ENUM_INTERNAL(tanh)
+TLI_DEFINE_STRING_INTERNAL("tanh")
+/// float tanhf(float x);
+TLI_DEFINE_ENUM_INTERNAL(tanhf)
+TLI_DEFINE_STRING_INTERNAL("tanhf")
+/// long double tanhl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(tanhl)
+TLI_DEFINE_STRING_INTERNAL("tanhl")
+/// long double tanl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(tanl)
+TLI_DEFINE_STRING_INTERNAL("tanl")
+/// clock_t times(struct tms *buffer);
+TLI_DEFINE_ENUM_INTERNAL(times)
+TLI_DEFINE_STRING_INTERNAL("times")
+/// FILE *tmpfile(void);
+TLI_DEFINE_ENUM_INTERNAL(tmpfile)
+TLI_DEFINE_STRING_INTERNAL("tmpfile")
+/// FILE *tmpfile64(void)
+TLI_DEFINE_ENUM_INTERNAL(tmpfile64)
+TLI_DEFINE_STRING_INTERNAL("tmpfile64")
+/// int toascii(int c);
+TLI_DEFINE_ENUM_INTERNAL(toascii)
+TLI_DEFINE_STRING_INTERNAL("toascii")
+/// double trunc(double x);
+TLI_DEFINE_ENUM_INTERNAL(trunc)
+TLI_DEFINE_STRING_INTERNAL("trunc")
+/// float truncf(float x);
+TLI_DEFINE_ENUM_INTERNAL(truncf)
+TLI_DEFINE_STRING_INTERNAL("truncf")
+/// long double truncl(long double x);
+TLI_DEFINE_ENUM_INTERNAL(truncl)
+TLI_DEFINE_STRING_INTERNAL("truncl")
+/// int uname(struct utsname *name);
+TLI_DEFINE_ENUM_INTERNAL(uname)
+TLI_DEFINE_STRING_INTERNAL("uname")
+/// int ungetc(int c, FILE *stream);
+TLI_DEFINE_ENUM_INTERNAL(ungetc)
+TLI_DEFINE_STRING_INTERNAL("ungetc")
+/// int unlink(const char *path);
+TLI_DEFINE_ENUM_INTERNAL(unlink)
+TLI_DEFINE_STRING_INTERNAL("unlink")
+/// int unsetenv(const char *name);
+TLI_DEFINE_ENUM_INTERNAL(unsetenv)
+TLI_DEFINE_STRING_INTERNAL("unsetenv")
+/// int utime(const char *path, const struct utimbuf *times);
+TLI_DEFINE_ENUM_INTERNAL(utime)
+TLI_DEFINE_STRING_INTERNAL("utime")
+/// int utimes(const char *path, const struct timeval times[2]);
+TLI_DEFINE_ENUM_INTERNAL(utimes)
+TLI_DEFINE_STRING_INTERNAL("utimes")
+/// void *valloc(size_t size);
+TLI_DEFINE_ENUM_INTERNAL(valloc)
+TLI_DEFINE_STRING_INTERNAL("valloc")
+/// int vfprintf(FILE *stream, const char *format, va_list ap);
+TLI_DEFINE_ENUM_INTERNAL(vfprintf)
+TLI_DEFINE_STRING_INTERNAL("vfprintf")
+/// int vfscanf(FILE *stream, const char *format, va_list arg);
+TLI_DEFINE_ENUM_INTERNAL(vfscanf)
+TLI_DEFINE_STRING_INTERNAL("vfscanf")
+/// int vprintf(const char *restrict format, va_list ap);
+TLI_DEFINE_ENUM_INTERNAL(vprintf)
+TLI_DEFINE_STRING_INTERNAL("vprintf")
+/// int vscanf(const char *format, va_list arg);
+TLI_DEFINE_ENUM_INTERNAL(vscanf)
+TLI_DEFINE_STRING_INTERNAL("vscanf")
+/// int vsnprintf(char *s, size_t n, const char *format, va_list ap);
+TLI_DEFINE_ENUM_INTERNAL(vsnprintf)
+TLI_DEFINE_STRING_INTERNAL("vsnprintf")
+/// int vsprintf(char *s, const char *format, va_list ap);
+TLI_DEFINE_ENUM_INTERNAL(vsprintf)
+TLI_DEFINE_STRING_INTERNAL("vsprintf")
+/// int vsscanf(const char *s, const char *format, va_list arg);
+TLI_DEFINE_ENUM_INTERNAL(vsscanf)
+TLI_DEFINE_STRING_INTERNAL("vsscanf")
+/// ssize_t write(int fildes, const void *buf, size_t nbyte);
+TLI_DEFINE_ENUM_INTERNAL(write)
+TLI_DEFINE_STRING_INTERNAL("write")
+
+#undef TLI_DEFINE_ENUM_INTERNAL
+#undef TLI_DEFINE_STRING_INTERNAL
+#endif // One of TLI_DEFINE_ENUM/STRING are defined.
+
+#undef TLI_DEFINE_ENUM
+#undef TLI_DEFINE_STRING
diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h
new file mode 100644
index 000000000000..e0a1ee378274
--- /dev/null
+++ b/include/llvm/Analysis/TargetLibraryInfo.h
@@ -0,0 +1,328 @@
+//===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H
+#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+
+namespace llvm {
+/// VecDesc - Describes a possible vectorization of a function.
+/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
+/// by a factor 'VectorizationFactor'.
+struct VecDesc {
+ const char *ScalarFnName;
+ const char *VectorFnName;
+ unsigned VectorizationFactor;
+};
+class PreservedAnalyses;
+
+ namespace LibFunc {
+ enum Func {
+#define TLI_DEFINE_ENUM
+#include "llvm/Analysis/TargetLibraryInfo.def"
+
+ NumLibFuncs
+ };
+ }
+
+/// \brief Implementation of the target library information.
+///
+/// This class constructs tables that hold the target library information and
+/// make it available. However, it is somewhat expensive to compute and only
+/// depends on the triple. So users typicaly interact with the \c
+/// TargetLibraryInfo wrapper below.
+class TargetLibraryInfoImpl {
+ friend class TargetLibraryInfo;
+
+ unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4];
+ llvm::DenseMap<unsigned, std::string> CustomNames;
+ static const char *const StandardNames[LibFunc::NumLibFuncs];
+
+ enum AvailabilityState {
+ StandardName = 3, // (memset to all ones)
+ CustomName = 1,
+ Unavailable = 0 // (memset to all zeros)
+ };
+ void setState(LibFunc::Func F, AvailabilityState State) {
+ AvailableArray[F/4] &= ~(3 << 2*(F&3));
+ AvailableArray[F/4] |= State << 2*(F&3);
+ }
+ AvailabilityState getState(LibFunc::Func F) const {
+ return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
+ }
+
+ /// Vectorization descriptors - sorted by ScalarFnName.
+ std::vector<VecDesc> VectorDescs;
+ /// Scalarization descriptors - same content as VectorDescs but sorted based
+ /// on VectorFnName rather than ScalarFnName.
+ std::vector<VecDesc> ScalarDescs;
+
+public:
+ /// \brief List of known vector-functions libraries.
+ ///
+ /// The vector-functions library defines, which functions are vectorizable
+ /// and with which factor. The library can be specified by either frontend,
+ /// or a commandline option, and then used by
+ /// addVectorizableFunctionsFromVecLib for filling up the tables of
+ /// vectorizable functions.
+ enum VectorLibrary {
+ NoLibrary, // Don't use any vector library.
+ Accelerate // Use Accelerate framework.
+ };
+
+ TargetLibraryInfoImpl();
+ explicit TargetLibraryInfoImpl(const Triple &T);
+
+ // Provide value semantics.
+ TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI);
+ TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI);
+ TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
+ TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
+
+ /// \brief Searches for a particular function name.
+ ///
+ /// If it is one of the known library functions, return true and set F to the
+ /// corresponding value.
+ bool getLibFunc(StringRef funcName, LibFunc::Func &F) const;
+
+ /// \brief Forces a function to be marked as unavailable.
+ void setUnavailable(LibFunc::Func F) {
+ setState(F, Unavailable);
+ }
+
+ /// \brief Forces a function to be marked as available.
+ void setAvailable(LibFunc::Func F) {
+ setState(F, StandardName);
+ }
+
+ /// \brief Forces a function to be marked as available and provide an
+ /// alternate name that must be used.
+ void setAvailableWithName(LibFunc::Func F, StringRef Name) {
+ if (StandardNames[F] != Name) {
+ setState(F, CustomName);
+ CustomNames[F] = Name;
+ assert(CustomNames.find(F) != CustomNames.end());
+ } else {
+ setState(F, StandardName);
+ }
+ }
+
+ /// \brief Disables all builtins.
+ ///
+ /// This can be used for options like -fno-builtin.
+ void disableAllFunctions();
+
+ /// addVectorizableFunctions - Add a set of scalar -> vector mappings,
+ /// queryable via getVectorizedFunction and getScalarizedFunction.
+ void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
+
+ /// Calls addVectorizableFunctions with a known preset of functions for the
+ /// given vector library.
+ void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib);
+
+ /// isFunctionVectorizable - Return true if the function F has a
+ /// vector equivalent with vectorization factor VF.
+ bool isFunctionVectorizable(StringRef F, unsigned VF) const {
+ return !getVectorizedFunction(F, VF).empty();
+ }
+
+ /// isFunctionVectorizable - Return true if the function F has a
+ /// vector equivalent with any vectorization factor.
+ bool isFunctionVectorizable(StringRef F) const;
+
+ /// getVectorizedFunction - Return the name of the equivalent of
+ /// F, vectorized with factor VF. If no such mapping exists,
+ /// return the empty string.
+ StringRef getVectorizedFunction(StringRef F, unsigned VF) const;
+
+ /// isFunctionScalarizable - Return true if the function F has a
+ /// scalar equivalent, and set VF to be the vectorization factor.
+ bool isFunctionScalarizable(StringRef F, unsigned &VF) const {
+ return !getScalarizedFunction(F, VF).empty();
+ }
+
+ /// getScalarizedFunction - Return the name of the equivalent of
+ /// F, scalarized. If no such mapping exists, return the empty string.
+ ///
+ /// Set VF to the vectorization factor.
+ StringRef getScalarizedFunction(StringRef F, unsigned &VF) const;
+};
+
+/// \brief Provides information about what library functions are available for
+/// the current target.
+///
+/// This both allows optimizations to handle them specially and frontends to
+/// disable such optimizations through -fno-builtin etc.
+class TargetLibraryInfo {
+ friend class TargetLibraryAnalysis;
+ friend class TargetLibraryInfoWrapperPass;
+
+ const TargetLibraryInfoImpl *Impl;
+
+public:
+ explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl) : Impl(&Impl) {}
+
+ // Provide value semantics.
+ TargetLibraryInfo(const TargetLibraryInfo &TLI) : Impl(TLI.Impl) {}
+ TargetLibraryInfo(TargetLibraryInfo &&TLI) : Impl(TLI.Impl) {}
+ TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) {
+ Impl = TLI.Impl;
+ return *this;
+ }
+ TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) {
+ Impl = TLI.Impl;
+ return *this;
+ }
+
+ /// \brief Searches for a particular function name.
+ ///
+ /// If it is one of the known library functions, return true and set F to the
+ /// corresponding value.
+ bool getLibFunc(StringRef funcName, LibFunc::Func &F) const {
+ return Impl->getLibFunc(funcName, F);
+ }
+
+ /// \brief Tests whether a library function is available.
+ bool has(LibFunc::Func F) const {
+ return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable;
+ }
+ bool isFunctionVectorizable(StringRef F, unsigned VF) const {
+ return Impl->isFunctionVectorizable(F, VF);
+ };
+ bool isFunctionVectorizable(StringRef F) const {
+ return Impl->isFunctionVectorizable(F);
+ };
+ StringRef getVectorizedFunction(StringRef F, unsigned VF) const {
+ return Impl->getVectorizedFunction(F, VF);
+ };
+
+ /// \brief Tests if the function is both available and a candidate for
+ /// optimized code generation.
+ bool hasOptimizedCodeGen(LibFunc::Func F) const {
+ if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable)
+ return false;
+ switch (F) {
+ default: break;
+ case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl:
+ case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl:
+ case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl:
+ case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl:
+ case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl:
+ case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite:
+ case LibFunc::sqrtl_finite:
+ case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl:
+ case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl:
+ case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl:
+ case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl:
+ case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill:
+ case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl:
+ case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl:
+ case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl:
+ case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l:
+ case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l:
+ case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy:
+ case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen:
+ case LibFunc::memchr:
+ return true;
+ }
+ return false;
+ }
+
+ StringRef getName(LibFunc::Func F) const {
+ auto State = Impl->getState(F);
+ if (State == TargetLibraryInfoImpl::Unavailable)
+ return StringRef();
+ if (State == TargetLibraryInfoImpl::StandardName)
+ return Impl->StandardNames[F];
+ assert(State == TargetLibraryInfoImpl::CustomName);
+ return Impl->CustomNames.find(F)->second;
+ }
+
+ /// \brief Handle invalidation from the pass manager.
+ ///
+ /// If we try to invalidate this info, just return false. It cannot become
+ /// invalid even if the module changes.
+ bool invalidate(Module &, const PreservedAnalyses &) { return false; }
+};
+
+/// \brief Analysis pass providing the \c TargetLibraryInfo.
+///
+/// Note that this pass's result cannot be invalidated, it is immutable for the
+/// life of the module.
+class TargetLibraryAnalysis {
+public:
+ typedef TargetLibraryInfo Result;
+
+ /// \brief Opaque, unique identifier for this analysis pass.
+ static void *ID() { return (void *)&PassID; }
+
+ /// \brief Default construct the library analysis.
+ ///
+ /// This will use the module's triple to construct the library info for that
+ /// module.
+ TargetLibraryAnalysis() {}
+
+ /// \brief Construct a library analysis with preset info.
+ ///
+ /// This will directly copy the preset info into the result without
+ /// consulting the module's triple.
+ TargetLibraryAnalysis(TargetLibraryInfoImpl PresetInfoImpl)
+ : PresetInfoImpl(std::move(PresetInfoImpl)) {}
+
+ // Move semantics. We spell out the constructors for MSVC.
+ TargetLibraryAnalysis(TargetLibraryAnalysis &&Arg)
+ : PresetInfoImpl(std::move(Arg.PresetInfoImpl)), Impls(std::move(Arg.Impls)) {}
+ TargetLibraryAnalysis &operator=(TargetLibraryAnalysis &&RHS) {
+ PresetInfoImpl = std::move(RHS.PresetInfoImpl);
+ Impls = std::move(RHS.Impls);
+ return *this;
+ }
+
+ TargetLibraryInfo run(Module &M);
+ TargetLibraryInfo run(Function &F);
+
+ /// \brief Provide access to a name for this pass for debugging purposes.
+ static StringRef name() { return "TargetLibraryAnalysis"; }
+
+private:
+ static char PassID;
+
+ Optional<TargetLibraryInfoImpl> PresetInfoImpl;
+
+ StringMap<std::unique_ptr<TargetLibraryInfoImpl>> Impls;
+
+ TargetLibraryInfoImpl &lookupInfoImpl(Triple T);
+};
+
+class TargetLibraryInfoWrapperPass : public ImmutablePass {
+ TargetLibraryInfoImpl TLIImpl;
+ TargetLibraryInfo TLI;
+
+ virtual void anchor();
+
+public:
+ static char ID;
+ TargetLibraryInfoWrapperPass();
+ explicit TargetLibraryInfoWrapperPass(const Triple &T);
+ explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI);
+
+ TargetLibraryInfo &getTLI() { return TLI; }
+ const TargetLibraryInfo &getTLI() const { return TLI; }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h
index 4bd5dd8a221e..86bf1549dc78 100644
--- a/include/llvm/Analysis/TargetTransformInfo.h
+++ b/include/llvm/Analysis/TargetTransformInfo.h
@@ -1,4 +1,4 @@
-//===- llvm/Analysis/TargetTransformInfo.h ----------------------*- C++ -*-===//
+//===- TargetTransformInfo.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,66 +6,89 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This pass exposes codegen information to IR-level passes. Every
-// transformation that uses codegen information is broken into three parts:
-// 1. The IR-level analysis pass.
-// 2. The IR-level transformation interface which provides the needed
-// information.
-// 3. Codegen-level implementation which uses target-specific hooks.
-//
-// This file defines #2, which is the interface that IR-level transformations
-// use for querying the codegen.
-//
+/// \file
+/// This pass exposes codegen information to IR-level passes. Every
+/// transformation that uses codegen information is broken into three parts:
+/// 1. The IR-level analysis pass.
+/// 2. The IR-level transformation interface which provides the needed
+/// information.
+/// 3. Codegen-level implementation which uses target-specific hooks.
+///
+/// This file defines #2, which is the interface that IR-level transformations
+/// use for querying the codegen.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H
#define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H
+#include "llvm/ADT/Optional.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Pass.h"
#include "llvm/Support/DataTypes.h"
+#include <functional>
namespace llvm {
class Function;
class GlobalValue;
class Loop;
+class PreservedAnalyses;
class Type;
class User;
class Value;
-/// TargetTransformInfo - This pass provides access to the codegen
-/// interfaces that are needed for IR-level transformations.
+/// \brief Information about a load/store intrinsic defined by the target.
+struct MemIntrinsicInfo {
+ MemIntrinsicInfo()
+ : ReadMem(false), WriteMem(false), Vol(false), MatchingId(0),
+ NumMemRefs(0), PtrVal(nullptr) {}
+ bool ReadMem;
+ bool WriteMem;
+ bool Vol;
+ // Same Id is set by the target for corresponding load/store intrinsics.
+ unsigned short MatchingId;
+ int NumMemRefs;
+ Value *PtrVal;
+};
+
+/// \brief This pass provides access to the codegen interfaces that are needed
+/// for IR-level transformations.
class TargetTransformInfo {
-protected:
- /// \brief The TTI instance one level down the stack.
+public:
+ /// \brief Construct a TTI object using a type implementing the \c Concept
+ /// API below.
///
- /// This is used to implement the default behavior all of the methods which
- /// is to delegate up through the stack of TTIs until one can answer the
- /// query.
- TargetTransformInfo *PrevTTI;
+ /// This is used by targets to construct a TTI wrapping their target-specific
+ /// implementaion that encodes appropriate costs for their target.
+ template <typename T> TargetTransformInfo(T Impl);
- /// \brief The top of the stack of TTI analyses available.
+ /// \brief Construct a baseline TTI object using a minimal implementation of
+ /// the \c Concept API below.
///
- /// This is a convenience routine maintained as TTI analyses become available
- /// that complements the PrevTTI delegation chain. When one part of an
- /// analysis pass wants to query another part of the analysis pass it can use
- /// this to start back at the top of the stack.
- TargetTransformInfo *TopTTI;
+ /// The TTI implementation will reflect the information in the DataLayout
+ /// provided if non-null.
+ explicit TargetTransformInfo(const DataLayout *DL);
- /// All pass subclasses must in their initializePass routine call
- /// pushTTIStack with themselves to update the pointers tracking the previous
- /// TTI instance in the analysis group's stack, and the top of the analysis
- /// group's stack.
- void pushTTIStack(Pass *P);
+ // Provide move semantics.
+ TargetTransformInfo(TargetTransformInfo &&Arg);
+ TargetTransformInfo &operator=(TargetTransformInfo &&RHS);
- /// All pass subclasses must call TargetTransformInfo::getAnalysisUsage.
- virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+ // We need to define the destructor out-of-line to define our sub-classes
+ // out-of-line.
+ ~TargetTransformInfo();
-public:
- /// This class is intended to be subclassed by real implementations.
- virtual ~TargetTransformInfo() = 0;
+ /// \brief Handle the invalidation of this information.
+ ///
+ /// When used as a result of \c TargetIRAnalysis this method will be called
+ /// when the function this was computed for changes. When it returns false,
+ /// the information is preserved across those changes.
+ bool invalidate(Function &, const PreservedAnalyses &) {
+ // FIXME: We should probably in some way ensure that the subtarget
+ // information for a function hasn't changed.
+ return false;
+ }
/// \name Generic Target Information
/// @{
@@ -86,9 +109,9 @@ public:
/// skipped by renaming the registers in the CPU, but they still are encoded
/// and thus wouldn't be considered 'free' here.
enum TargetCostConstants {
- TCC_Free = 0, ///< Expected to fold away in lowering.
- TCC_Basic = 1, ///< The cost of a typical 'add' instruction.
- TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86.
+ TCC_Free = 0, ///< Expected to fold away in lowering.
+ TCC_Basic = 1, ///< The cost of a typical 'add' instruction.
+ TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86.
};
/// \brief Estimate the cost of a specific operation when lowered.
@@ -105,16 +128,15 @@ public:
///
/// The returned cost is defined in terms of \c TargetCostConstants, see its
/// comments for a detailed explanation of the cost values.
- virtual unsigned getOperationCost(unsigned Opcode, Type *Ty,
- Type *OpTy = nullptr) const;
+ unsigned getOperationCost(unsigned Opcode, Type *Ty,
+ Type *OpTy = nullptr) const;
/// \brief Estimate the cost of a GEP operation when lowered.
///
/// The contract for this function is the same as \c getOperationCost except
/// that it supports an interface that provides extra information specific to
/// the GEP operation.
- virtual unsigned getGEPCost(const Value *Ptr,
- ArrayRef<const Value *> Operands) const;
+ unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) const;
/// \brief Estimate the cost of a function call when lowered.
///
@@ -125,31 +147,31 @@ public:
/// This is the most basic query for estimating call cost: it only knows the
/// function type and (potentially) the number of arguments at the call site.
/// The latter is only interesting for varargs function types.
- virtual unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const;
+ unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const;
/// \brief Estimate the cost of calling a specific function when lowered.
///
/// This overload adds the ability to reason about the particular function
/// being called in the event it is a library call with special lowering.
- virtual unsigned getCallCost(const Function *F, int NumArgs = -1) const;
+ unsigned getCallCost(const Function *F, int NumArgs = -1) const;
/// \brief Estimate the cost of calling a specific function when lowered.
///
/// This overload allows specifying a set of candidate argument values.
- virtual unsigned getCallCost(const Function *F,
- ArrayRef<const Value *> Arguments) const;
+ unsigned getCallCost(const Function *F,
+ ArrayRef<const Value *> Arguments) const;
/// \brief Estimate the cost of an intrinsic when lowered.
///
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
- virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<Type *> ParamTys) const;
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> ParamTys) const;
/// \brief Estimate the cost of an intrinsic when lowered.
///
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
- virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<const Value *> Arguments) const;
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> Arguments) const;
/// \brief Estimate the cost of a given IR user when lowered.
///
@@ -166,13 +188,22 @@ public:
///
/// The returned cost is defined in terms of \c TargetCostConstants, see its
/// comments for a detailed explanation of the cost values.
- virtual unsigned getUserCost(const User *U) const;
+ unsigned getUserCost(const User *U) const;
- /// \brief hasBranchDivergence - Return true if branch divergence exists.
+ /// \brief Return true if branch divergence exists.
+ ///
/// Branch divergence has a significantly negative impact on GPU performance
/// when threads in the same wavefront take different paths due to conditional
/// branches.
- virtual bool hasBranchDivergence() const;
+ bool hasBranchDivergence() const;
+
+ /// \brief Returns whether V is a source of divergence.
+ ///
+ /// This function provides the target-dependent information for
+ /// the target-independent DivergenceAnalysis. DivergenceAnalysis first
+ /// builds the dependency graph, and then runs the reachability algorithm
+ /// starting with the sources of divergence.
+ bool isSourceOfDivergence(const Value *V) const;
/// \brief Test whether calls to a function lower to actual program function
/// calls.
@@ -186,7 +217,7 @@ public:
/// and execution-speed costs. This would allow modelling the core of this
/// query more accurately as a call is a single small instruction, but
/// incurs significant execution cost.
- virtual bool isLoweredToCall(const Function *F) const;
+ bool isLoweredToCall(const Function *F) const;
/// Parameters that control the generic loop unrolling transformation.
struct UnrollingPreferences {
@@ -196,6 +227,13 @@ public:
/// exceed this cost. Set this to UINT_MAX to disable the loop body cost
/// restriction.
unsigned Threshold;
+ /// If complete unrolling could help other optimizations (e.g. InstSimplify)
+ /// to remove N% of instructions, then we can go beyond unroll threshold.
+ /// This value set the minimal percent for allowing that.
+ unsigned MinPercentOfOptimized;
+ /// The absolute cost threshold. We won't go beyond this even if complete
+ /// unrolling could result in optimizing out 90% of instructions.
+ unsigned AbsoluteThreshold;
/// The cost threshold for the unrolled loop when optimizing for size (set
/// to UINT_MAX to disable).
unsigned OptSizeThreshold;
@@ -203,8 +241,8 @@ public:
/// for partial/runtime unrolling (set to UINT_MAX to disable).
unsigned PartialThreshold;
/// The cost threshold for the unrolled loop when optimizing for size, like
- /// OptSizeThreshold, but used for partial/runtime unrolling (set to UINT_MAX
- /// to disable).
+ /// OptSizeThreshold, but used for partial/runtime unrolling (set to
+ /// UINT_MAX to disable).
unsigned PartialOptSizeThreshold;
/// A forced unrolling factor (the number of concatenated bodies of the
/// original loop in the unrolled loop body). When set to 0, the unrolling
@@ -218,18 +256,20 @@ public:
unsigned MaxCount;
/// Allow partial unrolling (unrolling of loops to expand the size of the
/// loop body, not only to eliminate small constant-trip-count loops).
- bool Partial;
+ bool Partial;
/// Allow runtime unrolling (unrolling of loops to expand the size of the
- /// loop body even when the number of loop iterations is not known at compile
- /// time).
- bool Runtime;
+ /// loop body even when the number of loop iterations is not known at
+ /// compile time).
+ bool Runtime;
+ /// Allow emitting expensive instructions (such as divisions) when computing
+ /// the trip count of a loop for runtime unrolling.
+ bool AllowExpensiveTripCount;
};
/// \brief Get target-customized preferences for the generic loop unrolling
/// transformation. The caller will initialize UP with the current
/// target-independent defaults.
- virtual void getUnrollingPreferences(const Function *F, Loop *L,
- UnrollingPreferences &UP) const;
+ void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const;
/// @}
@@ -244,38 +284,33 @@ public:
/// support is considered as "Fast" if it can outperform, or is on a par
/// with, SW implementation when the population is sparse; otherwise, it is
/// considered as "Slow".
- enum PopcntSupportKind {
- PSK_Software,
- PSK_SlowHardware,
- PSK_FastHardware
- };
+ enum PopcntSupportKind { PSK_Software, PSK_SlowHardware, PSK_FastHardware };
/// \brief Return true if the specified immediate is legal add immediate, that
/// is the target has add instructions which can add a register with the
/// immediate without having to materialize the immediate into a register.
- virtual bool isLegalAddImmediate(int64_t Imm) const;
+ bool isLegalAddImmediate(int64_t Imm) const;
/// \brief Return true if the specified immediate is legal icmp immediate,
/// that is the target has icmp instructions which can compare a register
/// against the immediate without having to materialize the immediate into a
/// register.
- virtual bool isLegalICmpImmediate(int64_t Imm) const;
+ bool isLegalICmpImmediate(int64_t Imm) const;
/// \brief Return true if the addressing mode represented by AM is legal for
/// this target, for a load/store of the specified type.
/// The type may be VoidTy, in which case only return true if the addressing
/// mode is legal for a load/store of any legal type.
/// TODO: Handle pre/postinc as well.
- virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
- int64_t BaseOffset, bool HasBaseReg,
- int64_t Scale) const;
+ bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale) const;
/// \brief Return true if the target works with masked instruction
/// AVX2 allows masks for consecutive load and store for i32 and i64 elements.
/// AVX-512 architecture will also allow masks for non-consecutive memory
/// accesses.
- virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) const;
- virtual bool isLegalMaskedLoad (Type *DataType, int Consecutive) const;
+ bool isLegalMaskedStore(Type *DataType, int Consecutive) const;
+ bool isLegalMaskedLoad(Type *DataType, int Consecutive) const;
/// \brief Return the cost of the scaling factor used in the addressing
/// mode represented by AM for this target, for a load/store
@@ -283,45 +318,55 @@ public:
/// If the AM is supported, the return value must be >= 0.
/// If the AM is not supported, it returns a negative value.
/// TODO: Handle pre/postinc as well.
- virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
- int64_t BaseOffset, bool HasBaseReg,
- int64_t Scale) const;
+ int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale) const;
/// \brief Return true if it's free to truncate a value of type Ty1 to type
/// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16
/// by referencing its sub-register AX.
- virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const;
+ bool isTruncateFree(Type *Ty1, Type *Ty2) const;
+
+ /// \brief Return true if it is profitable to hoist instruction in the
+ /// then/else to before if.
+ bool isProfitableToHoist(Instruction *I) const;
/// \brief Return true if this type is legal.
- virtual bool isTypeLegal(Type *Ty) const;
+ bool isTypeLegal(Type *Ty) const;
/// \brief Returns the target's jmp_buf alignment in bytes.
- virtual unsigned getJumpBufAlignment() const;
+ unsigned getJumpBufAlignment() const;
/// \brief Returns the target's jmp_buf size in bytes.
- virtual unsigned getJumpBufSize() const;
+ unsigned getJumpBufSize() const;
/// \brief Return true if switches should be turned into lookup tables for the
/// target.
- virtual bool shouldBuildLookupTables() const;
+ bool shouldBuildLookupTables() const;
+
+ /// \brief Don't restrict interleaved unrolling to small loops.
+ bool enableAggressiveInterleaving(bool LoopHasReductions) const;
/// \brief Return hardware support for population count.
- virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
+ PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
/// \brief Return true if the hardware has a fast square-root instruction.
- virtual bool haveFastSqrt(Type *Ty) const;
+ bool haveFastSqrt(Type *Ty) const;
+
+ /// \brief Return the expected cost of supporting the floating point operation
+ /// of the specified type.
+ unsigned getFPOpCost(Type *Ty) const;
/// \brief Return the expected cost of materializing for the given integer
/// immediate of the specified type.
- virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const;
+ unsigned getIntImmCost(const APInt &Imm, Type *Ty) const;
/// \brief Return the expected cost of materialization for the given integer
/// immediate of the specified type for a given instruction. The cost can be
/// zero if the immediate can be folded into the specified instruction.
- virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
- Type *Ty) const;
- virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx,
- const APInt &Imm, Type *Ty) const;
+ unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
+ Type *Ty) const;
+ unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
+ Type *Ty) const;
/// @}
/// \name Vector Target Information
@@ -338,10 +383,10 @@ public:
/// \brief Additional information about an operand's possible values.
enum OperandValueKind {
- OK_AnyValue, // Operand can have any value.
- OK_UniformValue, // Operand is uniform (splat of a value).
- OK_UniformConstantValue, // Operand is uniform constant.
- OK_NonUniformConstantValue // Operand is a non uniform constant value.
+ OK_AnyValue, // Operand can have any value.
+ OK_UniformValue, // Operand is uniform (splat of a value).
+ OK_UniformConstantValue, // Operand is uniform constant.
+ OK_NonUniformConstantValue // Operand is a non uniform constant value.
};
/// \brief Additional properties of an operand's values.
@@ -350,18 +395,18 @@ public:
/// \return The number of scalar or vector registers that the target has.
/// If 'Vectors' is true, it returns the number of vector registers. If it is
/// set to false, it returns the number of scalar registers.
- virtual unsigned getNumberOfRegisters(bool Vector) const;
+ unsigned getNumberOfRegisters(bool Vector) const;
/// \return The width of the largest scalar or vector register type.
- virtual unsigned getRegisterBitWidth(bool Vector) const;
+ unsigned getRegisterBitWidth(bool Vector) const;
/// \return The maximum interleave factor that any transform should try to
/// perform for this target. This number depends on the level of parallelism
/// and the number of execution units in the CPU.
- virtual unsigned getMaxInterleaveFactor() const;
+ unsigned getMaxInterleaveFactor(unsigned VF) const;
/// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc.
- virtual unsigned
+ unsigned
getArithmeticInstrCost(unsigned Opcode, Type *Ty,
OperandValueKind Opd1Info = OK_AnyValue,
OperandValueKind Opd2Info = OK_AnyValue,
@@ -371,31 +416,33 @@ public:
/// \return The cost of a shuffle instruction of kind Kind and of type Tp.
/// The index and subtype parameters are used by the subvector insertion and
/// extraction shuffle kinds.
- virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0,
- Type *SubTp = nullptr) const;
+ unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0,
+ Type *SubTp = nullptr) const;
/// \return The expected cost of cast instructions, such as bitcast, trunc,
/// zext, etc.
- virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst,
- Type *Src) const;
+ unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const;
/// \return The expected cost of control-flow related instructions such as
/// Phi, Ret, Br.
- virtual unsigned getCFInstrCost(unsigned Opcode) const;
+ unsigned getCFInstrCost(unsigned Opcode) const;
/// \returns The expected cost of compare and select instructions.
- virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
- Type *CondTy = nullptr) const;
+ unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
+ Type *CondTy = nullptr) const;
/// \return The expected cost of vector Insert and Extract.
/// Use -1 to indicate that there is no information on the index value.
- virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
- unsigned Index = -1) const;
+ unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
+ unsigned Index = -1) const;
/// \return The cost of Load and Store instructions.
- virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src,
- unsigned Alignment,
- unsigned AddressSpace) const;
+ unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
+ unsigned AddressSpace) const;
+
+ /// \return The cost of masked Load and Store instructions.
+ unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
+ unsigned AddressSpace) const;
/// \brief Calculate the cost of performing a vector reduction.
///
@@ -410,16 +457,20 @@ public:
/// Split:
/// (v0, v1, v2, v3)
/// ((v0+v2), (v1+v3), undef, undef)
- virtual unsigned getReductionCost(unsigned Opcode, Type *Ty,
- bool IsPairwiseForm) const;
+ unsigned getReductionCost(unsigned Opcode, Type *Ty,
+ bool IsPairwiseForm) const;
/// \returns The cost of Intrinsic instructions.
- virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type *> Tys) const;
+ unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
+ ArrayRef<Type *> Tys) const;
+
+ /// \returns The cost of Call instructions.
+ unsigned getCallInstrCost(Function *F, Type *RetTy,
+ ArrayRef<Type *> Tys) const;
/// \returns The number of pieces into which the provided type must be
/// split during legalization. Zero is returned when the answer is unknown.
- virtual unsigned getNumberOfParts(Type *Tp) const;
+ unsigned getNumberOfParts(Type *Tp) const;
/// \returns The cost of the address computation. For most targets this can be
/// merged into the instruction indexing mode. Some targets might want to
@@ -428,28 +479,399 @@ public:
/// The 'IsComplex' parameter is a hint that the address computation is likely
/// to involve multiple instructions and as such unlikely to be merged into
/// the address indexing mode.
- virtual unsigned getAddressComputationCost(Type *Ty,
- bool IsComplex = false) const;
+ unsigned getAddressComputationCost(Type *Ty, bool IsComplex = false) const;
/// \returns The cost, if any, of keeping values of the given types alive
/// over a callsite.
///
/// Some types may require the use of register classes that do not have
/// any callee-saved registers, so would require a spill and fill.
- virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const;
+ unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const;
+
+ /// \returns True if the intrinsic is a supported memory intrinsic. Info
+ /// will contain additional information - whether the intrinsic may write
+ /// or read to memory, volatility and the pointer. Info is undefined
+ /// if false is returned.
+ bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const;
+
+ /// \returns A value which is the result of the given memory intrinsic. New
+ /// instructions may be created to extract the result from the given intrinsic
+ /// memory operation. Returns nullptr if the target cannot create a result
+ /// from the given intrinsic.
+ Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
+ Type *ExpectedType) const;
/// @}
- /// Analysis group identification.
+private:
+ /// \brief The abstract base class used to type erase specific TTI
+ /// implementations.
+ class Concept;
+
+ /// \brief The template model for the base class which wraps a concrete
+ /// implementation in a type erased interface.
+ template <typename T> class Model;
+
+ std::unique_ptr<Concept> TTIImpl;
+};
+
+class TargetTransformInfo::Concept {
+public:
+ virtual ~Concept() = 0;
+
+ virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0;
+ virtual unsigned getGEPCost(const Value *Ptr,
+ ArrayRef<const Value *> Operands) = 0;
+ virtual unsigned getCallCost(FunctionType *FTy, int NumArgs) = 0;
+ virtual unsigned getCallCost(const Function *F, int NumArgs) = 0;
+ virtual unsigned getCallCost(const Function *F,
+ ArrayRef<const Value *> Arguments) = 0;
+ virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> ParamTys) = 0;
+ virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> Arguments) = 0;
+ virtual unsigned getUserCost(const User *U) = 0;
+ virtual bool hasBranchDivergence() = 0;
+ virtual bool isSourceOfDivergence(const Value *V) = 0;
+ virtual bool isLoweredToCall(const Function *F) = 0;
+ virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0;
+ virtual bool isLegalAddImmediate(int64_t Imm) = 0;
+ virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
+ virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
+ int64_t BaseOffset, bool HasBaseReg,
+ int64_t Scale) = 0;
+ virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0;
+ virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0;
+ virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
+ int64_t BaseOffset, bool HasBaseReg,
+ int64_t Scale) = 0;
+ virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0;
+ virtual bool isProfitableToHoist(Instruction *I) = 0;
+ virtual bool isTypeLegal(Type *Ty) = 0;
+ virtual unsigned getJumpBufAlignment() = 0;
+ virtual unsigned getJumpBufSize() = 0;
+ virtual bool shouldBuildLookupTables() = 0;
+ virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0;
+ virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) = 0;
+ virtual bool haveFastSqrt(Type *Ty) = 0;
+ virtual unsigned getFPOpCost(Type *Ty) = 0;
+ virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) = 0;
+ virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
+ Type *Ty) = 0;
+ virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx,
+ const APInt &Imm, Type *Ty) = 0;
+ virtual unsigned getNumberOfRegisters(bool Vector) = 0;
+ virtual unsigned getRegisterBitWidth(bool Vector) = 0;
+ virtual unsigned getMaxInterleaveFactor(unsigned VF) = 0;
+ virtual unsigned
+ getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info,
+ OperandValueKind Opd2Info,
+ OperandValueProperties Opd1PropInfo,
+ OperandValueProperties Opd2PropInfo) = 0;
+ virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index,
+ Type *SubTp) = 0;
+ virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0;
+ virtual unsigned getCFInstrCost(unsigned Opcode) = 0;
+ virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
+ Type *CondTy) = 0;
+ virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
+ unsigned Index) = 0;
+ virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src,
+ unsigned Alignment,
+ unsigned AddressSpace) = 0;
+ virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
+ unsigned Alignment,
+ unsigned AddressSpace) = 0;
+ virtual unsigned getReductionCost(unsigned Opcode, Type *Ty,
+ bool IsPairwiseForm) = 0;
+ virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
+ ArrayRef<Type *> Tys) = 0;
+ virtual unsigned getCallInstrCost(Function *F, Type *RetTy,
+ ArrayRef<Type *> Tys) = 0;
+ virtual unsigned getNumberOfParts(Type *Tp) = 0;
+ virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex) = 0;
+ virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) = 0;
+ virtual bool getTgtMemIntrinsic(IntrinsicInst *Inst,
+ MemIntrinsicInfo &Info) = 0;
+ virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
+ Type *ExpectedType) = 0;
+};
+
+template <typename T>
+class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
+ T Impl;
+
+public:
+ Model(T Impl) : Impl(std::move(Impl)) {}
+ ~Model() override {}
+
+ unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) override {
+ return Impl.getOperationCost(Opcode, Ty, OpTy);
+ }
+ unsigned getGEPCost(const Value *Ptr,
+ ArrayRef<const Value *> Operands) override {
+ return Impl.getGEPCost(Ptr, Operands);
+ }
+ unsigned getCallCost(FunctionType *FTy, int NumArgs) override {
+ return Impl.getCallCost(FTy, NumArgs);
+ }
+ unsigned getCallCost(const Function *F, int NumArgs) override {
+ return Impl.getCallCost(F, NumArgs);
+ }
+ unsigned getCallCost(const Function *F,
+ ArrayRef<const Value *> Arguments) override {
+ return Impl.getCallCost(F, Arguments);
+ }
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> ParamTys) override {
+ return Impl.getIntrinsicCost(IID, RetTy, ParamTys);
+ }
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> Arguments) override {
+ return Impl.getIntrinsicCost(IID, RetTy, Arguments);
+ }
+ unsigned getUserCost(const User *U) override { return Impl.getUserCost(U); }
+ bool hasBranchDivergence() override { return Impl.hasBranchDivergence(); }
+ bool isSourceOfDivergence(const Value *V) override {
+ return Impl.isSourceOfDivergence(V);
+ }
+ bool isLoweredToCall(const Function *F) override {
+ return Impl.isLoweredToCall(F);
+ }
+ void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) override {
+ return Impl.getUnrollingPreferences(L, UP);
+ }
+ bool isLegalAddImmediate(int64_t Imm) override {
+ return Impl.isLegalAddImmediate(Imm);
+ }
+ bool isLegalICmpImmediate(int64_t Imm) override {
+ return Impl.isLegalICmpImmediate(Imm);
+ }
+ bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale) override {
+ return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
+ Scale);
+ }
+ bool isLegalMaskedStore(Type *DataType, int Consecutive) override {
+ return Impl.isLegalMaskedStore(DataType, Consecutive);
+ }
+ bool isLegalMaskedLoad(Type *DataType, int Consecutive) override {
+ return Impl.isLegalMaskedLoad(DataType, Consecutive);
+ }
+ int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale) override {
+ return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale);
+ }
+ bool isTruncateFree(Type *Ty1, Type *Ty2) override {
+ return Impl.isTruncateFree(Ty1, Ty2);
+ }
+ bool isProfitableToHoist(Instruction *I) override {
+ return Impl.isProfitableToHoist(I);
+ }
+ bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); }
+ unsigned getJumpBufAlignment() override { return Impl.getJumpBufAlignment(); }
+ unsigned getJumpBufSize() override { return Impl.getJumpBufSize(); }
+ bool shouldBuildLookupTables() override {
+ return Impl.shouldBuildLookupTables();
+ }
+ bool enableAggressiveInterleaving(bool LoopHasReductions) override {
+ return Impl.enableAggressiveInterleaving(LoopHasReductions);
+ }
+ PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) override {
+ return Impl.getPopcntSupport(IntTyWidthInBit);
+ }
+ bool haveFastSqrt(Type *Ty) override { return Impl.haveFastSqrt(Ty); }
+
+ unsigned getFPOpCost(Type *Ty) override {
+ return Impl.getFPOpCost(Ty);
+ }
+
+ unsigned getIntImmCost(const APInt &Imm, Type *Ty) override {
+ return Impl.getIntImmCost(Imm, Ty);
+ }
+ unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
+ Type *Ty) override {
+ return Impl.getIntImmCost(Opc, Idx, Imm, Ty);
+ }
+ unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
+ Type *Ty) override {
+ return Impl.getIntImmCost(IID, Idx, Imm, Ty);
+ }
+ unsigned getNumberOfRegisters(bool Vector) override {
+ return Impl.getNumberOfRegisters(Vector);
+ }
+ unsigned getRegisterBitWidth(bool Vector) override {
+ return Impl.getRegisterBitWidth(Vector);
+ }
+ unsigned getMaxInterleaveFactor(unsigned VF) override {
+ return Impl.getMaxInterleaveFactor(VF);
+ }
+ unsigned
+ getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info,
+ OperandValueKind Opd2Info,
+ OperandValueProperties Opd1PropInfo,
+ OperandValueProperties Opd2PropInfo) override {
+ return Impl.getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info,
+ Opd1PropInfo, Opd2PropInfo);
+ }
+ unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index,
+ Type *SubTp) override {
+ return Impl.getShuffleCost(Kind, Tp, Index, SubTp);
+ }
+ unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override {
+ return Impl.getCastInstrCost(Opcode, Dst, Src);
+ }
+ unsigned getCFInstrCost(unsigned Opcode) override {
+ return Impl.getCFInstrCost(Opcode);
+ }
+ unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
+ Type *CondTy) override {
+ return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy);
+ }
+ unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
+ unsigned Index) override {
+ return Impl.getVectorInstrCost(Opcode, Val, Index);
+ }
+ unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
+ unsigned AddressSpace) override {
+ return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
+ }
+ unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
+ unsigned AddressSpace) override {
+ return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
+ }
+ unsigned getReductionCost(unsigned Opcode, Type *Ty,
+ bool IsPairwiseForm) override {
+ return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm);
+ }
+ unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
+ ArrayRef<Type *> Tys) override {
+ return Impl.getIntrinsicInstrCost(ID, RetTy, Tys);
+ }
+ unsigned getCallInstrCost(Function *F, Type *RetTy,
+ ArrayRef<Type *> Tys) override {
+ return Impl.getCallInstrCost(F, RetTy, Tys);
+ }
+ unsigned getNumberOfParts(Type *Tp) override {
+ return Impl.getNumberOfParts(Tp);
+ }
+ unsigned getAddressComputationCost(Type *Ty, bool IsComplex) override {
+ return Impl.getAddressComputationCost(Ty, IsComplex);
+ }
+ unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) override {
+ return Impl.getCostOfKeepingLiveOverCall(Tys);
+ }
+ bool getTgtMemIntrinsic(IntrinsicInst *Inst,
+ MemIntrinsicInfo &Info) override {
+ return Impl.getTgtMemIntrinsic(Inst, Info);
+ }
+ Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
+ Type *ExpectedType) override {
+ return Impl.getOrCreateResultFromMemIntrinsic(Inst, ExpectedType);
+ }
+};
+
+template <typename T>
+TargetTransformInfo::TargetTransformInfo(T Impl)
+ : TTIImpl(new Model<T>(Impl)) {}
+
+/// \brief Analysis pass providing the \c TargetTransformInfo.
+///
+/// The core idea of the TargetIRAnalysis is to expose an interface through
+/// which LLVM targets can analyze and provide information about the middle
+/// end's target-independent IR. This supports use cases such as target-aware
+/// cost modeling of IR constructs.
+///
+/// This is a function analysis because much of the cost modeling for targets
+/// is done in a subtarget specific way and LLVM supports compiling different
+/// functions targeting different subtargets in order to support runtime
+/// dispatch according to the observed subtarget.
+class TargetIRAnalysis {
+public:
+ typedef TargetTransformInfo Result;
+
+ /// \brief Opaque, unique identifier for this analysis pass.
+ static void *ID() { return (void *)&PassID; }
+
+ /// \brief Provide access to a name for this pass for debugging purposes.
+ static StringRef name() { return "TargetIRAnalysis"; }
+
+ /// \brief Default construct a target IR analysis.
+ ///
+ /// This will use the module's datalayout to construct a baseline
+ /// conservative TTI result.
+ TargetIRAnalysis();
+
+ /// \brief Construct an IR analysis pass around a target-provide callback.
+ ///
+ /// The callback will be called with a particular function for which the TTI
+ /// is needed and must return a TTI object for that function.
+ TargetIRAnalysis(std::function<Result(Function &)> TTICallback);
+
+ // Value semantics. We spell out the constructors for MSVC.
+ TargetIRAnalysis(const TargetIRAnalysis &Arg)
+ : TTICallback(Arg.TTICallback) {}
+ TargetIRAnalysis(TargetIRAnalysis &&Arg)
+ : TTICallback(std::move(Arg.TTICallback)) {}
+ TargetIRAnalysis &operator=(const TargetIRAnalysis &RHS) {
+ TTICallback = RHS.TTICallback;
+ return *this;
+ }
+ TargetIRAnalysis &operator=(TargetIRAnalysis &&RHS) {
+ TTICallback = std::move(RHS.TTICallback);
+ return *this;
+ }
+
+ Result run(Function &F);
+
+private:
+ static char PassID;
+
+ /// \brief The callback used to produce a result.
+ ///
+ /// We use a completely opaque callback so that targets can provide whatever
+ /// mechanism they desire for constructing the TTI for a given function.
+ ///
+ /// FIXME: Should we really use std::function? It's relatively inefficient.
+ /// It might be possible to arrange for even stateful callbacks to outlive
+ /// the analysis and thus use a function_ref which would be lighter weight.
+ /// This may also be less error prone as the callback is likely to reference
+ /// the external TargetMachine, and that reference needs to never dangle.
+ std::function<Result(Function &)> TTICallback;
+
+ /// \brief Helper function used as the callback in the default constructor.
+ static Result getDefaultTTI(Function &F);
+};
+
+/// \brief Wrapper pass for TargetTransformInfo.
+///
+/// This pass can be constructed from a TTI object which it stores internally
+/// and is queried by passes.
+class TargetTransformInfoWrapperPass : public ImmutablePass {
+ TargetIRAnalysis TIRA;
+ Optional<TargetTransformInfo> TTI;
+
+ virtual void anchor();
+
+public:
static char ID;
+
+ /// \brief We must provide a default constructor for the pass but it should
+ /// never be used.
+ ///
+ /// Use the constructor below or call one of the creation routines.
+ TargetTransformInfoWrapperPass();
+
+ explicit TargetTransformInfoWrapperPass(TargetIRAnalysis TIRA);
+
+ TargetTransformInfo &getTTI(Function &F);
};
-/// \brief Create the base case instance of a pass in the TTI analysis group.
+/// \brief Create an analysis pass wrapper around a TTI object.
///
-/// This class provides the base case for the stack of TTI analyzes. It doesn't
-/// delegate to anything and uses the STTI and VTTI objects passed in to
-/// satisfy the queries.
-ImmutablePass *createNoTargetTransformInfoPass();
+/// This analysis pass just holds the TTI instance and makes it available to
+/// clients.
+ImmutablePass *createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA);
} // End llvm namespace
diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h
new file mode 100644
index 000000000000..253319ccd441
--- /dev/null
+++ b/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -0,0 +1,441 @@
+//===- TargetTransformInfoImpl.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides helpers for the implementation of
+/// a TargetTransformInfo-conforming class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H
+#define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H
+
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/Type.h"
+
+namespace llvm {
+
+/// \brief Base class for use as a mix-in that aids implementing
+/// a TargetTransformInfo-compatible class.
+class TargetTransformInfoImplBase {
+protected:
+ typedef TargetTransformInfo TTI;
+
+ const DataLayout *DL;
+
+ explicit TargetTransformInfoImplBase(const DataLayout *DL)
+ : DL(DL) {}
+
+public:
+ // Provide value semantics. MSVC requires that we spell all of these out.
+ TargetTransformInfoImplBase(const TargetTransformInfoImplBase &Arg)
+ : DL(Arg.DL) {}
+ TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg)
+ : DL(std::move(Arg.DL)) {}
+ TargetTransformInfoImplBase &
+ operator=(const TargetTransformInfoImplBase &RHS) {
+ DL = RHS.DL;
+ return *this;
+ }
+ TargetTransformInfoImplBase &operator=(TargetTransformInfoImplBase &&RHS) {
+ DL = std::move(RHS.DL);
+ return *this;
+ }
+
+ unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) {
+ switch (Opcode) {
+ default:
+ // By default, just classify everything as 'basic'.
+ return TTI::TCC_Basic;
+
+ case Instruction::GetElementPtr:
+ llvm_unreachable("Use getGEPCost for GEP operations!");
+
+ case Instruction::BitCast:
+ assert(OpTy && "Cast instructions must provide the operand type");
+ if (Ty == OpTy || (Ty->isPointerTy() && OpTy->isPointerTy()))
+ // Identity and pointer-to-pointer casts are free.
+ return TTI::TCC_Free;
+
+ // Otherwise, the default basic cost is used.
+ return TTI::TCC_Basic;
+
+ case Instruction::IntToPtr: {
+ if (!DL)
+ return TTI::TCC_Basic;
+
+ // An inttoptr cast is free so long as the input is a legal integer type
+ // which doesn't contain values outside the range of a pointer.
+ unsigned OpSize = OpTy->getScalarSizeInBits();
+ if (DL->isLegalInteger(OpSize) &&
+ OpSize <= DL->getPointerTypeSizeInBits(Ty))
+ return TTI::TCC_Free;
+
+ // Otherwise it's not a no-op.
+ return TTI::TCC_Basic;
+ }
+ case Instruction::PtrToInt: {
+ if (!DL)
+ return TTI::TCC_Basic;
+
+ // A ptrtoint cast is free so long as the result is large enough to store
+ // the pointer, and a legal integer type.
+ unsigned DestSize = Ty->getScalarSizeInBits();
+ if (DL->isLegalInteger(DestSize) &&
+ DestSize >= DL->getPointerTypeSizeInBits(OpTy))
+ return TTI::TCC_Free;
+
+ // Otherwise it's not a no-op.
+ return TTI::TCC_Basic;
+ }
+ case Instruction::Trunc:
+ // trunc to a native type is free (assuming the target has compare and
+ // shift-right of the same width).
+ if (DL && DL->isLegalInteger(DL->getTypeSizeInBits(Ty)))
+ return TTI::TCC_Free;
+
+ return TTI::TCC_Basic;
+ }
+ }
+
+ unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) {
+ // In the basic model, we just assume that all-constant GEPs will be folded
+ // into their uses via addressing modes.
+ for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx)
+ if (!isa<Constant>(Operands[Idx]))
+ return TTI::TCC_Basic;
+
+ return TTI::TCC_Free;
+ }
+
+ unsigned getCallCost(FunctionType *FTy, int NumArgs) {
+ assert(FTy && "FunctionType must be provided to this routine.");
+
+ // The target-independent implementation just measures the size of the
+ // function by approximating that each argument will take on average one
+ // instruction to prepare.
+
+ if (NumArgs < 0)
+ // Set the argument number to the number of explicit arguments in the
+ // function.
+ NumArgs = FTy->getNumParams();
+
+ return TTI::TCC_Basic * (NumArgs + 1);
+ }
+
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> ParamTys) {
+ switch (IID) {
+ default:
+ // Intrinsics rarely (if ever) have normal argument setup constraints.
+ // Model them as having a basic instruction cost.
+ // FIXME: This is wrong for libc intrinsics.
+ return TTI::TCC_Basic;
+
+ case Intrinsic::annotation:
+ case Intrinsic::assume:
+ case Intrinsic::dbg_declare:
+ case Intrinsic::dbg_value:
+ case Intrinsic::invariant_start:
+ case Intrinsic::invariant_end:
+ case Intrinsic::lifetime_start:
+ case Intrinsic::lifetime_end:
+ case Intrinsic::objectsize:
+ case Intrinsic::ptr_annotation:
+ case Intrinsic::var_annotation:
+ case Intrinsic::experimental_gc_result_int:
+ case Intrinsic::experimental_gc_result_float:
+ case Intrinsic::experimental_gc_result_ptr:
+ case Intrinsic::experimental_gc_result:
+ case Intrinsic::experimental_gc_relocate:
+ // These intrinsics don't actually represent code after lowering.
+ return TTI::TCC_Free;
+ }
+ }
+
+ bool hasBranchDivergence() { return false; }
+
+ bool isSourceOfDivergence(const Value *V) { return false; }
+
+ bool isLoweredToCall(const Function *F) {
+ // FIXME: These should almost certainly not be handled here, and instead
+ // handled with the help of TLI or the target itself. This was largely
+ // ported from existing analysis heuristics here so that such refactorings
+ // can take place in the future.
+
+ if (F->isIntrinsic())
+ return false;
+
+ if (F->hasLocalLinkage() || !F->hasName())
+ return true;
+
+ StringRef Name = F->getName();
+
+ // These will all likely lower to a single selection DAG node.
+ if (Name == "copysign" || Name == "copysignf" || Name == "copysignl" ||
+ Name == "fabs" || Name == "fabsf" || Name == "fabsl" || Name == "sin" ||
+ Name == "fmin" || Name == "fminf" || Name == "fminl" ||
+ Name == "fmax" || Name == "fmaxf" || Name == "fmaxl" ||
+ Name == "sinf" || Name == "sinl" || Name == "cos" || Name == "cosf" ||
+ Name == "cosl" || Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl")
+ return false;
+
+ // These are all likely to be optimized into something smaller.
+ if (Name == "pow" || Name == "powf" || Name == "powl" || Name == "exp2" ||
+ Name == "exp2l" || Name == "exp2f" || Name == "floor" ||
+ Name == "floorf" || Name == "ceil" || Name == "round" ||
+ Name == "ffs" || Name == "ffsl" || Name == "abs" || Name == "labs" ||
+ Name == "llabs")
+ return false;
+
+ return true;
+ }
+
+ void getUnrollingPreferences(Loop *, TTI::UnrollingPreferences &) {}
+
+ bool isLegalAddImmediate(int64_t Imm) { return false; }
+
+ bool isLegalICmpImmediate(int64_t Imm) { return false; }
+
+ bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale) {
+ // Guess that only reg and reg+reg addressing is allowed. This heuristic is
+ // taken from the implementation of LSR.
+ return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1);
+ }
+
+ bool isLegalMaskedStore(Type *DataType, int Consecutive) { return false; }
+
+ bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; }
+
+ int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale) {
+ // Guess that all legal addressing mode are free.
+ if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale))
+ return 0;
+ return -1;
+ }
+
+ bool isTruncateFree(Type *Ty1, Type *Ty2) { return false; }
+
+ bool isProfitableToHoist(Instruction *I) { return true; }
+
+ bool isTypeLegal(Type *Ty) { return false; }
+
+ unsigned getJumpBufAlignment() { return 0; }
+
+ unsigned getJumpBufSize() { return 0; }
+
+ bool shouldBuildLookupTables() { return true; }
+
+ bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; }
+
+ TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) {
+ return TTI::PSK_Software;
+ }
+
+ bool haveFastSqrt(Type *Ty) { return false; }
+
+ unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; }
+
+ unsigned getIntImmCost(const APInt &Imm, Type *Ty) { return TTI::TCC_Basic; }
+
+ unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
+ Type *Ty) {
+ return TTI::TCC_Free;
+ }
+
+ unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
+ Type *Ty) {
+ return TTI::TCC_Free;
+ }
+
+ unsigned getNumberOfRegisters(bool Vector) { return 8; }
+
+ unsigned getRegisterBitWidth(bool Vector) { return 32; }
+
+ unsigned getMaxInterleaveFactor(unsigned VF) { return 1; }
+
+ unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty,
+ TTI::OperandValueKind Opd1Info,
+ TTI::OperandValueKind Opd2Info,
+ TTI::OperandValueProperties Opd1PropInfo,
+ TTI::OperandValueProperties Opd2PropInfo) {
+ return 1;
+ }
+
+ unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Ty, int Index,
+ Type *SubTp) {
+ return 1;
+ }
+
+ unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; }
+
+ unsigned getCFInstrCost(unsigned Opcode) { return 1; }
+
+ unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
+ return 1;
+ }
+
+ unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) {
+ return 1;
+ }
+
+ unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
+ unsigned AddressSpace) {
+ return 1;
+ }
+
+ unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
+ unsigned AddressSpace) {
+ return 1;
+ }
+
+ unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
+ ArrayRef<Type *> Tys) {
+ return 1;
+ }
+
+ unsigned getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) {
+ return 1;
+ }
+
+ unsigned getNumberOfParts(Type *Tp) { return 0; }
+
+ unsigned getAddressComputationCost(Type *Tp, bool) { return 0; }
+
+ unsigned getReductionCost(unsigned, Type *, bool) { return 1; }
+
+ unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) { return 0; }
+
+ bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) {
+ return false;
+ }
+
+ Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
+ Type *ExpectedType) {
+ return nullptr;
+ }
+};
+
+/// \brief CRTP base class for use as a mix-in that aids implementing
+/// a TargetTransformInfo-compatible class.
+template <typename T>
+class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase {
+private:
+ typedef TargetTransformInfoImplBase BaseT;
+
+protected:
+ explicit TargetTransformInfoImplCRTPBase(const DataLayout *DL)
+ : BaseT(DL) {}
+
+public:
+ // Provide value semantics. MSVC requires that we spell all of these out.
+ TargetTransformInfoImplCRTPBase(const TargetTransformInfoImplCRTPBase &Arg)
+ : BaseT(static_cast<const BaseT &>(Arg)) {}
+ TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
+ TargetTransformInfoImplCRTPBase &
+ operator=(const TargetTransformInfoImplCRTPBase &RHS) {
+ BaseT::operator=(static_cast<const BaseT &>(RHS));
+ return *this;
+ }
+ TargetTransformInfoImplCRTPBase &
+ operator=(TargetTransformInfoImplCRTPBase &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
+ return *this;
+ }
+
+ using BaseT::getCallCost;
+
+ unsigned getCallCost(const Function *F, int NumArgs) {
+ assert(F && "A concrete function must be provided to this routine.");
+
+ if (NumArgs < 0)
+ // Set the argument number to the number of explicit arguments in the
+ // function.
+ NumArgs = F->arg_size();
+
+ if (Intrinsic::ID IID = F->getIntrinsicID()) {
+ FunctionType *FTy = F->getFunctionType();
+ SmallVector<Type *, 8> ParamTys(FTy->param_begin(), FTy->param_end());
+ return static_cast<T *>(this)
+ ->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys);
+ }
+
+ if (!static_cast<T *>(this)->isLoweredToCall(F))
+ return TTI::TCC_Basic; // Give a basic cost if it will be lowered
+ // directly.
+
+ return static_cast<T *>(this)->getCallCost(F->getFunctionType(), NumArgs);
+ }
+
+ unsigned getCallCost(const Function *F, ArrayRef<const Value *> Arguments) {
+ // Simply delegate to generic handling of the call.
+ // FIXME: We should use instsimplify or something else to catch calls which
+ // will constant fold with these arguments.
+ return static_cast<T *>(this)->getCallCost(F, Arguments.size());
+ }
+
+ using BaseT::getIntrinsicCost;
+
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> Arguments) {
+ // Delegate to the generic intrinsic handling code. This mostly provides an
+ // opportunity for targets to (for example) special case the cost of
+ // certain intrinsics based on constants used as arguments.
+ SmallVector<Type *, 8> ParamTys;
+ ParamTys.reserve(Arguments.size());
+ for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx)
+ ParamTys.push_back(Arguments[Idx]->getType());
+ return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys);
+ }
+
+ unsigned getUserCost(const User *U) {
+ if (isa<PHINode>(U))
+ return TTI::TCC_Free; // Model all PHI nodes as free.
+
+ if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
+ SmallVector<const Value *, 4> Indices(GEP->idx_begin(), GEP->idx_end());
+ return static_cast<T *>(this)
+ ->getGEPCost(GEP->getPointerOperand(), Indices);
+ }
+
+ if (auto CS = ImmutableCallSite(U)) {
+ const Function *F = CS.getCalledFunction();
+ if (!F) {
+ // Just use the called value type.
+ Type *FTy = CS.getCalledValue()->getType()->getPointerElementType();
+ return static_cast<T *>(this)
+ ->getCallCost(cast<FunctionType>(FTy), CS.arg_size());
+ }
+
+ SmallVector<const Value *, 8> Arguments(CS.arg_begin(), CS.arg_end());
+ return static_cast<T *>(this)->getCallCost(F, Arguments);
+ }
+
+ if (const CastInst *CI = dyn_cast<CastInst>(U)) {
+ // Result of a cmp instruction is often extended (to be used by other
+ // cmp instructions, logical or return instructions). These are usually
+ // nop on most sane targets.
+ if (isa<CmpInst>(CI->getOperand(0)))
+ return TTI::TCC_Free;
+ }
+
+ return static_cast<T *>(this)->getOperationCost(
+ Operator::getOpcode(U), U->getType(),
+ U->getNumOperands() == 1 ? U->getOperand(0)->getType() : nullptr);
+ }
+};
+}
+
+#endif
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index cc588381727d..653821d02271 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -16,6 +16,7 @@
#define LLVM_ANALYSIS_VALUETRACKING_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/Instruction.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@@ -28,17 +29,18 @@ namespace llvm {
class AssumptionCache;
class DominatorTree;
class TargetLibraryInfo;
+ class LoopInfo;
/// Determine which bits of V are known to be either zero or one and return
/// them in the KnownZero/KnownOne bit sets.
///
/// This function is defined on values with integer type, values with pointer
- /// type (but only if TD is non-null), and vectors of integers. In the case
+ /// type, and vectors of integers. In the case
/// 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,
+ const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@@ -46,11 +48,16 @@ namespace llvm {
/// \p KnownZero the set of bits that are known to be zero
void computeKnownBitsFromRangeMetadata(const MDNode &Ranges,
APInt &KnownZero);
+ /// Returns true if LHS and RHS have no common bits set.
+ bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr,
+ const DominatorTree *DT = nullptr);
/// 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 &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@@ -60,7 +67,8 @@ namespace llvm {
/// 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, const DataLayout &DL,
+ bool OrZero = false, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@@ -69,8 +77,8 @@ namespace llvm {
/// 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, AssumptionCache *AC = nullptr,
+ bool isKnownNonZero(Value *V, const DataLayout &DL, unsigned Depth = 0,
+ AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@@ -79,13 +87,12 @@ namespace llvm {
/// zero for bits that V cannot have.
///
/// This function is defined on values with integer type, values with pointer
- /// type (but only if TD is non-null), and vectors of integers. In the case
+ /// type, and vectors of integers. In the case
/// 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,
- AssumptionCache *AC = nullptr,
+ bool MaskedValueIsZero(Value *V, const APInt &Mask, const DataLayout &DL,
+ unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@@ -97,7 +104,7 @@ namespace llvm {
///
/// 'Op' must have a scalar integer type.
///
- unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr,
+ unsigned ComputeNumSignBits(Value *Op, const DataLayout &DL,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@@ -116,6 +123,11 @@ namespace llvm {
///
bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0);
+ /// CannotBeOrderedLessThanZero - Return true if we can prove that the
+ /// specified FP value is either a NaN or never less than 0.0.
+ ///
+ bool CannotBeOrderedLessThanZero(const Value *V, unsigned Depth = 0);
+
/// isBytewiseValue - If the specified value can be set by repeating the same
/// byte in memory, return the i8 value that it is represented with. This is
/// true for all i8 values obviously, but is also true for i32 0, i32 -1,
@@ -137,11 +149,12 @@ namespace llvm {
/// it can be expressed as a base pointer plus a constant offset. Return the
/// base and offset to the caller.
Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
- const DataLayout *TD);
+ const DataLayout &DL);
static inline const Value *
GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset,
- const DataLayout *TD) {
- return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD);
+ const DataLayout &DL) {
+ return GetPointerBaseWithConstantOffset(const_cast<Value *>(Ptr), Offset,
+ DL);
}
/// getConstantStringInfo - This function computes the length of a
@@ -162,26 +175,59 @@ namespace llvm {
/// being addressed. Note that the returned value has pointer type if the
/// specified value does. If the MaxLookup value is non-zero, it limits the
/// number of instructions to be stripped off.
- Value *GetUnderlyingObject(Value *V, const DataLayout *TD = nullptr,
+ Value *GetUnderlyingObject(Value *V, const DataLayout &DL,
unsigned MaxLookup = 6);
- static inline const Value *
- GetUnderlyingObject(const Value *V, const DataLayout *TD = nullptr,
- unsigned MaxLookup = 6) {
- return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup);
+ static inline const Value *GetUnderlyingObject(const Value *V,
+ const DataLayout &DL,
+ unsigned MaxLookup = 6) {
+ return GetUnderlyingObject(const_cast<Value *>(V), DL, MaxLookup);
}
- /// GetUnderlyingObjects - This method is similar to GetUnderlyingObject
- /// except that it can look through phi and select instructions and return
- /// multiple objects.
- void GetUnderlyingObjects(Value *V,
- SmallVectorImpl<Value *> &Objects,
- const DataLayout *TD = nullptr,
+ /// \brief This method is similar to GetUnderlyingObject except that it can
+ /// look through phi and select instructions and return multiple objects.
+ ///
+ /// If LoopInfo is passed, loop phis are further analyzed. If a pointer
+ /// accesses different objects in each iteration, we don't look through the
+ /// phi node. E.g. consider this loop nest:
+ ///
+ /// int **A;
+ /// for (i)
+ /// for (j) {
+ /// A[i][j] = A[i-1][j] * B[j]
+ /// }
+ ///
+ /// This is transformed by Load-PRE to stash away A[i] for the next iteration
+ /// of the outer loop:
+ ///
+ /// Curr = A[0]; // Prev_0
+ /// for (i: 1..N) {
+ /// Prev = Curr; // Prev = PHI (Prev_0, Curr)
+ /// Curr = A[i];
+ /// for (j: 0..N) {
+ /// Curr[j] = Prev[j] * B[j]
+ /// }
+ /// }
+ ///
+ /// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects
+ /// should not assume that Curr and Prev share the same underlying object thus
+ /// it shouldn't look through the phi above.
+ void GetUnderlyingObjects(Value *V, SmallVectorImpl<Value *> &Objects,
+ const DataLayout &DL, LoopInfo *LI = nullptr,
unsigned MaxLookup = 6);
/// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer
/// are lifetime markers.
bool onlyUsedByLifetimeMarkers(const Value *V);
+ /// isDereferenceablePointer - Return true if this is always a dereferenceable
+ /// pointer. If the context instruction is specified perform context-sensitive
+ /// analysis and return true if the pointer is dereferenceable at the
+ /// specified instruction.
+ bool isDereferenceablePointer(const Value *V, const DataLayout &DL,
+ const Instruction *CtxI = nullptr,
+ const DominatorTree *DT = nullptr,
+ const TargetLibraryInfo *TLI = nullptr);
+
/// isSafeToSpeculativelyExecute - Return true if the instruction does not
/// have any effects besides calculating the result and does not have
/// undefined behavior.
@@ -195,37 +241,82 @@ namespace llvm {
/// memory leak. It also returns false for instructions related to control
/// flow, specifically terminators and PHI nodes.
///
- /// This method only looks at the instruction itself and its operands, so if
- /// this method returns true, it is safe to move the instruction as long as
- /// the correct dominance relationships for the operands and users hold.
- /// However, this method can return true for instructions that read memory;
+ /// If the CtxI is specified this method performs context-sensitive analysis
+ /// and returns true if it is safe to execute the instruction immediately
+ /// before the CtxI.
+ ///
+ /// If the CtxI is NOT specified this method only looks at the instruction
+ /// itself and its operands, so if this method returns true, it is safe to
+ /// move the instruction as long as the correct dominance relationships for
+ /// the operands and users hold.
+ ///
+ /// This method can return true for instructions that read memory;
/// for such instructions, moving them may change the resulting value.
bool isSafeToSpeculativelyExecute(const Value *V,
- const DataLayout *TD = nullptr);
+ const Instruction *CtxI = nullptr,
+ const DominatorTree *DT = nullptr,
+ const TargetLibraryInfo *TLI = nullptr);
/// isKnownNonNull - Return true if this pointer couldn't possibly be null by
/// its definition. This returns true for allocas, non-extern-weak globals
/// and byval arguments.
bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr);
+ /// isKnownNonNullAt - Return true if this pointer couldn't possibly be null.
+ /// If the context instruction is specified perform context-sensitive analysis
+ /// and return true if the pointer couldn't possibly be null at the specified
+ /// instruction.
+ bool isKnownNonNullAt(const Value *V,
+ const Instruction *CtxI = nullptr,
+ const DominatorTree *DT = nullptr,
+ 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,
+ const DataLayout &DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS,
- const DataLayout *DL,
+ const DataLayout &DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
+
+ /// \brief Specific patterns of select instructions we can match.
+ enum SelectPatternFlavor {
+ SPF_UNKNOWN = 0,
+ SPF_SMIN, // Signed minimum
+ SPF_UMIN, // Unsigned minimum
+ SPF_SMAX, // Signed maximum
+ SPF_UMAX, // Unsigned maximum
+ SPF_ABS, // Absolute value
+ SPF_NABS // Negated absolute value
+ };
+ /// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind
+ /// and providing the out parameter results if we successfully match.
+ ///
+ /// If CastOp is not nullptr, also match MIN/MAX idioms where the type does
+ /// not match that of the original select. If this is the case, the cast
+ /// operation (one of Trunc,SExt,Zext) that must be done to transform the
+ /// type of LHS and RHS into the type of V is returned in CastOp.
+ ///
+ /// For example:
+ /// %1 = icmp slt i32 %a, i32 4
+ /// %2 = sext i32 %a to i64
+ /// %3 = select i1 %1, i64 %2, i64 4
+ ///
+ /// -> LHS = %a, RHS = i32 4, *CastOp = Instruction::SExt
+ ///
+ SelectPatternFlavor matchSelectPattern(Value *V, Value *&LHS, Value *&RHS,
+ Instruction::CastOps *CastOp = nullptr);
+
} // end namespace llvm
#endif
diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h
index ed2dcf84f924..96c420151858 100644
--- a/include/llvm/Bitcode/BitCodes.h
+++ b/include/llvm/Bitcode/BitCodes.h
@@ -125,7 +125,7 @@ public:
case Blob:
return false;
}
- llvm_unreachable("Invalid encoding");
+ report_fatal_error("Invalid encoding");
}
/// isChar6 - Return true if this character is legal in the Char6 encoding.
@@ -164,8 +164,8 @@ template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; };
/// specialized format instead of the fully-general, fully-vbr, format.
class BitCodeAbbrev : public RefCountedBase<BitCodeAbbrev> {
SmallVector<BitCodeAbbrevOp, 32> OperandList;
- ~BitCodeAbbrev() {}
// Only RefCountedBase is allowed to delete.
+ ~BitCodeAbbrev() = default;
friend class RefCountedBase<BitCodeAbbrev>;
public:
diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h
index 8fe9b7e8434d..ae915c688ba0 100644
--- a/include/llvm/Bitcode/BitcodeWriterPass.h
+++ b/include/llvm/Bitcode/BitcodeWriterPass.h
@@ -26,7 +26,11 @@ class PreservedAnalyses;
/// \brief Create and return a pass that writes the module to the specified
/// ostream. Note that this pass is designed for use with the legacy pass
/// manager.
-ModulePass *createBitcodeWriterPass(raw_ostream &Str);
+///
+/// If \c ShouldPreserveUseListOrder, encode use-list order so it can be
+/// reproduced when deserialized.
+ModulePass *createBitcodeWriterPass(raw_ostream &Str,
+ bool ShouldPreserveUseListOrder = false);
/// \brief Pass for writing a module of IR out to a bitcode file.
///
@@ -34,10 +38,16 @@ ModulePass *createBitcodeWriterPass(raw_ostream &Str);
/// a pass for the legacy pass manager, use the function above.
class BitcodeWriterPass {
raw_ostream &OS;
+ bool ShouldPreserveUseListOrder;
public:
/// \brief Construct a bitcode writer pass around a particular output stream.
- explicit BitcodeWriterPass(raw_ostream &OS) : OS(OS) {}
+ ///
+ /// If \c ShouldPreserveUseListOrder, encode use-list order so it can be
+ /// reproduced when deserialized.
+ explicit BitcodeWriterPass(raw_ostream &OS,
+ bool ShouldPreserveUseListOrder = false)
+ : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}
/// \brief Run the bitcode writer pass, and output the module to the selected
/// output stream.
diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h
index 865a3e668428..46e64d112ea7 100644
--- a/include/llvm/Bitcode/BitstreamReader.h
+++ b/include/llvm/Bitcode/BitstreamReader.h
@@ -24,8 +24,6 @@
namespace llvm {
-class Deserializer;
-
/// 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
@@ -50,8 +48,8 @@ private:
/// information in the BlockInfo block. Only llvm-bcanalyzer uses this.
bool IgnoreBlockInfoNames;
- BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION;
- void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION;
+ BitstreamReader(const BitstreamReader&) = delete;
+ void operator=(const BitstreamReader&) = delete;
public:
BitstreamReader() : IgnoreBlockInfoNames(true) {
}
@@ -164,7 +162,6 @@ struct BitstreamEntry {
/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
/// be passed by value.
class BitstreamCursor {
- friend class Deserializer;
BitstreamReader *BitStream;
size_t NextChar;
@@ -201,6 +198,8 @@ class BitstreamCursor {
public:
+ static const size_t MaxChunkSize = sizeof(word_t) * 8;
+
BitstreamCursor() { init(nullptr); }
explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
@@ -258,8 +257,8 @@ public:
AF_DontAutoprocessAbbrevs = 2
};
- /// Advance the current bitstream, returning the next entry in the stream.
- BitstreamEntry advance(unsigned Flags = 0) {
+ /// Advance the current bitstream, returning the next entry in the stream.
+ BitstreamEntry advance(unsigned Flags = 0) {
while (1) {
unsigned Code = ReadCode();
if (Code == bitc::END_BLOCK) {
@@ -301,7 +300,7 @@ public:
/// Reset the stream to the specified bit number.
void JumpToBit(uint64_t BitNo) {
- uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1);
+ size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1);
unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
assert(canSkipToPos(ByteNo) && "Invalid location");
@@ -315,7 +314,8 @@ public:
}
void fillCurWord() {
- assert(Size == 0 || NextChar < (unsigned)Size);
+ if (Size != 0 && NextChar >= Size)
+ report_fatal_error("Unexpected end of file");
// Read the next word from the stream.
uint8_t Array[sizeof(word_t)] = {0};
@@ -337,7 +337,7 @@ public:
}
word_t Read(unsigned NumBits) {
- static const unsigned BitsInWord = sizeof(word_t) * 8;
+ static const unsigned BitsInWord = MaxChunkSize;
assert(NumBits && NumBits <= BitsInWord &&
"Cannot return zero or more than BitsInWord bits!");
@@ -490,11 +490,11 @@ private:
//===--------------------------------------------------------------------===//
public:
-
/// Return the abbreviation for the specified AbbrevId.
const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) {
- unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV;
- assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
+ unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV;
+ if (AbbrevNo >= CurAbbrevs.size())
+ report_fatal_error("Invalid abbrev number");
return CurAbbrevs[AbbrevNo].get();
}
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index 043ecd3d65d7..3a6b5c704d19 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -146,7 +146,27 @@ namespace bitc {
METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)]
METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)]
METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
- METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]]
+ METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]]
+ METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num]
+ METADATA_SUBRANGE = 13, // [distinct, count, lo]
+ METADATA_ENUMERATOR = 14, // [distinct, value, name]
+ METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc]
+ METADATA_FILE = 16, // [distinct, filename, directory]
+ METADATA_DERIVED_TYPE = 17, // [distinct, ...]
+ METADATA_COMPOSITE_TYPE= 18, // [distinct, ...]
+ METADATA_SUBROUTINE_TYPE=19, // [distinct, flags, types]
+ METADATA_COMPILE_UNIT = 20, // [distinct, ...]
+ METADATA_SUBPROGRAM = 21, // [distinct, ...]
+ METADATA_LEXICAL_BLOCK = 22, // [distinct, scope, file, line, column]
+ METADATA_LEXICAL_BLOCK_FILE=23,//[distinct, scope, file, discriminator]
+ METADATA_NAMESPACE = 24, // [distinct, scope, file, name, line]
+ METADATA_TEMPLATE_TYPE = 25, // [distinct, scope, name, type, ...]
+ METADATA_TEMPLATE_VALUE= 26, // [distinct, scope, name, type, value, ...]
+ METADATA_GLOBAL_VAR = 27, // [distinct, ...]
+ METADATA_LOCAL_VAR = 28, // [distinct, ...]
+ METADATA_EXPRESSION = 29, // [distinct, n x element]
+ METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...]
+ METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name]
};
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
@@ -273,7 +293,7 @@ namespace bitc {
FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval]
FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval]
- FUNC_CODE_INST_GEP = 4, // GEP: [n x operands]
+ FUNC_CODE_INST_GEP_OLD = 4, // GEP: [n x operands]
FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval]
FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval]
FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval]
@@ -298,7 +318,7 @@ namespace bitc {
// This store code encodes the pointer type, rather than the value type
// this is so information only available in the pointer type (e.g. address
// spaces) is retained.
- FUNC_CODE_INST_STORE = 24, // STORE: [ptrty,ptr,val, align, vol]
+ FUNC_CODE_INST_STORE_OLD = 24, // STORE: [ptrty,ptr,val, align, vol]
// 25 is unused.
FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands]
FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands]
@@ -307,7 +327,7 @@ namespace bitc {
FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
// new select on i1 or [N x i1]
FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred]
- FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands]
+ FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, // INBOUNDS_GEP: [n x operands]
FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...]
// 32 is unused.
FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN
@@ -316,7 +336,7 @@ namespace bitc {
FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal]
FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope]
- FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol,
+ FUNC_CODE_INST_CMPXCHG_OLD = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol,
// ordering, synchscope]
FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
// align, vol,
@@ -325,8 +345,13 @@ namespace bitc {
FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
// ordering, synchscope]
- FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol
+ FUNC_CODE_INST_STOREATOMIC_OLD = 42, // STORE: [ptrty,ptr,val, align, vol
// ordering, synchscope]
+ FUNC_CODE_INST_GEP = 43, // GEP: [inbounds, n x operands]
+ FUNC_CODE_INST_STORE = 44, // STORE: [ptrty,ptr,valty,val, align, vol]
+ FUNC_CODE_INST_STOREATOMIC = 45, // STORE: [ptrty,ptr,val, align, vol
+ FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align,
+ // vol,ordering,synchscope]
};
enum UseListCodes {
@@ -376,7 +401,9 @@ namespace bitc {
ATTR_KIND_IN_ALLOCA = 38,
ATTR_KIND_NON_NULL = 39,
ATTR_KIND_JUMP_TABLE = 40,
- ATTR_KIND_DEREFERENCEABLE = 41
+ ATTR_KIND_DEREFERENCEABLE = 41,
+ ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42,
+ ATTR_KIND_CONVERGENT = 43
};
enum ComdatSelectionKindCodes {
diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h
index 48bdabc88391..9d30098fddee 100644
--- a/include/llvm/Bitcode/ReaderWriter.h
+++ b/include/llvm/Bitcode/ReaderWriter.h
@@ -29,12 +29,14 @@ namespace llvm {
class raw_ostream;
/// Read the header of the specified bitcode buffer and prepare for lazy
- /// deserialization of function bodies. If successful, this moves Buffer. On
+ /// deserialization of function bodies. If ShouldLazyLoadMetadata is true,
+ /// lazily load metadata as well. 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);
+ DiagnosticHandlerFunction DiagnosticHandler = nullptr,
+ bool ShouldLazyLoadMetadata = false);
/// Read the header of the specified stream and prepare for lazy
/// deserialization and streaming of function bodies.
@@ -54,11 +56,16 @@ namespace llvm {
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
- /// should be in "binary" mode.
- void WriteBitcodeToFile(const Module *M, raw_ostream &Out);
-
+ /// \brief Write the specified module to the specified raw output stream.
+ ///
+ /// For streams where it matters, the given stream should be in "binary"
+ /// mode.
+ ///
+ /// If \c ShouldPreserveUseListOrder, encode the use-list order for each \a
+ /// Value in \c M. These will be reconstructed exactly when \a M is
+ /// deserialized.
+ void WriteBitcodeToFile(const Module *M, raw_ostream &Out,
+ bool ShouldPreserveUseListOrder = false);
/// isBitcodeWrapper - Return true if the given bytes are the magic bytes
/// for an LLVM IR bitcode wrapper.
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index e3ce57ad1850..47201e2564e3 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -16,8 +16,10 @@
#ifndef LLVM_CODEGEN_ASMPRINTER_H
#define LLVM_CODEGEN_ASMPRINTER_H
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/DwarfStringPoolEntry.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
@@ -29,6 +31,8 @@ class ByteStreamer;
class GCStrategy;
class Constant;
class ConstantArray;
+class DIE;
+class DIEAbbrev;
class GCMetadataPrinter;
class GlobalValue;
class GlobalVariable;
@@ -46,11 +50,11 @@ class MCCFIInstruction;
class MCContext;
class MCExpr;
class MCInst;
-class MCInstrInfo;
class MCSection;
class MCStreamer;
class MCSubtargetInfo;
class MCSymbol;
+class MCTargetOptions;
class MDNode;
class DwarfDebug;
class Mangler;
@@ -69,7 +73,6 @@ public:
///
const MCAsmInfo *MAI;
- const MCInstrInfo *MII;
/// This is the context for the output file that we are streaming. This owns
/// all of the global MC-related objects for the generated translation unit.
MCContext &OutContext;
@@ -77,7 +80,7 @@ public:
/// This is the MCStreamer object for the file we are generating. This
/// contains the transient state for the current translation unit that we are
/// generating (such as the current section etc).
- MCStreamer &OutStreamer;
+ std::unique_ptr<MCStreamer> OutStreamer;
/// The current machine function.
const MachineFunction *MF;
@@ -99,7 +102,16 @@ public:
/// default, this is equal to CurrentFnSym.
MCSymbol *CurrentFnSymForSize;
+ /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of
+ /// its number of uses by other globals.
+ typedef std::pair<const GlobalVariable *, unsigned> GOTEquivUsePair;
+ MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs;
+
private:
+ MCSymbol *CurrentFnBegin;
+ MCSymbol *CurrentFnEnd;
+ MCSymbol *CurExceptionSym;
+
// The garbage collection metadata printer table.
void *GCMetadataPrinters; // Really a DenseMap.
@@ -127,10 +139,10 @@ private:
DwarfDebug *DD;
protected:
- explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer);
+ explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
public:
- virtual ~AsmPrinter();
+ ~AsmPrinter() override;
DwarfDebug *getDwarfDebug() { return DD; }
DwarfDebug *getDwarfDebug() const { return DD; }
@@ -143,6 +155,10 @@ public:
///
unsigned getFunctionNumber() const;
+ MCSymbol *getFunctionBegin() const { return CurrentFnBegin; }
+ MCSymbol *getFunctionEnd() const { return CurrentFnEnd; }
+ MCSymbol *getCurExceptionSym();
+
/// Return information about object file lowering.
const TargetLoweringObjectFile &getObjFileLowering() const;
@@ -184,7 +200,6 @@ public:
/// Emit the specified function out to the OutStreamer.
bool runOnMachineFunction(MachineFunction &MF) override {
SetupMachineFunction(MF);
- EmitFunctionHeader();
EmitFunctionBody();
return false;
}
@@ -197,9 +212,6 @@ public:
/// runOnMachineFunction.
void SetupMachineFunction(MachineFunction &MF);
- /// This method emits the header for the current function.
- void EmitFunctionHeader();
-
/// This method emits the body and trailer for a function.
void EmitFunctionBody();
@@ -238,16 +250,27 @@ public:
///
void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const;
- /// This method prints the label for the specified MachineBasicBlock, an
- /// alignment (if present) and a comment describing it if appropriate.
- void EmitBasicBlockStart(const MachineBasicBlock &MBB) const;
-
/// Lower the specified LLVM Constant to an MCExpr.
const MCExpr *lowerConstant(const Constant *CV);
/// \brief Print a general LLVM constant to the .s file.
void EmitGlobalConstant(const Constant *CV);
+ /// \brief Unnamed constant global variables solely contaning a pointer to
+ /// another globals variable act like a global variable "proxy", or GOT
+ /// equivalents, i.e., it's only used to hold the address of the latter. One
+ /// optimization is to replace accesses to these proxies by using the GOT
+ /// entry for the final global instead. Hence, we select GOT equivalent
+ /// candidates among all the module global variables, avoid emitting them
+ /// unnecessarily and finally replace references to them by pc relative
+ /// accesses to GOT entries.
+ void computeGlobalGOTEquivs(Module &M);
+
+ /// \brief Constant expressions using GOT equivalent globals may not be
+ /// eligible for PC relative GOT entry conversion, in such cases we need to
+ /// emit the proxies we previously omitted in EmitGlobalVariable.
+ void emitGlobalGOTEquivs();
+
//===------------------------------------------------------------------===//
// Overridable Hooks
//===------------------------------------------------------------------===//
@@ -271,6 +294,12 @@ public:
/// function.
virtual void EmitFunctionBodyEnd() {}
+ /// Targets can override this to emit stuff at the start of a basic block.
+ /// By default, this method prints the label for the specified
+ /// MachineBasicBlock, an alignment (if present) and a comment describing it
+ /// if appropriate.
+ virtual void EmitBasicBlockStart(const MachineBasicBlock &MBB) const;
+
/// Targets can override this to emit stuff at the end of a basic block.
virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {}
@@ -304,12 +333,7 @@ public:
// Symbol Lowering Routines.
//===------------------------------------------------------------------===//
public:
- /// Return the MCSymbol corresponding to the assembler temporary label with
- /// the specified stem and unique ID.
- MCSymbol *GetTempSymbol(Twine Name, unsigned ID) const;
-
- /// Return an assembler temporary label with the specified stem.
- MCSymbol *GetTempSymbol(Twine Name) const;
+ MCSymbol *createTempSymbol(const Twine &Name) const;
/// Return the MCSymbol for a private symbol with global value name as its
/// base, with the specified suffix.
@@ -397,42 +421,21 @@ public:
/// Emit the 4-byte offset of Label from the start of its section. This can
/// be done with a special directive if the target supports it (e.g. cygwin)
/// or by emitting it as an offset from a label at the start of the section.
+ void emitSectionOffset(const MCSymbol *Label) const;
+
+ /// Emit the 4-byte offset of a string from the start of its section.
///
- /// SectionLabel is a temporary label emitted at the start of the section
- /// that Label lives in.
- void EmitSectionOffset(const MCSymbol *Label,
- const MCSymbol *SectionLabel) const;
+ /// When possible, emit a DwarfStringPool section offset without any
+ /// relocations, and without using the symbol. Otherwise, defers to \a
+ /// emitSectionOffset().
+ void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const;
/// 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
- /// \param PieceOffset offset of the piece in bits, if this is one
- /// piece of an aggregate value.
- ///
- /// If size and offset is zero an operation for the entire
- /// register is emitted: Some targets do not provide a DWARF
- /// register number for every register. If this is the case, this
- /// function will attempt to emit a DWARF register by emitting a
- /// piece of a super-register or by piecing together multiple
- /// subregisters that alias the register.
- void EmitDwarfRegOpPiece(ByteStreamer &BS, const MachineLocation &MLoc,
- unsigned PieceSize = 0,
- unsigned PieceOffset = 0) const;
-
/// EmitDwarfRegOp - Emit a dwarf register operation.
- /// \param Indirect whether this is a register-indirect address
- virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc,
- bool Indirect) const;
+ virtual void EmitDwarfRegOp(ByteStreamer &BS,
+ const MachineLocation &MLoc) const;
//===------------------------------------------------------------------===//
// Dwarf Lowering Routines
@@ -441,6 +444,12 @@ public:
/// \brief Emit frame instruction to describe the layout of the frame.
void emitCFIInstruction(const MCCFIInstruction &Inst) const;
+ /// \brief Emit Dwarf abbreviation table.
+ void emitDwarfAbbrevs(const std::vector<DIEAbbrev *>& Abbrevs) const;
+
+ /// \brief Recursively emit Dwarf DIE tree.
+ void emitDwarfDIE(const DIE &Die) const;
+
//===------------------------------------------------------------------===//
// Inline Asm Support
//===------------------------------------------------------------------===//
@@ -474,7 +483,7 @@ public:
/// 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;
+ virtual void emitInlineAsmStart() const;
/// Let the target do anything it needs to do after emitting inlineasm.
/// This callback can be used restore the original mode in case the
@@ -491,11 +500,15 @@ private:
mutable const MachineInstr *LastMI;
mutable unsigned LastFn;
mutable unsigned Counter;
- mutable unsigned SetCounter;
+
+ /// This method emits the header for the current function.
+ virtual void EmitFunctionHeader();
/// Emit a blob of inline asm to the output streamer.
void
- EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = nullptr,
+ EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
+ const MCTargetOptions &MCOptions,
+ const MDNode *LocMDNode = nullptr,
InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const;
/// This method formats and emits the specified machine instruction that is an
diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h
new file mode 100644
index 000000000000..d07265560430
--- /dev/null
+++ b/include/llvm/CodeGen/BasicTTIImpl.h
@@ -0,0 +1,767 @@
+//===- BasicTTIImpl.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides a helper that implements much of the TTI interface in
+/// terms of the target-independent code generator and TargetLowering
+/// interfaces.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_BASICTTIIMPL_H
+#define LLVM_CODEGEN_BASICTTIIMPL_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/TargetTransformInfoImpl.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+
+namespace llvm {
+
+extern cl::opt<unsigned> PartialUnrollingThreshold;
+
+/// \brief Base class which can be used to help build a TTI implementation.
+///
+/// This class provides as much implementation of the TTI interface as is
+/// possible using the target independent parts of the code generator.
+///
+/// In order to subclass it, your class must implement a getST() method to
+/// return the subtarget, and a getTLI() method to return the target lowering.
+/// We need these methods implemented in the derived class so that this class
+/// doesn't have to duplicate storage for them.
+template <typename T>
+class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
+private:
+ typedef TargetTransformInfoImplCRTPBase<T> BaseT;
+ typedef TargetTransformInfo TTI;
+
+ /// Estimate the overhead of scalarizing an instruction. Insert and Extract
+ /// are set if the result needs to be inserted and/or extracted from vectors.
+ unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) {
+ assert(Ty->isVectorTy() && "Can only scalarize vectors");
+ unsigned Cost = 0;
+
+ for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) {
+ if (Insert)
+ Cost += static_cast<T *>(this)
+ ->getVectorInstrCost(Instruction::InsertElement, Ty, i);
+ if (Extract)
+ Cost += static_cast<T *>(this)
+ ->getVectorInstrCost(Instruction::ExtractElement, Ty, i);
+ }
+
+ return Cost;
+ }
+
+ /// Estimate the cost overhead of SK_Alternate shuffle.
+ unsigned getAltShuffleOverhead(Type *Ty) {
+ assert(Ty->isVectorTy() && "Can only shuffle vectors");
+ unsigned Cost = 0;
+ // Shuffle cost is equal to the cost of extracting element from its argument
+ // plus the cost of inserting them onto the result vector.
+
+ // e.g. <4 x float> has a mask of <0,5,2,7> i.e we need to extract from
+ // index 0 of first vector, index 1 of second vector,index 2 of first
+ // vector and finally index 3 of second vector and insert them at index
+ // <0,1,2,3> of result vector.
+ for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) {
+ Cost += static_cast<T *>(this)
+ ->getVectorInstrCost(Instruction::InsertElement, Ty, i);
+ Cost += static_cast<T *>(this)
+ ->getVectorInstrCost(Instruction::ExtractElement, Ty, i);
+ }
+ return Cost;
+ }
+
+ /// \brief Local query method delegates up to T which *must* implement this!
+ const TargetSubtargetInfo *getST() const {
+ return static_cast<const T *>(this)->getST();
+ }
+
+ /// \brief Local query method delegates up to T which *must* implement this!
+ const TargetLoweringBase *getTLI() const {
+ return static_cast<const T *>(this)->getTLI();
+ }
+
+protected:
+ explicit BasicTTIImplBase(const TargetMachine *TM)
+ : BaseT(TM->getDataLayout()) {}
+
+public:
+ // Provide value semantics. MSVC requires that we spell all of these out.
+ BasicTTIImplBase(const BasicTTIImplBase &Arg)
+ : BaseT(static_cast<const BaseT &>(Arg)) {}
+ BasicTTIImplBase(BasicTTIImplBase &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
+ BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) {
+ BaseT::operator=(static_cast<const BaseT &>(RHS));
+ return *this;
+ }
+ BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
+ return *this;
+ }
+
+ /// \name Scalar TTI Implementations
+ /// @{
+
+ bool hasBranchDivergence() { return false; }
+
+ bool isSourceOfDivergence(const Value *V) { return false; }
+
+ bool isLegalAddImmediate(int64_t imm) {
+ return getTLI()->isLegalAddImmediate(imm);
+ }
+
+ bool isLegalICmpImmediate(int64_t imm) {
+ return getTLI()->isLegalICmpImmediate(imm);
+ }
+
+ bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale) {
+ TargetLoweringBase::AddrMode AM;
+ AM.BaseGV = BaseGV;
+ AM.BaseOffs = BaseOffset;
+ AM.HasBaseReg = HasBaseReg;
+ AM.Scale = Scale;
+ return getTLI()->isLegalAddressingMode(AM, Ty);
+ }
+
+ int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale) {
+ TargetLoweringBase::AddrMode AM;
+ AM.BaseGV = BaseGV;
+ AM.BaseOffs = BaseOffset;
+ AM.HasBaseReg = HasBaseReg;
+ AM.Scale = Scale;
+ return getTLI()->getScalingFactorCost(AM, Ty);
+ }
+
+ bool isTruncateFree(Type *Ty1, Type *Ty2) {
+ return getTLI()->isTruncateFree(Ty1, Ty2);
+ }
+
+ bool isProfitableToHoist(Instruction *I) {
+ return getTLI()->isProfitableToHoist(I);
+ }
+
+ bool isTypeLegal(Type *Ty) {
+ EVT VT = getTLI()->getValueType(Ty);
+ return getTLI()->isTypeLegal(VT);
+ }
+
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> Arguments) {
+ return BaseT::getIntrinsicCost(IID, RetTy, Arguments);
+ }
+
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> ParamTys) {
+ if (IID == Intrinsic::cttz) {
+ if (getTLI()->isCheapToSpeculateCttz())
+ return TargetTransformInfo::TCC_Basic;
+ return TargetTransformInfo::TCC_Expensive;
+ }
+
+ if (IID == Intrinsic::ctlz) {
+ if (getTLI()->isCheapToSpeculateCtlz())
+ return TargetTransformInfo::TCC_Basic;
+ return TargetTransformInfo::TCC_Expensive;
+ }
+
+ return BaseT::getIntrinsicCost(IID, RetTy, ParamTys);
+ }
+
+ unsigned getJumpBufAlignment() { return getTLI()->getJumpBufAlignment(); }
+
+ unsigned getJumpBufSize() { return getTLI()->getJumpBufSize(); }
+
+ bool shouldBuildLookupTables() {
+ const TargetLoweringBase *TLI = getTLI();
+ return TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) ||
+ TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other);
+ }
+
+ bool haveFastSqrt(Type *Ty) {
+ const TargetLoweringBase *TLI = getTLI();
+ EVT VT = TLI->getValueType(Ty);
+ return TLI->isTypeLegal(VT) &&
+ TLI->isOperationLegalOrCustom(ISD::FSQRT, VT);
+ }
+
+ unsigned getFPOpCost(Type *Ty) {
+ // By default, FP instructions are no more expensive since they are
+ // implemented in HW. Target specific TTI can override this.
+ return TargetTransformInfo::TCC_Basic;
+ }
+
+ unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) {
+ const TargetLoweringBase *TLI = getTLI();
+ switch (Opcode) {
+ default: break;
+ case Instruction::Trunc: {
+ if (TLI->isTruncateFree(OpTy, Ty))
+ return TargetTransformInfo::TCC_Free;
+ return TargetTransformInfo::TCC_Basic;
+ }
+ case Instruction::ZExt: {
+ if (TLI->isZExtFree(OpTy, Ty))
+ return TargetTransformInfo::TCC_Free;
+ return TargetTransformInfo::TCC_Basic;
+ }
+ }
+
+ return BaseT::getOperationCost(Opcode, Ty, OpTy);
+ }
+
+ void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) {
+ // This unrolling functionality is target independent, but to provide some
+ // motivation for its intended use, for x86:
+
+ // According to the Intel 64 and IA-32 Architectures Optimization Reference
+ // Manual, Intel Core models and later have a loop stream detector (and
+ // associated uop queue) that can benefit from partial unrolling.
+ // The relevant requirements are:
+ // - The loop must have no more than 4 (8 for Nehalem and later) branches
+ // taken, and none of them may be calls.
+ // - The loop can have no more than 18 (28 for Nehalem and later) uops.
+
+ // According to the Software Optimization Guide for AMD Family 15h
+ // Processors, models 30h-4fh (Steamroller and later) have a loop predictor
+ // and loop buffer which can benefit from partial unrolling.
+ // The relevant requirements are:
+ // - The loop must have fewer than 16 branches
+ // - The loop must have less than 40 uops in all executed loop branches
+
+ // The number of taken branches in a loop is hard to estimate here, and
+ // benchmarking has revealed that it is better not to be conservative when
+ // estimating the branch count. As a result, we'll ignore the branch limits
+ // until someone finds a case where it matters in practice.
+
+ unsigned MaxOps;
+ const TargetSubtargetInfo *ST = getST();
+ if (PartialUnrollingThreshold.getNumOccurrences() > 0)
+ MaxOps = PartialUnrollingThreshold;
+ else if (ST->getSchedModel().LoopMicroOpBufferSize > 0)
+ MaxOps = ST->getSchedModel().LoopMicroOpBufferSize;
+ else
+ return;
+
+ // Scan the loop: don't unroll loops with calls.
+ for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); I != E;
+ ++I) {
+ BasicBlock *BB = *I;
+
+ for (BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE; ++J)
+ if (isa<CallInst>(J) || isa<InvokeInst>(J)) {
+ ImmutableCallSite CS(J);
+ if (const Function *F = CS.getCalledFunction()) {
+ if (!static_cast<T *>(this)->isLoweredToCall(F))
+ continue;
+ }
+
+ return;
+ }
+ }
+
+ // Enable runtime and partial unrolling up to the specified size.
+ UP.Partial = UP.Runtime = true;
+ UP.PartialThreshold = UP.PartialOptSizeThreshold = MaxOps;
+ }
+
+ /// @}
+
+ /// \name Vector TTI Implementations
+ /// @{
+
+ unsigned getNumberOfRegisters(bool Vector) { return 1; }
+
+ unsigned getRegisterBitWidth(bool Vector) { return 32; }
+
+ unsigned getMaxInterleaveFactor(unsigned VF) { return 1; }
+
+ unsigned getArithmeticInstrCost(
+ unsigned Opcode, Type *Ty,
+ TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue,
+ TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue,
+ TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None,
+ TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None) {
+ // Check if any of the operands are vector operands.
+ const TargetLoweringBase *TLI = getTLI();
+ int ISD = TLI->InstructionOpcodeToISD(Opcode);
+ assert(ISD && "Invalid opcode");
+
+ std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(Ty);
+
+ bool IsFloat = Ty->getScalarType()->isFloatingPointTy();
+ // Assume that floating point arithmetic operations cost twice as much as
+ // integer operations.
+ unsigned OpCost = (IsFloat ? 2 : 1);
+
+ if (TLI->isOperationLegalOrPromote(ISD, LT.second)) {
+ // The operation is legal. Assume it costs 1.
+ // If the type is split to multiple registers, assume that there is some
+ // overhead to this.
+ // TODO: Once we have extract/insert subvector cost we need to use them.
+ if (LT.first > 1)
+ return LT.first * 2 * OpCost;
+ return LT.first * 1 * OpCost;
+ }
+
+ if (!TLI->isOperationExpand(ISD, LT.second)) {
+ // If the operation is custom lowered then assume
+ // thare the code is twice as expensive.
+ return LT.first * 2 * OpCost;
+ }
+
+ // Else, assume that we need to scalarize this op.
+ if (Ty->isVectorTy()) {
+ unsigned Num = Ty->getVectorNumElements();
+ unsigned Cost = static_cast<T *>(this)
+ ->getArithmeticInstrCost(Opcode, Ty->getScalarType());
+ // return the cost of multiple scalar invocation plus the cost of
+ // inserting
+ // and extracting the values.
+ return getScalarizationOverhead(Ty, true, true) + Num * Cost;
+ }
+
+ // We don't know anything about this scalar instruction.
+ return OpCost;
+ }
+
+ unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index,
+ Type *SubTp) {
+ if (Kind == TTI::SK_Alternate) {
+ return getAltShuffleOverhead(Tp);
+ }
+ return 1;
+ }
+
+ unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) {
+ const TargetLoweringBase *TLI = getTLI();
+ int ISD = TLI->InstructionOpcodeToISD(Opcode);
+ assert(ISD && "Invalid opcode");
+
+ std::pair<unsigned, MVT> SrcLT = TLI->getTypeLegalizationCost(Src);
+ std::pair<unsigned, MVT> DstLT = TLI->getTypeLegalizationCost(Dst);
+
+ // Check for NOOP conversions.
+ if (SrcLT.first == DstLT.first &&
+ SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) {
+
+ // Bitcast between types that are legalized to the same type are free.
+ if (Opcode == Instruction::BitCast || Opcode == Instruction::Trunc)
+ return 0;
+ }
+
+ if (Opcode == Instruction::Trunc &&
+ TLI->isTruncateFree(SrcLT.second, DstLT.second))
+ return 0;
+
+ if (Opcode == Instruction::ZExt &&
+ TLI->isZExtFree(SrcLT.second, DstLT.second))
+ return 0;
+
+ // If the cast is marked as legal (or promote) then assume low cost.
+ if (SrcLT.first == DstLT.first &&
+ TLI->isOperationLegalOrPromote(ISD, DstLT.second))
+ return 1;
+
+ // Handle scalar conversions.
+ if (!Src->isVectorTy() && !Dst->isVectorTy()) {
+
+ // Scalar bitcasts are usually free.
+ if (Opcode == Instruction::BitCast)
+ return 0;
+
+ // Just check the op cost. If the operation is legal then assume it costs
+ // 1.
+ if (!TLI->isOperationExpand(ISD, DstLT.second))
+ return 1;
+
+ // Assume that illegal scalar instruction are expensive.
+ return 4;
+ }
+
+ // Check vector-to-vector casts.
+ if (Dst->isVectorTy() && Src->isVectorTy()) {
+
+ // If the cast is between same-sized registers, then the check is simple.
+ if (SrcLT.first == DstLT.first &&
+ SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) {
+
+ // Assume that Zext is done using AND.
+ if (Opcode == Instruction::ZExt)
+ return 1;
+
+ // Assume that sext is done using SHL and SRA.
+ if (Opcode == Instruction::SExt)
+ return 2;
+
+ // Just check the op cost. If the operation is legal then assume it
+ // costs
+ // 1 and multiply by the type-legalization overhead.
+ if (!TLI->isOperationExpand(ISD, DstLT.second))
+ return SrcLT.first * 1;
+ }
+
+ // If we are converting vectors and the operation is illegal, or
+ // if the vectors are legalized to different types, estimate the
+ // scalarization costs.
+ unsigned Num = Dst->getVectorNumElements();
+ unsigned Cost = static_cast<T *>(this)->getCastInstrCost(
+ Opcode, Dst->getScalarType(), Src->getScalarType());
+
+ // Return the cost of multiple scalar invocation plus the cost of
+ // inserting and extracting the values.
+ return getScalarizationOverhead(Dst, true, true) + Num * Cost;
+ }
+
+ // We already handled vector-to-vector and scalar-to-scalar conversions.
+ // This
+ // is where we handle bitcast between vectors and scalars. We need to assume
+ // that the conversion is scalarized in one way or another.
+ if (Opcode == Instruction::BitCast)
+ // Illegal bitcasts are done by storing and loading from a stack slot.
+ return (Src->isVectorTy() ? getScalarizationOverhead(Src, false, true)
+ : 0) +
+ (Dst->isVectorTy() ? getScalarizationOverhead(Dst, true, false)
+ : 0);
+
+ llvm_unreachable("Unhandled cast");
+ }
+
+ unsigned getCFInstrCost(unsigned Opcode) {
+ // Branches are assumed to be predicted.
+ return 0;
+ }
+
+ unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
+ const TargetLoweringBase *TLI = getTLI();
+ int ISD = TLI->InstructionOpcodeToISD(Opcode);
+ assert(ISD && "Invalid opcode");
+
+ // Selects on vectors are actually vector selects.
+ if (ISD == ISD::SELECT) {
+ assert(CondTy && "CondTy must exist");
+ if (CondTy->isVectorTy())
+ ISD = ISD::VSELECT;
+ }
+
+ std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(ValTy);
+
+ if (!(ValTy->isVectorTy() && !LT.second.isVector()) &&
+ !TLI->isOperationExpand(ISD, LT.second)) {
+ // The operation is legal. Assume it costs 1. Multiply
+ // by the type-legalization overhead.
+ return LT.first * 1;
+ }
+
+ // Otherwise, assume that the cast is scalarized.
+ if (ValTy->isVectorTy()) {
+ unsigned Num = ValTy->getVectorNumElements();
+ if (CondTy)
+ CondTy = CondTy->getScalarType();
+ unsigned Cost = static_cast<T *>(this)->getCmpSelInstrCost(
+ Opcode, ValTy->getScalarType(), CondTy);
+
+ // Return the cost of multiple scalar invocation plus the cost of
+ // inserting
+ // and extracting the values.
+ return getScalarizationOverhead(ValTy, true, false) + Num * Cost;
+ }
+
+ // Unknown scalar opcode.
+ return 1;
+ }
+
+ unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) {
+ std::pair<unsigned, MVT> LT =
+ getTLI()->getTypeLegalizationCost(Val->getScalarType());
+
+ return LT.first;
+ }
+
+ unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
+ unsigned AddressSpace) {
+ assert(!Src->isVoidTy() && "Invalid type");
+ std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Src);
+
+ // Assuming that all loads of legal types cost 1.
+ unsigned Cost = LT.first;
+
+ if (Src->isVectorTy() &&
+ Src->getPrimitiveSizeInBits() < LT.second.getSizeInBits()) {
+ // This is a vector load that legalizes to a larger type than the vector
+ // itself. Unless the corresponding extending load or truncating store is
+ // legal, then this will scalarize.
+ TargetLowering::LegalizeAction LA = TargetLowering::Expand;
+ EVT MemVT = getTLI()->getValueType(Src, true);
+ if (MemVT.isSimple() && MemVT != MVT::Other) {
+ if (Opcode == Instruction::Store)
+ LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT());
+ else
+ LA = getTLI()->getLoadExtAction(ISD::EXTLOAD, LT.second, MemVT);
+ }
+
+ if (LA != TargetLowering::Legal && LA != TargetLowering::Custom) {
+ // This is a vector load/store for some illegal type that is scalarized.
+ // We must account for the cost of building or decomposing the vector.
+ Cost += getScalarizationOverhead(Src, Opcode != Instruction::Store,
+ Opcode == Instruction::Store);
+ }
+ }
+
+ return Cost;
+ }
+
+ unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> Tys) {
+ unsigned ISD = 0;
+ switch (IID) {
+ default: {
+ // Assume that we need to scalarize this intrinsic.
+ unsigned ScalarizationCost = 0;
+ unsigned ScalarCalls = 1;
+ Type *ScalarRetTy = RetTy;
+ if (RetTy->isVectorTy()) {
+ ScalarizationCost = getScalarizationOverhead(RetTy, true, false);
+ ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements());
+ ScalarRetTy = RetTy->getScalarType();
+ }
+ SmallVector<Type *, 4> ScalarTys;
+ for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
+ Type *Ty = Tys[i];
+ if (Ty->isVectorTy()) {
+ ScalarizationCost += getScalarizationOverhead(Ty, false, true);
+ ScalarCalls = std::max(ScalarCalls, Ty->getVectorNumElements());
+ Ty = Ty->getScalarType();
+ }
+ ScalarTys.push_back(Ty);
+ }
+ if (ScalarCalls == 1)
+ return 1; // Return cost of a scalar intrinsic. Assume it to be cheap.
+
+ unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost(
+ IID, ScalarRetTy, ScalarTys);
+
+ return ScalarCalls * ScalarCost + ScalarizationCost;
+ }
+ // Look for intrinsics that can be lowered directly or turned into a scalar
+ // intrinsic call.
+ case Intrinsic::sqrt:
+ ISD = ISD::FSQRT;
+ break;
+ case Intrinsic::sin:
+ ISD = ISD::FSIN;
+ break;
+ case Intrinsic::cos:
+ ISD = ISD::FCOS;
+ break;
+ case Intrinsic::exp:
+ ISD = ISD::FEXP;
+ break;
+ case Intrinsic::exp2:
+ ISD = ISD::FEXP2;
+ break;
+ case Intrinsic::log:
+ ISD = ISD::FLOG;
+ break;
+ case Intrinsic::log10:
+ ISD = ISD::FLOG10;
+ break;
+ case Intrinsic::log2:
+ ISD = ISD::FLOG2;
+ break;
+ case Intrinsic::fabs:
+ ISD = ISD::FABS;
+ break;
+ case Intrinsic::minnum:
+ ISD = ISD::FMINNUM;
+ break;
+ case Intrinsic::maxnum:
+ ISD = ISD::FMAXNUM;
+ break;
+ case Intrinsic::copysign:
+ ISD = ISD::FCOPYSIGN;
+ break;
+ case Intrinsic::floor:
+ ISD = ISD::FFLOOR;
+ break;
+ case Intrinsic::ceil:
+ ISD = ISD::FCEIL;
+ break;
+ case Intrinsic::trunc:
+ ISD = ISD::FTRUNC;
+ break;
+ case Intrinsic::nearbyint:
+ ISD = ISD::FNEARBYINT;
+ break;
+ case Intrinsic::rint:
+ ISD = ISD::FRINT;
+ break;
+ case Intrinsic::round:
+ ISD = ISD::FROUND;
+ break;
+ case Intrinsic::pow:
+ ISD = ISD::FPOW;
+ break;
+ case Intrinsic::fma:
+ ISD = ISD::FMA;
+ break;
+ case Intrinsic::fmuladd:
+ ISD = ISD::FMA;
+ break;
+ // FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free.
+ case Intrinsic::lifetime_start:
+ case Intrinsic::lifetime_end:
+ return 0;
+ case Intrinsic::masked_store:
+ return static_cast<T *>(this)
+ ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0);
+ case Intrinsic::masked_load:
+ return static_cast<T *>(this)
+ ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0);
+ }
+
+ const TargetLoweringBase *TLI = getTLI();
+ std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(RetTy);
+
+ if (TLI->isOperationLegalOrPromote(ISD, LT.second)) {
+ // The operation is legal. Assume it costs 1.
+ // If the type is split to multiple registers, assume that there is some
+ // overhead to this.
+ // TODO: Once we have extract/insert subvector cost we need to use them.
+ if (LT.first > 1)
+ return LT.first * 2;
+ return LT.first * 1;
+ }
+
+ if (!TLI->isOperationExpand(ISD, LT.second)) {
+ // If the operation is custom lowered then assume
+ // thare the code is twice as expensive.
+ return LT.first * 2;
+ }
+
+ // If we can't lower fmuladd into an FMA estimate the cost as a floating
+ // point mul followed by an add.
+ if (IID == Intrinsic::fmuladd)
+ return static_cast<T *>(this)
+ ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) +
+ static_cast<T *>(this)
+ ->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy);
+
+ // Else, assume that we need to scalarize this intrinsic. For math builtins
+ // this will emit a costly libcall, adding call overhead and spills. Make it
+ // very expensive.
+ if (RetTy->isVectorTy()) {
+ unsigned ScalarizationCost = getScalarizationOverhead(RetTy, true, false);
+ unsigned ScalarCalls = RetTy->getVectorNumElements();
+ SmallVector<Type *, 4> ScalarTys;
+ for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
+ Type *Ty = Tys[i];
+ if (Ty->isVectorTy())
+ Ty = Ty->getScalarType();
+ ScalarTys.push_back(Ty);
+ }
+ unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost(
+ IID, RetTy->getScalarType(), ScalarTys);
+ for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
+ if (Tys[i]->isVectorTy()) {
+ ScalarizationCost += getScalarizationOverhead(Tys[i], false, true);
+ ScalarCalls = std::max(ScalarCalls, Tys[i]->getVectorNumElements());
+ }
+ }
+
+ return ScalarCalls * ScalarCost + ScalarizationCost;
+ }
+
+ // This is going to be turned into a library call, make it expensive.
+ return 10;
+ }
+
+ /// \brief Compute a cost of the given call instruction.
+ ///
+ /// Compute the cost of calling function F with return type RetTy and
+ /// argument types Tys. F might be nullptr, in this case the cost of an
+ /// arbitrary call with the specified signature will be returned.
+ /// This is used, for instance, when we estimate call of a vector
+ /// counterpart of the given function.
+ /// \param F Called function, might be nullptr.
+ /// \param RetTy Return value types.
+ /// \param Tys Argument types.
+ /// \returns The cost of Call instruction.
+ unsigned getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) {
+ return 10;
+ }
+
+ unsigned getNumberOfParts(Type *Tp) {
+ std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Tp);
+ return LT.first;
+ }
+
+ unsigned getAddressComputationCost(Type *Ty, bool IsComplex) { return 0; }
+
+ unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwise) {
+ assert(Ty->isVectorTy() && "Expect a vector type");
+ unsigned NumVecElts = Ty->getVectorNumElements();
+ unsigned NumReduxLevels = Log2_32(NumVecElts);
+ unsigned ArithCost =
+ NumReduxLevels *
+ static_cast<T *>(this)->getArithmeticInstrCost(Opcode, Ty);
+ // Assume the pairwise shuffles add a cost.
+ unsigned ShuffleCost =
+ NumReduxLevels * (IsPairwise + 1) *
+ static_cast<T *>(this)
+ ->getShuffleCost(TTI::SK_ExtractSubvector, Ty, NumVecElts / 2, Ty);
+ return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true);
+ }
+
+ /// @}
+};
+
+/// \brief Concrete BasicTTIImpl that can be used if no further customization
+/// is needed.
+class BasicTTIImpl : public BasicTTIImplBase<BasicTTIImpl> {
+ typedef BasicTTIImplBase<BasicTTIImpl> BaseT;
+ friend class BasicTTIImplBase<BasicTTIImpl>;
+
+ const TargetSubtargetInfo *ST;
+ const TargetLoweringBase *TLI;
+
+ const TargetSubtargetInfo *getST() const { return ST; }
+ const TargetLoweringBase *getTLI() const { return TLI; }
+
+public:
+ explicit BasicTTIImpl(const TargetMachine *ST, Function &F);
+
+ // Provide value semantics. MSVC requires that we spell all of these out.
+ BasicTTIImpl(const BasicTTIImpl &Arg)
+ : BaseT(static_cast<const BaseT &>(Arg)), ST(Arg.ST), TLI(Arg.TLI) {}
+ BasicTTIImpl(BasicTTIImpl &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)),
+ TLI(std::move(Arg.TLI)) {}
+ BasicTTIImpl &operator=(const BasicTTIImpl &RHS) {
+ BaseT::operator=(static_cast<const BaseT &>(RHS));
+ ST = RHS.ST;
+ TLI = RHS.TLI;
+ return *this;
+ }
+ BasicTTIImpl &operator=(BasicTTIImpl &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
+ ST = std::move(RHS.ST);
+ TLI = std::move(RHS.TLI);
+ return *this;
+ }
+};
+
+}
+
+#endif
diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h
index dd7703b1dbf7..1fd4eeb46b38 100644
--- a/include/llvm/CodeGen/CallingConvLower.h
+++ b/include/llvm/CodeGen/CallingConvLower.h
@@ -19,6 +19,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/IR/CallingConv.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Target/TargetCallingConv.h"
namespace llvm {
@@ -122,8 +123,8 @@ public:
// There is no need to differentiate between a pending CCValAssign and other
// kinds, as they are stored in a different list.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT,
- LocInfo HTP) {
- return getReg(ValNo, ValVT, 0, LocVT, HTP);
+ LocInfo HTP, unsigned ExtraInfo = 0) {
+ return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP);
}
void convertToReg(unsigned RegNo) {
@@ -146,6 +147,7 @@ public:
unsigned getLocReg() const { assert(isRegLoc()); return Loc; }
unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; }
+ unsigned getExtraInfo() const { return Loc; }
MVT getLocVT() const { return LocVT; }
LocInfo getLocInfo() const { return HTP; }
@@ -312,13 +314,13 @@ public:
/// produce a single value.
void AnalyzeCallResult(MVT VT, CCAssignFn Fn);
- /// getFirstUnallocated - Return the first unallocated register in the set, or
- /// NumRegs if they are all allocated.
- unsigned getFirstUnallocated(const MCPhysReg *Regs, unsigned NumRegs) const {
- for (unsigned i = 0; i != NumRegs; ++i)
+ /// getFirstUnallocated - Return the index of the first unallocated register
+ /// in the set, or Regs.size() if they are all allocated.
+ unsigned getFirstUnallocated(ArrayRef<MCPhysReg> Regs) const {
+ for (unsigned i = 0; i < Regs.size(); ++i)
if (!isAllocated(Regs[i]))
return i;
- return NumRegs;
+ return Regs.size();
}
/// AllocateReg - Attempt to allocate one register. If it is not available,
@@ -341,9 +343,9 @@ public:
/// AllocateReg - Attempt to allocate one of the specified registers. If none
/// are available, return zero. Otherwise, return the first one available,
/// marking it and any aliases as allocated.
- unsigned AllocateReg(const MCPhysReg *Regs, unsigned NumRegs) {
- unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
- if (FirstUnalloc == NumRegs)
+ unsigned AllocateReg(ArrayRef<MCPhysReg> Regs) {
+ unsigned FirstUnalloc = getFirstUnallocated(Regs);
+ if (FirstUnalloc == Regs.size())
return 0; // Didn't find the reg.
// Mark the register and any aliases as allocated.
@@ -382,10 +384,9 @@ public:
}
/// Version of AllocateReg with list of registers to be shadowed.
- unsigned AllocateReg(const MCPhysReg *Regs, const MCPhysReg *ShadowRegs,
- unsigned NumRegs) {
- unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
- if (FirstUnalloc == NumRegs)
+ unsigned AllocateReg(ArrayRef<MCPhysReg> Regs, const MCPhysReg *ShadowRegs) {
+ unsigned FirstUnalloc = getFirstUnallocated(Regs);
+ if (FirstUnalloc == Regs.size())
return 0; // Didn't find the reg.
// Mark the register and any aliases as allocated.
@@ -415,8 +416,8 @@ public:
/// Version of AllocateStack with list of extra registers to be shadowed.
/// Note that, unlike AllocateReg, this shadows ALL of the shadow registers.
unsigned AllocateStack(unsigned Size, unsigned Align,
- const MCPhysReg *ShadowRegs, unsigned NumShadowRegs) {
- for (unsigned i = 0; i < NumShadowRegs; ++i)
+ ArrayRef<MCPhysReg> ShadowRegs) {
+ for (unsigned i = 0; i < ShadowRegs.size(); ++i)
MarkAllocated(ShadowRegs[i]);
return AllocateStack(Size, Align);
}
diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h
index 973c5954f9ad..a1b9b4e566a2 100644
--- a/include/llvm/CodeGen/CommandFlags.h
+++ b/include/llvm/CodeGen/CommandFlags.h
@@ -16,9 +16,12 @@
#ifndef LLVM_CODEGEN_COMMANDFLAGS_H
#define LLVM_CODEGEN_COMMANDFLAGS_H
+#include "llvm/IR/Module.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
+#include "llvm//MC/SubtargetFeature.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Host.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <string>
@@ -123,11 +126,6 @@ EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math",
cl::desc("Force codegen to assume rounding mode can change dynamically"),
cl::init(false));
-cl::opt<bool>
-GenerateSoftFloatCalls("soft-float",
- cl::desc("Generate software floating point library calls"),
- cl::init(false));
-
cl::opt<llvm::FloatABI::ABIType>
FloatABIForCalls("float-abi",
cl::desc("Choose float ABI type"),
@@ -207,6 +205,10 @@ FunctionSections("function-sections",
cl::desc("Emit functions into separate sections"),
cl::init(false));
+cl::opt<bool> UniqueSectionNames("unique-section-names",
+ cl::desc("Give unique names to every section"),
+ cl::init(true));
+
cl::opt<llvm::JumpTable::JumpTableType>
JTableType("jump-table-type",
cl::desc("Choose the type of Jump-Instruction Table for jumptable."),
@@ -222,57 +224,17 @@ 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() {
TargetOptions Options;
Options.LessPreciseFPMADOption = EnableFPMAD;
- Options.NoFramePointerElim = DisableFPElim;
Options.AllowFPOpFusion = FuseFPOps;
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
Options.NoNaNsFPMath = EnableNoNaNsFPMath;
Options.HonorSignDependentRoundingFPMathOption =
EnableHonorSignDependentRoundingFPMath;
- Options.UseSoftFloat = GenerateSoftFloatCalls;
if (FloatABIForCalls != FloatABI::Default)
Options.FloatABIType = FloatABIForCalls;
Options.NoZerosInBSS = DontPlaceZerosInBSS;
@@ -284,17 +246,71 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
Options.UseInitArray = !UseCtors;
Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections;
+ Options.UniqueSectionNames = UniqueSectionNames;
Options.MCOptions = InitMCTargetOptionsFromFlags();
Options.JTType = JTableType;
- Options.FCFI = FCFI;
- Options.CFIType = CFIType;
- Options.CFIEnforcing = CFIEnforcing;
- Options.CFIFuncName = CFIFuncName;
Options.ThreadModel = TMModel;
return Options;
}
+static inline std::string getCPUStr() {
+ // If user asked for the 'native' CPU, autodetect here. If autodection fails,
+ // this will set the CPU to an empty string which tells the target to
+ // pick a basic default.
+ if (MCPU == "native")
+ return sys::getHostCPUName();
+
+ return MCPU;
+}
+
+static inline std::string getFeaturesStr() {
+ SubtargetFeatures Features;
+
+ // If user asked for the 'native' CPU, we need to autodetect features.
+ // This is necessary for x86 where the CPU might not support all the
+ // features the autodetected CPU name lists in the target. For example,
+ // not all Sandybridge processors support AVX.
+ if (MCPU == "native") {
+ StringMap<bool> HostFeatures;
+ if (sys::getHostCPUFeatures(HostFeatures))
+ for (auto &F : HostFeatures)
+ Features.AddFeature(F.first(), F.second);
+ }
+
+ for (unsigned i = 0; i != MAttrs.size(); ++i)
+ Features.AddFeature(MAttrs[i]);
+
+ return Features.getString();
+}
+
+/// \brief Set function attributes of functions in Module M based on CPU,
+/// Features, and command line flags.
+static inline void setFunctionAttributes(StringRef CPU, StringRef Features,
+ Module &M) {
+ for (auto &F : M) {
+ auto &Ctx = F.getContext();
+ AttributeSet Attrs = F.getAttributes(), NewAttrs;
+
+ if (!CPU.empty())
+ NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
+ "target-cpu", CPU);
+
+ if (!Features.empty())
+ NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
+ "target-features", Features);
+
+ if (DisableFPElim.getNumOccurrences() > 0)
+ NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
+ "no-frame-pointer-elim",
+ DisableFPElim ? "true" : "false");
+
+ // Let NewAttrs override Attrs.
+ NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs);
+ F.setAttributes(NewAttrs);
+ }
+}
+
#endif
diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h
index e310aef3dcbb..8e40ef77d374 100644
--- a/include/llvm/CodeGen/DIE.h
+++ b/include/llvm/CodeGen/DIE.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/DwarfStringPoolEntry.h"
#include "llvm/Support/Dwarf.h"
#include <vector>
@@ -95,7 +96,7 @@ public:
/// Emit - Print the abbreviation using the specified asm printer.
///
- void Emit(AsmPrinter *AP) const;
+ void Emit(const AsmPrinter *AP) const;
#ifndef NDEBUG
void print(raw_ostream &O);
@@ -200,8 +201,6 @@ public:
/// to DWARF attribute classes.
///
class DIEValue {
- virtual void anchor();
-
public:
enum Type {
isInteger,
@@ -216,13 +215,14 @@ public:
isLocList,
};
-protected:
+private:
/// Ty - Type of data stored in the value.
///
Type Ty;
+protected:
explicit DIEValue(Type T) : Ty(T) {}
- virtual ~DIEValue() {}
+ ~DIEValue() {}
public:
// Accessors
@@ -230,14 +230,14 @@ public:
/// EmitValue - Emit value via the Dwarf writer.
///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0;
+ void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
/// SizeOf - Return the size of a value in bytes.
///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0;
+ unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
- virtual void print(raw_ostream &O) const = 0;
+ void print(raw_ostream &O) const;
void dump() const;
#endif
};
@@ -246,6 +246,8 @@ public:
/// DIEInteger - An integer value DIE.
///
class DIEInteger : public DIEValue {
+ friend DIEValue;
+
uint64_t Integer;
public:
@@ -273,21 +275,18 @@ public:
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;
+ void setValue(uint64_t Val) { Integer = Val; }
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
@@ -295,28 +294,26 @@ public:
/// DIEExpr - An expression DIE.
//
class DIEExpr : public DIEValue {
+ friend class 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; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
@@ -324,28 +321,26 @@ public:
/// DIELabel - A label DIE.
//
class DIELabel : public DIEValue {
+ friend class 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; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
@@ -353,6 +348,8 @@ public:
/// DIEDelta - A simple label difference DIE.
///
class DIEDelta : public DIEValue {
+ friend class DIEValue;
+
const MCSymbol *LabelHi;
const MCSymbol *LabelLo;
@@ -360,19 +357,15 @@ 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; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
@@ -380,29 +373,25 @@ public:
/// DIEString - A container for string values.
///
class DIEString : public DIEValue {
- const DIEValue *Access;
- StringRef Str;
+ friend class DIEValue;
+
+ DwarfStringPoolEntryRef S;
public:
- DIEString(const DIEValue *Acc, StringRef S)
- : DIEValue(isString), Access(Acc), Str(S) {}
+ DIEString(DwarfStringPoolEntryRef S) : DIEValue(isString), S(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;
+ StringRef getString() const { return S.getString(); }
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *D) { return D->getType() == isString; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
@@ -411,6 +400,8 @@ public:
/// this class can also be used as a proxy for a debug information entry not
/// yet defined (ie. types.)
class DIEEntry : public DIEValue {
+ friend class DIEValue;
+
DIE &Entry;
public:
@@ -419,53 +410,49 @@ public:
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);
+ static unsigned getRefAddrSize(const AsmPrinter *AP);
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const {
+ return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
+ : sizeof(int32_t);
+ }
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
//===--------------------------------------------------------------------===//
/// \brief A signature reference to a type unit.
class DIETypeSignature : public DIEValue {
+ friend class 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;
+ // \brief Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) {
+ return E->getType() == isTypeSignature;
+ }
- /// Returns size of a ref_sig8 entry.
- unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const {
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;
+ void printImpl(raw_ostream &O) const;
#endif
};
@@ -473,13 +460,15 @@ public:
/// DIELoc - Represents an expression location.
//
class DIELoc : public DIEValue, public DIE {
+ friend class DIEValue;
+
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;
+ unsigned ComputeSize(const AsmPrinter *AP) const;
/// BestForm - Choose the best form for data.
///
@@ -496,19 +485,15 @@ public:
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; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
@@ -516,13 +501,15 @@ public:
/// DIEBlock - Represents a block of values.
//
class DIEBlock : public DIEValue, public DIE {
+ friend class DIEValue;
+
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;
+ unsigned ComputeSize(const AsmPrinter *AP) const;
/// BestForm - Choose the best form for data.
///
@@ -536,19 +523,15 @@ public:
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; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
@@ -557,6 +540,8 @@ public:
/// section.
//
class DIELocList : public DIEValue {
+ friend class DIEValue;
+
// Index into the .debug_loc vector.
size_t Index;
@@ -566,19 +551,15 @@ public:
/// 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; }
+private:
+ void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+ unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
+
#ifndef NDEBUG
- void print(raw_ostream &O) const override;
+ void printImpl(raw_ostream &O) const;
#endif
};
diff --git a/include/llvm/CodeGen/DwarfStringPoolEntry.h b/include/llvm/CodeGen/DwarfStringPoolEntry.h
new file mode 100644
index 000000000000..fc2b5ddd2d2c
--- /dev/null
+++ b/include/llvm/CodeGen/DwarfStringPoolEntry.h
@@ -0,0 +1,51 @@
+//===- llvm/CodeGen/DwarfStringPoolEntry.h - String pool entry --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H
+#define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H
+
+#include "llvm/ADT/StringMap.h"
+
+namespace llvm {
+
+class MCSymbol;
+
+/// Data for a string pool entry.
+struct DwarfStringPoolEntry {
+ MCSymbol *Symbol;
+ unsigned Offset;
+ unsigned Index;
+};
+
+/// String pool entry reference.
+struct DwarfStringPoolEntryRef {
+ const StringMapEntry<DwarfStringPoolEntry> *I = nullptr;
+
+public:
+ DwarfStringPoolEntryRef() = default;
+ explicit DwarfStringPoolEntryRef(
+ const StringMapEntry<DwarfStringPoolEntry> &I)
+ : I(&I) {}
+
+ explicit operator bool() const { return I; }
+ MCSymbol *getSymbol() const {
+ assert(I->second.Symbol && "No symbol available!");
+ return I->second.Symbol;
+ }
+ unsigned getOffset() const { return I->second.Offset; }
+ unsigned getIndex() const { return I->second.Index; }
+ StringRef getString() const { return I->first(); }
+
+ bool operator==(const DwarfStringPoolEntryRef &X) const { return I == X.I; }
+ bool operator!=(const DwarfStringPoolEntryRef &X) const { return I != X.I; }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
deleted file mode 100644
index ec8e2ef243b7..000000000000
--- a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
+++ /dev/null
@@ -1,122 +0,0 @@
-//===-- 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 7c574df4ba41..82c762ed850f 100644
--- a/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/include/llvm/CodeGen/FunctionLoweringInfo.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/ISDOpcodes.h"
@@ -73,6 +74,16 @@ public:
/// cross-basic-block values.
DenseMap<const Value*, unsigned> ValueMap;
+ // Keep track of frame indices allocated for statepoints as they could be used
+ // across basic block boundaries.
+ // Key of the map is statepoint instruction, value is a map from spilled
+ // llvm Value to the optional stack stack slot index.
+ // If optional is unspecified it means that we have visited this value
+ // but didn't spill it.
+ typedef DenseMap<const Value*, Optional<int>> StatepointSpilledValueMapTy;
+ DenseMap<const Instruction*, StatepointSpilledValueMapTy>
+ StatepointRelocatedValues;
+
/// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in
/// the entry block. This allows the allocas to be efficiently referenced
/// anywhere in the function.
@@ -221,6 +232,8 @@ public:
int getArgumentFrameIndex(const Argument *A);
private:
+ void addSEHHandlersForLPads(ArrayRef<const LandingPadInst *> LPads);
+
/// LiveOutRegInfo - Information about live out vregs.
IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo;
};
@@ -232,11 +245,6 @@ private:
/// floating-point support.
void ComputeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo *MMI);
-/// AddCatchInfo - Extract the personality and type infos from an eh.selector
-/// call, and add them to the specified machine basic block.
-void AddCatchInfo(const CallInst &I,
- MachineModuleInfo *MMI, MachineBasicBlock *MBB);
-
/// AddLandingPadInfo - Extract the exception handling information from the
/// landingpad instruction and add them to the specified machine module info.
void AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI,
diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h
index c7f1ab87fcb1..357b2d8a7ca7 100644
--- a/include/llvm/CodeGen/GCMetadata.h
+++ b/include/llvm/CodeGen/GCMetadata.h
@@ -34,184 +34,173 @@
#define LLVM_CODEGEN_GCMETADATA_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/CodeGen/GCStrategy.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
#include <memory>
namespace llvm {
- class AsmPrinter;
- class GCStrategy;
- class Constant;
- class MCSymbol;
-
- namespace GC {
- /// PointKind - The type of a collector-safe point.
- ///
- enum PointKind {
- Loop, ///< Instr is a loop (backwards branch).
- Return, ///< Instr is a return instruction.
- PreCall, ///< Instr is a call instruction.
- PostCall ///< Instr is the return address of a call.
- };
+class AsmPrinter;
+class Constant;
+class MCSymbol;
+
+/// GCPoint - Metadata for a collector-safe point in machine code.
+///
+struct GCPoint {
+ GC::PointKind Kind; ///< The kind of the safe point.
+ MCSymbol *Label; ///< A label.
+ DebugLoc Loc;
+
+ GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL)
+ : Kind(K), Label(L), Loc(DL) {}
+};
+
+/// GCRoot - Metadata for a pointer to an object managed by the garbage
+/// collector.
+struct GCRoot {
+ int Num; ///< Usually a frame index.
+ int StackOffset; ///< Offset from the stack pointer.
+ const Constant *Metadata; ///< Metadata straight from the call
+ ///< to llvm.gcroot.
+
+ GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {}
+};
+
+/// Garbage collection metadata for a single function. Currently, this
+/// information only applies to GCStrategies which use GCRoot.
+class GCFunctionInfo {
+public:
+ typedef std::vector<GCPoint>::iterator iterator;
+ typedef std::vector<GCRoot>::iterator roots_iterator;
+ typedef std::vector<GCRoot>::const_iterator live_iterator;
+
+private:
+ const Function &F;
+ GCStrategy &S;
+ uint64_t FrameSize;
+ std::vector<GCRoot> Roots;
+ std::vector<GCPoint> SafePoints;
+
+ // FIXME: Liveness. A 2D BitVector, perhaps?
+ //
+ // BitVector Liveness;
+ //
+ // bool islive(int point, int root) =
+ // Liveness[point * SafePoints.size() + root]
+ //
+ // The bit vector is the more compact representation where >3.2% of roots
+ // are live per safe point (1.5% on 64-bit hosts).
+
+public:
+ GCFunctionInfo(const Function &F, GCStrategy &S);
+ ~GCFunctionInfo();
+
+ /// getFunction - Return the function to which this metadata applies.
+ ///
+ const Function &getFunction() const { return F; }
+
+ /// getStrategy - Return the GC strategy for the function.
+ ///
+ GCStrategy &getStrategy() { return S; }
+
+ /// addStackRoot - Registers a root that lives on the stack. Num is the
+ /// stack object ID for the alloca (if the code generator is
+ // using MachineFrameInfo).
+ void addStackRoot(int Num, const Constant *Metadata) {
+ Roots.push_back(GCRoot(Num, Metadata));
+ }
+
+ /// removeStackRoot - Removes a root.
+ roots_iterator removeStackRoot(roots_iterator position) {
+ return Roots.erase(position);
+ }
+
+ /// addSafePoint - Notes the existence of a safe point. Num is the ID of the
+ /// label just prior to the safe point (if the code generator is using
+ /// MachineModuleInfo).
+ void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
+ SafePoints.push_back(GCPoint(Kind, Label, DL));
}
- /// GCPoint - Metadata for a collector-safe point in machine code.
+ /// getFrameSize/setFrameSize - Records the function's frame size.
///
- struct GCPoint {
- GC::PointKind Kind; ///< The kind of the safe point.
- MCSymbol *Label; ///< A label.
- DebugLoc Loc;
-
- GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL)
- : Kind(K), Label(L), Loc(DL) {}
- };
-
- /// GCRoot - Metadata for a pointer to an object managed by the garbage
- /// collector.
- struct GCRoot {
- int Num; ///< Usually a frame index.
- int StackOffset; ///< Offset from the stack pointer.
- const Constant *Metadata; ///< Metadata straight from the call
- ///< to llvm.gcroot.
-
- GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {}
- };
-
-
- /// Garbage collection metadata for a single function. Currently, this
- /// information only applies to GCStrategies which use GCRoot.
- class GCFunctionInfo {
- public:
- typedef std::vector<GCPoint>::iterator iterator;
- typedef std::vector<GCRoot>::iterator roots_iterator;
- typedef std::vector<GCRoot>::const_iterator live_iterator;
-
- private:
- const Function &F;
- GCStrategy &S;
- uint64_t FrameSize;
- std::vector<GCRoot> Roots;
- std::vector<GCPoint> SafePoints;
-
- // FIXME: Liveness. A 2D BitVector, perhaps?
- //
- // BitVector Liveness;
- //
- // bool islive(int point, int root) =
- // Liveness[point * SafePoints.size() + root]
- //
- // The bit vector is the more compact representation where >3.2% of roots
- // are live per safe point (1.5% on 64-bit hosts).
-
- public:
- GCFunctionInfo(const Function &F, GCStrategy &S);
- ~GCFunctionInfo();
-
- /// getFunction - Return the function to which this metadata applies.
- ///
- const Function &getFunction() const { return F; }
-
- /// getStrategy - Return the GC strategy for the function.
- ///
- GCStrategy &getStrategy() { return S; }
-
- /// addStackRoot - Registers a root that lives on the stack. Num is the
- /// stack object ID for the alloca (if the code generator is
- // using MachineFrameInfo).
- void addStackRoot(int Num, const Constant *Metadata) {
- Roots.push_back(GCRoot(Num, Metadata));
- }
-
- /// removeStackRoot - Removes a root.
- roots_iterator removeStackRoot(roots_iterator position) {
- return Roots.erase(position);
- }
-
- /// addSafePoint - Notes the existence of a safe point. Num is the ID of the
- /// label just prior to the safe point (if the code generator is using
- /// MachineModuleInfo).
- void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
- SafePoints.push_back(GCPoint(Kind, Label, DL));
- }
-
- /// getFrameSize/setFrameSize - Records the function's frame size.
- ///
- uint64_t getFrameSize() const { return FrameSize; }
- void setFrameSize(uint64_t S) { FrameSize = S; }
-
- /// begin/end - Iterators for safe points.
- ///
- iterator begin() { return SafePoints.begin(); }
- iterator end() { return SafePoints.end(); }
- size_t size() const { return SafePoints.size(); }
-
- /// roots_begin/roots_end - Iterators for all roots in the function.
- ///
- roots_iterator roots_begin() { return Roots.begin(); }
- roots_iterator roots_end () { return Roots.end(); }
- size_t roots_size() const { return Roots.size(); }
-
- /// live_begin/live_end - Iterators for live roots at a given safe point.
- ///
- live_iterator live_begin(const iterator &p) { return roots_begin(); }
- live_iterator live_end (const iterator &p) { return roots_end(); }
- size_t live_size(const iterator &p) const { return roots_size(); }
- };
-
- /// 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;
-
- strategy_map_type StrategyMap;
- list_type StrategyList;
-
- 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;
-
- GCModuleInfo();
-
- /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should
- /// call it in doFinalization().
- ///
- void clear();
-
- /// begin/end - Iterators for used strategies.
- ///
- iterator begin() const { return StrategyList.begin(); }
- iterator end() const { return StrategyList.end(); }
-
- /// get - Look up function metadata. This is currently assumed
- /// have the side effect of initializing the associated GCStrategy. That
- /// will soon change.
- GCFunctionInfo &getFunctionInfo(const Function &F);
- };
+ uint64_t getFrameSize() const { return FrameSize; }
+ void setFrameSize(uint64_t S) { FrameSize = S; }
+ /// begin/end - Iterators for safe points.
+ ///
+ iterator begin() { return SafePoints.begin(); }
+ iterator end() { return SafePoints.end(); }
+ size_t size() const { return SafePoints.size(); }
+
+ /// roots_begin/roots_end - Iterators for all roots in the function.
+ ///
+ roots_iterator roots_begin() { return Roots.begin(); }
+ roots_iterator roots_end() { return Roots.end(); }
+ size_t roots_size() const { return Roots.size(); }
+
+ /// live_begin/live_end - Iterators for live roots at a given safe point.
+ ///
+ live_iterator live_begin(const iterator &p) { return roots_begin(); }
+ live_iterator live_end(const iterator &p) { return roots_end(); }
+ size_t live_size(const iterator &p) const { return roots_size(); }
+};
+
+/// An analysis pass which caches information about the entire Module.
+/// Records both the function level information used by GCRoots and a
+/// cache of the 'active' gc strategy objects for the current Module.
+class GCModuleInfo : public ImmutablePass {
+ /// An owning list of all GCStrategies which have been created
+ SmallVector<std::unique_ptr<GCStrategy>, 1> GCStrategyList;
+ /// A helper map to speedup lookups into the above list
+ StringMap<GCStrategy*> GCStrategyMap;
+
+public:
+ /// Lookup the GCStrategy object associated with the given gc name.
+ /// Objects are owned internally; No caller should attempt to delete the
+ /// returned objects.
+ GCStrategy *getGCStrategy(const StringRef Name);
+
+ /// List of per function info objects. In theory, Each of these
+ /// may be associated with a different GC.
+ typedef std::vector<std::unique_ptr<GCFunctionInfo>> FuncInfoVec;
+
+ FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); }
+ FuncInfoVec::iterator funcinfo_end() { return Functions.end(); }
+
+private:
+ /// Owning list of all GCFunctionInfos associated with this Module
+ FuncInfoVec Functions;
+
+ /// Non-owning map to bypass linear search when finding the GCFunctionInfo
+ /// associated with a particular Function.
+ typedef DenseMap<const Function *, GCFunctionInfo *> finfo_map_type;
+ finfo_map_type FInfoMap;
+
+public:
+ typedef SmallVector<std::unique_ptr<GCStrategy>,1>::const_iterator iterator;
+
+ static char ID;
+
+ GCModuleInfo();
+
+ /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should
+ /// call it in doFinalization().
+ ///
+ void clear();
+
+ /// begin/end - Iterators for used strategies.
+ ///
+ iterator begin() const { return GCStrategyList.begin(); }
+ iterator end() const { return GCStrategyList.end(); }
+
+ /// get - Look up function metadata. This is currently assumed
+ /// have the side effect of initializing the associated GCStrategy. That
+ /// will soon change.
+ GCFunctionInfo &getFunctionInfo(const Function &F);
+};
}
#endif
diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h
index 25fafba93f8b..220847029113 100644
--- a/include/llvm/CodeGen/GCMetadataPrinter.h
+++ b/include/llvm/CodeGen/GCMetadataPrinter.h
@@ -26,43 +26,39 @@
namespace llvm {
- class GCMetadataPrinter;
+class GCMetadataPrinter;
- /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the
- /// defaults from Registry.
- typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry;
+/// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the
+/// defaults from Registry.
+typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry;
- /// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are
- /// created, managed, and owned by the AsmPrinter.
- class GCMetadataPrinter {
- private:
- GCStrategy *S;
- friend class AsmPrinter;
+/// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are
+/// created, managed, and owned by the AsmPrinter.
+class GCMetadataPrinter {
+private:
+ GCStrategy *S;
+ friend class AsmPrinter;
- protected:
- // May only be subclassed.
- GCMetadataPrinter();
+protected:
+ // May only be subclassed.
+ GCMetadataPrinter();
- private:
- GCMetadataPrinter(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION;
- GCMetadataPrinter &
- operator=(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION;
+private:
+ GCMetadataPrinter(const GCMetadataPrinter &) = delete;
+ GCMetadataPrinter &operator=(const GCMetadataPrinter &) = delete;
- public:
- GCStrategy &getStrategy() { return *S; }
+public:
+ GCStrategy &getStrategy() { return *S; }
- /// Called before the assembly for the module is generated by
- /// the AsmPrinter (but after target specific hooks.)
- virtual void beginAssembly(Module &M, GCModuleInfo &Info,
- AsmPrinter &AP) {}
- /// Called after the assembly for the module is generated by
- /// the AsmPrinter (but before target specific hooks)
- virtual void finishAssembly(Module &M, GCModuleInfo &Info,
- AsmPrinter &AP) {}
-
- virtual ~GCMetadataPrinter();
- };
+ /// Called before the assembly for the module is generated by
+ /// the AsmPrinter (but after target specific hooks.)
+ virtual void beginAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {}
+ /// Called after the assembly for the module is generated by
+ /// the AsmPrinter (but before target specific hooks)
+ virtual void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {}
+ virtual ~GCMetadataPrinter();
+};
}
#endif
diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h
index 0b0c3124c537..a1b8e895898f 100644
--- a/include/llvm/CodeGen/GCStrategy.h
+++ b/include/llvm/CodeGen/GCStrategy.h
@@ -16,11 +16,11 @@
// GCStrategy is relevant for implementations using either gc.root or
// gc.statepoint based lowering strategies, but is currently focused mostly on
// options for gc.root. This will change over time.
-//
+//
// When requested by a subclass of GCStrategy, the gc.root implementation will
// populate GCModuleInfo and GCFunctionInfo with that about each Function in
// the Module that opts in to garbage collection. Specifically:
-//
+//
// - Safe points
// Garbage collection is generally only possible at certain points in code.
// GCStrategy can request that the collector insert such points:
@@ -28,7 +28,7 @@
// - At and after any call to a subroutine
// - Before returning from the current function
// - Before backwards branches (loops)
-//
+//
// - Roots
// When a reference to a GC-allocated object exists on the stack, it must be
// stored in an alloca registered with llvm.gcoot.
@@ -42,155 +42,136 @@
// insertion support is planned. gc.statepoint does not currently support
// custom stack map formats; such can be generated by parsing the standard
// stack map section if desired.
-//
+//
// The read and write barrier support can be used with either implementation.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_GCSTRATEGY_H
-#define LLVM_CODEGEN_GCSTRATEGY_H
+#ifndef LLVM_IR_GCSTRATEGY_H
+#define LLVM_IR_GCSTRATEGY_H
#include "llvm/ADT/Optional.h"
-#include "llvm/CodeGen/GCMetadata.h"
-#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Registry.h"
#include <string>
namespace llvm {
- /// GCStrategy describes a garbage collector algorithm's code generation
- /// requirements, and provides overridable hooks for those needs which cannot
- /// 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 {
- private:
- std::string Name;
- friend class GCModuleInfo;
-
- protected:
- bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots,
- /// if set, none of the other options can be
- /// anything but their default values.
-
- unsigned NeededSafePoints; ///< Bitmask of required safe points.
- bool CustomReadBarriers; ///< Default is to insert loads.
- bool CustomWriteBarriers; ///< Default is to insert stores.
- bool CustomRoots; ///< Default is to pass through to backend.
- bool CustomSafePoints; ///< Default is to use NeededSafePoints
- ///< to find safe points.
- bool InitRoots; ///< If set, roots are nulled during lowering.
- bool UsesMetadata; ///< If set, backend must emit metadata tables.
-
- public:
- GCStrategy();
- virtual ~GCStrategy() {}
-
- /// Return the name of the GC strategy. This is the value of the collector
- /// name string specified on functions which use this strategy.
- const std::string &getName() const { return Name; }
-
- /// By default, write barriers are replaced with simple store
- /// instructions. If true, 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 */
- ///@{
-
- /// 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;
- }
-
- /// True if the given kind of safe point is required. By default, none are
- /// recorded.
- bool needsSafePoint(GC::PointKind Kind) const {
- return (NeededSafePoints & 1 << Kind) != 0;
- }
-
- /// By default, roots are left for the code generator so it can generate a
- /// stack map. If true, then performCustomLowering must delete them.
- bool customRoots() const { return CustomRoots; }
-
- /// By default, the GC analysis will find safe points according to
- /// NeededSafePoints. If true, then findCustomSafePoints must create them.
- bool customSafePoints() const { return CustomSafePoints; }
-
- /// If set, gcroot intrinsics should initialize their allocas to null
- /// before the first use. This is necessary for most GCs and is enabled by
- /// default.
- bool initializeRoots() const { return InitRoots; }
-
- /// If set, appropriate metadata tables must be emitted by the back-end
- /// (assembler, JIT, or otherwise). For statepoint, this method is
- /// currently unsupported. The stackmap information can be found in the
- /// StackMap section as described in the documentation.
- bool usesMetadata() const { return UsesMetadata; }
-
- ///@}
-
- /// 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. 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;
+namespace GC {
+/// PointKind - Used to indicate whether the address of the call instruction
+/// or the address after the call instruction is listed in the stackmap. For
+/// most runtimes, PostCall safepoints are appropriate.
+///
+enum PointKind {
+ PreCall, ///< Instr is a call instruction.
+ PostCall ///< Instr is the return address of a call.
+};
+}
+
+/// GCStrategy describes a garbage collector algorithm's code generation
+/// requirements, and provides overridable hooks for those needs which cannot
+/// be abstractly described. GCStrategy objects must be looked up through
+/// the Function. The objects themselves are owned by the Context and must
+/// be immutable.
+class GCStrategy {
+private:
+ std::string Name;
+ friend class GCModuleInfo;
+
+protected:
+ bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots,
+ /// if set, none of the other options can be
+ /// anything but their default values.
+
+ unsigned NeededSafePoints; ///< Bitmask of required safe points.
+ bool CustomReadBarriers; ///< Default is to insert loads.
+ bool CustomWriteBarriers; ///< Default is to insert stores.
+ bool CustomRoots; ///< Default is to pass through to backend.
+ bool InitRoots; ///< If set, roots are nulled during lowering.
+ bool UsesMetadata; ///< If set, backend must emit metadata tables.
+
+public:
+ GCStrategy();
+ virtual ~GCStrategy() {}
+
+ /// Return the name of the GC strategy. This is the value of the collector
+ /// name string specified on functions which use this strategy.
+ const std::string &getName() const { return Name; }
+
+ /// By default, write barriers are replaced with simple store
+ /// instructions. If true, you must provide a custom pass to lower
+ /// calls to @llvm.gcwrite.
+ bool customWriteBarrier() const { return CustomWriteBarriers; }
+
+ /// By default, read barriers are replaced with simple load
+ /// instructions. If true, you must provide a custom pass to lower
+ /// calls to @llvm.gcread.
+ bool customReadBarrier() const { return CustomReadBarriers; }
+
+ /// Returns true if this strategy is expecting the use of gc.statepoints,
+ /// and false otherwise.
+ bool useStatepoints() const { return UseStatepoints; }
+
+ /** @name Statepoint Specific Properties */
+ ///@{
+
+ /// If the value specified can be reliably distinguished, returns true for
+ /// pointers to GC managed locations and false for pointers to non-GC
+ /// managed locations. Note a GCStrategy can always return 'None' (i.e. an
+ /// empty optional indicating it can't reliably distinguish.
+ virtual Optional<bool> isGCManagedPointer(const Value *V) const {
+ return None;
+ }
+ ///@}
+
+ /** @name GCRoot Specific Properties
+ * These properties and overrides only apply to collector strategies using
+ * GCRoot.
+ */
+ ///@{
+
+ /// True if safe points of any kind are required. By default, none are
+ /// recorded.
+ bool needsSafePoints() const { return NeededSafePoints != 0; }
+
+ /// True if the given kind of safe point is required. By default, none are
+ /// recorded.
+ bool needsSafePoint(GC::PointKind Kind) const {
+ return (NeededSafePoints & 1 << Kind) != 0;
+ }
+
+ /// By default, roots are left for the code generator so it can generate a
+ /// stack map. If true, you must provide a custom pass to lower
+ /// calls to @llvm.gcroot.
+ bool customRoots() const { return CustomRoots; }
+
+ /// If set, gcroot intrinsics should initialize their allocas to null
+ /// before the first use. This is necessary for most GCs and is enabled by
+ /// default.
+ bool initializeRoots() const { return InitRoots; }
+
+ /// If set, appropriate metadata tables must be emitted by the back-end
+ /// (assembler, JIT, or otherwise). For statepoint, this method is
+ /// currently unsupported. The stackmap information can be found in the
+ /// StackMap section as described in the documentation.
+ bool usesMetadata() const { return UsesMetadata; }
+
+ ///@}
+};
+
+/// Subclasses of GCStrategy are made available for use during compilation by
+/// adding them to the global GCRegistry. This can done either within the
+/// LLVM source tree or via a loadable plugin. An example registeration
+/// would be:
+/// static GCRegistry::Add<CustomGC> X("custom-name",
+/// "my custom supper fancy gc strategy");
+///
+/// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also
+/// register your GCMetadataPrinter subclass with the
+/// GCMetadataPrinterRegistery as well.
+typedef Registry<GCStrategy> GCRegistry;
}
#endif
diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h
index 51a31842a5c0..5207f801c84e 100644
--- a/include/llvm/CodeGen/GCs.h
+++ b/include/llvm/CodeGen/GCs.h
@@ -15,29 +15,32 @@
#define LLVM_CODEGEN_GCS_H
namespace llvm {
- class GCStrategy;
- class GCMetadataPrinter;
+class GCStrategy;
+class GCMetadataPrinter;
- /// FIXME: Collector instances are not useful on their own. These no longer
- /// serve any purpose except to link in the plugins.
+/// FIXME: Collector instances are not useful on their own. These no longer
+/// serve any purpose except to link in the plugins.
- /// Creates an ocaml-compatible garbage collector.
- void linkOcamlGC();
+/// Creates a CoreCLR-compatible garbage collector.
+void linkCoreCLRGC();
- /// Creates an ocaml-compatible metadata printer.
- void linkOcamlGCPrinter();
+/// Creates an ocaml-compatible garbage collector.
+void linkOcamlGC();
- /// Creates an erlang-compatible garbage collector.
- void linkErlangGC();
+/// Creates an ocaml-compatible metadata printer.
+void linkOcamlGCPrinter();
- /// Creates an erlang-compatible metadata printer.
- void linkErlangGCPrinter();
+/// Creates an erlang-compatible garbage collector.
+void linkErlangGC();
- /// Creates a shadow stack garbage collector. This collector requires no code
- /// generator support.
- void linkShadowStackGC();
+/// Creates an erlang-compatible metadata printer.
+void linkErlangGCPrinter();
- void linkStatepointExampleGC();
+/// 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 952362ed6ce3..c2071fe5dd2d 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -229,11 +229,18 @@ namespace ISD {
SMULO, UMULO,
/// Simple binary floating point operators.
- FADD, FSUB, FMUL, FMA, FDIV, FREM,
+ FADD, FSUB, FMUL, FDIV, FREM,
+
+ /// FMA - Perform a * b + c with no intermediate rounding step.
+ FMA,
+
+ /// FMAD - Perform a * b + c, while getting the same result as the
+ /// separately rounded operations.
+ FMAD,
/// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This
- /// DAG node does not require that X and Y have the same type, just that the
- /// are both floating point. X and the result must have the same type.
+ /// DAG node does not require that X and Y have the same type, just that
+ /// they are both floating point. X and the result must have the same type.
/// FCOPYSIGN(f32, f64) is allowed.
FCOPYSIGN,
@@ -301,6 +308,10 @@ namespace ISD {
/// part.
MULHU, MULHS,
+ /// [US]{MIN/MAX} - Binary minimum or maximum or signed or unsigned
+ /// integers.
+ SMIN, SMAX, UMIN, UMAX,
+
/// Bitwise operators - logical and, logical or, logical xor.
AND, OR, XOR,
@@ -680,13 +691,29 @@ namespace ISD {
ATOMIC_LOAD_UMIN,
ATOMIC_LOAD_UMAX,
- // Masked load and store
+ // Masked load and store - consecutive vector load and store operations
+ // with additional mask operand that prevents memory accesses to the
+ // masked-off lanes.
MLOAD, MSTORE,
+ // Masked gather and scatter - load and store operations for a vector of
+ // random addresses with additional mask operand that prevents memory
+ // accesses to the masked-off lanes.
+ MGATHER, MSCATTER,
+
/// This corresponds to the llvm.lifetime.* intrinsics. The first operand
/// is the chain and the second operand is the alloca pointer.
LIFETIME_START, LIFETIME_END,
+ /// GC_TRANSITION_START/GC_TRANSITION_END - These operators mark the
+ /// beginning and end of GC transition sequence, and carry arbitrary
+ /// information that target might need for lowering. The first operand is
+ /// a chain, the rest are specified by the target and not touched by the DAG
+ /// optimizers. GC_TRANSITION_START..GC_TRANSITION_END pairs may not be
+ /// nested.
+ GC_TRANSITION_START,
+ GC_TRANSITION_END,
+
/// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific pre-isel opcode values start here.
BUILTIN_OP_END
@@ -696,7 +723,7 @@ namespace ISD {
/// which do not reference a specific memory location should be less than
/// this value. Those that do must not be less than this value, and can
/// be used with SelectionDAG::getMemIntrinsicNode.
- static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+180;
+ static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+200;
//===--------------------------------------------------------------------===//
/// MemIndexedMode enum - This enum defines the load / store indexed
diff --git a/include/llvm/CodeGen/JumpInstrTables.h b/include/llvm/CodeGen/JumpInstrTables.h
deleted file mode 100644
index 005bc1eb2b2d..000000000000
--- a/include/llvm/CodeGen/JumpInstrTables.h
+++ /dev/null
@@ -1,105 +0,0 @@
-//===-- JumpInstrTables.h: Jump-Instruction Tables --------------*- C++ -*-===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief An implementation of tables consisting of jump instructions
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_JUMPINSTRTABLES_H
-#define LLVM_CODEGEN_JUMPINSTRTABLES_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Pass.h"
-#include "llvm/Target/TargetOptions.h"
-
-namespace llvm {
-class Constant;
-class Function;
-class FunctionType;
-class JumpInstrTableInfo;
-class Module;
-
-/// A class to manage a set of jump tables indexed on function type. It looks at
-/// each function in the module to find all the functions that have the
-/// jumptable attribute set. For each such function, it creates a new
-/// jump-instruction-table function and stores the mapping in the ImmutablePass
-/// JumpInstrTableInfo.
-///
-/// These special functions get lowered in AsmPrinter to assembly of the form:
-/// \verbatim
-/// .globl f
-/// .type f,@function
-/// .align 8,0x90
-/// f:
-/// jmp f_orig@PLT
-/// \endverbatim
-///
-/// 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;
-
- JumpInstrTables();
- JumpInstrTables(JumpTable::JumpTableType JTT);
- virtual ~JumpInstrTables();
- bool runOnModule(Module &M) override;
- const char *getPassName() const override { return "Jump-Instruction Tables"; }
- void getAnalysisUsage(AnalysisUsage &AU) const override;
-
- /// Creates a jump-instruction table function for the Target and adds it to
- /// the tables.
- Function *insertEntry(Module &M, Function *Target);
-
- /// 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 {
- /// The number of this table
- unsigned TableNum;
-
- /// The current number of jump entries in the table.
- unsigned Count;
- };
-
- typedef DenseMap<FunctionType *, struct TableMeta> JumpMap;
-
- /// The current state of functions and jump entries in the table(s).
- JumpMap Metadata;
-
- /// The ImmutablePass that stores information about the generated tables.
- JumpInstrTableInfo *JITI;
-
- /// The total number of tables.
- unsigned TableCount;
-
- /// The type of tables to build.
- JumpTable::JumpTableType JTType;
-};
-
-/// Creates a JumpInstrTables pass for the given type of jump table.
-ModulePass *createJumpInstrTablesPass(JumpTable::JumpTableType JTT);
-}
-
-#endif /* LLVM_CODEGEN_JUMPINSTRTABLES_H */
diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h
index cf601ae5384c..f347f66e0981 100644
--- a/include/llvm/CodeGen/LatencyPriorityQueue.h
+++ b/include/llvm/CodeGen/LatencyPriorityQueue.h
@@ -83,8 +83,6 @@ namespace llvm {
void remove(SUnit *SU) override;
- void dump(ScheduleDAG* DAG) const override;
-
// scheduledNode - As nodes are scheduled, we look to see if there are any
// successor nodes that have a single unscheduled predecessor. If so, that
// single predecessor has a higher priority, since scheduling it will make
diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h
index 11a360a491a7..7d7e48af2a0f 100644
--- a/include/llvm/CodeGen/LexicalScopes.h
+++ b/include/llvm/CodeGen/LexicalScopes.h
@@ -23,7 +23,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/DebugLoc.h"
-#include "llvm/IR/Metadata.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/ValueHandle.h"
#include <unordered_map>
#include <utility>
@@ -45,7 +45,8 @@ typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange;
class LexicalScope {
public:
- LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A)
+ LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *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");
@@ -57,8 +58,8 @@ public:
// Accessors.
LexicalScope *getParent() const { return Parent; }
const MDNode *getDesc() const { return Desc; }
- const MDNode *getInlinedAt() const { return InlinedAtLocation; }
- const MDNode *getScopeNode() const { return Desc; }
+ const DILocation *getInlinedAt() const { return InlinedAtLocation; }
+ const DILocalScope *getScopeNode() const { return Desc; }
bool isAbstractScope() const { return AbstractScope; }
SmallVectorImpl<LexicalScope *> &getChildren() { return Children; }
SmallVectorImpl<InsnRange> &getRanges() { return Ranges; }
@@ -118,8 +119,8 @@ public:
private:
LexicalScope *Parent; // Parent to this scope.
- const MDNode *Desc; // Debug info descriptor.
- const MDNode *InlinedAtLocation; // Location at which this
+ const DILocalScope *Desc; // Debug info descriptor.
+ const DILocation *InlinedAtLocation; // Location at which this
// scope is inlined.
bool AbstractScope; // Abstract Scope
SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope.
@@ -158,16 +159,16 @@ public:
/// getMachineBasicBlocks - Populate given set using machine basic blocks
/// which have machine instructions that belong to lexical scope identified by
/// DebugLoc.
- void getMachineBasicBlocks(DebugLoc DL,
+ void getMachineBasicBlocks(const DILocation *DL,
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.
- bool dominates(DebugLoc DL, MachineBasicBlock *MBB);
+ bool dominates(const DILocation *DL, MachineBasicBlock *MBB);
/// findLexicalScope - Find lexical scope, either regular or inlined, for the
/// given DebugLoc. Return NULL if not found.
- LexicalScope *findLexicalScope(DebugLoc DL);
+ LexicalScope *findLexicalScope(const DILocation *DL);
/// getAbstractScopesList - Return a reference to list of abstract scopes.
ArrayRef<LexicalScope *> getAbstractScopesList() const {
@@ -175,17 +176,19 @@ public:
}
/// findAbstractScope - Find an abstract scope or return null.
- LexicalScope *findAbstractScope(const MDNode *N) {
+ LexicalScope *findAbstractScope(const DILocalScope *N) {
auto I = AbstractScopeMap.find(N);
return I != AbstractScopeMap.end() ? &I->second : nullptr;
}
- /// findInlinedScope - Find an inlined scope for the given DebugLoc or return
- /// NULL.
- LexicalScope *findInlinedScope(DebugLoc DL);
+ /// findInlinedScope - Find an inlined scope for the given scope/inlined-at.
+ LexicalScope *findInlinedScope(const DILocalScope *N, const DILocation *IA) {
+ auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA));
+ return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
+ }
/// findLexicalScope - Find regular lexical scope or return null.
- LexicalScope *findLexicalScope(const MDNode *N) {
+ LexicalScope *findLexicalScope(const DILocalScope *N) {
auto I = LexicalScopeMap.find(N);
return I != LexicalScopeMap.end() ? &I->second : nullptr;
}
@@ -194,18 +197,24 @@ public:
void dump();
/// getOrCreateAbstractScope - Find or create an abstract lexical scope.
- LexicalScope *getOrCreateAbstractScope(const MDNode *N);
+ LexicalScope *getOrCreateAbstractScope(const DILocalScope *Scope);
private:
- /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
+ /// getOrCreateLexicalScope - Find lexical scope for the given Scope/IA. If
/// not available then create new lexical scope.
- LexicalScope *getOrCreateLexicalScope(DebugLoc DL);
+ LexicalScope *getOrCreateLexicalScope(const DILocalScope *Scope,
+ const DILocation *IA = nullptr);
+ LexicalScope *getOrCreateLexicalScope(const DILocation *DL) {
+ return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt())
+ : nullptr;
+ }
/// getOrCreateRegularScope - Find or create a regular lexical scope.
- LexicalScope *getOrCreateRegularScope(MDNode *Scope);
+ LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope);
/// getOrCreateInlinedScope - Find or create an inlined lexical scope.
- LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt);
+ LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope,
+ const DILocation *InlinedAt);
/// extractLexicalScopes - Extract instruction ranges for each lexical scopes
/// for the given machine function.
@@ -221,17 +230,18 @@ private:
/// LexicalScopeMap - Tracks the scopes in the current function.
// Use an unordered_map to ensure value pointer validity over insertion.
- std::unordered_map<const MDNode *, LexicalScope> LexicalScopeMap;
+ std::unordered_map<const DILocalScope *, LexicalScope> LexicalScopeMap;
/// InlinedLexicalScopeMap - Tracks inlined function scopes in current
/// function.
- std::unordered_map<std::pair<const MDNode *, const MDNode *>, LexicalScope,
- pair_hash<const MDNode *, const MDNode *>>
- InlinedLexicalScopeMap;
+ std::unordered_map<std::pair<const DILocalScope *, const DILocation *>,
+ LexicalScope,
+ pair_hash<const DILocalScope *, const DILocation *>>
+ InlinedLexicalScopeMap;
/// AbstractScopeMap - These scopes are not included LexicalScopeMap.
// Use an unordered_map to ensure value pointer validity over insertion.
- std::unordered_map<const MDNode *, LexicalScope> AbstractScopeMap;
+ std::unordered_map<const DILocalScope *, LexicalScope> AbstractScopeMap;
/// AbstractScopesList - Tracks abstract scopes constructed while processing
/// a function.
diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h
index e7ccbfa617e5..fee131e4a3c6 100644
--- a/include/llvm/CodeGen/LinkAllCodegenComponents.h
+++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h
@@ -36,6 +36,7 @@ namespace {
(void) llvm::createGreedyRegisterAllocator();
(void) llvm::createDefaultPBQPRegisterAllocator();
+ llvm::linkCoreCLRGC();
llvm::linkOcamlGC();
llvm::linkErlangGC();
llvm::linkShadowStackGC();
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index ce9845ee1673..9b8b91c9b80e 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/include/llvm/CodeGen/LiveInterval.h
@@ -27,6 +27,7 @@
#include "llvm/Support/Allocator.h"
#include <cassert>
#include <climits>
+#include <set>
namespace llvm {
class CoalescerPair;
@@ -194,6 +195,12 @@ namespace llvm {
Segments segments; // the liveness segments
VNInfoList valnos; // value#'s
+ // The segment set is used temporarily to accelerate initial computation
+ // of live ranges of physical registers in computeRegUnitRange.
+ // After that the set is flushed to the segment vector and deleted.
+ typedef std::set<Segment> SegmentSet;
+ std::unique_ptr<SegmentSet> segmentSet;
+
typedef Segments::iterator iterator;
iterator begin() { return segments.begin(); }
iterator end() { return segments.end(); }
@@ -211,12 +218,16 @@ namespace llvm {
const_vni_iterator vni_end() const { return valnos.end(); }
/// Constructs a new LiveRange object.
- LiveRange() {
- }
+ LiveRange(bool UseSegmentSet = false)
+ : segmentSet(UseSegmentSet ? llvm::make_unique<SegmentSet>()
+ : nullptr) {}
/// Constructs a new LiveRange object by copying segments and valnos from
/// another LiveRange.
LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) {
+ assert(Other.segmentSet == nullptr &&
+ "Copying of LiveRanges with active SegmentSets is not supported");
+
// Duplicate valnos.
for (const VNInfo *VNI : Other.valnos) {
createValueCopy(VNI, Allocator);
@@ -437,14 +448,12 @@ namespace llvm {
/// Add the specified Segment to this range, merging segments as
/// appropriate. This returns an iterator to the inserted segment (which
/// may have grown since it was inserted).
- iterator addSegment(Segment S) {
- return addSegmentFrom(S, segments.begin());
- }
+ iterator addSegment(Segment S);
- /// extendInBlock - If this range is live before Kill in the basic block
- /// that starts at StartIdx, extend it to be live up to Kill, and return
- /// the value. If there is no segment before Kill, return NULL.
- VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill);
+ /// If this range is live before @p Use in the basic block that starts at
+ /// @p StartIdx, extend it to be live up to @p Use, and return the value. If
+ /// there is no segment before @p Use, return nullptr.
+ VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Use);
/// join - Join two live ranges (this, and other) together. This applies
/// mappings to the value numbers in the LHS/RHS ranges as specified. If
@@ -540,6 +549,12 @@ namespace llvm {
return thisIndex < otherIndex;
}
+ /// Flush segment set into the regular segment vector.
+ /// The method is to be called after the live range
+ /// has been created, if use of the segment set was
+ /// activated in the constructor of the live range.
+ void flushSegmentSet();
+
void print(raw_ostream &OS) const;
void dump() const;
@@ -557,10 +572,8 @@ namespace llvm {
void append(const LiveRange::Segment S);
private:
-
- iterator addSegmentFrom(Segment S, iterator From);
- void extendSegmentEndTo(iterator I, SlotIndex NewEnd);
- iterator extendSegmentStartTo(iterator I, SlotIndex NewStr);
+ friend class LiveRangeUpdater;
+ void addSegmentToSet(Segment S);
void markValNoForDeletion(VNInfo *V);
};
@@ -606,6 +619,10 @@ namespace llvm {
LiveInterval(unsigned Reg, float Weight)
: SubRanges(nullptr), reg(Reg), weight(Weight) {}
+ ~LiveInterval() {
+ clearSubRanges();
+ }
+
template<typename T>
class SingleLinkedListIterator {
T *P;
@@ -681,9 +698,7 @@ namespace llvm {
}
/// Removes all subregister liveness information.
- void clearSubRanges() {
- SubRanges = nullptr;
- }
+ void clearSubRanges();
/// Removes all subranges without any segments (subranges without segments
/// are not considered valid and should only exist temporarily).
@@ -726,13 +741,14 @@ namespace llvm {
#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;
}
+
+ /// Free memory held by SubRange.
+ void freeSubRange(SubRange *S);
};
inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) {
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index d8c921fce313..9673f80e0856 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -27,12 +27,15 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <cmath>
#include <iterator>
namespace llvm {
+extern cl::opt<bool> UseSegmentSetForPhysRegs;
+
class AliasAnalysis;
class BitVector;
class BlockFrequency;
@@ -97,7 +100,7 @@ namespace llvm {
public:
static char ID; // Pass identification, replacement for typeid
LiveIntervals();
- virtual ~LiveIntervals();
+ ~LiveIntervals() override;
// Calculate the spill weight to assign to a single instruction.
static float getSpillWeight(bool isDef, bool isUse,
@@ -181,12 +184,6 @@ namespace llvm {
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 {
return Indexes;
}
@@ -383,7 +380,8 @@ namespace llvm {
LiveRange *LR = RegUnitRanges[Unit];
if (!LR) {
// Compute missing ranges on demand.
- RegUnitRanges[Unit] = LR = new LiveRange();
+ // Use segment set to speed-up initial computation of the live range.
+ RegUnitRanges[Unit] = LR = new LiveRange(UseSegmentSetForPhysRegs);
computeRegUnitRange(*LR, Unit);
}
return *LR;
@@ -399,6 +397,15 @@ namespace llvm {
return RegUnitRanges[Unit];
}
+ /// Remove value numbers and related live segments starting at position
+ /// @p Pos that are part of any liverange of physical register @p Reg or one
+ /// of its subregisters.
+ void removePhysRegDefAt(unsigned Reg, SlotIndex Pos);
+
+ /// Remove value number and related live segments of @p LI and its subranges
+ /// that start at position @p Pos.
+ void removeVRegDefAt(LiveInterval &LI, SlotIndex Pos);
+
private:
/// Compute live intervals for all virtual registers.
void computeVirtRegs();
diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h
index 1381c46a2750..967f0cbac719 100644
--- a/include/llvm/CodeGen/LiveIntervalUnion.h
+++ b/include/llvm/CodeGen/LiveIntervalUnion.h
@@ -179,8 +179,8 @@ public:
}
private:
- Query(const Query&) LLVM_DELETED_FUNCTION;
- void operator=(const Query&) LLVM_DELETED_FUNCTION;
+ Query(const Query&) = delete;
+ void operator=(const Query&) = delete;
};
// Array of LiveIntervalUnions.
diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h
index 91e4ddcde170..6ffd3eeea351 100644
--- a/include/llvm/CodeGen/LivePhysRegs.h
+++ b/include/llvm/CodeGen/LivePhysRegs.h
@@ -44,8 +44,8 @@ class LivePhysRegs {
const TargetRegisterInfo *TRI;
SparseSet<unsigned> LiveRegs;
- LivePhysRegs(const LivePhysRegs&) LLVM_DELETED_FUNCTION;
- LivePhysRegs &operator=(const LivePhysRegs&) LLVM_DELETED_FUNCTION;
+ LivePhysRegs(const LivePhysRegs&) = delete;
+ LivePhysRegs &operator=(const LivePhysRegs&) = delete;
public:
/// \brief Constructs a new empty LivePhysRegs set.
LivePhysRegs() : TRI(nullptr), LiveRegs() {}
@@ -57,9 +57,9 @@ public:
}
/// \brief Clear and initialize the LivePhysRegs set.
- void init(const TargetRegisterInfo *_TRI) {
- assert(_TRI && "Invalid TargetRegisterInfo pointer.");
- TRI = _TRI;
+ void init(const TargetRegisterInfo *TRI) {
+ assert(TRI && "Invalid TargetRegisterInfo pointer.");
+ this->TRI = TRI;
LiveRegs.clear();
LiveRegs.setUniverse(TRI->getNumRegs());
}
@@ -93,7 +93,8 @@ public:
}
/// \brief Removes physical registers clobbered by the regmask operand @p MO.
- void removeRegsInMask(const MachineOperand &MO);
+ void removeRegsInMask(const MachineOperand &MO,
+ SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers);
/// \brief Returns true if register @p Reg is contained in the set. This also
/// works if only the super register of @p Reg has been defined, because we
@@ -109,7 +110,11 @@ public:
/// instruction(bundle): Remove killed-uses, add defs. This is the not
/// recommended way, because it depends on accurate kill flags. If possible
/// use stepBackwards() instead of this function.
- void stepForward(const MachineInstr &MI);
+ /// The clobbers set will be the list of registers either defined or clobbered
+ /// by a regmask. The operand will identify whether this is a regmask or
+ /// register operand.
+ void stepForward(const MachineInstr &MI,
+ SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> &Clobbers);
/// \brief Adds all live-in registers of basic block @p MBB.
void addLiveIns(const MachineBasicBlock *MBB) {
diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h
index 44c3c4eaf7b1..de855f2fe7a0 100644
--- a/include/llvm/CodeGen/LiveRangeEdit.h
+++ b/include/llvm/CodeGen/LiveRangeEdit.h
@@ -122,7 +122,7 @@ public:
MRI.setDelegate(this);
}
- ~LiveRangeEdit() { MRI.resetDelegate(this); }
+ ~LiveRangeEdit() override { MRI.resetDelegate(this); }
LiveInterval &getParent() const {
assert(Parent && "No parent LiveInterval");
diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h
index df683983fa53..f495507c66ec 100644
--- a/include/llvm/CodeGen/LiveStackAnalysis.h
+++ b/include/llvm/CodeGen/LiveStackAnalysis.h
@@ -21,6 +21,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <map>
+#include <unordered_map>
namespace llvm {
@@ -33,7 +34,7 @@ namespace llvm {
/// S2IMap - Stack slot indices to live interval mapping.
///
- typedef std::map<int, LiveInterval> SS2IntervalMap;
+ typedef std::unordered_map<int, LiveInterval> SS2IntervalMap;
SS2IntervalMap S2IMap;
/// S2RCMap - Stack slot indices to register class mapping.
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index 1440b967aea2..357aef0ee60d 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -315,9 +315,18 @@ public:
// LiveIn management methods.
- /// addLiveIn - Add the specified register as a live in. Note that it
- /// is an error to add the same register to the same set more than once.
- void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); }
+ /// Adds the specified register as a live in. Note that it is an error to add
+ /// the same register to the same set more than once unless the intention is
+ /// to call sortUniqueLiveIns after all registers are added.
+ void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); }
+
+ /// Sorts and uniques the LiveIns vector. It can be significantly faster to do
+ /// this than repeatedly calling isLiveIn before calling addLiveIn for every
+ /// LiveIn insertion.
+ void sortUniqueLiveIns() {
+ std::sort(LiveIns.begin(), LiveIns.end());
+ LiveIns.erase(std::unique(LiveIns.begin(), LiveIns.end()), LiveIns.end());
+ }
/// Add PhysReg as live in to this block, and ensure that there is a copy of
/// PhysReg to a virtual register of class RC. Return the virtual register
@@ -624,17 +633,18 @@ public:
///< neighborhood.
};
- /// computeRegisterLiveness - Return whether (physical) register \c Reg
- /// has been <def>ined and not <kill>ed as of just before \c MI.
+ /// Return whether (physical) register \p Reg has been <def>ined and not
+ /// <kill>ed as of just before \p Before.
///
- /// Search is localised to a neighborhood of
- /// \c Neighborhood instructions before (searching for defs or kills) and
- /// Neighborhood instructions after (searching just for defs) MI.
+ /// Search is localised to a neighborhood of \p Neighborhood instructions
+ /// before (searching for defs or kills) and \p Neighborhood instructions
+ /// after (searching just for defs) \p Before.
///
- /// \c Reg must be a physical register.
+ /// \p Reg must be a physical register.
LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI,
- unsigned Reg, MachineInstr *MI,
- unsigned Neighborhood=10);
+ unsigned Reg,
+ const_iterator Before,
+ unsigned Neighborhood=10) const;
// Debugging methods.
void dump() const;
diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
index 1aef689eb7a4..feb394e7a69e 100644
--- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
+++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
@@ -35,7 +35,7 @@ public:
MachineBlockFrequencyInfo();
- ~MachineBlockFrequencyInfo();
+ ~MachineBlockFrequencyInfo() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h
index e099e716c63d..4131194a0c0f 100644
--- a/include/llvm/CodeGen/MachineDominanceFrontier.h
+++ b/include/llvm/CodeGen/MachineDominanceFrontier.h
@@ -26,8 +26,8 @@ public:
typedef DominanceFrontierBase<MachineBasicBlock>::iterator iterator;
typedef DominanceFrontierBase<MachineBasicBlock>::const_iterator const_iterator;
- void operator=(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION;
- MachineDominanceFrontier(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION;
+ void operator=(const MachineDominanceFrontier &) = delete;
+ MachineDominanceFrontier(const MachineDominanceFrontier &) = delete;
static char ID;
diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h
index a6980a6daeac..4428fa618fb0 100644
--- a/include/llvm/CodeGen/MachineDominators.h
+++ b/include/llvm/CodeGen/MachineDominators.h
@@ -45,9 +45,6 @@ class MachineDominatorTree : public MachineFunctionPass {
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.
@@ -67,74 +64,7 @@ class MachineDominatorTree : public MachineFunctionPass {
/// 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();
- }
+ void applySplitCriticalEdges() const;
public:
static char ID; // Pass ID, replacement for typeid
@@ -142,7 +72,7 @@ public:
MachineDominatorTree();
- ~MachineDominatorTree();
+ ~MachineDominatorTree() override;
DominatorTreeBase<MachineBasicBlock> &getBase() {
applySplitCriticalEdges();
@@ -307,7 +237,7 @@ public:
(void)Inserted;
assert(Inserted &&
"A basic block inserted via edge splitting cannot appear twice");
- CriticalEdgesToSplit.push_back(CriticalEdge(FromBB, ToBB, NewBB));
+ CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB});
}
};
diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h
index 667736021f92..40f3b4944cc1 100644
--- a/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/include/llvm/CodeGen/MachineFrameInfo.h
@@ -246,6 +246,21 @@ class MachineFrameInfo {
/// True if this is a varargs function that contains a musttail call.
bool HasMustTailInVarArgFunc;
+ /// True if this function contains a tail call. If so immutable objects like
+ /// function arguments are no longer so. A tail call *can* override fixed
+ /// stack objects like arguments so we can't treat them as immutable.
+ bool HasTailCall;
+
+ /// Not null, if shrink-wrapping found a better place for the prologue.
+ MachineBasicBlock *Save;
+ /// Not null, if shrink-wrapping found a better place for the epilogue.
+ MachineBasicBlock *Restore;
+
+ /// Check if it exists a path from \p MBB leading to the basic
+ /// block with a SavePoint (a.k.a. prologue).
+ bool isBeforeSavePoint(const MachineFunction &MF,
+ const MachineBasicBlock &MBB) const;
+
public:
explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign,
bool RealignOpt)
@@ -269,6 +284,9 @@ public:
HasInlineAsmWithSPAdjust = false;
HasVAStart = false;
HasMustTailInVarArgFunc = false;
+ Save = nullptr;
+ Restore = nullptr;
+ HasTailCall = false;
}
/// hasStackObjects - Return true if there are any stack objects in this
@@ -496,6 +514,10 @@ public:
bool hasMustTailInVarArgFunc() const { return HasMustTailInVarArgFunc; }
void setHasMustTailInVarArgFunc(bool B) { HasMustTailInVarArgFunc = B; }
+ /// Returns true if the function contains a tail call.
+ bool hasTailCall() const { return HasTailCall; }
+ void setHasTailCall() { HasTailCall = true; }
+
/// 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
@@ -516,10 +538,6 @@ public:
/// on the stack. Returns an index with a negative value.
int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset);
- /// Allocates memory at a fixed, target-specific offset from the frame
- /// pointer. Marks the function as having its frame address taken.
- int CreateFrameAllocation(uint64_t Size);
-
/// isFixedObjectIndex - Returns true if the specified index corresponds to a
/// fixed stack object.
bool isFixedObjectIndex(int ObjectIdx) const {
@@ -537,6 +555,9 @@ public:
/// isImmutableObjectIndex - Returns true if the specified index corresponds
/// to an immutable object.
bool isImmutableObjectIndex(int ObjectIdx) const {
+ // Tail calling functions can clobber their function arguments.
+ if (HasTailCall)
+ return false;
assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
"Invalid Object Idx!");
return Objects[ObjectIdx+NumFixedObjects].isImmutable;
@@ -601,6 +622,11 @@ public:
void setCalleeSavedInfoValid(bool v) { CSIValid = v; }
+ MachineBasicBlock *getSavePoint() const { return Save; }
+ void setSavePoint(MachineBasicBlock *NewSave) { Save = NewSave; }
+ MachineBasicBlock *getRestorePoint() const { return Restore; }
+ void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; }
+
/// getPristineRegs - Return a set of physical registers that are pristine on
/// entry to the MBB.
///
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index 4e9ff9ebb4fe..94610cabf566 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -145,8 +145,8 @@ class MachineFunction {
/// True if the function includes any inline assembly.
bool HasInlineAsm;
- MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION;
- void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION;
+ MachineFunction(const MachineFunction &) = delete;
+ void operator=(const MachineFunction&) = delete;
public:
MachineFunction(const Function *Fn, const TargetMachine &TM,
unsigned FunctionNum, MachineModuleInfo &MMI);
@@ -176,6 +176,13 @@ public:
const TargetSubtargetInfo &getSubtarget() const { return *STI; }
void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; }
+ /// getSubtarget - This method returns a pointer to the specified type of
+ /// TargetSubtargetInfo. In debug builds, it verifies that the object being
+ /// returned is of the correct type.
+ template<typename STC> const STC &getSubtarget() const {
+ return *static_cast<const STC *>(STI);
+ }
+
/// getRegInfo - Return information about the registers currently in use.
///
MachineRegisterInfo &getRegInfo() { return *RegInfo; }
diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h
index 36f1c6627096..023eeb1b4d0e 100644
--- a/include/llvm/CodeGen/MachineFunctionAnalysis.h
+++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h
@@ -31,7 +31,7 @@ private:
public:
static char ID;
explicit MachineFunctionAnalysis(const TargetMachine &tm);
- ~MachineFunctionAnalysis();
+ ~MachineFunctionAnalysis() override;
MachineFunction &getMF() const { return *MF; }
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index bcf1f5caaa8c..e57257c76bc7 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -42,7 +42,7 @@ class MachineFunction;
class MachineMemOperand;
//===----------------------------------------------------------------------===//
-/// MachineInstr - Representation of each machine instruction.
+/// Representation of each machine instruction.
///
/// This class isn't a POD type, but it must have a trivial destructor. When a
/// MachineFunction is deleted, all the contained MachineInstrs are deallocated
@@ -93,25 +93,25 @@ private:
DebugLoc debugLoc; // Source line information.
- MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION;
- void operator=(const MachineInstr&) LLVM_DELETED_FUNCTION;
+ MachineInstr(const MachineInstr&) = delete;
+ void operator=(const MachineInstr&) = delete;
// Use MachineFunction::DeleteMachineInstr() instead.
- ~MachineInstr() LLVM_DELETED_FUNCTION;
+ ~MachineInstr() = delete;
// Intrusive list support
friend struct ilist_traits<MachineInstr>;
friend struct ilist_traits<MachineBasicBlock>;
void setParent(MachineBasicBlock *P) { Parent = P; }
- /// MachineInstr ctor - This constructor creates a copy of the given
+ /// This constructor creates a copy of the given
/// MachineInstr in the given MachineFunction.
MachineInstr(MachineFunction &, const MachineInstr &);
- /// MachineInstr ctor - This constructor create a MachineInstr and add the
- /// implicit operands. It reserves space for number of operands specified by
+ /// This constructor create a MachineInstr and add the implicit operands.
+ /// It reserves space for number of operands specified by
/// MCInstrDesc. An explicit DebugLoc is supplied.
- MachineInstr(MachineFunction&, const MCInstrDesc &MCID,
- const DebugLoc dl, bool NoImp = false);
+ MachineInstr(MachineFunction &, const MCInstrDesc &MCID, DebugLoc dl,
+ bool NoImp = false);
// MachineInstrs are pool-allocated and owned by MachineFunction.
friend class MachineFunction;
@@ -120,43 +120,38 @@ public:
const MachineBasicBlock* getParent() const { return Parent; }
MachineBasicBlock* getParent() { return Parent; }
- /// getAsmPrinterFlags - Return the asm printer flags bitvector.
- ///
+ /// Return the asm printer flags bitvector.
uint8_t getAsmPrinterFlags() const { return AsmPrinterFlags; }
- /// clearAsmPrinterFlags - clear the AsmPrinter bitvector
- ///
+ /// Clear the AsmPrinter bitvector.
void clearAsmPrinterFlags() { AsmPrinterFlags = 0; }
- /// getAsmPrinterFlag - Return whether an AsmPrinter flag is set.
- ///
+ /// Return whether an AsmPrinter flag is set.
bool getAsmPrinterFlag(CommentFlag Flag) const {
return AsmPrinterFlags & Flag;
}
- /// setAsmPrinterFlag - Set a flag for the AsmPrinter.
- ///
+ /// Set a flag for the AsmPrinter.
void setAsmPrinterFlag(CommentFlag Flag) {
AsmPrinterFlags |= (uint8_t)Flag;
}
- /// clearAsmPrinterFlag - clear specific AsmPrinter flags
- ///
+ /// Clear specific AsmPrinter flags.
void clearAsmPrinterFlag(CommentFlag Flag) {
AsmPrinterFlags &= ~Flag;
}
- /// getFlags - Return the MI flags bitvector.
+ /// Return the MI flags bitvector.
uint8_t getFlags() const {
return Flags;
}
- /// getFlag - Return whether an MI flag is set.
+ /// Return whether an MI flag is set.
bool getFlag(MIFlag Flag) const {
return Flags & Flag;
}
- /// setFlag - Set a MI flag.
+ /// Set a MI flag.
void setFlag(MIFlag Flag) {
Flags |= (uint8_t)Flag;
}
@@ -172,8 +167,7 @@ public:
Flags &= ~((uint8_t)Flag);
}
- /// isInsideBundle - Return true if MI is in a bundle (but not the first MI
- /// in a bundle).
+ /// Return true if MI is in a bundle (but not the first MI in a bundle).
///
/// A bundle looks like this before it's finalized:
/// ----------------
@@ -212,7 +206,7 @@ public:
return getFlag(BundledPred);
}
- /// isBundled - Return true if this instruction part of a bundle. This is true
+ /// Return true if this instruction part of a bundle. This is true
/// if either itself or its following instruction is marked "InsideBundle".
bool isBundled() const {
return isBundledWithPred() || isBundledWithSucc();
@@ -240,30 +234,25 @@ public:
/// Break bundle below this instruction.
void unbundleFromSucc();
- /// getDebugLoc - Returns the debug location id of this MachineInstr.
- ///
- DebugLoc getDebugLoc() const { return debugLoc; }
+ /// Returns the debug location id of this MachineInstr.
+ const DebugLoc &getDebugLoc() const { return debugLoc; }
- /// \brief Return the debug variable referenced by
+ /// Return the debug variable referenced by
/// this DBG_VALUE instruction.
- DIVariable getDebugVariable() const {
+ const DILocalVariable *getDebugVariable() const {
assert(isDebugValue() && "not a DBG_VALUE");
- DIVariable Var(getOperand(2).getMetadata());
- assert(Var.Verify() && "not a DIVariable");
- return Var;
+ return cast<DILocalVariable>(getOperand(2).getMetadata());
}
- /// \brief Return the complex address expression referenced by
+ /// Return the complex address expression referenced by
/// this DBG_VALUE instruction.
- DIExpression getDebugExpression() const {
+ const DIExpression *getDebugExpression() const {
assert(isDebugValue() && "not a DBG_VALUE");
- DIExpression Expr(getOperand(3).getMetadata());
- assert(Expr.Verify() && "not a DIExpression");
- return Expr;
+ return cast<DIExpression>(getOperand(3).getMetadata());
}
- /// emitError - Emit an error referring to the source location of this
- /// instruction. This should only be used for inline assembly that is somehow
+ /// Emit an error referring to the source location of this instruction.
+ /// This should only be used for inline assembly that is somehow
/// impossible to compile. Other errors should have been handled much
/// earlier.
///
@@ -271,13 +260,11 @@ public:
///
void emitError(StringRef Msg) const;
- /// getDesc - Returns the target instruction descriptor of this
- /// MachineInstr.
+ /// Returns the target instruction descriptor of this MachineInstr.
const MCInstrDesc &getDesc() const { return *MCID; }
- /// getOpcode - Returns the opcode of this MachineInstr.
- ///
- int getOpcode() const { return MCID->Opcode; }
+ /// Returns the opcode of this MachineInstr.
+ unsigned getOpcode() const { return MCID->Opcode; }
/// Access to explicit operands of the instruction.
///
@@ -292,8 +279,7 @@ public:
return Operands[i];
}
- /// getNumExplicitOperands - Returns the number of non-implicit operands.
- ///
+ /// Returns the number of non-implicit operands.
unsigned getNumExplicitOperands() const;
/// iterator/begin/end - Iterate over all operands of a machine instruction.
@@ -357,8 +343,7 @@ public:
return iterator_range<mmo_iterator>(memoperands_begin(), memoperands_end());
}
- /// hasOneMemOperand - Return true if this instruction has exactly one
- /// MachineMemOperand.
+ /// Return true if this instruction has exactly one MachineMemOperand.
bool hasOneMemOperand() const {
return NumMemRefs == 1;
}
@@ -372,7 +357,7 @@ public:
AllInBundle // Return true if all instructions in bundle have property
};
- /// hasProperty - Return true if the instruction (or in the case of a bundle,
+ /// Return true if the instruction (or in the case of a bundle,
/// the instructions inside the bundle) has the specified property.
/// The first argument is the property being queried.
/// The second argument indicates whether the query should look inside
@@ -386,23 +371,22 @@ public:
return hasPropertyInBundle(1 << MCFlag, Type);
}
- /// isVariadic - Return true if this instruction can have a variable number of
- /// operands. In this case, the variable operands will be after the normal
+ /// Return true if this instruction can have a variable number of operands.
+ /// In this case, the variable operands will be after the normal
/// operands but before the implicit definitions and uses (if any are
/// present).
bool isVariadic(QueryType Type = IgnoreBundle) const {
return hasProperty(MCID::Variadic, Type);
}
- /// hasOptionalDef - Set if this instruction has an optional definition, e.g.
+ /// Set if this instruction has an optional definition, e.g.
/// ARM instructions which can set condition code if 's' bit is set.
bool hasOptionalDef(QueryType Type = IgnoreBundle) const {
return hasProperty(MCID::HasOptionalDef, Type);
}
- /// isPseudo - Return true if this is a pseudo instruction that doesn't
+ /// Return true if this is a pseudo instruction that doesn't
/// correspond to a real machine instruction.
- ///
bool isPseudo(QueryType Type = IgnoreBundle) const {
return hasProperty(MCID::Pseudo, Type);
}
@@ -415,16 +399,15 @@ public:
return hasProperty(MCID::Call, Type);
}
- /// isBarrier - Returns true if the specified instruction stops control flow
+ /// Returns true if the specified instruction stops control flow
/// from executing the instruction immediately following it. Examples include
/// unconditional branches and return instructions.
bool isBarrier(QueryType Type = AnyInBundle) const {
return hasProperty(MCID::Barrier, Type);
}
- /// isTerminator - Returns true if this instruction part of the terminator for
- /// a basic block. Typically this is things like return and branch
- /// instructions.
+ /// Returns true if this instruction part of the terminator for a basic block.
+ /// Typically this is things like return and branch instructions.
///
/// Various passes use this to insert code into the bottom of a basic block,
/// but before control flow occurs.
@@ -432,21 +415,21 @@ public:
return hasProperty(MCID::Terminator, Type);
}
- /// isBranch - Returns true if this is a conditional, unconditional, or
- /// indirect branch. Predicates below can be used to discriminate between
+ /// Returns true if this is a conditional, unconditional, or indirect branch.
+ /// Predicates below can be used to discriminate between
/// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to
/// get more information.
bool isBranch(QueryType Type = AnyInBundle) const {
return hasProperty(MCID::Branch, Type);
}
- /// isIndirectBranch - Return true if this is an indirect branch, such as a
+ /// Return true if this is an indirect branch, such as a
/// branch through a register.
bool isIndirectBranch(QueryType Type = AnyInBundle) const {
return hasProperty(MCID::IndirectBranch, Type);
}
- /// isConditionalBranch - Return true if this is a branch which may fall
+ /// Return true if this is a branch which may fall
/// through to the next instruction or may transfer control flow to some other
/// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more
/// information about this branch.
@@ -454,7 +437,7 @@ public:
return isBranch(Type) & !isBarrier(Type) & !isIndirectBranch(Type);
}
- /// isUnconditionalBranch - Return true if this is a branch which always
+ /// Return true if this is a branch which always
/// transfers control flow to some other block. The
/// TargetInstrInfo::AnalyzeBranch method can be used to get more information
/// about this branch.
@@ -472,43 +455,41 @@ public:
return hasProperty(MCID::Predicable, Type);
}
- /// isCompare - Return true if this instruction is a comparison.
+ /// Return true if this instruction is a comparison.
bool isCompare(QueryType Type = IgnoreBundle) const {
return hasProperty(MCID::Compare, Type);
}
- /// isMoveImmediate - Return true if this instruction is a move immediate
+ /// Return true if this instruction is a move immediate
/// (including conditional moves) instruction.
bool isMoveImmediate(QueryType Type = IgnoreBundle) const {
return hasProperty(MCID::MoveImm, Type);
}
- /// isBitcast - Return true if this instruction is a bitcast instruction.
- ///
+ /// Return true if this instruction is a bitcast instruction.
bool isBitcast(QueryType Type = IgnoreBundle) const {
return hasProperty(MCID::Bitcast, Type);
}
- /// isSelect - Return true if this instruction is a select instruction.
- ///
+ /// Return true if this instruction is a select instruction.
bool isSelect(QueryType Type = IgnoreBundle) const {
return hasProperty(MCID::Select, Type);
}
- /// isNotDuplicable - Return true if this instruction cannot be safely
- /// duplicated. For example, if the instruction has a unique labels attached
+ /// Return true if this instruction cannot be safely duplicated.
+ /// For example, if the instruction has a unique labels attached
/// to it, duplicating it would cause multiple definition errors.
bool isNotDuplicable(QueryType Type = AnyInBundle) const {
return hasProperty(MCID::NotDuplicable, Type);
}
- /// hasDelaySlot - Returns true if the specified instruction has a delay slot
+ /// Returns true if the specified instruction has a delay slot
/// which must be filled by the code generator.
bool hasDelaySlot(QueryType Type = AnyInBundle) const {
return hasProperty(MCID::DelaySlot, Type);
}
- /// canFoldAsLoad - Return true for instructions that can be folded as
+ /// Return true for instructions that can be folded as
/// memory operands in other instructions. The most common use for this
/// is instructions that are simple loads from memory that don't modify
/// the loaded value in any way, but it can also be used for instructions
@@ -567,7 +548,7 @@ public:
// Side Effect Analysis
//===--------------------------------------------------------------------===//
- /// mayLoad - Return true if this instruction could possibly read memory.
+ /// Return true if this instruction could possibly read memory.
/// Instructions with this flag set are not necessarily simple load
/// instructions, they may load a value and modify it, for example.
bool mayLoad(QueryType Type = AnyInBundle) const {
@@ -579,8 +560,7 @@ public:
return hasProperty(MCID::MayLoad, Type);
}
-
- /// mayStore - Return true if this instruction could possibly modify memory.
+ /// Return true if this instruction could possibly modify memory.
/// Instructions with this flag set are not necessarily simple store
/// instructions, they may store a modified value based on their operands, or
/// may not actually modify anything, for example.
@@ -593,11 +573,16 @@ public:
return hasProperty(MCID::MayStore, Type);
}
+ /// Return true if this instruction could possibly read or modify memory.
+ bool mayLoadOrStore(QueryType Type = AnyInBundle) const {
+ return mayLoad(Type) || mayStore(Type);
+ }
+
//===--------------------------------------------------------------------===//
// Flags that indicate whether an instruction can be modified by a method.
//===--------------------------------------------------------------------===//
- /// isCommutable - Return true if this may be a 2- or 3-address
+ /// Return true if this may be a 2- or 3-address
/// instruction (of the form "X = op Y, Z, ..."), which produces the same
/// result if Y and Z are exchanged. If this flag is set, then the
/// TargetInstrInfo::commuteInstruction method may be used to hack on the
@@ -611,7 +596,7 @@ public:
return hasProperty(MCID::Commutable, Type);
}
- /// isConvertibleTo3Addr - Return true if this is a 2-address instruction
+ /// Return true if this is a 2-address instruction
/// which can be changed into a 3-address instruction if needed. Doing this
/// transformation can be profitable in the register allocator, because it
/// means that the instruction can use a 2-address form if possible, but
@@ -629,7 +614,7 @@ public:
return hasProperty(MCID::ConvertibleTo3Addr, Type);
}
- /// usesCustomInsertionHook - Return true if this instruction requires
+ /// Return true if this instruction requires
/// custom insertion support when the DAG scheduler is inserting it into a
/// machine basic block. If this is true for the instruction, it basically
/// means that it is a pseudo instruction used at SelectionDAG time that is
@@ -641,7 +626,7 @@ public:
return hasProperty(MCID::UsesCustomInserter, Type);
}
- /// hasPostISelHook - Return true if this instruction requires *adjustment*
+ /// Return true if this instruction requires *adjustment*
/// after instruction selection by calling a target hook. For example, this
/// can be used to fill in ARM 's' optional operand depending on whether
/// the conditional flag register is used.
@@ -649,8 +634,8 @@ public:
return hasProperty(MCID::HasPostISelHook, Type);
}
- /// isRematerializable - Returns true if this instruction is a candidate for
- /// remat. This flag is deprecated, please don't use it anymore. If this
+ /// 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.
bool isRematerializable(QueryType Type = AllInBundle) const {
@@ -659,9 +644,9 @@ public:
return hasProperty(MCID::Rematerializable, Type);
}
- /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or
- /// less) than a move instruction. This is useful during certain types of
- /// optimizations (e.g., remat during two-address conversion or machine licm)
+ /// Returns true if this instruction has the same cost (or less) than a move
+ /// instruction. This is useful during certain types of optimizations
+ /// (e.g., remat during two-address conversion or machine licm)
/// where we would like to remat or hoist the instruction, but not if it costs
/// more than moving the instruction into the appropriate register. Note, we
/// are not marking copies from and to the same register class with this flag.
@@ -670,7 +655,7 @@ public:
return hasProperty(MCID::CheapAsAMove, Type);
}
- /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands
+ /// Returns true if this instruction source operands
/// have special register allocation requirements that are not captured by the
/// operand register classes. e.g. ARM::STRD's two source registers must be an
/// even / odd pair, ARM::STM registers have to be in ascending order.
@@ -680,7 +665,7 @@ public:
return hasProperty(MCID::ExtraSrcRegAllocReq, Type);
}
- /// hasExtraDefRegAllocReq - Returns true if this instruction def operands
+ /// Returns true if this instruction def operands
/// have special register allocation requirements that are not captured by the
/// operand register classes. e.g. ARM::LDRD's two def registers must be an
/// even / odd pair, ARM::LDM registers have to be in ascending order.
@@ -698,7 +683,7 @@ public:
IgnoreVRegDefs // Ignore virtual register definitions
};
- /// isIdenticalTo - Return true if this instruction is identical to (same
+ /// Return true if this instruction is identical to (same
/// opcode and same operands as) the specified instruction.
bool isIdenticalTo(const MachineInstr *Other,
MICheckType Check = CheckDefs) const;
@@ -739,8 +724,7 @@ public:
bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; }
bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; }
- /// isLabel - Returns true if the MachineInstr represents a label.
- ///
+ /// Returns true if the MachineInstr represents a label.
bool isLabel() const { return isEHLabel() || isGCLabel(); }
bool isCFIInstruction() const {
return getOpcode() == TargetOpcode::CFI_INSTRUCTION;
@@ -789,19 +773,19 @@ public:
return getOpcode() == TargetOpcode::EXTRACT_SUBREG;
}
- /// isCopyLike - Return true if the instruction behaves like a copy.
+ /// Return true if the instruction behaves like a copy.
/// This does not include native copy instructions.
bool isCopyLike() const {
return isCopy() || isSubregToReg();
}
- /// isIdentityCopy - Return true is the instruction is an identity copy.
+ /// Return true is the instruction is an identity copy.
bool isIdentityCopy() const {
return isCopy() && getOperand(0).getReg() == getOperand(1).getReg() &&
getOperand(0).getSubReg() == getOperand(1).getSubReg();
}
- /// isTransient - Return true if this is a transient instruction that is
+ /// Return true if this is a transient instruction that is
/// either very likely to be eliminated during register allocation (such as
/// copy-like instructions), or if this instruction doesn't have an
/// execution-time cost.
@@ -832,8 +816,8 @@ public:
/// skips, 0 for unbundled instructions.
unsigned getBundleSize() const;
- /// readsRegister - Return true if the MachineInstr reads the specified
- /// register. If TargetRegisterInfo is passed, then it also checks if there
+ /// Return true if the MachineInstr reads the specified register.
+ /// If TargetRegisterInfo is passed, then it also checks if there
/// is a read of a super-register.
/// This does not count partial redefines of virtual registers as reads:
/// %reg1024:6 = OP.
@@ -842,30 +826,29 @@ public:
return findRegisterUseOperandIdx(Reg, false, TRI) != -1;
}
- /// readsVirtualRegister - Return true if the MachineInstr reads the specified
- /// virtual register. Take into account that a partial define is a
+ /// Return true if the MachineInstr reads the specified virtual register.
+ /// Take into account that a partial define is a
/// read-modify-write operation.
bool readsVirtualRegister(unsigned Reg) const {
return readsWritesVirtualRegister(Reg).first;
}
- /// readsWritesVirtualRegister - Return a pair of bools (reads, writes)
- /// indicating if this instruction reads or writes Reg. This also considers
- /// partial defines.
+ /// Return a pair of bools (reads, writes) indicating if this instruction
+ /// reads or writes Reg. This also considers partial defines.
/// If Ops is not null, all operand indices for Reg are added.
std::pair<bool,bool> readsWritesVirtualRegister(unsigned Reg,
SmallVectorImpl<unsigned> *Ops = nullptr) const;
- /// killsRegister - Return true if the MachineInstr kills the specified
- /// register. If TargetRegisterInfo is passed, then it also checks if there is
+ /// Return true if the MachineInstr kills the specified register.
+ /// If TargetRegisterInfo is passed, then it also checks if there is
/// a kill of a super-register.
bool killsRegister(unsigned Reg,
const TargetRegisterInfo *TRI = nullptr) const {
return findRegisterUseOperandIdx(Reg, true, TRI) != -1;
}
- /// definesRegister - Return true if the MachineInstr fully defines the
- /// specified register. If TargetRegisterInfo is passed, then it also checks
+ /// Return true if the MachineInstr fully defines the specified register.
+ /// If TargetRegisterInfo is passed, then it also checks
/// if there is a def of a super-register.
/// NOTE: It's ignoring subreg indices on virtual registers.
bool definesRegister(unsigned Reg,
@@ -873,28 +856,28 @@ public:
return findRegisterDefOperandIdx(Reg, false, false, TRI) != -1;
}
- /// modifiesRegister - Return true if the MachineInstr modifies (fully define
- /// or partially define) the specified register.
+ /// Return true if the MachineInstr modifies (fully define or partially
+ /// define) the specified register.
/// NOTE: It's ignoring subreg indices on virtual registers.
bool modifiesRegister(unsigned Reg, const TargetRegisterInfo *TRI) const {
return findRegisterDefOperandIdx(Reg, false, true, TRI) != -1;
}
- /// registerDefIsDead - Returns true if the register is dead in this machine
- /// instruction. If TargetRegisterInfo is passed, then it also checks
+ /// Returns true if the register is dead in this machine instruction.
+ /// If TargetRegisterInfo is passed, then it also checks
/// if there is a dead def of a super-register.
bool registerDefIsDead(unsigned Reg,
const TargetRegisterInfo *TRI = nullptr) const {
return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1;
}
- /// findRegisterUseOperandIdx() - Returns the operand index that is a use of
- /// the specific register or -1 if it is not found. It further tightens
- /// the search criteria to a use that kills the register if isKill is true.
+ /// Returns the operand index that is a use of the specific register or -1
+ /// if it is not found. It further tightens the search criteria to a use
+ /// that kills the register if isKill is true.
int findRegisterUseOperandIdx(unsigned Reg, bool isKill = false,
const TargetRegisterInfo *TRI = nullptr) const;
- /// findRegisterUseOperand - Wrapper for findRegisterUseOperandIdx, it returns
+ /// Wrapper for findRegisterUseOperandIdx, it returns
/// a pointer to the MachineOperand rather than an index.
MachineOperand *findRegisterUseOperand(unsigned Reg, bool isKill = false,
const TargetRegisterInfo *TRI = nullptr) {
@@ -902,17 +885,17 @@ public:
return (Idx == -1) ? nullptr : &getOperand(Idx);
}
- /// findRegisterDefOperandIdx() - Returns the operand index that is a def of
- /// the specified register or -1 if it is not found. If isDead is true, defs
- /// that are not dead are skipped. If Overlap is true, then it also looks for
- /// defs that merely overlap the specified register. If TargetRegisterInfo is
- /// non-null, then it also checks if there is a def of a super-register.
+ /// Returns the operand index that is a def of the specified register or
+ /// -1 if it is not found. If isDead is true, defs that are not dead are
+ /// skipped. If Overlap is true, then it also looks for defs that merely
+ /// overlap the specified register. If TargetRegisterInfo is non-null,
+ /// then it also checks if there is a def of a super-register.
/// This may also return a register mask operand when Overlap is true.
int findRegisterDefOperandIdx(unsigned Reg,
bool isDead = false, bool Overlap = false,
const TargetRegisterInfo *TRI = nullptr) const;
- /// findRegisterDefOperand - Wrapper for findRegisterDefOperandIdx, it returns
+ /// Wrapper for findRegisterDefOperandIdx, it returns
/// a pointer to the MachineOperand rather than an index.
MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false,
const TargetRegisterInfo *TRI = nullptr) {
@@ -920,12 +903,12 @@ public:
return (Idx == -1) ? nullptr : &getOperand(Idx);
}
- /// findFirstPredOperandIdx() - Find the index of the first operand in the
+ /// Find the index of the first operand in the
/// operand list that is used to represent the predicate. It returns -1 if
/// none is found.
int findFirstPredOperandIdx() const;
- /// findInlineAsmFlagIdx() - Find the index of the flag word operand that
+ /// Find the index of the flag word operand that
/// corresponds to operand OpIdx on an inline asm instruction. Returns -1 if
/// getOperand(OpIdx) does not belong to an inline asm operand group.
///
@@ -937,9 +920,9 @@ public:
///
int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = nullptr) const;
- /// getRegClassConstraint - Compute the static register class constraint for
- /// operand OpIdx. For normal instructions, this is derived from the
- /// MCInstrDesc. For inline assembly it is derived from the flag words.
+ /// Compute the static register class constraint for operand OpIdx.
+ /// For normal instructions, this is derived from the MCInstrDesc.
+ /// For inline assembly it is derived from the flag words.
///
/// Returns NULL if the static register classs constraint cannot be
/// determined.
@@ -980,20 +963,20 @@ public:
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI) const;
- /// tieOperands - Add a tie between the register operands at DefIdx and
- /// UseIdx. The tie will cause the register allocator to ensure that the two
+ /// Add a tie between the register operands at DefIdx and UseIdx.
+ /// The tie will cause the register allocator to ensure that the two
/// operands are assigned the same physical register.
///
/// Tied operands are managed automatically for explicit operands in the
/// MCInstrDesc. This method is for exceptional cases like inline asm.
void tieOperands(unsigned DefIdx, unsigned UseIdx);
- /// findTiedOperandIdx - Given the index of a tied register operand, find the
+ /// Given the index of a tied register operand, find the
/// operand it is tied to. Defs are tied to uses and vice versa. Returns the
/// index of the tied operand which must exist.
unsigned findTiedOperandIdx(unsigned OpIdx) const;
- /// isRegTiedToUseOperand - Given the index of a register def operand,
+ /// Given the index of a register def operand,
/// check if the register def is tied to a source operand, due to either
/// two-address elimination or inline assembly constraints. Returns the
/// first tied use operand index by reference if UseOpIdx is not null.
@@ -1007,9 +990,9 @@ public:
return true;
}
- /// isRegTiedToDefOperand - Return true if the use operand of the specified
- /// index is tied to a def operand. It also returns the def operand index by
- /// reference if DefOpIdx is not null.
+ /// Return true if the use operand of the specified index is tied to a def
+ /// operand. It also returns the def operand index by reference if DefOpIdx
+ /// is not null.
bool isRegTiedToDefOperand(unsigned UseOpIdx,
unsigned *DefOpIdx = nullptr) const {
const MachineOperand &MO = getOperand(UseOpIdx);
@@ -1020,16 +1003,15 @@ public:
return true;
}
- /// clearKillInfo - Clears kill flags on all operands.
- ///
+ /// Clears kill flags on all operands.
void clearKillInfo();
- /// substituteRegister - Replace all occurrences of FromReg with ToReg:SubIdx,
+ /// Replace all occurrences of FromReg with ToReg:SubIdx,
/// properly composing subreg indices where necessary.
void substituteRegister(unsigned FromReg, unsigned ToReg, unsigned SubIdx,
const TargetRegisterInfo &RegInfo);
- /// addRegisterKilled - We have determined MI kills a register. Look for the
+ /// We have determined MI kills a register. Look for the
/// operand that uses it and mark it as IsKill. If AddIfNotFound is true,
/// add a implicit operand if it's not found. Returns true if the operand
/// exists / is added.
@@ -1037,23 +1019,31 @@ public:
const TargetRegisterInfo *RegInfo,
bool AddIfNotFound = false);
- /// clearRegisterKills - Clear all kill flags affecting Reg. If RegInfo is
+ /// Clear all kill flags affecting Reg. If RegInfo is
/// provided, this includes super-register kills.
void clearRegisterKills(unsigned Reg, const TargetRegisterInfo *RegInfo);
- /// addRegisterDead - We have determined MI defined a register without a use.
+ /// We have determined MI defined a register without a use.
/// Look for the operand that defines it and mark it as IsDead. If
/// AddIfNotFound is true, add a implicit operand if it's not found. Returns
/// true if the operand exists / is added.
bool addRegisterDead(unsigned Reg, const TargetRegisterInfo *RegInfo,
bool AddIfNotFound = false);
- /// addRegisterDefined - We have determined MI defines a register. Make sure
- /// there is an operand defining Reg.
+ /// Clear all dead flags on operands defining register @p Reg.
+ void clearRegisterDeads(unsigned Reg);
+
+ /// Mark all subregister defs of register @p Reg with the undef flag.
+ /// This function is used when we determined to have a subregister def in an
+ /// otherwise undefined super register.
+ void addRegisterDefReadUndef(unsigned Reg);
+
+ /// We have determined MI defines a register. Make sure there is an operand
+ /// defining Reg.
void addRegisterDefined(unsigned Reg,
const TargetRegisterInfo *RegInfo = nullptr);
- /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as
+ /// Mark every physreg used by this instruction as
/// dead except those in the UsedRegs list.
///
/// On instructions with register mask operands, also add implicit-def
@@ -1061,32 +1051,30 @@ public:
void setPhysRegsDeadExcept(ArrayRef<unsigned> UsedRegs,
const TargetRegisterInfo &TRI);
- /// isSafeToMove - Return true if it is safe to move this instruction. If
+ /// Return true if it is safe to move this instruction. If
/// SawStore is set to true, it means that there is a store (or call) between
/// the instruction's location and its intended destination.
- bool isSafeToMove(const TargetInstrInfo *TII, AliasAnalysis *AA,
- bool &SawStore) const;
+ bool isSafeToMove(AliasAnalysis *AA, bool &SawStore) const;
- /// hasOrderedMemoryRef - Return true if this instruction may have an ordered
+ /// Return true if this instruction may have an ordered
/// or volatile memory reference, or if the information describing the memory
/// reference is not available. Return false if it is known to have no
/// ordered or volatile memory references.
bool hasOrderedMemoryRef() const;
- /// isInvariantLoad - Return true if this instruction is loading from a
+ /// Return true if this instruction is loading from a
/// location whose value is invariant across the function. For example,
/// loading a value from the constant pool or from the argument area of
/// a function if it does not change. This should only return true of *all*
/// loads the instruction does are invariant (if it does multiple loads).
bool isInvariantLoad(AliasAnalysis *AA) const;
- /// isConstantValuePHI - If the specified instruction is a PHI that always
- /// merges together the same virtual register, return the register, otherwise
- /// return 0.
+ /// If the specified instruction is a PHI that always merges together the
+ /// same virtual register, return the register, otherwise return 0.
unsigned isConstantValuePHI() const;
- /// hasUnmodeledSideEffects - Return true if this instruction has side
- /// effects that are not modeled by mayLoad / mayStore, etc.
+ /// Return true if this instruction has side effects that are not modeled
+ /// by mayLoad / mayStore, etc.
/// For all instructions, the property is encoded in MCInstrDesc::Flags
/// (see MCInstrDesc::hasUnmodeledSideEffects(). The only exception is
/// INLINEASM instruction, in which case the side effect property is encoded
@@ -1094,19 +1082,17 @@ public:
///
bool hasUnmodeledSideEffects() const;
- /// allDefsAreDead - Return true if all the defs of this instruction are dead.
- ///
+ /// Return true if all the defs of this instruction are dead.
bool allDefsAreDead() const;
- /// copyImplicitOps - Copy implicit register operands from specified
+ /// Copy implicit register operands from specified
/// instruction to this instruction.
void copyImplicitOps(MachineFunction &MF, const MachineInstr *MI);
//
// Debugging support
//
- void print(raw_ostream &OS, const TargetMachine *TM = nullptr,
- bool SkipOpers = false) const;
+ void print(raw_ostream &OS, bool SkipOpers = false) const;
void dump() const;
//===--------------------------------------------------------------------===//
@@ -1131,44 +1117,41 @@ public:
/// preferred.
void addOperand(const MachineOperand &Op);
- /// setDesc - Replace the instruction descriptor (thus opcode) of
+ /// Replace the instruction descriptor (thus opcode) of
/// the current instruction with a new one.
- ///
void setDesc(const MCInstrDesc &tid) { MCID = &tid; }
- /// setDebugLoc - Replace current source information with new such.
+ /// Replace current source information with new such.
/// Avoid using this, the constructor argument is preferable.
- ///
- void setDebugLoc(const DebugLoc dl) {
- debugLoc = dl;
+ void setDebugLoc(DebugLoc dl) {
+ debugLoc = std::move(dl);
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
}
- /// RemoveOperand - Erase an operand from an instruction, leaving it with one
+ /// Erase an operand from an instruction, leaving it with one
/// fewer operand than it started with.
- ///
void RemoveOperand(unsigned i);
- /// addMemOperand - Add a MachineMemOperand to the machine instruction.
+ /// Add a MachineMemOperand to the machine instruction.
/// This function should be used only occasionally. The setMemRefs function
/// is the primary method for setting up a MachineInstr's MemRefs list.
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO);
- /// setMemRefs - Assign this MachineInstr's memory reference descriptor
- /// list. This does not transfer ownership.
+ /// Assign this MachineInstr's memory reference descriptor list.
+ /// This does not transfer ownership.
void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) {
MemRefs = NewMemRefs;
NumMemRefs = uint8_t(NewMemRefsEnd - NewMemRefs);
assert(NumMemRefs == NewMemRefsEnd - NewMemRefs && "Too many memrefs");
}
-private:
- /// getRegInfo - If this instruction is embedded into a MachineFunction,
- /// return the MachineRegisterInfo object for the current function, otherwise
- /// return null.
- MachineRegisterInfo *getRegInfo();
+ /// Clear this MachineInstr's memory reference descriptor list.
+ void clearMemRefs() {
+ MemRefs = nullptr;
+ NumMemRefs = 0;
+ }
- /// untieRegOperand - Break any tie involving OpIdx.
+ /// Break any tie involving OpIdx.
void untieRegOperand(unsigned OpIdx) {
MachineOperand &MO = getOperand(OpIdx);
if (MO.isReg() && MO.isTied()) {
@@ -1177,22 +1160,27 @@ private:
}
}
- /// addImplicitDefUseOperands - Add all implicit def and use operands to
- /// this instruction.
+
+private:
+ /// If this instruction is embedded into a MachineFunction, return the
+ /// MachineRegisterInfo object for the current function, otherwise
+ /// return null.
+ MachineRegisterInfo *getRegInfo();
+
+ /// Add all implicit def and use operands to this instruction.
void addImplicitDefUseOperands(MachineFunction &MF);
- /// RemoveRegOperandsFromUseLists - Unlink all of the register operands in
- /// this instruction from their respective use lists. This requires that the
- /// operands already be on their use lists.
+ /// Unlink all of the register operands in this instruction from their
+ /// respective use lists. This requires that the operands already be on their
+ /// use lists.
void RemoveRegOperandsFromUseLists(MachineRegisterInfo&);
- /// AddRegOperandsToUseLists - Add all of the register operands in
- /// this instruction from their respective use lists. This requires that the
- /// operands not be on their use lists yet.
+ /// Add all of the register operands in this instruction from their
+ /// respective use lists. This requires that the operands not be on their
+ /// use lists yet.
void AddRegOperandsToUseLists(MachineRegisterInfo&);
- /// hasPropertyInBundle - Slow path for hasProperty when we're dealing with a
- /// bundle.
+ /// Slow path for hasProperty when we're dealing with a bundle.
bool hasPropertyInBundle(unsigned Mask, QueryType Type) const;
/// \brief Implements the logic of getRegClassConstraintEffectForVReg for the
@@ -1203,8 +1191,8 @@ private:
const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const;
};
-/// MachineInstrExpressionTrait - Special DenseMapInfo traits to compare
-/// MachineInstr* by *value* of the instruction rather than by pointer value.
+/// Special DenseMapInfo traits to compare MachineInstr* by *value* of the
+/// instruction rather than by pointer value.
/// The hashing and equality testing functions ignore definitions so this is
/// useful for CSE, etc.
struct MachineInstrExpressionTrait : DenseMapInfo<MachineInstr*> {
diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h
index 8859b6a019ea..47397c6d6743 100644
--- a/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -174,8 +174,9 @@ 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");
+ assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable())
+ : true) &&
+ "first MDNode argument of a DBG_VALUE not a variable");
return *this;
}
@@ -355,8 +356,10 @@ 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");
+ assert(isa<DILocalVariable>(Variable) && "not a variable");
+ assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
+ assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
+ "Expected inlined-at fields to agree");
if (IsIndirect)
return BuildMI(MF, DL, MCID)
.addReg(Reg, RegState::Debug)
@@ -382,8 +385,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
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");
+ assert(isa<DILocalVariable>(Variable) && "not a variable");
+ assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
MachineFunction &MF = *BB.getParent();
MachineInstr *MI =
BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr);
diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h
index 4fbd46b6fb57..f7bcf45d93c5 100644
--- a/include/llvm/CodeGen/MachineLoopInfo.h
+++ b/include/llvm/CodeGen/MachineLoopInfo.h
@@ -74,8 +74,8 @@ class MachineLoopInfo : public MachineFunctionPass {
LoopInfoBase<MachineBasicBlock, MachineLoop> LI;
friend class LoopBase<MachineBasicBlock, MachineLoop>;
- void operator=(const MachineLoopInfo &) LLVM_DELETED_FUNCTION;
- MachineLoopInfo(const MachineLoopInfo &) LLVM_DELETED_FUNCTION;
+ void operator=(const MachineLoopInfo &) = delete;
+ MachineLoopInfo(const MachineLoopInfo &) = delete;
public:
static char ID; // Pass identification, replacement for typeid
diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h
index eb5086cbe5a5..a16c294a0749 100644
--- a/include/llvm/CodeGen/MachineMemOperand.h
+++ b/include/llvm/CodeGen/MachineMemOperand.h
@@ -199,6 +199,24 @@ public:
/// Profile - Gather unique data for the object.
///
void Profile(FoldingSetNodeID &ID) const;
+
+ friend bool operator==(const MachineMemOperand &LHS,
+ const MachineMemOperand &RHS) {
+ return LHS.getValue() == RHS.getValue() &&
+ LHS.getPseudoValue() == RHS.getPseudoValue() &&
+ LHS.getSize() == RHS.getSize() &&
+ LHS.getOffset() == RHS.getOffset() &&
+ LHS.getFlags() == RHS.getFlags() &&
+ LHS.getAAInfo() == RHS.getAAInfo() &&
+ LHS.getRanges() == RHS.getRanges() &&
+ LHS.getAlignment() == RHS.getAlignment() &&
+ LHS.getAddrSpace() == RHS.getAddrSpace();
+ }
+
+ friend bool operator!=(const MachineMemOperand &LHS,
+ const MachineMemOperand &RHS) {
+ return !(LHS == RHS);
+ }
};
raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MRO);
diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h
index 584ce65c9d17..ce45c1659153 100644
--- a/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/include/llvm/CodeGen/MachineModuleInfo.h
@@ -35,6 +35,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/ValueHandle.h"
@@ -50,6 +51,7 @@ namespace llvm {
// Forward declarations.
class Constant;
class GlobalVariable;
+class BlockAddress;
class MDNode;
class MMIAddrLabelMap;
class MachineBasicBlock;
@@ -57,21 +59,33 @@ class MachineFunction;
class Module;
class PointerType;
class StructType;
+struct WinEHFuncInfo;
+
+struct SEHHandler {
+ // Filter or finally function. Null indicates a catch-all.
+ const Function *FilterOrFinally;
+
+ // Address of block to recover at. Null for a finally handler.
+ const BlockAddress *RecoverBA;
+};
//===----------------------------------------------------------------------===//
/// LandingPadInfo - This structure is used to retain landing pad info for
/// the current function.
///
struct LandingPadInfo {
- MachineBasicBlock *LandingPadBlock; // Landing pad block.
- SmallVector<MCSymbol*, 1> BeginLabels; // Labels prior to invoke.
- SmallVector<MCSymbol*, 1> EndLabels; // Labels after invoke.
- MCSymbol *LandingPadLabel; // Label at beginning of landing pad.
- const Function *Personality; // Personality function.
- std::vector<int> TypeIds; // List of type ids (filters negative)
+ MachineBasicBlock *LandingPadBlock; // Landing pad block.
+ SmallVector<MCSymbol *, 1> BeginLabels; // Labels prior to invoke.
+ SmallVector<MCSymbol *, 1> EndLabels; // Labels after invoke.
+ SmallVector<SEHHandler, 1> SEHHandlers; // SEH handlers active at this lpad.
+ MCSymbol *LandingPadLabel; // Label at beginning of landing pad.
+ const Function *Personality; // Personality function.
+ std::vector<int> TypeIds; // List of type ids (filters negative).
+ int WinEHState; // WinEH specific state number.
explicit LandingPadInfo(MachineBasicBlock *MBB)
- : LandingPadBlock(MBB), LandingPadLabel(nullptr), Personality(nullptr) {}
+ : LandingPadBlock(MBB), LandingPadLabel(nullptr), Personality(nullptr),
+ WinEHState(-1) {}
};
//===----------------------------------------------------------------------===//
@@ -86,7 +100,10 @@ public:
virtual ~MachineModuleInfoImpl();
typedef std::vector<std::pair<MCSymbol*, StubValueTy> > SymbolListTy;
protected:
- static SymbolListTy GetSortedStubs(const DenseMap<MCSymbol*, StubValueTy>&);
+
+ /// Return the entries from a DenseMap in a deterministic sorted orer.
+ /// Clears the map.
+ static SymbolListTy getSortedStubs(DenseMap<MCSymbol*, StubValueTy>&);
};
//===----------------------------------------------------------------------===//
@@ -168,16 +185,21 @@ class MachineModuleInfo : public ImmutablePass {
/// details.
bool UsesMorestackAddr;
+ EHPersonality PersonalityTypeCache;
+
+ DenseMap<const Function *, std::unique_ptr<WinEHFuncInfo>> FuncInfoMap;
+
public:
static char ID; // Pass identification, replacement for typeid
struct VariableDbgInfo {
- TrackingMDNodeRef Var;
- TrackingMDNodeRef Expr;
+ const DILocalVariable *Var;
+ const DIExpression *Expr;
unsigned Slot;
- DebugLoc Loc;
+ const DILocation *Loc;
- VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc)
+ VariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr,
+ unsigned Slot, const DILocation *Loc)
: Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {}
};
typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy;
@@ -187,7 +209,7 @@ public:
// Real constructor.
MachineModuleInfo(const MCAsmInfo &MAI, const MCRegisterInfo &MRI,
const MCObjectFileInfo *MOFI);
- ~MachineModuleInfo();
+ ~MachineModuleInfo() override;
// Initialization and Finalization
bool doInitialization(Module &) override;
@@ -203,6 +225,12 @@ public:
void setModule(const Module *M) { TheModule = M; }
const Module *getModule() const { return TheModule; }
+ const Function *getWinEHParent(const Function *F) const;
+ WinEHFuncInfo &getWinEHFuncInfo(const Function *F);
+ bool hasWinEHFuncInfo(const Function *F) const {
+ return FuncInfoMap.count(getWinEHParent(F)) > 0;
+ }
+
/// getInfo - Keep track of various per-function pieces of information for
/// backends that would like to do so.
///
@@ -300,6 +328,8 @@ public:
void addPersonality(MachineBasicBlock *LandingPad,
const Function *Personality);
+ void addWinEHState(MachineBasicBlock *LandingPad, int State);
+
/// getPersonalityIndex - Get index of the current personality function inside
/// Personalitites array
unsigned getPersonalityIndex() const;
@@ -330,6 +360,12 @@ public:
///
void addCleanup(MachineBasicBlock *LandingPad);
+ void addSEHCatchHandler(MachineBasicBlock *LandingPad, const Function *Filter,
+ const BlockAddress *RecoverLabel);
+
+ void addSEHCleanupHandler(MachineBasicBlock *LandingPad,
+ const Function *Cleanup);
+
/// getTypeIDFor - Return the type id for the specified typeinfo. This is
/// function wide.
unsigned getTypeIDFor(const GlobalValue *TI);
@@ -407,10 +443,13 @@ public:
/// of one is required to emit exception handling info.
const Function *getPersonality() const;
+ /// Classify the personality function amongst known EH styles.
+ EHPersonality getPersonalityType();
+
/// setVariableDbgInfo - Collect information used to emit debugging
/// information of a variable.
- void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot,
- DebugLoc Loc) {
+ void setVariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr,
+ unsigned Slot, const DILocation *Loc) {
VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc);
}
diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h
index 7afc7eb6b357..a67f9b5666b1 100644
--- a/include/llvm/CodeGen/MachineModuleInfoImpls.h
+++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h
@@ -58,14 +58,14 @@ namespace llvm {
}
/// Accessor methods to return the set of stubs in sorted order.
- SymbolListTy GetFnStubList() const {
- return GetSortedStubs(FnStubs);
+ SymbolListTy GetFnStubList() {
+ return getSortedStubs(FnStubs);
}
- SymbolListTy GetGVStubList() const {
- return GetSortedStubs(GVStubs);
+ SymbolListTy GetGVStubList() {
+ return getSortedStubs(GVStubs);
}
- SymbolListTy GetHiddenGVStubList() const {
- return GetSortedStubs(HiddenGVStubs);
+ SymbolListTy GetHiddenGVStubList() {
+ return getSortedStubs(HiddenGVStubs);
}
};
@@ -87,8 +87,8 @@ namespace llvm {
/// Accessor methods to return the set of stubs in sorted order.
- SymbolListTy GetGVStubList() const {
- return GetSortedStubs(GVStubs);
+ SymbolListTy GetGVStubList() {
+ return getSortedStubs(GVStubs);
}
};
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index eed1e575f93b..ddffdcaf1e4d 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/include/llvm/CodeGen/MachineOperand.h
@@ -65,7 +65,7 @@ public:
private:
/// OpKind - Specify what kind of operand this is. This discriminates the
/// union.
- MachineOperandType OpKind;
+ MachineOperandType OpKind : 8;
/// Subregister number for MO_Register. A value of 0 indicates the
/// MO_Register has no subReg.
@@ -217,7 +217,7 @@ public:
///
void clearParent() { ParentMI = nullptr; }
- void print(raw_ostream &os, const TargetMachine *TM = nullptr) const;
+ void print(raw_ostream &os, const TargetRegisterInfo *TRI = nullptr) const;
//===--------------------------------------------------------------------===//
// Accessors that tell you what kind of MachineOperand you're looking at.
@@ -554,6 +554,12 @@ public:
/// already, the setFPImm method should be used.
void ChangeToFPImmediate(const ConstantFP *FPImm);
+ /// ChangeToES - Replace this operand with a new external symbol operand.
+ void ChangeToES(const char *SymName, unsigned char TargetFlags = 0);
+
+ /// ChangeToMCSymbol - Replace this operand with a new MC symbol operand.
+ void ChangeToMCSymbol(MCSymbol *Sym);
+
/// 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.
diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h
index c962e687243e..6731983c5874 100644
--- a/include/llvm/CodeGen/MachinePassRegistry.h
+++ b/include/llvm/CodeGen/MachinePassRegistry.h
@@ -122,11 +122,12 @@ template<class RegistryClass>
class RegisterPassParser : public MachinePassRegistryListener,
public cl::parser<typename RegistryClass::FunctionPassCtor> {
public:
- RegisterPassParser() {}
- ~RegisterPassParser() { RegistryClass::setListener(nullptr); }
+ RegisterPassParser(cl::Option &O)
+ : cl::parser<typename RegistryClass::FunctionPassCtor>(O) {}
+ ~RegisterPassParser() override { RegistryClass::setListener(nullptr); }
- void initialize(cl::Option &O) {
- cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(O);
+ void initialize() {
+ cl::parser<typename RegistryClass::FunctionPassCtor>::initialize();
// Add existing passes to option.
for (RegistryClass *Node = RegistryClass::getList();
diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h
index aab5c407629f..70bdb191ad34 100644
--- a/include/llvm/CodeGen/MachinePostDominators.h
+++ b/include/llvm/CodeGen/MachinePostDominators.h
@@ -33,7 +33,7 @@ public:
MachinePostDominatorTree();
- ~MachinePostDominatorTree();
+ ~MachinePostDominatorTree() override;
FunctionPass *createMachinePostDominatorTreePass();
diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h
index 43499dba71c0..cf49c297c288 100644
--- a/include/llvm/CodeGen/MachineRegionInfo.h
+++ b/include/llvm/CodeGen/MachineRegionInfo.h
@@ -57,8 +57,6 @@ public:
}
- ~MachineRegionNode() { }
-
bool operator==(const MachineRegion &RN) const {
return this == reinterpret_cast<const MachineRegionNode*>(&RN);
}
@@ -80,7 +78,7 @@ class MachineRegionInfo : public RegionInfoBase<RegionTraits<MachineFunction>> {
public:
explicit MachineRegionInfo();
- virtual ~MachineRegionInfo();
+ ~MachineRegionInfo() override;
// updateStatistics - Update statistic about created regions.
void updateStatistics(MachineRegion *R) final;
@@ -98,7 +96,7 @@ public:
static char ID;
explicit MachineRegionInfoPass();
- ~MachineRegionInfoPass();
+ ~MachineRegionInfoPass() override;
MachineRegionInfo &getRegionInfo() {
return RI;
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index caa48a5cf0cf..e5b837aeea28 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -123,8 +123,8 @@ private:
/// second element.
std::vector<std::pair<unsigned, unsigned> > LiveIns;
- MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION;
- void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION;
+ MachineRegisterInfo(const MachineRegisterInfo&) = delete;
+ void operator=(const MachineRegisterInfo&) = delete;
public:
explicit MachineRegisterInfo(const MachineFunction *MF);
@@ -182,7 +182,18 @@ public:
/// information.
void invalidateLiveness() { TracksLiveness = false; }
- bool tracksSubRegLiveness() const { return TracksSubRegLiveness; }
+ /// Returns true if liveness for register class @p RC should be tracked at
+ /// the subregister level.
+ bool shouldTrackSubRegLiveness(const TargetRegisterClass &RC) const {
+ return subRegLivenessEnabled() && RC.HasDisjunctSubRegs;
+ }
+ bool shouldTrackSubRegLiveness(unsigned VReg) const {
+ assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Must pass a VReg");
+ return shouldTrackSubRegLiveness(*getRegClass(VReg));
+ }
+ bool subRegLivenessEnabled() const {
+ return TracksSubRegLiveness;
+ }
void enableSubRegLiveness(bool Enable = true) {
TracksSubRegLiveness = Enable;
@@ -593,7 +604,7 @@ public:
/// virtual register, for example after removing instructions or splitting
/// the live range.
///
- bool recomputeRegClass(unsigned Reg, const TargetMachine&);
+ bool recomputeRegClass(unsigned Reg);
/// createVirtualRegister - Create and return a new virtual register in the
/// function with the specified register class.
@@ -609,22 +620,25 @@ public:
/// setRegAllocationHint - Specify a register allocation hint for the
/// specified virtual register.
- void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) {
- RegAllocHints[Reg].first = Type;
- RegAllocHints[Reg].second = PrefReg;
+ void setRegAllocationHint(unsigned VReg, unsigned Type, unsigned PrefReg) {
+ assert(TargetRegisterInfo::isVirtualRegister(VReg));
+ RegAllocHints[VReg].first = Type;
+ RegAllocHints[VReg].second = PrefReg;
}
/// getRegAllocationHint - Return the register allocation hint for the
/// specified virtual register.
std::pair<unsigned, unsigned>
- getRegAllocationHint(unsigned Reg) const {
- return RegAllocHints[Reg];
+ getRegAllocationHint(unsigned VReg) const {
+ assert(TargetRegisterInfo::isVirtualRegister(VReg));
+ return RegAllocHints[VReg];
}
/// getSimpleHint - Return the preferred register allocation hint, or 0 if a
/// standard simple hint (Type == 0) is not set.
- unsigned getSimpleHint(unsigned Reg) const {
- std::pair<unsigned, unsigned> Hint = getRegAllocationHint(Reg);
+ unsigned getSimpleHint(unsigned VReg) const {
+ assert(TargetRegisterInfo::isVirtualRegister(VReg));
+ std::pair<unsigned, unsigned> Hint = getRegAllocationHint(VReg);
return Hint.first ? 0 : Hint.second;
}
@@ -829,7 +843,6 @@ public:
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::pointer pointer;
- defusechain_iterator(const defusechain_iterator &I) : Op(I.Op) {}
defusechain_iterator() : Op(nullptr) {}
bool operator==(const defusechain_iterator &x) const {
@@ -932,7 +945,6 @@ public:
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::pointer pointer;
- defusechain_instr_iterator(const defusechain_instr_iterator &I) : Op(I.Op){}
defusechain_instr_iterator() : Op(nullptr) {}
bool operator==(const defusechain_instr_iterator &x) const {
diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h
index 486a26e92714..5f988ad86320 100644
--- a/include/llvm/CodeGen/MachineSSAUpdater.h
+++ b/include/llvm/CodeGen/MachineSSAUpdater.h
@@ -107,8 +107,8 @@ public:
private:
unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB);
- void operator=(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION;
- MachineSSAUpdater(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION;
+ void operator=(const MachineSSAUpdater&) = delete;
+ MachineSSAUpdater(const MachineSSAUpdater&) = delete;
};
} // End llvm namespace
diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h
index a31940161ca5..e80e14e5ccf7 100644
--- a/include/llvm/CodeGen/MachineScheduler.h
+++ b/include/llvm/CodeGen/MachineScheduler.h
@@ -385,7 +385,7 @@ public:
ShouldTrackPressure(false), RPTracker(RegPressure),
TopRPTracker(TopPressure), BotRPTracker(BotPressure) {}
- virtual ~ScheduleDAGMILive();
+ ~ScheduleDAGMILive() override;
/// Return true if this DAG supports VReg liveness and RegPressure.
bool hasVRegLiveness() const override { return true; }
@@ -909,7 +909,7 @@ public:
PostGenericScheduler(const MachineSchedContext *C):
GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {}
- virtual ~PostGenericScheduler() {}
+ ~PostGenericScheduler() override {}
void initPolicy(MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End,
diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h
index e3fbfe89c203..a728df354677 100644
--- a/include/llvm/CodeGen/MachineValueType.h
+++ b/include/llvm/CodeGen/MachineValueType.h
@@ -26,7 +26,7 @@ namespace llvm {
/// MVT - Machine Value Type. Every type that is supported natively by some
/// processor targeted by LLVM occurs here. This means that any legal value
/// type can be represented by an MVT.
- class MVT {
+class MVT {
public:
enum SimpleValueType {
// INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are
@@ -86,22 +86,23 @@ namespace llvm {
v4i64 = 39, // 4 x i64
v8i64 = 40, // 8 x i64
v16i64 = 41, // 16 x i64
-
+ v1i128 = 42, // 1 x i128
+
FIRST_INTEGER_VECTOR_VALUETYPE = v2i1,
- LAST_INTEGER_VECTOR_VALUETYPE = v16i64,
-
- v2f16 = 42, // 2 x f16
- v4f16 = 43, // 4 x f16
- v8f16 = 44, // 8 x f16
- v1f32 = 45, // 1 x f32
- v2f32 = 46, // 2 x f32
- v4f32 = 47, // 4 x f32
- v8f32 = 48, // 8 x f32
- v16f32 = 49, // 16 x f32
- v1f64 = 50, // 1 x f64
- v2f64 = 51, // 2 x f64
- v4f64 = 52, // 4 x f64
- v8f64 = 53, // 8 x f64
+ LAST_INTEGER_VECTOR_VALUETYPE = v1i128,
+
+ v2f16 = 43, // 2 x f16
+ v4f16 = 44, // 4 x f16
+ v8f16 = 45, // 8 x f16
+ v1f32 = 46, // 1 x f32
+ v2f32 = 47, // 2 x f32
+ v4f32 = 48, // 4 x f32
+ v8f32 = 49, // 8 x f32
+ v16f32 = 50, // 16 x f32
+ v1f64 = 51, // 1 x f64
+ v2f64 = 52, // 2 x f64
+ v4f64 = 53, // 4 x f64
+ v8f64 = 54, // 8 x f64
FIRST_FP_VECTOR_VALUETYPE = v2f16,
LAST_FP_VECTOR_VALUETYPE = v8f64,
@@ -109,18 +110,18 @@ namespace llvm {
FIRST_VECTOR_VALUETYPE = v2i1,
LAST_VECTOR_VALUETYPE = v8f64,
- x86mmx = 54, // This is an X86 MMX value
+ x86mmx = 55, // This is an X86 MMX value
- Glue = 55, // This glues nodes together during pre-RA sched
+ Glue = 56, // This glues nodes together during pre-RA sched
- isVoid = 56, // This has no value
+ isVoid = 57, // This has no value
- Untyped = 57, // This value takes a register, but has
+ Untyped = 58, // This value takes a register, but has
// 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.
+ LAST_VALUETYPE = 59, // This always remains at the end of the list.
// This is the current maximum for LAST_VALUETYPE.
// MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
@@ -152,13 +153,17 @@ namespace llvm {
// iPTR - An int value the size of the pointer of the current
// target. This should only be used internal to tblgen!
- iPTR = 255
+ iPTR = 255,
+
+ // Any - Any type. This is used for intrinsics that have overloadings.
+ // This is only for tblgen's consumption!
+ Any = 256
};
SimpleValueType SimpleTy;
- MVT() : SimpleTy((SimpleValueType)(INVALID_SIMPLE_VALUE_TYPE)) {}
- MVT(SimpleValueType SVT) : SimpleTy(SVT) { }
+ LLVM_CONSTEXPR MVT() : SimpleTy(INVALID_SIMPLE_VALUE_TYPE) {}
+ LLVM_CONSTEXPR MVT(SimpleValueType SVT) : SimpleTy(SVT) { }
bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; }
bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; }
@@ -218,10 +223,10 @@ namespace llvm {
/// 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::v8f16 || SimpleTy == MVT::v4f32 ||
- SimpleTy == MVT::v2f64);
+ return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 ||
+ SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 ||
+ SimpleTy == MVT::v1i128 || SimpleTy == MVT::v8f16 ||
+ SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64);
}
/// is256BitVector - Return true if this is a 256-bit vector type.
@@ -245,7 +250,8 @@ namespace llvm {
/// isOverloaded - Return true if this is an overloaded type for TableGen.
bool isOverloaded() const {
- return (SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
+ return (SimpleTy==MVT::Any ||
+ SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny);
}
@@ -305,6 +311,7 @@ namespace llvm {
case v4i64:
case v8i64:
case v16i64: return i64;
+ case v1i128: return i128;
case v2f16:
case v4f16:
case v8f16: return f16;
@@ -363,6 +370,7 @@ namespace llvm {
case v1i16:
case v1i32:
case v1i64:
+ case v1i128:
case v1f32:
case v1f64: return 1;
}
@@ -380,6 +388,7 @@ namespace llvm {
case iAny:
case fAny:
case vAny:
+ case Any:
llvm_unreachable("Value type is overloaded.");
case Metadata:
llvm_unreachable("Value type is metadata.");
@@ -421,6 +430,7 @@ namespace llvm {
case v8i16:
case v4i32:
case v2i64:
+ case v1i128:
case v8f16:
case v4f32:
case v2f64: return 128;
@@ -556,6 +566,9 @@ namespace llvm {
if (NumElements == 8) return MVT::v8i64;
if (NumElements == 16) return MVT::v16i64;
break;
+ case MVT::i128:
+ if (NumElements == 1) return MVT::v1i128;
+ break;
case MVT::f16:
if (NumElements == 2) return MVT::v2f16;
if (NumElements == 4) return MVT::v4f16;
diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h
index 4dc5674ae134..f73383ed1000 100644
--- a/include/llvm/CodeGen/PBQP/Graph.h
+++ b/include/llvm/CodeGen/PBQP/Graph.h
@@ -21,6 +21,7 @@
#include <list>
#include <map>
#include <set>
+#include <vector>
namespace llvm {
namespace PBQP {
@@ -507,14 +508,14 @@ namespace PBQP {
return getNode(NId).getAdjEdgeIds().size();
}
- /// @brief Set an edge's cost matrix.
+ /// @brief Update an edge's cost matrix.
/// @param EId Edge id.
/// @param Costs New cost matrix.
template <typename OtherMatrixT>
- void setEdgeCosts(EdgeId EId, OtherMatrixT Costs) {
+ void updateEdgeCosts(EdgeId EId, OtherMatrixT Costs) {
MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs));
if (Solver)
- Solver->handleSetEdgeCosts(EId, *AllocatedCosts);
+ Solver->handleUpdateCosts(EId, *AllocatedCosts);
getEdge(EId).Costs = AllocatedCosts;
}
@@ -548,14 +549,14 @@ namespace PBQP {
/// @brief Get the first node connected to this edge.
/// @param EId Edge id.
/// @return The first node connected to the given edge.
- NodeId getEdgeNode1Id(EdgeId EId) {
+ NodeId getEdgeNode1Id(EdgeId EId) const {
return getEdge(EId).getN1Id();
}
/// @brief Get the second node connected to this edge.
/// @param EId Edge id.
/// @return The second node connected to the given edge.
- NodeId getEdgeNode2Id(EdgeId EId) {
+ NodeId getEdgeNode2Id(EdgeId EId) const {
return getEdge(EId).getN2Id();
}
@@ -672,69 +673,6 @@ namespace PBQP {
Edges.clear();
FreeEdgeIds.clear();
}
-
- /// @brief Dump a graph to an output stream.
- template <typename OStream>
- void dumpToStream(OStream &OS) {
- OS << nodeIds().size() << " " << edgeIds().size() << "\n";
-
- for (auto NId : nodeIds()) {
- const Vector& V = getNodeCosts(NId);
- OS << "\n" << V.getLength() << "\n";
- assert(V.getLength() != 0 && "Empty vector in graph.");
- OS << V[0];
- for (unsigned i = 1; i < V.getLength(); ++i) {
- OS << " " << V[i];
- }
- OS << "\n";
- }
-
- for (auto EId : edgeIds()) {
- NodeId N1Id = getEdgeNode1Id(EId);
- NodeId N2Id = getEdgeNode2Id(EId);
- assert(N1Id != N2Id && "PBQP graphs shound not have self-edges.");
- const Matrix& M = getEdgeCosts(EId);
- OS << "\n" << N1Id << " " << N2Id << "\n"
- << M.getRows() << " " << M.getCols() << "\n";
- assert(M.getRows() != 0 && "No rows in matrix.");
- assert(M.getCols() != 0 && "No cols in matrix.");
- for (unsigned i = 0; i < M.getRows(); ++i) {
- OS << M[i][0];
- for (unsigned j = 1; j < M.getCols(); ++j) {
- OS << " " << M[i][j];
- }
- OS << "\n";
- }
- }
- }
-
- /// @brief Dump this graph to dbgs().
- void dump() {
- dumpToStream(dbgs());
- }
-
- /// @brief Print a representation of this graph in DOT format.
- /// @param OS Output stream to print on.
- template <typename OStream>
- void printDot(OStream &OS) {
- OS << "graph {\n";
- for (auto NId : nodeIds()) {
- OS << " node" << NId << " [ label=\""
- << NId << ": " << getNodeCosts(NId) << "\" ]\n";
- }
- OS << " edge [ len=" << nodeIds().size() << " ]\n";
- for (auto EId : edgeIds()) {
- OS << " node" << getEdgeNode1Id(EId)
- << " -- node" << getEdgeNode2Id(EId)
- << " [ label=\"";
- const Matrix &EdgeCosts = getEdgeCosts(EId);
- for (unsigned i = 0; i < EdgeCosts.getRows(); ++i) {
- OS << EdgeCosts.getRowAsVector(i) << "\\n";
- }
- OS << "\" ]\n";
- }
- OS << "}\n";
- }
};
} // namespace PBQP
diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h
index 21fde4d8a5cd..d4a544bfe721 100644
--- a/include/llvm/CodeGen/PBQP/ReductionRules.h
+++ b/include/llvm/CodeGen/PBQP/ReductionRules.h
@@ -132,9 +132,9 @@ namespace PBQP {
} else {
const Matrix &YZECosts = G.getEdgeCosts(YZEId);
if (YNId == G.getEdgeNode1Id(YZEId)) {
- G.setEdgeCosts(YZEId, Delta + YZECosts);
+ G.updateEdgeCosts(YZEId, Delta + YZECosts);
} else {
- G.setEdgeCosts(YZEId, Delta.transpose() + YZECosts);
+ G.updateEdgeCosts(YZEId, Delta.transpose() + YZECosts);
}
}
@@ -144,6 +144,25 @@ namespace PBQP {
// TODO: Try to normalize newly added/modified edge.
}
+#ifndef NDEBUG
+ // Does this Cost vector have any register options ?
+ template <typename VectorT>
+ bool hasRegisterOptions(const VectorT &V) {
+ unsigned VL = V.getLength();
+
+ // An empty or spill only cost vector does not provide any register option.
+ if (VL <= 1)
+ return false;
+
+ // If there are registers in the cost vector, but all of them have infinite
+ // costs, then ... there is no available register.
+ for (unsigned i = 1; i < VL; ++i)
+ if (V[i] != std::numeric_limits<PBQP::PBQPNum>::infinity())
+ return true;
+
+ return false;
+ }
+#endif
// \brief Find a solution to a fully reduced graph by backpropagation.
//
@@ -170,6 +189,15 @@ namespace PBQP {
RawVector v = G.getNodeCosts(NId);
+#ifndef NDEBUG
+ // Although a conservatively allocatable node can be allocated to a register,
+ // spilling it may provide a lower cost solution. Assert here that spilling
+ // is done by choice, not because there were no register available.
+ if (G.getNodeMetadata(NId).wasConservativelyAllocatable())
+ assert(hasRegisterOptions(v) && "A conservatively allocatable node "
+ "must have available register options");
+#endif
+
for (auto EId : G.adjEdgeIds(NId)) {
const Matrix& edgeCosts = G.getEdgeCosts(EId);
if (NId == G.getEdgeNode1Id(EId)) {
diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index 8ed32b8a8dd5..39f69549d7cf 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -120,12 +120,15 @@ protected:
/// Default setting for -enable-tail-merge on this target.
bool EnableTailMerge;
+ /// Default setting for -enable-shrink-wrap on this target.
+ bool EnableShrinkWrap;
+
public:
TargetPassConfig(TargetMachine *tm, PassManagerBase &pm);
// Dummy constructor.
TargetPassConfig();
- virtual ~TargetPassConfig();
+ ~TargetPassConfig() override;
static char ID;
@@ -179,6 +182,9 @@ public:
/// Return true if the optimized regalloc pipeline is enabled.
bool getOptimizeRegAlloc() const;
+ /// Return true if shrink wrapping is enabled.
+ bool getEnableShrinkWrap() const;
+
/// Return true if the default global register allocator is in use and
/// has not be overriden on the command line with '-regalloc=...'
bool usingDefaultRegAlloc() const;
@@ -214,7 +220,7 @@ public:
///
/// This can also be used to plug a new MachineSchedStrategy into an instance
/// of the standard ScheduleDAGMI:
- /// return new ScheduleDAGMI(C, new MyStrategy(C))
+ /// return new ScheduleDAGMI(C, make_unique<MyStrategy>(C), /* IsPostRA= */false)
///
/// Return NULL to select the default (generic) machine scheduler.
virtual ScheduleDAGInstrs *
@@ -354,13 +360,6 @@ protected:
namespace llvm {
FunctionPass *createAtomicExpandPass(const TargetMachine *TM);
- /// \brief Create a basic TargetTransformInfo analysis pass.
- ///
- /// This pass implements the target transform info analysis using the target
- /// independent information available to the LLVM code generator.
- ImmutablePass *
- createBasicTargetTransformInfoPass(const TargetMachine *TM);
-
/// createUnreachableBlockEliminationPass - The LLVM code generator does not
/// work well with unreachable basic blocks (what live ranges make sense for a
/// block that cannot be reached?). As such, a code generator should either
@@ -433,6 +432,10 @@ namespace llvm {
/// basic blocks.
extern char &SpillPlacementID;
+ /// ShrinkWrap pass. Look for the best place to insert save and restore
+ // instruction and update the MachineFunctionInfo with that information.
+ extern char &ShrinkWrapID;
+
/// VirtRegRewriter pass. Rewrite virtual registers to physical registers as
/// assigned in VirtRegMap.
extern char &VirtRegRewriterID;
@@ -517,11 +520,15 @@ namespace llvm {
/// information.
extern char &MachineBlockPlacementStatsID;
- /// GCLowering Pass - Performs target-independent LLVM IR transformations for
- /// highly portable strategies.
- ///
+ /// GCLowering Pass - Used by gc.root to perform its default lowering
+ /// operations.
FunctionPass *createGCLoweringPass();
+ /// ShadowStackGCLowering - Implements the custom lowering mechanism
+ /// used by the shadow stack GC. Only runs on functions which opt in to
+ /// the shadow stack collector.
+ FunctionPass *createShadowStackGCLoweringPass();
+
/// GCMachineCodeAnalysis - Target-independent pass to mark safe points
/// in machine code. Must be added very late during code generation, just
/// prior to output, and importantly after all CFG transformations (such as
@@ -569,6 +576,10 @@ namespace llvm {
/// adapted to code generation. Required if using dwarf exception handling.
FunctionPass *createDwarfEHPass(const TargetMachine *TM);
+ /// createWinEHPass - Prepares personality functions used by MSVC on Windows,
+ /// in addition to the Itanium LSDA based personalities.
+ FunctionPass *createWinEHPass(const TargetMachine *TM);
+
/// createSjLjEHPreparePass - This pass adapts exception handling code to use
/// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow.
///
@@ -611,13 +622,13 @@ namespace llvm {
ModulePass *createForwardControlFlowIntegrityPass();
} // End llvm namespace
-/// This initializer registers TargetMachine constructor, so the pass being
-/// initialized can use target dependent interfaces. Please do not move this
-/// macro to be together with INITIALIZE_PASS, which is a complete target
-/// independent initializer, and we don't want to make libScalarOpts depend
-/// on libCodeGen.
-#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \
- static void* initialize##passName##PassOnce(PassRegistry &Registry) { \
+/// Target machine pass initializer for passes with dependencies. Use with
+/// INITIALIZE_TM_PASS_END.
+#define INITIALIZE_TM_PASS_BEGIN INITIALIZE_PASS_BEGIN
+
+/// Target machine pass initializer for passes with dependencies. Use with
+/// INITIALIZE_TM_PASS_BEGIN.
+#define INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) \
PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \
PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis, \
PassInfo::TargetMachineCtor_t(callTargetMachineCtor< passName >)); \
@@ -628,4 +639,13 @@ namespace llvm {
CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
}
+/// This initializer registers TargetMachine constructor, so the pass being
+/// initialized can use target dependent interfaces. Please do not move this
+/// macro to be together with INITIALIZE_PASS, which is a complete target
+/// independent initializer, and we don't want to make libScalarOpts depend
+/// on libCodeGen.
+#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \
+ INITIALIZE_TM_PASS_BEGIN(passName, arg, name, cfg, analysis) \
+ INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis)
+
#endif
diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h
index 5c0e9859915f..6046e46547b2 100644
--- a/include/llvm/CodeGen/RegAllocPBQP.h
+++ b/include/llvm/CodeGen/RegAllocPBQP.h
@@ -23,6 +23,9 @@
#include "llvm/Support/ErrorHandling.h"
namespace llvm {
+
+class raw_ostream;
+
namespace PBQP {
namespace RegAlloc {
@@ -177,21 +180,34 @@ class NodeMetadata {
public:
typedef RegAlloc::AllowedRegVector AllowedRegVector;
- typedef enum { Unprocessed,
- OptimallyReducible,
- ConservativelyAllocatable,
- NotProvablyAllocatable } ReductionState;
+ // The node's reduction state. The order in this enum is important,
+ // as it is assumed nodes can only progress up (i.e. towards being
+ // optimally reducible) when reducing the graph.
+ typedef enum {
+ Unprocessed,
+ NotProvablyAllocatable,
+ ConservativelyAllocatable,
+ OptimallyReducible
+ } ReductionState;
NodeMetadata()
: RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr),
- VReg(0) {}
+ VReg(0)
+#ifndef NDEBUG
+ , everConservativelyAllocatable(false)
+#endif
+ {}
// FIXME: Re-implementing default behavior to work around MSVC. Remove once
// MSVC synthesizes move constructors properly.
NodeMetadata(const NodeMetadata &Other)
: RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts),
OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg),
- AllowedRegs(Other.AllowedRegs) {
+ AllowedRegs(Other.AllowedRegs)
+#ifndef NDEBUG
+ , everConservativelyAllocatable(Other.everConservativelyAllocatable)
+#endif
+ {
if (NumOpts > 0) {
std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts],
&OptUnsafeEdges[0]);
@@ -203,7 +219,11 @@ public:
NodeMetadata(NodeMetadata &&Other)
: RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts),
OptUnsafeEdges(std::move(Other.OptUnsafeEdges)), VReg(Other.VReg),
- AllowedRegs(std::move(Other.AllowedRegs)) {}
+ AllowedRegs(std::move(Other.AllowedRegs))
+#ifndef NDEBUG
+ , everConservativelyAllocatable(Other.everConservativelyAllocatable)
+#endif
+ {}
// FIXME: Re-implementing default behavior to work around MSVC. Remove once
// MSVC synthesizes move constructors properly.
@@ -216,6 +236,9 @@ public:
OptUnsafeEdges.get());
VReg = Other.VReg;
AllowedRegs = Other.AllowedRegs;
+#ifndef NDEBUG
+ everConservativelyAllocatable = Other.everConservativelyAllocatable;
+#endif
return *this;
}
@@ -228,6 +251,9 @@ public:
OptUnsafeEdges = std::move(Other.OptUnsafeEdges);
VReg = Other.VReg;
AllowedRegs = std::move(Other.AllowedRegs);
+#ifndef NDEBUG
+ everConservativelyAllocatable = Other.everConservativelyAllocatable;
+#endif
return *this;
}
@@ -245,7 +271,18 @@ public:
}
ReductionState getReductionState() const { return RS; }
- void setReductionState(ReductionState RS) { this->RS = RS; }
+ void setReductionState(ReductionState RS) {
+ assert(RS >= this->RS && "A node's reduction state can not be downgraded");
+ this->RS = RS;
+
+#ifndef NDEBUG
+ // Remember this state to assert later that a non-infinite register
+ // option was available.
+ if (RS == ConservativelyAllocatable)
+ everConservativelyAllocatable = true;
+#endif
+ }
+
void handleAddEdge(const MatrixMetadata& MD, bool Transpose) {
DeniedOpts += Transpose ? MD.getWorstRow() : MD.getWorstCol();
@@ -269,6 +306,12 @@ public:
&OptUnsafeEdges[NumOpts]);
}
+#ifndef NDEBUG
+ bool wasConservativelyAllocatable() const {
+ return everConservativelyAllocatable;
+ }
+#endif
+
private:
ReductionState RS;
unsigned NumOpts;
@@ -276,6 +319,10 @@ private:
std::unique_ptr<unsigned[]> OptUnsafeEdges;
unsigned VReg;
GraphMetadata::AllowedRegVecRef AllowedRegs;
+
+#ifndef NDEBUG
+ bool everConservativelyAllocatable;
+#endif
};
class RegAllocSolverImpl {
@@ -309,6 +356,8 @@ public:
}
void handleAddNode(NodeId NId) {
+ assert(G.getNodeCosts(NId).getLength() > 1 &&
+ "PBQP Graph should not contain single or zero-option nodes");
G.getNodeMetadata(NId).setup(G.getNodeCosts(NId));
}
void handleRemoveNode(NodeId NId) {}
@@ -328,15 +377,7 @@ public:
NodeMetadata& NMd = G.getNodeMetadata(NId);
const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata();
NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId));
- if (G.getNodeDegree(NId) == 3) {
- // This node is becoming optimally reducible.
- moveToOptimallyReducibleNodes(NId);
- } else if (NMd.getReductionState() ==
- NodeMetadata::NotProvablyAllocatable &&
- NMd.isConservativelyAllocatable()) {
- // This node just became conservatively allocatable.
- moveToConservativelyAllocatableNodes(NId);
- }
+ promote(NId, NMd);
}
void handleReconnectEdge(EdgeId EId, NodeId NId) {
@@ -345,20 +386,44 @@ public:
NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId));
}
- void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) {
- handleRemoveEdge(EId);
-
+ void handleUpdateCosts(EdgeId EId, const Matrix& NewCosts) {
NodeId N1Id = G.getEdgeNode1Id(EId);
NodeId N2Id = G.getEdgeNode2Id(EId);
NodeMetadata& N1Md = G.getNodeMetadata(N1Id);
NodeMetadata& N2Md = G.getNodeMetadata(N2Id);
+ bool Transpose = N1Id != G.getEdgeNode1Id(EId);
+
+ // Metadata are computed incrementally. First, update them
+ // by removing the old cost.
+ const MatrixMetadata& OldMMd = G.getEdgeCosts(EId).getMetadata();
+ N1Md.handleRemoveEdge(OldMMd, Transpose);
+ N2Md.handleRemoveEdge(OldMMd, !Transpose);
+
+ // And update now the metadata with the new cost.
const MatrixMetadata& MMd = NewCosts.getMetadata();
- N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId));
- N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId));
+ N1Md.handleAddEdge(MMd, Transpose);
+ N2Md.handleAddEdge(MMd, !Transpose);
+
+ // As the metadata may have changed with the update, the nodes may have
+ // become ConservativelyAllocatable or OptimallyReducible.
+ promote(N1Id, N1Md);
+ promote(N2Id, N2Md);
}
private:
+ void promote(NodeId NId, NodeMetadata& NMd) {
+ if (G.getNodeDegree(NId) == 3) {
+ // This node is becoming optimally reducible.
+ moveToOptimallyReducibleNodes(NId);
+ } else if (NMd.getReductionState() ==
+ NodeMetadata::NotProvablyAllocatable &&
+ NMd.isConservativelyAllocatable()) {
+ // This node just became conservatively allocatable.
+ moveToConservativelyAllocatableNodes(NId);
+ }
+ }
+
void removeFromCurrentSet(NodeId NId) {
switch (G.getNodeMetadata(NId).getReductionState()) {
case NodeMetadata::Unprocessed: break;
@@ -479,8 +544,10 @@ private:
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);
+ PBQPNum N1SC = G.getNodeCosts(N1Id)[0];
+ PBQPNum N2SC = G.getNodeCosts(N2Id)[0];
+ if (N1SC == N2SC)
+ return G.getNodeDegree(N1Id) < G.getNodeDegree(N2Id);
return N1SC < N2SC;
}
private:
@@ -499,6 +566,17 @@ private:
typedef PBQP::Graph<RegAllocSolverImpl> BaseT;
public:
PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {}
+
+ /// @brief Dump this graph to dbgs().
+ void dump() const;
+
+ /// @brief Dump this graph to an output stream.
+ /// @param OS Output stream to print on.
+ void dump(raw_ostream &OS) const;
+
+ /// @brief Print a representation of this graph in DOT format.
+ /// @param OS Output stream to print on.
+ void printDot(raw_ostream &OS) const;
};
inline Solution solve(PBQPRAGraph& G) {
diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h
index cc9e00055146..fcb6feed68ca 100644
--- a/include/llvm/CodeGen/RegisterPressure.h
+++ b/include/llvm/CodeGen/RegisterPressure.h
@@ -35,21 +35,6 @@ struct RegisterPressure {
SmallVector<unsigned,8> LiveInRegs;
SmallVector<unsigned,8> LiveOutRegs;
- /// Increase register pressure for each pressure set impacted by this register
- /// class. Normally called by RegPressureTracker, but may be called manually
- /// to account for live through (global liveness).
- ///
- /// \param Reg is either a virtual register number or register unit number.
- void increase(unsigned Reg, const TargetRegisterInfo *TRI,
- const MachineRegisterInfo *MRI);
-
- /// Decrease register pressure for each pressure set impacted by this register
- /// class. This is only useful to account for spilling or rematerialization.
- ///
- /// \param Reg is either a virtual register number or register unit number.
- void decrease(unsigned Reg, const TargetRegisterInfo *TRI,
- const MachineRegisterInfo *MRI);
-
void dump(const TargetRegisterInfo *TRI) const;
};
diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h
index 474861e45df1..df3fd34e0af6 100644
--- a/include/llvm/CodeGen/RegisterScavenging.h
+++ b/include/llvm/CodeGen/RegisterScavenging.h
@@ -9,7 +9,7 @@
//
// This file declares the machine register scavenger class. It can provide
// information such as unused register at any point in a machine basic block.
-// It also provides a mechanism to make registers availbale by evicting them
+// It also provides a mechanism to make registers available by evicting them
// to spill slots.
//
//===----------------------------------------------------------------------===//
@@ -36,8 +36,7 @@ class RegScavenger {
MachineBasicBlock::iterator MBBI;
unsigned NumRegUnits;
- /// Tracking - True if RegScavenger is currently tracking the liveness of
- /// registers.
+ /// True if RegScavenger is currently tracking the liveness of registers.
bool Tracking;
/// Information on scavenged registers (held in a spill slot).
@@ -58,8 +57,8 @@ class RegScavenger {
/// A vector of information on scavenged registers.
SmallVector<ScavengedInfo, 2> Scavenged;
- /// RegUnitsAvailable - The current state of each reg unit immediatelly
- /// before MBBI. One bit per register unit. If bit is not set it means any
+ /// The current state of each reg unit immediately 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;
@@ -72,18 +71,17 @@ public:
RegScavenger()
: MBB(nullptr), NumRegUnits(0), Tracking(false) {}
- /// enterBasicBlock - Start tracking liveness from the begin of the specific
- /// basic block.
+ /// Start tracking liveness from the begin of the specific basic block.
void enterBasicBlock(MachineBasicBlock *mbb);
- /// initRegState - allow resetting register state info for multiple
+ /// Allow resetting register state info for multiple
/// passes over/within the same function.
void initRegState();
- /// forward - Move the internal MBB iterator and update register states.
+ /// Move the internal MBB iterator and update register states.
void forward();
- /// forward - Move the internal MBB iterator and update register states until
+ /// Move the internal MBB iterator and update register states until
/// it has processed the specific iterator.
void forward(MachineBasicBlock::iterator I) {
if (!Tracking && MBB->begin() != I) forward();
@@ -99,7 +97,7 @@ public:
while (MBBI != I) unprocess();
}
- /// skipTo - Move the internal MBB iterator but do not update register states.
+ /// Move the internal MBB iterator but do not update register states.
void skipTo(MachineBasicBlock::iterator I) {
if (I == MachineBasicBlock::iterator(nullptr))
Tracking = false;
@@ -110,14 +108,13 @@ public:
return MBBI;
}
- /// isRegUsed - return if a specific register is currently used.
+ /// 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.
+ /// Return all available registers in the register class in Mask.
BitVector getRegsAvailable(const TargetRegisterClass *RC);
- /// FindUnusedReg - Find a unused register of the specified register class.
+ /// Find an unused register of the specified register class.
/// Return 0 if none is found.
unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const;
@@ -144,7 +141,7 @@ public:
A.push_back(I->FrameIndex);
}
- /// scavengeRegister - Make a register of the specific register class
+ /// Make a register of the specific register class
/// available and do the appropriate bookkeeping. SPAdj is the stack
/// adjustment due to call frame, it's passed along to eliminateFrameIndex().
/// Returns the scavenged register.
@@ -154,11 +151,10 @@ public:
return scavengeRegister(RegClass, MBBI, SPAdj);
}
- /// setRegUsed - Tell the scavenger a register is used.
- ///
+ /// Tell the scavenger a register is used.
void setRegUsed(unsigned Reg);
private:
- /// isReserved - Returns true if a register is reserved. It is never "unused".
+ /// Returns true if a register is reserved. It is never "unused".
bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); }
/// setUsed / setUnused - Mark the state of one or a number of register units.
@@ -177,9 +173,8 @@ private:
/// 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.
+ /// Return the candidate register that is unused for the longest after
+ /// StartMI. UseMI is set to the instruction where the search stopped.
///
/// No more than InstrLimit instructions are inspected.
unsigned findSurvivorReg(MachineBasicBlock::iterator StartMI,
diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h
index 114fe7c35b82..0097e0472e5c 100644
--- a/include/llvm/CodeGen/ResourcePriorityQueue.h
+++ b/include/llvm/CodeGen/ResourcePriorityQueue.h
@@ -64,7 +64,7 @@ namespace llvm {
/// ResourcesModel - Represents VLIW state.
/// Not limited to VLIW targets per say, but assumes
/// definition of DFA by a target.
- DFAPacketizer *ResourcesModel;
+ std::unique_ptr<DFAPacketizer> ResourcesModel;
/// Resource model - packet/bundle model. Purely
/// internal at the time.
@@ -77,10 +77,6 @@ namespace llvm {
public:
ResourcePriorityQueue(SelectionDAGISel *IS);
- ~ResourcePriorityQueue() {
- delete ResourcesModel;
- }
-
bool isBottomUp() const override { return false; }
void initNodes(std::vector<SUnit> &sunits) override;
@@ -124,8 +120,6 @@ namespace llvm {
void remove(SUnit *SU) override;
- void dump(ScheduleDAG* DAG) const override;
-
/// scheduledNode - Main resource tracking point.
void scheduledNode(SUnit *Node) override;
bool isResourceAvailable(SUnit *SU);
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index 64c9c4729e92..2be5de640e29 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -425,6 +425,10 @@ namespace RTLIB {
/// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or
/// UNKNOWN_LIBCALL if there is none.
Libcall getUINTTOFP(EVT OpVT, EVT RetVT);
+
+ /// Return the SYNC_FETCH_AND_* value for the given opcode and type, or
+ /// UNKNOWN_LIBCALL if there is none.
+ Libcall getATOMIC(unsigned Opc, MVT VT);
}
}
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index 80aee8c62880..839131416560 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -628,12 +628,6 @@ namespace llvm {
}
bool operator!=(const SUnitIterator& x) const { return !operator==(x); }
- const SUnitIterator &operator=(const SUnitIterator &I) {
- assert(I.Node==Node && "Cannot assign iterators to two different nodes!");
- Operand = I.Operand;
- return *this;
- }
-
pointer operator*() const {
return Node->Preds[Operand].getSUnit();
}
diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h
index 00dd8f9a633e..1196783e820b 100644
--- a/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -158,7 +158,7 @@ namespace llvm {
bool RemoveKillFlags = false,
LiveIntervals *LIS = nullptr);
- virtual ~ScheduleDAGInstrs() {}
+ ~ScheduleDAGInstrs() override {}
bool isPostRA() const { return IsPostRA; }
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index ee4bc08495ec..89f9005b8b21 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -41,14 +41,16 @@ class TargetSelectionDAGInfo;
class SDVTListNode : public FoldingSetNode {
friend struct FoldingSetTrait<SDVTListNode>;
- /// FastID - A reference to an Interned FoldingSetNodeID for this node.
+ /// A reference to an Interned FoldingSetNodeID for this node.
/// The Allocator in SelectionDAG holds the data.
/// SDVTList contains all types which are frequently accessed in SelectionDAG.
- /// The size of this list is not expected big so it won't introduce memory penalty.
+ /// The size of this list is not expected to be big so it won't introduce
+ /// a memory penalty.
FoldingSetNodeIDRef FastID;
const EVT *VTs;
unsigned int NumVTs;
- /// The hash value for SDVTList is fixed so cache it to avoid hash calculation
+ /// The hash value for SDVTList is fixed, so cache it to avoid
+ /// hash calculation.
unsigned HashValue;
public:
SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) :
@@ -61,8 +63,8 @@ public:
}
};
-// Specialize FoldingSetTrait for SDVTListNode
-// To avoid computing temp FoldingSetNodeID and hash value.
+/// Specialize FoldingSetTrait for SDVTListNode
+/// to avoid computing temp FoldingSetNodeID and hash value.
template<> struct FoldingSetTrait<SDVTListNode> : DefaultFoldingSetTrait<SDVTListNode> {
static void Profile(const SDVTListNode &X, FoldingSetNodeID& ID) {
ID = X.FastID;
@@ -98,7 +100,7 @@ private:
static void createNode(const SDNode &);
};
-/// SDDbgInfo - Keeps track of dbg_value information through SDISel. We do
+/// Keeps track of dbg_value information through SDISel. We do
/// not build SDNodes for these so as not to perturb the generated code;
/// instead the info is kept off to the side in this structure. Each SDNode may
/// have one or more associated dbg_value entries. This information is kept in
@@ -110,13 +112,14 @@ private:
/// motion, and debug info for them is potentially useful even if the parameter
/// is unused. Right now only byval parameters are handled separately.
class SDDbgInfo {
+ BumpPtrAllocator Alloc;
SmallVector<SDDbgValue*, 32> DbgValues;
SmallVector<SDDbgValue*, 32> ByvalParmDbgValues;
typedef DenseMap<const SDNode*, SmallVector<SDDbgValue*, 2> > DbgValMapType;
DbgValMapType DbgValMap;
- void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION;
- SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION;
+ void operator=(const SDDbgInfo&) = delete;
+ SDDbgInfo(const SDDbgInfo&) = delete;
public:
SDDbgInfo() {}
@@ -136,8 +139,11 @@ public:
DbgValMap.clear();
DbgValues.clear();
ByvalParmDbgValues.clear();
+ Alloc.Reset();
}
+ BumpPtrAllocator &getAlloc() { return Alloc; }
+
bool empty() const {
return DbgValues.empty() && ByvalParmDbgValues.empty();
}
@@ -159,10 +165,10 @@ public:
class SelectionDAG;
void checkForCycles(const SelectionDAG *DAG, bool force = false);
-/// SelectionDAG class - This is used to represent a portion of an LLVM function
-/// in a low-level Data Dependence DAG representation suitable for instruction
-/// selection. This DAG is constructed as the first step of instruction
-/// selection in order to allow implementation of machine specific optimizations
+/// This is used to represent a portion of an LLVM function in a low-level
+/// Data Dependence DAG representation suitable for instruction selection.
+/// This DAG is constructed as the first step of instruction selection in order
+/// to allow implementation of machine specific optimizations
/// and code simplifications.
///
/// The representation used by the SelectionDAG is a target-independent
@@ -178,40 +184,39 @@ class SelectionDAG {
LLVMContext *Context;
CodeGenOpt::Level OptLevel;
- /// EntryNode - The starting token.
+ /// The starting token.
SDNode EntryNode;
- /// Root - The root of the entire DAG.
+ /// The root of the entire DAG.
SDValue Root;
- /// AllNodes - A linked list of nodes in the current DAG.
+ /// A linked list of nodes in the current DAG.
ilist<SDNode> AllNodes;
- /// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use
+ /// The AllocatorType for allocating SDNodes. We use
/// pool allocation with recycling.
typedef RecyclingAllocator<BumpPtrAllocator, SDNode, sizeof(LargestSDNode),
AlignOf<MostAlignedSDNode>::Alignment>
NodeAllocatorType;
- /// NodeAllocator - Pool allocation for nodes.
+ /// Pool allocation for nodes.
NodeAllocatorType NodeAllocator;
- /// CSEMap - This structure is used to memoize nodes, automatically performing
+ /// This structure is used to memoize nodes, automatically performing
/// CSE with existing nodes when a duplicate is requested.
FoldingSet<SDNode> CSEMap;
- /// OperandAllocator - Pool allocation for machine-opcode SDNode operands.
+ /// Pool allocation for machine-opcode SDNode operands.
BumpPtrAllocator OperandAllocator;
- /// Allocator - Pool allocation for misc. objects that are created once per
- /// SelectionDAG.
+ /// Pool allocation for misc. objects that are created once per SelectionDAG.
BumpPtrAllocator Allocator;
- /// DbgInfo - Tracks dbg_value information through SDISel.
+ /// Tracks dbg_value information through SDISel.
SDDbgInfo *DbgInfo;
public:
- /// DAGUpdateListener - Clients of various APIs that cause global effects on
+ /// Clients of various APIs that cause global effects on
/// the DAG can optionally implement this interface. This allows the clients
/// to handle the various sorts of updates that happen.
///
@@ -232,15 +237,15 @@ public:
DAG.UpdateListeners = Next;
}
- /// NodeDeleted - The node N that was deleted and, if E is not null, an
+ /// The node N that was deleted and, if E is not null, an
/// equivalent node E that replaced it.
virtual void NodeDeleted(SDNode *N, SDNode *E);
- /// NodeUpdated - The node N that was updated.
+ /// The node N that was updated.
virtual void NodeUpdated(SDNode *N);
};
- /// NewNodesMustHaveLegalTypes - When true, additional steps are taken to
+ /// When true, additional steps are taken to
/// ensure that getConstant() and similar functions return DAG nodes that
/// have legal types. This is important after type legalization since
/// any illegally typed nodes generated after this point will not experience
@@ -251,32 +256,28 @@ private:
/// DAGUpdateListener is a friend so it can manipulate the listener stack.
friend struct DAGUpdateListener;
- /// UpdateListeners - Linked list of registered DAGUpdateListener instances.
+ /// Linked list of registered DAGUpdateListener instances.
/// This stack is maintained by DAGUpdateListener RAII.
DAGUpdateListener *UpdateListeners;
- /// setGraphColorHelper - Implementation of setSubgraphColor.
+ /// Implementation of setSubgraphColor.
/// Return whether we had to truncate the search.
- ///
bool setSubgraphColorHelper(SDNode *N, const char *Color,
DenseSet<SDNode *> &visited,
int level, bool &printed);
- void operator=(const SelectionDAG&) LLVM_DELETED_FUNCTION;
- SelectionDAG(const SelectionDAG&) LLVM_DELETED_FUNCTION;
+ void operator=(const SelectionDAG&) = delete;
+ SelectionDAG(const SelectionDAG&) = delete;
public:
explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level);
~SelectionDAG();
- /// init - Prepare this SelectionDAG to process code in the given
- /// MachineFunction.
- ///
+ /// Prepare this SelectionDAG to process code in the given MachineFunction.
void init(MachineFunction &mf);
- /// clear - Clear state and free memory necessary to make this
+ /// Clear state and free memory necessary to make this
/// SelectionDAG ready to process a new block.
- ///
void clear();
MachineFunction &getMachineFunction() const { return *MF; }
@@ -286,8 +287,7 @@ public:
const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return *TSI; }
LLVMContext *getContext() const {return Context; }
- /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'.
- ///
+ /// Pop up a GraphViz/gv window with the DAG rendered using 'dot'.
void viewGraph(const std::string &Title);
void viewGraph();
@@ -295,24 +295,21 @@ public:
std::map<const SDNode *, std::string> NodeGraphAttrs;
#endif
- /// clearGraphAttrs - Clear all previously defined node graph attributes.
+ /// Clear all previously defined node graph attributes.
/// Intended to be used from a debugging tool (eg. gdb).
void clearGraphAttrs();
- /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
- ///
+ /// Set graph attributes for a node. (eg. "color=red".)
void setGraphAttrs(const SDNode *N, const char *Attrs);
- /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
+ /// Get graph attributes for a node. (eg. "color=red".)
/// Used from getNodeAttributes.
const std::string getGraphAttrs(const SDNode *N) const;
- /// setGraphColor - Convenience for setting node color attribute.
- ///
+ /// Convenience for setting node color attribute.
void setGraphColor(const SDNode *N, const char *Color);
- /// setGraphColor - Convenience for setting subgraph color attribute.
- ///
+ /// Convenience for setting subgraph color attribute.
void setSubgraphColor(SDNode *N, const char *Color);
typedef ilist<SDNode>::const_iterator allnodes_const_iterator;
@@ -325,17 +322,15 @@ public:
return AllNodes.size();
}
- /// getRoot - Return the root tag of the SelectionDAG.
- ///
+ /// Return the root tag of the SelectionDAG.
const SDValue &getRoot() const { return Root; }
- /// getEntryNode - Return the token chain corresponding to the entry of the
- /// function.
+ /// Return the token chain corresponding to the entry of the function.
SDValue getEntryNode() const {
return SDValue(const_cast<SDNode *>(&EntryNode), 0);
}
- /// setRoot - Set the current root tag of the SelectionDAG.
+ /// Set the current root tag of the SelectionDAG.
///
const SDValue &setRoot(SDValue N) {
assert((!N.getNode() || N.getValueType() == MVT::Other) &&
@@ -348,22 +343,22 @@ public:
return Root;
}
- /// Combine - This iterates over the nodes in the SelectionDAG, folding
+ /// This iterates over the nodes in the SelectionDAG, folding
/// certain types of nodes together, or eliminating superfluous nodes. The
/// Level argument controls whether Combine is allowed to produce nodes and
/// types that are illegal on the target.
void Combine(CombineLevel Level, AliasAnalysis &AA,
CodeGenOpt::Level OptLevel);
- /// LegalizeTypes - This transforms the SelectionDAG into a SelectionDAG that
- /// only uses types natively supported by the target. Returns "true" if it
- /// made any changes.
+ /// This transforms the SelectionDAG into a SelectionDAG that
+ /// only uses types natively supported by the target.
+ /// Returns "true" if it made any changes.
///
/// Note that this is an involved process that may invalidate pointers into
/// the graph.
bool LegalizeTypes();
- /// Legalize - This transforms the SelectionDAG into a SelectionDAG that is
+ /// This transforms the SelectionDAG into a SelectionDAG that is
/// compatible with the target instruction selector, as indicated by the
/// TargetLowering object.
///
@@ -392,7 +387,7 @@ public:
/// 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
+ /// 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
/// operation can introduce illegal types, which requires running
@@ -405,16 +400,14 @@ public:
/// the graph.
bool LegalizeVectors();
- /// RemoveDeadNodes - This method deletes all unreachable nodes in the
- /// SelectionDAG.
+ /// This method deletes all unreachable nodes in the SelectionDAG.
void RemoveDeadNodes();
- /// DeleteNode - Remove the specified node from the system. This node must
+ /// Remove the specified node from the system. This node must
/// have no referrers.
void DeleteNode(SDNode *N);
- /// getVTList - Return an SDVTList that represents the list of values
- /// specified.
+ /// Return an SDVTList that represents the list of values specified.
SDVTList getVTList(EVT VT);
SDVTList getVTList(EVT VT1, EVT VT2);
SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3);
@@ -424,36 +417,40 @@ public:
//===--------------------------------------------------------------------===//
// Node creation methods.
//
- SDValue getConstant(uint64_t Val, EVT VT, bool isTarget = false,
+ SDValue getConstant(uint64_t Val, SDLoc DL, EVT VT, bool isTarget = false,
bool isOpaque = false);
- SDValue getConstant(const APInt &Val, EVT VT, bool isTarget = false,
+ SDValue getConstant(const APInt &Val, SDLoc DL, EVT VT, bool isTarget = false,
bool isOpaque = false);
- SDValue getConstant(const ConstantInt &Val, EVT VT, bool isTarget = false,
- bool isOpaque = false);
- SDValue getIntPtrConstant(uint64_t Val, bool isTarget = false);
- SDValue getTargetConstant(uint64_t Val, EVT VT, bool isOpaque = false) {
- return getConstant(Val, VT, true, isOpaque);
+ SDValue getConstant(const ConstantInt &Val, SDLoc DL, EVT VT,
+ bool isTarget = false, bool isOpaque = false);
+ SDValue getIntPtrConstant(uint64_t Val, SDLoc DL, bool isTarget = false);
+ SDValue getTargetConstant(uint64_t Val, SDLoc DL, EVT VT,
+ bool isOpaque = false) {
+ return getConstant(Val, DL, VT, true, isOpaque);
}
- SDValue getTargetConstant(const APInt &Val, EVT VT, bool isOpaque = false) {
- return getConstant(Val, VT, true, isOpaque);
+ SDValue getTargetConstant(const APInt &Val, SDLoc DL, EVT VT,
+ bool isOpaque = false) {
+ return getConstant(Val, DL, VT, true, isOpaque);
}
- SDValue getTargetConstant(const ConstantInt &Val, EVT VT,
+ SDValue getTargetConstant(const ConstantInt &Val, SDLoc DL, EVT VT,
bool isOpaque = false) {
- return getConstant(Val, VT, true, isOpaque);
+ return getConstant(Val, DL, VT, true, isOpaque);
}
// The forms below that take a double should only be used for simple
// constants that can be exactly represented in VT. No checks are made.
- SDValue getConstantFP(double Val, EVT VT, bool isTarget = false);
- SDValue getConstantFP(const APFloat& Val, EVT VT, bool isTarget = false);
- SDValue getConstantFP(const ConstantFP &CF, EVT VT, bool isTarget = false);
- SDValue getTargetConstantFP(double Val, EVT VT) {
- return getConstantFP(Val, VT, true);
+ SDValue getConstantFP(double Val, SDLoc DL, EVT VT, bool isTarget = false);
+ SDValue getConstantFP(const APFloat& Val, SDLoc DL, EVT VT,
+ bool isTarget = false);
+ SDValue getConstantFP(const ConstantFP &CF, SDLoc DL, EVT VT,
+ bool isTarget = false);
+ SDValue getTargetConstantFP(double Val, SDLoc DL, EVT VT) {
+ return getConstantFP(Val, DL, VT, true);
}
- SDValue getTargetConstantFP(const APFloat& Val, EVT VT) {
- return getConstantFP(Val, VT, true);
+ SDValue getTargetConstantFP(const APFloat& Val, SDLoc DL, EVT VT) {
+ return getConstantFP(Val, DL, VT, true);
}
- SDValue getTargetConstantFP(const ConstantFP &Val, EVT VT) {
- return getConstantFP(Val, VT, true);
+ SDValue getTargetConstantFP(const ConstantFP &Val, SDLoc DL, EVT VT) {
+ return getConstantFP(Val, DL, VT, true);
}
SDValue getGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT,
int64_t offset = 0, bool isTargetGA = false,
@@ -561,10 +558,9 @@ public:
SDValue STy,
SDValue Rnd, SDValue Sat, ISD::CvtCode Code);
- /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of
- /// elements in VT, which must be a vector type, must match the number of
- /// mask elements NumElts. A integer mask element equal to -1 is treated as
- /// undefined.
+ /// Return an ISD::VECTOR_SHUFFLE node. The number of elements in VT,
+ /// which must be a vector type, must match the number of mask elements
+ /// NumElts. An integer mask element equal to -1 is treated as undefined.
SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2,
const int *MaskElts);
SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2,
@@ -580,63 +576,62 @@ public:
/// Example: shuffle A, B, <0,5,2,7> -> shuffle B, A, <4,1,6,3>
SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV);
- /// getAnyExtOrTrunc - Convert Op, which must be of integer type, to the
+ /// Convert Op, which must be of integer type, to the
/// integer type VT, by either any-extending or truncating it.
SDValue getAnyExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
- /// getSExtOrTrunc - Convert Op, which must be of integer type, to the
+ /// Convert Op, which must be of integer type, to the
/// integer type VT, by either sign-extending or truncating it.
SDValue getSExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
- /// getZExtOrTrunc - Convert Op, which must be of integer type, to the
+ /// Convert Op, which must be of integer type, to the
/// integer type VT, by either zero-extending or truncating it.
SDValue getZExtOrTrunc(SDValue Op, SDLoc DL, EVT VT);
- /// getZeroExtendInReg - Return the expression required to zero extend the Op
+ /// Return the expression required to zero extend the Op
/// value assuming it was the smaller SrcTy value.
SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy);
- /// getAnyExtendVectorInReg - Return an operation which will any-extend the
- /// low lanes of the operand into the specified vector type. For example,
+ /// Return an operation which will any-extend the low lanes of the operand
+ /// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by any-extending the low four
/// lanes of the operand from i8 to i32.
SDValue getAnyExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
- /// getSignExtendVectorInReg - Return an operation which will sign extend the
- /// low lanes of the operand into the specified vector type. For example,
+ /// Return an operation which will sign extend the low lanes of the operand
+ /// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by sign extending the low four
/// lanes of the operand from i8 to i32.
SDValue getSignExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
- /// getZeroExtendVectorInReg - Return an operation which will zero extend the
- /// low lanes of the operand into the specified vector type. For example,
+ /// Return an operation which will zero extend the low lanes of the operand
+ /// into the specified vector type. For example,
/// this can convert a v16i8 into a v4i32 by zero extending the low four
/// lanes of the operand from i8 to i32.
SDValue getZeroExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT);
- /// getBoolExtOrTrunc - Convert Op, which must be of integer type, to the
- /// integer type VT, by using an extension appropriate for the target's
+ /// Convert Op, which must be of integer type, to the integer type VT,
+ /// by using an extension appropriate for the target's
/// BooleanContent for type OpVT or truncating it.
SDValue getBoolExtOrTrunc(SDValue Op, SDLoc SL, EVT VT, EVT OpVT);
- /// getNOT - Create a bitwise NOT operation as (XOR Val, -1).
+ /// Create a bitwise NOT operation as (XOR Val, -1).
SDValue getNOT(SDLoc DL, SDValue Val, EVT VT);
/// \brief Create a logical NOT operation as (XOR Val, BooleanOne).
SDValue getLogicalNOT(SDLoc DL, SDValue Val, EVT VT);
- /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have
- /// a glue result (to ensure it's not CSE'd). CALLSEQ_START does not have a
- /// useful SDLoc.
+ /// Return a new CALLSEQ_START node, which always must have a glue result
+ /// (to ensure it's not CSE'd). CALLSEQ_START does not have a useful SDLoc.
SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, SDLoc DL) {
SDVTList VTs = getVTList(MVT::Other, MVT::Glue);
SDValue Ops[] = { Chain, Op };
return getNode(ISD::CALLSEQ_START, DL, VTs, Ops);
}
- /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a
- /// glue result (to ensure it's not CSE'd). CALLSEQ_END does not have
- /// a useful SDLoc.
+ /// Return a new CALLSEQ_END node, which always must have a
+ /// glue result (to ensure it's not CSE'd).
+ /// CALLSEQ_END does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2,
SDValue InGlue, SDLoc DL) {
SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue);
@@ -649,19 +644,28 @@ public:
return getNode(ISD::CALLSEQ_END, DL, NodeTys, Ops);
}
- /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful SDLoc.
+ /// Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getUNDEF(EVT VT) {
return getNode(ISD::UNDEF, SDLoc(), VT);
}
- /// getGLOBAL_OFFSET_TABLE - Return a GLOBAL_OFFSET_TABLE node. This does
- /// not have a useful SDLoc.
+ /// Return a GLOBAL_OFFSET_TABLE node. This does not have a useful SDLoc.
SDValue getGLOBAL_OFFSET_TABLE(EVT VT) {
return getNode(ISD::GLOBAL_OFFSET_TABLE, SDLoc(), VT);
}
- /// getNode - Gets or creates the specified node.
+ /// Gets or creates the specified node.
///
+ SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
+ ArrayRef<SDUse> Ops);
+ SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
+ ArrayRef<SDValue> Ops);
+ SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef<EVT> ResultTys,
+ ArrayRef<SDValue> Ops);
+ SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
+ ArrayRef<SDValue> Ops);
+
+ // Specialize based on number of operands.
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT);
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N);
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
@@ -672,47 +676,40 @@ public:
SDValue N3, SDValue N4);
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2,
SDValue N3, SDValue N4, SDValue N5);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, ArrayRef<SDUse> Ops);
- SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
- ArrayRef<SDValue> Ops);
- SDValue getNode(unsigned Opcode, SDLoc DL,
- ArrayRef<EVT> ResultTys,
- ArrayRef<SDValue> Ops);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
- ArrayRef<SDValue> Ops);
+
+ // Specialize again based on number of operands for nodes with a VTList
+ // rather than a single VT.
SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs);
SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
- SDValue N1, SDValue N2);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
- SDValue N1, SDValue N2, SDValue N3);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
- SDValue N1, SDValue N2, SDValue N3, SDValue N4);
- SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
- SDValue N1, SDValue N2, SDValue N3, SDValue N4,
- SDValue N5);
-
- /// getStackArgumentTokenFactor - Compute a TokenFactor to force all
- /// the incoming stack arguments to be loaded from the stack. This is
- /// used in tail call lowering to protect stack arguments from being
- /// clobbered.
+ SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue N2);
+ SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue N2, SDValue N3);
+ SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue N2, SDValue N3, SDValue N4);
+ SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1,
+ SDValue N2, SDValue N3, SDValue N4, SDValue N5);
+
+ /// Compute a TokenFactor to force all the incoming stack arguments to be
+ /// loaded from the stack. This is used in tail call lowering to protect
+ /// stack arguments from being clobbered.
SDValue getStackArgumentTokenFactor(SDValue Chain);
SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool isVol, bool AlwaysInline,
- MachinePointerInfo DstPtrInfo,
+ bool isTailCall, MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo);
SDValue getMemmove(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
- SDValue Size, unsigned Align, bool isVol,
+ SDValue Size, unsigned Align, bool isVol, bool isTailCall,
MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo);
SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
- SDValue Size, unsigned Align, bool isVol,
+ SDValue Size, unsigned Align, bool isVol, bool isTailCall,
MachinePointerInfo DstPtrInfo);
- /// getSetCC - Helper function to make it easier to build SetCC's if you just
+ /// Helper function to make it easier to build SetCC's if you just
/// have an ISD::CondCode instead of an SDValue.
///
SDValue getSetCC(SDLoc DL, EVT VT, SDValue LHS, SDValue RHS,
@@ -726,8 +723,8 @@ public:
return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond));
}
- // getSelect - Helper function to make it easier to build Select's if you just
- // have operands and don't want to check for vector.
+ /// Helper function to make it easier to build Select's if you just
+ /// have operands and don't want to check for vector.
SDValue getSelect(SDLoc DL, EVT VT, SDValue Cond,
SDValue LHS, SDValue RHS) {
assert(LHS.getValueType() == RHS.getValueType() &&
@@ -738,7 +735,7 @@ public:
Cond, LHS, RHS);
}
- /// getSelectCC - Helper function to make it easier to build SelectCC's if you
+ /// Helper function to make it easier to build SelectCC's if you
/// just have an ISD::CondCode instead of an SDValue.
///
SDValue getSelectCC(SDLoc DL, SDValue LHS, SDValue RHS,
@@ -747,12 +744,12 @@ public:
LHS, RHS, True, False, getCondCode(Cond));
}
- /// getVAArg - VAArg produces a result and token chain, and takes a pointer
+ /// VAArg produces a result and token chain, and takes a pointer
/// and a source value as input.
SDValue getVAArg(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
SDValue SV, unsigned Align);
- /// getAtomicCmpSwap - Gets a node for an atomic cmpxchg op. There are two
+ /// Gets a node for an atomic cmpxchg op. There are two
/// 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.
@@ -769,7 +766,7 @@ public:
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
- /// getAtomic - Gets a node for an atomic op, produces result (if relevant)
+ /// Gets a node for an atomic op, produces result (if relevant)
/// and chain and takes 2 operands.
SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, const Value *PtrVal,
@@ -780,15 +777,15 @@ public:
AtomicOrdering Ordering,
SynchronizationScope SynchScope);
- /// getAtomic - Gets a node for an atomic op, produces result and chain and
+ /// Gets a node for an atomic op, produces result and chain and
/// takes 1 operand.
SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT,
SDValue Chain, SDValue Ptr, MachineMemOperand *MMO,
AtomicOrdering Ordering,
SynchronizationScope SynchScope);
- /// getAtomic - Gets a node for an atomic op, produces result and chain and
- /// takes N operands.
+ /// Gets a node for an atomic op, produces result and chain and takes N
+ /// operands.
SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList,
ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
AtomicOrdering SuccessOrdering,
@@ -798,7 +795,7 @@ public:
ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
AtomicOrdering Ordering, SynchronizationScope SynchScope);
- /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a
+ /// Creates a MemIntrinsicNode that may produce a
/// result and takes a list of operands. Opcode may be INTRINSIC_VOID,
/// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not
/// less than FIRST_TARGET_MEMORY_OPCODE.
@@ -813,10 +810,10 @@ public:
ArrayRef<SDValue> Ops,
EVT MemVT, MachineMemOperand *MMO);
- /// getMergeValues - Create a MERGE_VALUES node from the given operands.
+ /// Create a MERGE_VALUES node from the given operands.
SDValue getMergeValues(ArrayRef<SDValue> Ops, SDLoc dl);
- /// getLoad - Loads are not normal binary operators: their result type is not
+ /// Loads are not normal binary operators: their result type is not
/// determined by their operands, and they produce a value AND a token chain.
///
SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr,
@@ -848,8 +845,7 @@ public:
SDValue Chain, SDValue Ptr, SDValue Offset,
EVT MemVT, MachineMemOperand *MMO);
- /// getStore - Helper function to build ISD::STORE nodes.
- ///
+ /// Helper function to build ISD::STORE nodes.
SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr,
MachinePointerInfo PtrInfo, bool isVolatile,
bool isNonTemporal, unsigned Alignment,
@@ -872,21 +868,25 @@ public:
SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val,
SDValue Ptr, SDValue Mask, EVT MemVT,
MachineMemOperand *MMO, bool IsTrunc);
- /// getSrcValue - Construct a node to track a Value* through the backend.
+ SDValue getMaskedGather(SDVTList VTs, EVT VT, SDLoc dl,
+ ArrayRef<SDValue> Ops, MachineMemOperand *MMO);
+ SDValue getMaskedScatter(SDVTList VTs, EVT VT, SDLoc dl,
+ ArrayRef<SDValue> Ops, MachineMemOperand *MMO);
+ /// Construct a node to track a Value* through the backend.
SDValue getSrcValue(const Value *v);
- /// getMDNode - Return an MDNodeSDNode which holds an MDNode.
+ /// Return an MDNodeSDNode which holds an MDNode.
SDValue getMDNode(const MDNode *MD);
- /// getAddrSpaceCast - Return an AddrSpaceCastSDNode.
+ /// Return an AddrSpaceCastSDNode.
SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr,
unsigned SrcAS, unsigned DestAS);
- /// getShiftAmountOperand - Return the specified value casted to
+ /// Return the specified value casted to
/// the target's desired shift amount type.
SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op);
- /// UpdateNodeOperands - *Mutate* the specified node in-place to have the
+ /// *Mutate* the specified node in-place to have the
/// specified operands. If the resultant node already exists in the DAG,
/// this does not modify the specified node, instead it returns the node that
/// already exists. If the resultant node does not exist in the DAG, the
@@ -902,7 +902,7 @@ public:
SDValue Op3, SDValue Op4, SDValue Op5);
SDNode *UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops);
- /// SelectNodeTo - These are used for target selectors to *mutate* the
+ /// These are used for target selectors to *mutate* the
/// specified node to have the specified return type, Target opcode, and
/// operands. Note that target opcodes are stored as
/// ~TargetOpcode in the node opcode field. The resultant node is returned.
@@ -932,12 +932,12 @@ public:
SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs,
ArrayRef<SDValue> Ops);
- /// MorphNodeTo - This *mutates* the specified node to have the specified
+ /// This *mutates* the specified node to have the specified
/// return type, opcode, and operands.
SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs,
ArrayRef<SDValue> Ops);
- /// getMachineNode - These are used for target selectors to create a new node
+ /// These are used for target selectors to create a new node
/// with specified return type(s), MachineInstr opcode, and operands.
///
/// Note that getMachineNode returns the resultant node. If there is already
@@ -976,25 +976,20 @@ public:
MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, SDVTList VTs,
ArrayRef<SDValue> Ops);
- /// getTargetExtractSubreg - A convenience function for creating
- /// TargetInstrInfo::EXTRACT_SUBREG nodes.
+ /// A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getTargetExtractSubreg(int SRIdx, SDLoc DL, EVT VT,
SDValue Operand);
- /// getTargetInsertSubreg - A convenience function for creating
- /// TargetInstrInfo::INSERT_SUBREG nodes.
+ /// A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getTargetInsertSubreg(int SRIdx, SDLoc DL, EVT VT,
SDValue Operand, SDValue Subreg);
- /// getNodeIfExists - Get the specified node if it's already available, or
- /// else return NULL.
+ /// Get the specified node if it's already available, or else return NULL.
SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef<SDValue> Ops,
bool nuw = false, bool nsw = false,
bool exact = false);
- /// getDbgValue - Creates a SDDbgValue node.
- ///
- /// SDNode
+ /// Creates a SDDbgValue node.
SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R,
bool IsIndirect, uint64_t Off, DebugLoc DL,
unsigned O);
@@ -1007,16 +1002,16 @@ public:
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
+ /// Remove the specified node from the system. If any of its
/// operands then becomes dead, remove them as well. Inform UpdateListener
/// for each node deleted.
void RemoveDeadNode(SDNode *N);
- /// RemoveDeadNodes - This method deletes the unreachable nodes in the
+ /// This method deletes the unreachable nodes in the
/// given list, and any nodes that become unreachable as a result.
void RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes);
- /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead.
+ /// Modify anything using 'From' to use 'To' instead.
/// This can cause recursive merging of nodes in the DAG. Use the first
/// version if 'From' is known to have a single result, use the second
/// if you have two nodes with identical results (or if 'To' has a superset
@@ -1035,30 +1030,29 @@ public:
void ReplaceAllUsesWith(SDNode *From, SDNode *To);
void ReplaceAllUsesWith(SDNode *From, const SDValue *To);
- /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving
+ /// Replace any uses of From with To, leaving
/// uses of other values produced by From.Val alone.
void ReplaceAllUsesOfValueWith(SDValue From, SDValue To);
- /// ReplaceAllUsesOfValuesWith - Like ReplaceAllUsesOfValueWith, but
- /// for multiple values at once. This correctly handles the case where
+ /// Like ReplaceAllUsesOfValueWith, but for multiple values at once.
+ /// This correctly handles the case where
/// there is an overlap between the From values and the To values.
void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To,
unsigned Num);
- /// AssignTopologicalOrder - Topological-sort the AllNodes list and a
+ /// Topological-sort the AllNodes list and a
/// assign a unique node id for each node in the DAG based on their
/// topological order. Returns the number of nodes.
unsigned AssignTopologicalOrder();
- /// RepositionNode - Move node N in the AllNodes list to be immediately
+ /// Move node N in the AllNodes list to be immediately
/// before the given iterator Position. This may be used to update the
/// topological ordering when the list of nodes is modified.
void RepositionNode(allnodes_iterator Position, SDNode *N) {
AllNodes.insert(Position, AllNodes.remove(N));
}
- /// isCommutativeBinOp - Returns true if the opcode is a commutative binary
- /// operation.
+ /// Returns true if the opcode is a commutative binary operation.
static bool isCommutativeBinOp(unsigned Opcode) {
// FIXME: This should get its info from the td file, so that we can include
// target info.
@@ -1099,19 +1093,19 @@ public:
}
}
- /// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the
+ /// Add a dbg_value SDNode. If SD is non-null that means the
/// value is produced by SD.
void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter);
- /// GetDbgValues - Get the debug values which reference the given SDNode.
+ /// Get the debug values which reference the given SDNode.
ArrayRef<SDDbgValue*> GetDbgValues(const SDNode* SD) {
return DbgInfo->getSDDbgValues(SD);
}
- /// TransferDbgValues - Transfer SDDbgValues.
+ /// Transfer SDDbgValues.
void TransferDbgValues(SDValue From, SDValue To);
- /// hasDebugValues - Return true if there are any SDDbgValue nodes associated
+ /// Return true if there are any SDDbgValue nodes associated
/// with this SelectionDAG.
bool hasDebugValues() const { return !DbgInfo->empty(); }
@@ -1126,28 +1120,31 @@ public:
void dump() const;
- /// CreateStackTemporary - Create a stack temporary, suitable for holding the
+ /// Create a stack temporary, suitable for holding the
/// specified value type. If minAlign is specified, the slot size will have
/// at least that alignment.
SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1);
- /// CreateStackTemporary - Create a stack temporary suitable for holding
+ /// Create a stack temporary suitable for holding
/// either of the specified value types.
SDValue CreateStackTemporary(EVT VT1, EVT VT2);
- /// FoldConstantArithmetic -
- SDValue FoldConstantArithmetic(unsigned Opcode, EVT VT,
+ SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT,
SDNode *Cst1, SDNode *Cst2);
- /// FoldSetCC - Constant fold a setcc to true or false.
+ SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT,
+ const ConstantSDNode *Cst1,
+ const ConstantSDNode *Cst2);
+
+ /// Constant fold a setcc to true or false.
SDValue FoldSetCC(EVT VT, SDValue N1,
SDValue N2, ISD::CondCode Cond, SDLoc dl);
- /// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We
- /// use this predicate to simplify operations downstream.
+ /// Return true if the sign bit of Op is known to be zero.
+ /// We use this predicate to simplify operations downstream.
bool SignBitIsZero(SDValue Op, unsigned Depth = 0) const;
- /// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero. We
+ /// Return true if 'Op & Mask' is known to be zero. We
/// use this predicate to simplify operations downstream. Op and Mask are
/// known to be the same type.
bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth = 0)
@@ -1160,7 +1157,7 @@ public:
void computeKnownBits(SDValue Op, APInt &KnownZero, APInt &KnownOne,
unsigned Depth = 0) const;
- /// ComputeNumSignBits - Return the number of times the sign bit of the
+ /// 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
/// information. For example, immediately after an "SRA X, 2", we know that
@@ -1169,26 +1166,26 @@ public:
/// class to allow target nodes to be understood.
unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const;
- /// isBaseWithConstantOffset - Return true if the specified operand is an
+ /// Return true if the specified operand is an
/// ISD::ADD with a ConstantSDNode on the right-hand side, or if it is an
/// ISD::OR with a ConstantSDNode that is guaranteed to have the same
/// semantics as an ADD. This handles the equivalence:
/// X|Cst == X+Cst iff X&Cst = 0.
bool isBaseWithConstantOffset(SDValue Op) const;
- /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN.
+ /// Test whether the given SDValue is known to never be NaN.
bool isKnownNeverNaN(SDValue Op) const;
- /// isKnownNeverZero - Test whether the given SDValue is known to never be
+ /// Test whether the given SDValue is known to never be
/// positive or negative Zero.
bool isKnownNeverZero(SDValue Op) const;
- /// isEqualTo - Test whether two SDValues are known to compare equal. This
+ /// Test whether two SDValues are known to compare equal. This
/// is true if they are the same value, or if one is negative zero and the
/// other positive zero.
bool isEqualTo(SDValue A, SDValue B) const;
- /// UnrollVectorOp - Utility function used by legalize and lowering to
+ /// Utility function used by legalize and lowering to
/// "unroll" a vector operation by splitting out the scalars and operating
/// on each element individually. If the ResNE is 0, fully unroll the vector
/// op. If ResNE is less than the width of the vector op, unroll up to ResNE.
@@ -1196,43 +1193,40 @@ public:
/// vector op and fill the end of the resulting vector with UNDEFS.
SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0);
- /// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a
- /// location that is 'Dist' units away from the location that the 'Base' load
- /// is loading from.
+ /// Return true if LD is loading 'Bytes' bytes from a location that is 'Dist'
+ /// units away from the location that the 'Base' load is loading from.
bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base,
unsigned Bytes, int Dist) const;
- /// InferPtrAlignment - Infer alignment of a load / store address. Return 0 if
+ /// Infer alignment of a load / store address. Return 0 if
/// it cannot be inferred.
unsigned InferPtrAlignment(SDValue Ptr) const;
- /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type
+ /// Compute the VTs needed for the low/hi parts of a type
/// which is split (or expanded) into two not necessarily identical pieces.
std::pair<EVT, EVT> GetSplitDestVTs(const EVT &VT) const;
- /// SplitVector - Split the vector with EXTRACT_SUBVECTOR using the provides
+ /// Split the vector with EXTRACT_SUBVECTOR using the provides
/// VTs and return the low/high part.
std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL,
const EVT &LoVT, const EVT &HiVT);
- /// SplitVector - Split the vector with EXTRACT_SUBVECTOR and return the
- /// low/high part.
+ /// Split the vector with EXTRACT_SUBVECTOR and return the low/high part.
std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL) {
EVT LoVT, HiVT;
std::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType());
return SplitVector(N, DL, LoVT, HiVT);
}
- /// SplitVectorOperand - Split the node's operand with EXTRACT_SUBVECTOR and
+ /// Split the node's operand with EXTRACT_SUBVECTOR and
/// return the low/high part.
std::pair<SDValue, SDValue> SplitVectorOperand(const SDNode *N, unsigned OpNo)
{
return SplitVector(N->getOperand(OpNo), SDLoc(N));
}
- /// ExtractVectorElements - Append the extracted elements from Start to Count
- /// out of the vector Op in Args. If Count is 0, all of the elements will be
- /// extracted.
+ /// Append the extracted elements from Start to Count out of the vector Op
+ /// in Args. If Count is 0, all of the elements will be extracted.
void ExtractVectorElements(SDValue Op, SmallVectorImpl<SDValue> &Args,
unsigned Start = 0, unsigned Count = 0);
@@ -1258,10 +1252,22 @@ private:
SDValue N1, SDValue N2, bool nuw, bool nsw,
bool exact);
- /// VTList - List of non-single value types.
+ /// Look up the node specified by ID in CSEMap. If it exists, return it. If
+ /// not, return the insertion token that will make insertion faster. This
+ /// overload is for nodes other than Constant or ConstantFP, use the other one
+ /// for those.
+ SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos);
+
+ /// Look up the node specified by ID in CSEMap. If it exists, return it. If
+ /// not, return the insertion token that will make insertion faster. Performs
+ /// additional processing for constant nodes.
+ SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, DebugLoc DL,
+ void *&InsertPos);
+
+ /// List of non-single value types.
FoldingSet<SDVTListNode> VTListMap;
- /// CondCodeNodes - Maps to auto-CSE operations.
+ /// Maps to auto-CSE operations.
std::vector<CondCodeSDNode*> CondCodeNodes;
std::vector<SDNode*> ValueTypeNodes;
diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h
index d53e66da5a71..a011e4c338c4 100644
--- a/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/include/llvm/CodeGen/SelectionDAGISel.h
@@ -58,7 +58,7 @@ public:
explicit SelectionDAGISel(TargetMachine &tm,
CodeGenOpt::Level OL = CodeGenOpt::Default);
- virtual ~SelectionDAGISel();
+ ~SelectionDAGISel() override;
const TargetLowering *getTargetLowering() const { return TLI; }
@@ -80,12 +80,12 @@ public:
virtual SDNode *Select(SDNode *N) = 0;
/// SelectInlineAsmMemoryOperand - Select the specified address as a target
- /// addressing mode, according to the specified constraint code. If this does
+ /// addressing mode, according to the specified constraint. If this does
/// not match or is not implemented, return true. The resultant operands
/// (which will appear in the machine instruction) should be added to the
/// OutOps vector.
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
- char ConstraintCode,
+ unsigned ConstraintID,
std::vector<SDValue> &OutOps) {
return true;
}
@@ -199,7 +199,7 @@ protected:
/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated
/// by tblgen. Others should not call it.
- void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops);
+ void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops, SDLoc DL);
public:
@@ -260,7 +260,10 @@ private:
SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs,
ArrayRef<SDValue> Ops, unsigned EmitNodeInfo);
- void PrepareEHLandingPad();
+ /// Prepares the landing pad to take incoming values or do other EH
+ /// personality specific tasks. Returns true if the block should be
+ /// instruction selected, false if no code should be emitted for it.
+ bool PrepareEHLandingPad();
/// \brief Perform instruction selection on all basic blocks in the function.
void SelectAllBasicBlocks(const Function &Fn);
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 933ec7fff483..daa19430192a 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -50,28 +50,10 @@ template <typename T> struct DenseMapInfo;
template <typename T> struct simplify_type;
template <typename T> struct ilist_traits;
-/// isBinOpWithFlags - Returns true if the opcode is a binary operation
-/// with flags.
-static bool isBinOpWithFlags(unsigned Opcode) {
- switch (Opcode) {
- case ISD::SDIV:
- case ISD::UDIV:
- case ISD::SRA:
- case ISD::SRL:
- case ISD::MUL:
- case ISD::ADD:
- case ISD::SUB:
- case ISD::SHL:
- return true;
- default:
- return false;
- }
-}
-
void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr,
bool force = false);
-/// SDVTList - This represents a list of ValueType's that has been intern'd by
+/// This represents a list of ValueType's that has been intern'd by
/// a SelectionDAG. Instances of this simple value class are returned by
/// SelectionDAG::getVTList(...).
///
@@ -83,11 +65,11 @@ struct SDVTList {
namespace ISD {
/// Node predicates
- /// isBuildVectorAllOnes - Return true if the specified node is a
+ /// Return true if the specified node is a
/// BUILD_VECTOR where all of the elements are ~0 or undef.
bool isBuildVectorAllOnes(const SDNode *N);
- /// isBuildVectorAllZeros - Return true if the specified node is a
+ /// Return true if the specified node is a
/// BUILD_VECTOR where all of the elements are 0 or undef.
bool isBuildVectorAllZeros(const SDNode *N);
@@ -95,18 +77,22 @@ namespace ISD {
/// all ConstantSDNode or undef.
bool isBuildVectorOfConstantSDNodes(const SDNode *N);
- /// isScalarToVector - Return true if the specified node is a
+ /// \brief Return true if the specified node is a BUILD_VECTOR node of
+ /// all ConstantFPSDNode or undef.
+ bool isBuildVectorOfConstantFPSDNodes(const SDNode *N);
+
+ /// Return true if the specified node is a
/// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low
/// element is not an undef.
bool isScalarToVector(const SDNode *N);
- /// allOperandsUndef - Return true if the node has at least one operand
+ /// Return true if the node has at least one operand
/// and all operands of the specified node are ISD::UNDEF.
bool allOperandsUndef(const SDNode *N);
} // end llvm:ISD namespace
//===----------------------------------------------------------------------===//
-/// SDValue - Unlike LLVM values, Selection DAG nodes may return multiple
+/// Unlike LLVM values, Selection DAG nodes may return multiple
/// values as the result of a computation. Many nodes return multiple values,
/// from loads (which define a token and a return value) to ADDC (which returns
/// a result and a carry value), to calls (which may return an arbitrary number
@@ -145,7 +131,7 @@ public:
bool operator<(const SDValue &O) const {
return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo);
}
- LLVM_EXPLICIT operator bool() const {
+ explicit operator bool() const {
return Node != nullptr;
}
@@ -153,11 +139,10 @@ public:
return SDValue(Node, R);
}
- // isOperandOf - Return true if this node is an operand of N.
+ // Return true if this node is an operand of N.
bool isOperandOf(SDNode *N) const;
- /// getValueType - Return the ValueType of the referenced return value.
- ///
+ /// Return the ValueType of the referenced return value.
inline EVT getValueType() const;
/// Return the simple ValueType of the referenced return value.
@@ -165,8 +150,7 @@ public:
return getValueType().getSimpleVT();
}
- /// getValueSizeInBits - Returns the size of the value in bits.
- ///
+ /// Returns the size of the value in bits.
unsigned getValueSizeInBits() const {
return getValueType().getSizeInBits();
}
@@ -184,26 +168,22 @@ public:
inline bool isTargetOpcode() const;
inline bool isMachineOpcode() const;
inline unsigned getMachineOpcode() const;
- inline const DebugLoc getDebugLoc() const;
+ inline const DebugLoc &getDebugLoc() const;
inline void dump() const;
inline void dumpr() const;
- /// reachesChainWithoutSideEffects - Return true if this operand (which must
- /// be a chain) reaches the specified operand without crossing any
- /// side-effecting instructions. In practice, this looks through token
- /// factors and non-volatile loads. In order to remain efficient, this only
+ /// Return true if this operand (which must be a chain) reaches the
+ /// specified operand without crossing any side-effecting instructions.
+ /// In practice, this looks through token factors and non-volatile loads.
+ /// In order to remain efficient, this only
/// looks a couple of nodes in, it does not do an exhaustive search.
bool reachesChainWithoutSideEffects(SDValue Dest,
unsigned Depth = 2) const;
- /// use_empty - Return true if there are no nodes using value ResNo
- /// of Node.
- ///
+ /// Return true if there are no nodes using value ResNo of Node.
inline bool use_empty() const;
- /// hasOneUse - Return true if there is exactly one node using value
- /// ResNo of Node.
- ///
+ /// Return true if there is exactly one node using value ResNo of Node.
inline bool hasOneUse() const;
};
@@ -230,7 +210,7 @@ template<> struct DenseMapInfo<SDValue> {
template <> struct isPodLike<SDValue> { static const bool value = true; };
-/// simplify_type specializations - Allow casting operators to work directly on
+/// Allow casting operators to work directly on
/// SDValues as if they were SDNode*'s.
template<> struct simplify_type<SDValue> {
typedef SDNode* SimpleType;
@@ -245,7 +225,7 @@ template<> struct simplify_type<const SDValue> {
}
};
-/// SDUse - Represents a use of a SDNode. This class holds an SDValue,
+/// Represents a use of a SDNode. This class holds an SDValue,
/// which records the SDNode being used and the result number, a
/// pointer to the SDNode using the value, and Next and Prev pointers,
/// which link together all the uses of an SDNode.
@@ -259,8 +239,8 @@ class SDUse {
/// this operand.
SDUse **Prev, *Next;
- SDUse(const SDUse &U) LLVM_DELETED_FUNCTION;
- void operator=(const SDUse &U) LLVM_DELETED_FUNCTION;
+ SDUse(const SDUse &U) = delete;
+ void operator=(const SDUse &U) = delete;
public:
SDUse() : Val(), User(nullptr), Prev(nullptr), Next(nullptr) {}
@@ -272,30 +252,30 @@ public:
/// the SDValue.
const SDValue &get() const { return Val; }
- /// getUser - This returns the SDNode that contains this Use.
+ /// This returns the SDNode that contains this Use.
SDNode *getUser() { return User; }
- /// getNext - Get the next SDUse in the use list.
+ /// Get the next SDUse in the use list.
SDUse *getNext() const { return Next; }
- /// getNode - Convenience function for get().getNode().
+ /// Convenience function for get().getNode().
SDNode *getNode() const { return Val.getNode(); }
- /// getResNo - Convenience function for get().getResNo().
+ /// Convenience function for get().getResNo().
unsigned getResNo() const { return Val.getResNo(); }
- /// getValueType - Convenience function for get().getValueType().
+ /// Convenience function for get().getValueType().
EVT getValueType() const { return Val.getValueType(); }
- /// operator== - Convenience function for get().operator==
+ /// Convenience function for get().operator==
bool operator==(const SDValue &V) const {
return Val == V;
}
- /// operator!= - Convenience function for get().operator!=
+ /// Convenience function for get().operator!=
bool operator!=(const SDValue &V) const {
return Val != V;
}
- /// operator< - Convenience function for get().operator<
+ /// Convenience function for get().operator<
bool operator<(const SDValue &V) const {
return Val < V;
}
@@ -306,13 +286,13 @@ private:
void setUser(SDNode *p) { User = p; }
- /// set - Remove this use from its existing use list, assign it the
+ /// Remove this use from its existing use list, assign it the
/// given value, and add it to the new value's node's use list.
inline void set(const SDValue &V);
- /// setInitial - like set, but only supports initializing a newly-allocated
+ /// Like set, but only supports initializing a newly-allocated
/// SDUse with a non-null value.
inline void setInitial(const SDValue &V);
- /// setNode - like set, but only sets the Node portion of the value,
+ /// Like set, but only sets the Node portion of the value,
/// leaving the ResNo portion unmodified.
inline void setNode(SDNode *N);
@@ -339,47 +319,45 @@ template<> struct simplify_type<SDUse> {
};
-/// SDNode - Represents one node in the SelectionDAG.
+/// Represents one node in the SelectionDAG.
///
class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
private:
- /// NodeType - The operation that this node performs.
- ///
+ /// The operation that this node performs.
int16_t NodeType;
- /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true,
+ /// This is true if OperandList was new[]'d. If true,
/// then they will be delete[]'d when the node is destroyed.
uint16_t OperandsNeedDelete : 1;
- /// HasDebugValue - This tracks whether this node has one or more dbg_value
+ /// This tracks whether this node has one or more dbg_value
/// nodes corresponding to it.
uint16_t HasDebugValue : 1;
protected:
- /// SubclassData - This member is defined by this class, but is not used for
+ /// 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.
uint16_t SubclassData : 14;
private:
- /// NodeId - Unique id per SDNode in the DAG.
+ /// Unique id per SDNode in the DAG.
int NodeId;
- /// OperandList - The values that are used by this operation.
- ///
+ /// The values that are used by this operation.
SDUse *OperandList;
- /// ValueList - The types of the values this node defines. SDNode's may
+ /// The types of the values this node defines. SDNode's may
/// define multiple values simultaneously.
const EVT *ValueList;
- /// UseList - List of uses for this SDNode.
+ /// List of uses for this SDNode.
SDUse *UseList;
- /// NumOperands/NumValues - The number of entries in the Operand/Value list.
+ /// The number of entries in the Operand/Value list.
unsigned short NumOperands, NumValues;
- /// debugLoc - source line information.
+ /// Source line information.
DebugLoc debugLoc;
// The ordering of the SDNodes. It roughly corresponds to the ordering of the
@@ -389,7 +367,7 @@ private:
// this ordering.
unsigned IROrder;
- /// getValueTypeList - Return a pointer to the specified value type.
+ /// Return a pointer to the specified value type.
static const EVT *getValueTypeList(EVT VT);
friend class SelectionDAG;
@@ -400,17 +378,17 @@ public:
// Accessors
//
- /// getOpcode - Return the SelectionDAG opcode value for this node. For
+ /// Return the SelectionDAG opcode value for this node. For
/// pre-isel nodes (those for which isMachineOpcode returns false), these
/// are the opcode values in the ISD and <target>ISD namespaces. For
/// post-isel opcodes, see getMachineOpcode.
unsigned getOpcode() const { return (unsigned short)NodeType; }
- /// isTargetOpcode - Test if this node has a target-specific opcode (in the
+ /// Test if this node has a target-specific opcode (in the
/// \<target\>ISD namespace).
bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; }
- /// isTargetMemoryOpcode - Test if this node has a target-specific
+ /// Test if this node has a target-specific
/// memory-referencing opcode (in the \<target\>ISD namespace and
/// greater than FIRST_TARGET_MEMORY_OPCODE).
bool isTargetMemoryOpcode() const {
@@ -427,11 +405,11 @@ public:
NodeType == ISD::INTRINSIC_VOID) && ((SubclassData >> 13) & 1);
}
- /// isMachineOpcode - Test if this node has a post-isel opcode, directly
+ /// Test if this node has a post-isel opcode, directly
/// corresponding to a MachineInstr opcode.
bool isMachineOpcode() const { return NodeType < 0; }
- /// getMachineOpcode - This may only be called if isMachineOpcode returns
+ /// This may only be called if isMachineOpcode returns
/// true. It returns the MachineInstr opcode value that the node's opcode
/// corresponds to.
unsigned getMachineOpcode() const {
@@ -439,50 +417,44 @@ public:
return ~NodeType;
}
- /// getHasDebugValue - get this bit.
+ /// Get this bit.
bool getHasDebugValue() const { return HasDebugValue; }
- /// setHasDebugValue - set this bit.
+ /// Set this bit.
void setHasDebugValue(bool b) { HasDebugValue = b; }
- /// use_empty - Return true if there are no uses of this node.
- ///
+ /// Return true if there are no uses of this node.
bool use_empty() const { return UseList == nullptr; }
- /// hasOneUse - Return true if there is exactly one use of this node.
- ///
+ /// Return true if there is exactly one use of this node.
bool hasOneUse() const {
return !use_empty() && std::next(use_begin()) == use_end();
}
- /// use_size - Return the number of uses of this node. This method takes
+ /// Return the number of uses of this node. This method takes
/// time proportional to the number of uses.
- ///
size_t use_size() const { return std::distance(use_begin(), use_end()); }
- /// getNodeId - Return the unique node id.
- ///
+ /// Return the unique node id.
int getNodeId() const { return NodeId; }
- /// setNodeId - Set unique node id.
+ /// Set unique node id.
void setNodeId(int Id) { NodeId = Id; }
- /// getIROrder - Return the node ordering.
- ///
+ /// Return the node ordering.
unsigned getIROrder() const { return IROrder; }
- /// setIROrder - Set the node ordering.
- ///
+ /// Set the node ordering.
void setIROrder(unsigned Order) { IROrder = Order; }
- /// getDebugLoc - Return the source location info.
- const DebugLoc getDebugLoc() const { return debugLoc; }
+ /// Return the source location info.
+ const DebugLoc &getDebugLoc() const { return debugLoc; }
- /// setDebugLoc - Set source location info. Try to avoid this, putting
+ /// Set source location info. Try to avoid this, putting
/// it in the constructor is preferable.
- void setDebugLoc(const DebugLoc dl) { debugLoc = dl; }
+ void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); }
- /// use_iterator - This class provides iterator support for SDUse
+ /// This class provides iterator support for SDUse
/// operands that use a specific SDNode.
class use_iterator
: public std::iterator<std::forward_iterator_tag, SDUse, ptrdiff_t> {
@@ -506,7 +478,7 @@ public:
return !operator==(x);
}
- /// atEnd - return true if this iterator is at the end of uses list.
+ /// Return true if this iterator is at the end of uses list.
bool atEnd() const { return Op == nullptr; }
// Iterator traversal: forward iteration only.
@@ -530,17 +502,14 @@ public:
SDUse &getUse() const { return *Op; }
- /// getOperandNo - Retrieve the operand # of this use in its user.
- ///
+ /// Retrieve the operand # of this use in its user.
unsigned getOperandNo() const {
assert(Op && "Cannot dereference end iterator!");
return (unsigned)(Op - Op->getUser()->OperandList);
}
};
- /// use_begin/use_end - Provide iteration support to walk over all uses
- /// of an SDNode.
-
+ /// Provide iteration support to walk over all uses of an SDNode.
use_iterator use_begin() const {
return use_iterator(UseList);
}
@@ -554,37 +523,34 @@ public:
return iterator_range<use_iterator>(use_begin(), use_end());
}
- /// hasNUsesOfValue - Return true if there are exactly NUSES uses of the
- /// indicated value. This method ignores uses of other values defined by this
- /// operation.
+ /// Return true if there are exactly NUSES uses of the indicated value.
+ /// This method ignores uses of other values defined by this operation.
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const;
- /// hasAnyUseOfValue - Return true if there are any use of the indicated
- /// value. This method ignores uses of other values defined by this operation.
+ /// Return true if there are any use of the indicated value.
+ /// This method ignores uses of other values defined by this operation.
bool hasAnyUseOfValue(unsigned Value) const;
- /// isOnlyUserOf - Return true if this node is the only use of N.
- ///
+ /// Return true if this node is the only use of N.
bool isOnlyUserOf(SDNode *N) const;
- /// isOperandOf - Return true if this node is an operand of N.
- ///
+ /// Return true if this node is an operand of N.
bool isOperandOf(SDNode *N) const;
- /// isPredecessorOf - Return true if this node is a predecessor of N.
+ /// Return true if this node is a predecessor of N.
/// NOTE: Implemented on top of hasPredecessor and every bit as
/// expensive. Use carefully.
bool isPredecessorOf(const SDNode *N) const {
return N->hasPredecessor(this);
}
- /// hasPredecessor - Return true if N is a predecessor of this node.
+ /// Return true if N is a predecessor of this node.
/// N is either an operand of this node, or can be reached by recursively
/// traversing up the operands.
/// NOTE: This is an expensive method. Use it carefully.
bool hasPredecessor(const SDNode *N) const;
- /// hasPredecesorHelper - Return true if N is a predecessor of this node.
+ /// Return true if N is a predecessor of this node.
/// N is either an operand of this node, or can be reached by recursively
/// traversing up the operands.
/// In this helper the Visited and worklist sets are held externally to
@@ -597,12 +563,10 @@ public:
SmallPtrSetImpl<const SDNode *> &Visited,
SmallVectorImpl<const SDNode *> &Worklist) const;
- /// getNumOperands - Return the number of values used by this operation.
- ///
+ /// Return the number of values used by this operation.
unsigned getNumOperands() const { return NumOperands; }
- /// getConstantOperandVal - Helper method returns the integer value of a
- /// ConstantSDNode operand.
+ /// Helper method returns the integer value of a ConstantSDNode operand.
uint64_t getConstantOperandVal(unsigned Num) const;
const SDValue &getOperand(unsigned Num) const {
@@ -620,7 +584,7 @@ public:
return X;
}
- /// getGluedNode - If this node has a glue operand, return the node
+ /// If this node has a glue operand, return the node
/// to which the glue operand points. Otherwise return NULL.
SDNode *getGluedNode() const {
if (getNumOperands() != 0 &&
@@ -645,7 +609,7 @@ public:
return FoundNode;
}
- /// getGluedUser - If this node has a glue value with a user, return
+ /// If this node has a glue value with a user, return
/// the user (there is at most one). Otherwise return NULL.
SDNode *getGluedUser() const {
for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI)
@@ -654,26 +618,21 @@ public:
return nullptr;
}
- /// getNumValues - Return the number of values defined/returned by this
- /// operator.
- ///
+ /// Return the number of values defined/returned by this operator.
unsigned getNumValues() const { return NumValues; }
- /// getValueType - Return the type of a specified result.
- ///
+ /// Return the type of a specified result.
EVT getValueType(unsigned ResNo) const {
assert(ResNo < NumValues && "Illegal result number!");
return ValueList[ResNo];
}
/// Return the type of a specified result as a simple type.
- ///
MVT getSimpleValueType(unsigned ResNo) const {
return getValueType(ResNo).getSimpleVT();
}
- /// getValueSizeInBits - Returns MVT::getSizeInBits(getValueType(ResNo)).
- ///
+ /// Returns MVT::getSizeInBits(getValueType(ResNo)).
unsigned getValueSizeInBits(unsigned ResNo) const {
return getValueType(ResNo).getSizeInBits();
}
@@ -682,8 +641,7 @@ public:
value_iterator value_begin() const { return ValueList; }
value_iterator value_end() const { return ValueList+NumValues; }
- /// getOperationName - Return the opcode of this operation for printing.
- ///
+ /// Return the opcode of this operation for printing.
std::string getOperationName(const SelectionDAG *G = nullptr) const;
static const char* getIndexedModeName(ISD::MemIndexedMode AM);
void print_types(raw_ostream &OS, const SelectionDAG *G) const;
@@ -691,7 +649,7 @@ public:
void print(raw_ostream &OS, const SelectionDAG *G = nullptr) const;
void printr(raw_ostream &OS, const SelectionDAG *G = nullptr) const;
- /// printrFull - Print a SelectionDAG node and all children down to
+ /// Print a SelectionDAG node and all children down to
/// the leaves. The given SelectionDAG allows target-specific nodes
/// to be printed in human-readable form. Unlike printr, this will
/// print the whole DAG, including children that appear multiple
@@ -699,7 +657,7 @@ public:
///
void printrFull(raw_ostream &O, const SelectionDAG *G = nullptr) const;
- /// printrWithDepth - Print a SelectionDAG node and children up to
+ /// Print a SelectionDAG node and children up to
/// depth "depth." The given SelectionDAG allows target-specific
/// nodes to be printed in human-readable form. Unlike printr, this
/// will print children that appear multiple times wherever they are
@@ -709,30 +667,29 @@ public:
unsigned depth = 100) const;
- /// dump - Dump this node, for debugging.
+ /// Dump this node, for debugging.
void dump() const;
- /// dumpr - Dump (recursively) this node and its use-def subgraph.
+ /// Dump (recursively) this node and its use-def subgraph.
void dumpr() const;
- /// dump - Dump this node, for debugging.
+ /// Dump this node, for debugging.
/// The given SelectionDAG allows target-specific nodes to be printed
/// in human-readable form.
void dump(const SelectionDAG *G) const;
- /// dumpr - Dump (recursively) this node and its use-def subgraph.
+ /// Dump (recursively) this node and its use-def subgraph.
/// The given SelectionDAG allows target-specific nodes to be printed
/// in human-readable form.
void dumpr(const SelectionDAG *G) const;
- /// dumprFull - printrFull to dbgs(). The given SelectionDAG allows
+ /// printrFull to dbgs(). The given SelectionDAG allows
/// target-specific nodes to be printed in human-readable form.
/// Unlike dumpr, this will print the whole DAG, including children
/// that appear multiple times.
- ///
void dumprFull(const SelectionDAG *G = nullptr) const;
- /// dumprWithDepth - printrWithDepth to dbgs(). The given
+ /// printrWithDepth to dbgs(). The given
/// SelectionDAG allows target-specific nodes to be printed in
/// human-readable form. Unlike dumpr, this will print children
/// that appear multiple times wherever they are used.
@@ -740,12 +697,10 @@ public:
void dumprWithDepth(const SelectionDAG *G = nullptr,
unsigned depth = 100) const;
- /// Profile - Gather unique data for the node.
- ///
+ /// Gather unique data for the node.
void Profile(FoldingSetNodeID &ID) const;
- /// addUse - This method should only be used by the SDUse class.
- ///
+ /// This method should only be used by the SDUse class.
void addUse(SDUse &U) { U.addToList(&UseList); }
protected:
@@ -754,14 +709,13 @@ protected:
return Ret;
}
- SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs,
+ SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
ArrayRef<SDValue> Ops)
- : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false),
- SubclassData(0), NodeId(-1),
- OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr),
- ValueList(VTs.VTs), UseList(nullptr),
- NumOperands(Ops.size()), NumValues(VTs.NumVTs),
- debugLoc(dl), IROrder(Order) {
+ : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false),
+ SubclassData(0), NodeId(-1),
+ OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr),
+ ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()),
+ NumValues(VTs.NumVTs), debugLoc(std::move(dl)), IROrder(Order) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumOperands == Ops.size() &&
"NumOperands wasn't wide enough for its operands!");
@@ -777,17 +731,17 @@ protected:
/// This constructor adds no operands itself; operands can be
/// set later with InitOperands.
- SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs)
- : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false),
- SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
- UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl),
- IROrder(Order) {
+ SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs)
+ : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false),
+ SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
+ UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs),
+ debugLoc(std::move(dl)), IROrder(Order) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumValues == VTs.NumVTs &&
"NumValues wasn't wide enough for its operands!");
}
- /// InitOperands - Initialize the operands list of this with 1 operand.
+ /// Initialize the operands list of this with 1 operand.
void InitOperands(SDUse *Ops, const SDValue &Op0) {
Ops[0].setUser(this);
Ops[0].setInitial(Op0);
@@ -796,7 +750,7 @@ protected:
checkForCycles(this);
}
- /// InitOperands - Initialize the operands list of this with 2 operands.
+ /// Initialize the operands list of this with 2 operands.
void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) {
Ops[0].setUser(this);
Ops[0].setInitial(Op0);
@@ -807,7 +761,7 @@ protected:
checkForCycles(this);
}
- /// InitOperands - Initialize the operands list of this with 3 operands.
+ /// Initialize the operands list of this with 3 operands.
void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1,
const SDValue &Op2) {
Ops[0].setUser(this);
@@ -821,7 +775,7 @@ protected:
checkForCycles(this);
}
- /// InitOperands - Initialize the operands list of this with 4 operands.
+ /// Initialize the operands list of this with 4 operands.
void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1,
const SDValue &Op2, const SDValue &Op3) {
Ops[0].setUser(this);
@@ -837,7 +791,7 @@ protected:
checkForCycles(this);
}
- /// InitOperands - Initialize the operands list of this with N operands.
+ /// Initialize the operands list of this with N operands.
void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) {
for (unsigned i = 0; i != N; ++i) {
Ops[i].setUser(this);
@@ -850,8 +804,7 @@ protected:
checkForCycles(this);
}
- /// DropOperands - Release the operands and set this node to have
- /// zero operands.
+ /// Release the operands and set this node to have zero operands.
void DropOperands();
};
@@ -945,7 +898,7 @@ inline bool SDValue::use_empty() const {
inline bool SDValue::hasOneUse() const {
return Node->hasNUsesOfValue(1, ResNo);
}
-inline const DebugLoc SDValue::getDebugLoc() const {
+inline const DebugLoc &SDValue::getDebugLoc() const {
return Node->getDebugLoc();
}
inline void SDValue::dump() const {
@@ -973,7 +926,63 @@ inline void SDUse::setNode(SDNode *N) {
if (N) N->addUse(*this);
}
-/// UnarySDNode - This class is used for single-operand SDNodes. This is solely
+/// These are IR-level optimization flags that may be propagated to SDNodes.
+/// TODO: This data structure should be shared by the IR optimizer and the
+/// the backend.
+struct SDNodeFlags {
+private:
+ bool NoUnsignedWrap : 1;
+ bool NoSignedWrap : 1;
+ bool Exact : 1;
+ bool UnsafeAlgebra : 1;
+ bool NoNaNs : 1;
+ bool NoInfs : 1;
+ bool NoSignedZeros : 1;
+ bool AllowReciprocal : 1;
+
+public:
+ /// Default constructor turns off all optimization flags.
+ SDNodeFlags() {
+ NoUnsignedWrap = false;
+ NoSignedWrap = false;
+ Exact = false;
+ UnsafeAlgebra = false;
+ NoNaNs = false;
+ NoInfs = false;
+ NoSignedZeros = false;
+ AllowReciprocal = false;
+ }
+
+ // These are mutators for each flag.
+ void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
+ void setNoSignedWrap(bool b) { NoSignedWrap = b; }
+ void setExact(bool b) { Exact = b; }
+ void setUnsafeAlgebra(bool b) { UnsafeAlgebra = b; }
+ void setNoNaNs(bool b) { NoNaNs = b; }
+ void setNoInfs(bool b) { NoInfs = b; }
+ void setNoSignedZeros(bool b) { NoSignedZeros = b; }
+ void setAllowReciprocal(bool b) { AllowReciprocal = b; }
+
+ // These are accessors for each flag.
+ bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
+ bool hasNoSignedWrap() const { return NoSignedWrap; }
+ bool hasExact() const { return Exact; }
+ bool hasUnsafeAlgebra() const { return UnsafeAlgebra; }
+ bool hasNoNaNs() const { return NoNaNs; }
+ bool hasNoInfs() const { return NoInfs; }
+ bool hasNoSignedZeros() const { return NoSignedZeros; }
+ bool hasAllowReciprocal() const { return AllowReciprocal; }
+
+ /// Return a raw encoding of the flags.
+ /// This function should only be used to add data to the NodeID value.
+ unsigned getRawFlags() const {
+ return (NoUnsignedWrap << 0) | (NoSignedWrap << 1) | (Exact << 2) |
+ (UnsafeAlgebra << 3) | (NoNaNs << 4) | (NoInfs << 5) |
+ (NoSignedZeros << 6) | (AllowReciprocal << 7);
+ }
+};
+
+/// This class is used for single-operand SDNodes. This is solely
/// to allow co-allocation of node operands with the node itself.
class UnarySDNode : public SDNode {
SDUse Op;
@@ -985,7 +994,7 @@ public:
}
};
-/// BinarySDNode - This class is used for two-operand SDNodes. This is solely
+/// This class is used for two-operand SDNodes. This is solely
/// to allow co-allocation of node operands with the node itself.
class BinarySDNode : public SDNode {
SDUse Ops[2];
@@ -997,37 +1006,37 @@ public:
}
};
-/// BinaryWithFlagsSDNode - This class is an extension of BinarySDNode
+/// Returns true if the opcode is a binary operation with flags.
+static bool isBinOpWithFlags(unsigned Opcode) {
+ switch (Opcode) {
+ case ISD::SDIV:
+ case ISD::UDIV:
+ case ISD::SRA:
+ case ISD::SRL:
+ case ISD::MUL:
+ case ISD::ADD:
+ case ISD::SUB:
+ case ISD::SHL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/// This class is an extension of BinarySDNode
/// used from those opcodes that have associated extra flags.
class BinaryWithFlagsSDNode : public BinarySDNode {
- enum { NUW = (1 << 0), NSW = (1 << 1), EXACT = (1 << 2) };
-
public:
+ SDNodeFlags Flags;
BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs,
SDValue X, SDValue Y)
- : BinarySDNode(Opc, Order, dl, VTs, X, Y) {}
- /// getRawSubclassData - Return the SubclassData value, which contains an
- /// encoding of the flags.
- /// This function should be used to add subclass data to the NodeID value.
- unsigned getRawSubclassData() const { return SubclassData; }
- void setHasNoUnsignedWrap(bool b) {
- SubclassData = (SubclassData & ~NUW) | (b ? NUW : 0);
- }
- void setHasNoSignedWrap(bool b) {
- SubclassData = (SubclassData & ~NSW) | (b ? NSW : 0);
- }
- void setIsExact(bool b) {
- SubclassData = (SubclassData & ~EXACT) | (b ? EXACT : 0);
- }
- bool hasNoUnsignedWrap() const { return SubclassData & NUW; }
- bool hasNoSignedWrap() const { return SubclassData & NSW; }
- bool isExact() const { return SubclassData & EXACT; }
+ : BinarySDNode(Opc, Order, dl, VTs, X, Y), Flags() {}
static bool classof(const SDNode *N) {
return isBinOpWithFlags(N->getOpcode());
}
};
-/// TernarySDNode - This class is used for three-operand SDNodes. This is solely
+/// This class is used for three-operand SDNodes. This is solely
/// to allow co-allocation of node operands with the node itself.
class TernarySDNode : public SDNode {
SDUse Ops[3];
@@ -1040,7 +1049,7 @@ public:
};
-/// HandleSDNode - This class is used to form a handle around another node that
+/// This class is used to form a handle around another node that
/// is persistent and is updated across invocations of replaceAllUsesWith on its
/// operand. This node should be directly created by end-users and not added to
/// the AllNodes list.
@@ -1072,14 +1081,14 @@ public:
}
};
-/// Abstact virtual class for operations for memory operations
+/// This is an abstract virtual class for memory operations.
class MemSDNode : public SDNode {
private:
- // MemoryVT - VT of in-memory value.
+ // VT of in-memory value.
EVT MemoryVT;
protected:
- /// MMO - Memory reference information.
+ /// Memory reference information.
MachineMemOperand *MMO;
public:
@@ -1100,7 +1109,7 @@ public:
return MMO->getAlignment();
}
- /// getRawSubclassData - Return the SubclassData value, which contains an
+ /// Return the SubclassData value, which contains an
/// encoding of the volatile flag, as well as bits used by subclasses. This
/// function should only be used to compute a FoldingSetNodeID value.
unsigned getRawSubclassData() const {
@@ -1129,10 +1138,10 @@ public:
/// Returns the Ranges that describes the dereference.
const MDNode *getRanges() const { return MMO->getRanges(); }
- /// getMemoryVT - Return the type of the in-memory value.
+ /// Return the type of the in-memory value.
EVT getMemoryVT() const { return MemoryVT; }
- /// getMemOperand - Return a MachineMemOperand object describing the memory
+ /// Return a MachineMemOperand object describing the memory
/// reference performed by operation.
MachineMemOperand *getMemOperand() const { return MMO; }
@@ -1140,12 +1149,12 @@ public:
return MMO->getPointerInfo();
}
- /// getAddressSpace - Return the address space for the associated pointer
+ /// Return the address space for the associated pointer
unsigned getAddressSpace() const {
return getPointerInfo().getAddrSpace();
}
- /// refineAlignment - Update this MemSDNode's MachineMemOperand information
+ /// Update this MemSDNode's MachineMemOperand information
/// to reflect the alignment of NewMMO, if it has a greater alignment.
/// This must only be used when the new alignment applies to all users of
/// this MachineMemOperand.
@@ -1182,13 +1191,14 @@ public:
N->getOpcode() == ISD::ATOMIC_STORE ||
N->getOpcode() == ISD::MLOAD ||
N->getOpcode() == ISD::MSTORE ||
+ N->getOpcode() == ISD::MGATHER ||
+ N->getOpcode() == ISD::MSCATTER ||
N->isMemIntrinsic() ||
N->isTargetMemoryOpcode();
}
};
-/// AtomicSDNode - A SDNode reprenting atomic operations.
-///
+/// This is an SDNode representing atomic operations.
class AtomicSDNode : public MemSDNode {
SDUse Ops[4];
@@ -1301,7 +1311,7 @@ public:
}
};
-/// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch
+/// This SDNode is used for target intrinsics that touch
/// memory and need an associated MachineMemOperand. Its opcode may be
/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, PREFETCH, or a target-specific opcode
/// with a value not less than FIRST_TARGET_MEMORY_OPCODE.
@@ -1324,7 +1334,7 @@ public:
}
};
-/// ShuffleVectorSDNode - This SDNode is used to implement the code generator
+/// This SDNode is used to implement the code generator
/// support for the llvm IR shufflevector instruction. It combines elements
/// from two input vectors into a new input vector, with the selection and
/// ordering of elements determined by an array of integers, referred to as
@@ -1368,6 +1378,21 @@ public:
}
static bool isSplatMask(const int *Mask, EVT VT);
+ /// Change values in a shuffle permute mask assuming
+ /// the two vector operands have swapped position.
+ static void commuteMask(SmallVectorImpl<int> &Mask) {
+ unsigned NumElems = Mask.size();
+ for (unsigned i = 0; i != NumElems; ++i) {
+ int idx = Mask[i];
+ if (idx < 0)
+ continue;
+ else if (idx < (int)NumElems)
+ Mask[i] = idx + NumElems;
+ else
+ Mask[i] = idx - NumElems;
+ }
+ }
+
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::VECTOR_SHUFFLE;
}
@@ -1376,9 +1401,10 @@ public:
class ConstantSDNode : public SDNode {
const ConstantInt *Value;
friend class SelectionDAG;
- ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, EVT VT)
+ ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val,
+ DebugLoc DL, EVT VT)
: SDNode(isTarget ? ISD::TargetConstant : ISD::Constant,
- 0, DebugLoc(), getSDVTList(VT)), Value(val) {
+ 0, DL, getSDVTList(VT)), Value(val) {
SubclassData |= (uint16_t)isOpaque;
}
public:
@@ -1403,28 +1429,28 @@ public:
class ConstantFPSDNode : public SDNode {
const ConstantFP *Value;
friend class SelectionDAG;
- ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT)
+ ConstantFPSDNode(bool isTarget, const ConstantFP *val, DebugLoc DL, EVT VT)
: SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP,
- 0, DebugLoc(), getSDVTList(VT)), Value(val) {
+ 0, DL, getSDVTList(VT)), Value(val) {
}
public:
const APFloat& getValueAPF() const { return Value->getValueAPF(); }
const ConstantFP *getConstantFPValue() const { return Value; }
- /// isZero - Return true if the value is positive or negative zero.
+ /// Return true if the value is positive or negative zero.
bool isZero() const { return Value->isZero(); }
- /// isNaN - Return true if the value is a NaN.
+ /// Return true if the value is a NaN.
bool isNaN() const { return Value->isNaN(); }
- /// isInfinity - Return true if the value is an infinity
+ /// Return true if the value is an infinity
bool isInfinity() const { return Value->isInfinity(); }
- /// isNegative - Return true if the value is negative.
+ /// 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
+ /// 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
/// two floating point values.
@@ -1608,13 +1634,12 @@ public:
}
};
-/// BuildVectorSDNode - A "pseudo-class" with methods for operating on
-/// BUILD_VECTORs.
+/// A "pseudo-class" with methods for operating on BUILD_VECTORs.
class BuildVectorSDNode : public SDNode {
// These are constructed as SDNodes and then cast to BuildVectorSDNodes.
- explicit BuildVectorSDNode() LLVM_DELETED_FUNCTION;
+ explicit BuildVectorSDNode() = delete;
public:
- /// isConstantSplat - Check if this is a constant splat, and if so, find the
+ /// Check if this is a constant splat, and if so, find the
/// smallest element size that splats the vector. If MinSplatBits is
/// nonzero, the element size must be at least that large. Note that the
/// splat element may be the entire vector (i.e., a one element vector).
@@ -1657,7 +1682,7 @@ public:
}
};
-/// SrcValueSDNode - An SDNode that holds an arbitrary LLVM IR Value. This is
+/// An SDNode that holds an arbitrary LLVM IR Value. This is
/// used when the SelectionDAG needs to make a simple reference to something
/// in the LLVM IR representation.
///
@@ -1669,7 +1694,7 @@ class SrcValueSDNode : public SDNode {
: SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {}
public:
- /// getValue - return the contained Value.
+ /// Return the contained Value.
const Value *getValue() const { return V; }
static bool classof(const SDNode *N) {
@@ -1796,7 +1821,7 @@ public:
}
};
-/// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the
+/// NOTE: avoid using this node as this may disappear in the
/// future and most targets don't support it.
class CvtRndSatSDNode : public SDNode {
ISD::CvtCode CvtCode;
@@ -1815,7 +1840,7 @@ public:
}
};
-/// VTSDNode - This class is used to represent EVT's, which are used
+/// This class is used to represent EVT's, which are used
/// to parameterize some operations.
class VTSDNode : public SDNode {
EVT ValueType;
@@ -1833,8 +1858,7 @@ public:
}
};
-/// LSBaseSDNode - Base class for LoadSDNode and StoreSDNode
-///
+/// Base class for LoadSDNode and StoreSDNode
class LSBaseSDNode : public MemSDNode {
//! Operand array for load and store
/*!
@@ -1860,16 +1884,16 @@ public:
return getOperand(getOpcode() == ISD::LOAD ? 2 : 3);
}
- /// getAddressingMode - Return the addressing mode for this load or store:
+ /// Return the addressing mode for this load or store:
/// unindexed, pre-inc, pre-dec, post-inc, or post-dec.
ISD::MemIndexedMode getAddressingMode() const {
return ISD::MemIndexedMode((SubclassData >> 2) & 7);
}
- /// isIndexed - Return true if this is a pre/post inc/dec load/store.
+ /// Return true if this is a pre/post inc/dec load/store.
bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; }
- /// isUnindexed - Return true if this is NOT a pre/post inc/dec load/store.
+ /// Return true if this is NOT a pre/post inc/dec load/store.
bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; }
static bool classof(const SDNode *N) {
@@ -1878,8 +1902,7 @@ public:
}
};
-/// LoadSDNode - This class is used to represent ISD::LOAD nodes.
-///
+/// This class is used to represent ISD::LOAD nodes.
class LoadSDNode : public LSBaseSDNode {
friend class SelectionDAG;
LoadSDNode(SDValue *ChainPtrOff, unsigned Order, DebugLoc dl, SDVTList VTs,
@@ -1893,7 +1916,7 @@ class LoadSDNode : public LSBaseSDNode {
}
public:
- /// getExtensionType - Return whether this is a plain node,
+ /// Return whether this is a plain node,
/// or one of the varieties of value-extending loads.
ISD::LoadExtType getExtensionType() const {
return ISD::LoadExtType(SubclassData & 3);
@@ -1907,8 +1930,7 @@ public:
}
};
-/// StoreSDNode - This class is used to represent ISD::STORE nodes.
-///
+/// This class is used to represent ISD::STORE nodes.
class StoreSDNode : public LSBaseSDNode {
friend class SelectionDAG;
StoreSDNode(SDValue *ChainValuePtrOff, unsigned Order, DebugLoc dl,
@@ -1923,7 +1945,7 @@ class StoreSDNode : public LSBaseSDNode {
}
public:
- /// isTruncatingStore - Return true if the op does a truncation before store.
+ /// Return true if the op does a truncation before store.
/// For integers this is the same as doing a TRUNCATE and storing the result.
/// For floats, it is the same as doing an FP_ROUND and storing the result.
bool isTruncatingStore() const { return SubclassData & 1; }
@@ -1937,9 +1959,7 @@ public:
}
};
-/// MaskedLoadStoreSDNode - This is a base class is used to represent MLOAD and
-/// MSTORE nodes
-///
+/// This base class is used to represent MLOAD and MSTORE nodes
class MaskedLoadStoreSDNode : public MemSDNode {
// Operands
SDUse Ops[4];
@@ -1965,8 +1985,7 @@ public:
}
};
-/// MaskedLoadSDNode - This class is used to represent an MLOAD node
-///
+/// This class is used to represent an MLOAD node
class MaskedLoadSDNode : public MaskedLoadStoreSDNode {
public:
friend class SelectionDAG;
@@ -1987,8 +2006,7 @@ public:
}
};
-/// MaskedStoreSDNode - This class is used to represent an MSTORE node
-///
+/// This class is used to represent an MSTORE node
class MaskedStoreSDNode : public MaskedLoadStoreSDNode {
public:
@@ -2000,7 +2018,7 @@ public:
VTs, MemVT, MMO) {
SubclassData |= (unsigned short)isTrunc;
}
- /// isTruncatingStore - Return true if the op does a truncation before store.
+ /// Return true if the op does a truncation before store.
/// For integers this is the same as doing a TRUNCATE and storing the result.
/// For floats, it is the same as doing an FP_ROUND and storing the result.
bool isTruncatingStore() const { return SubclassData & 1; }
@@ -2012,10 +2030,85 @@ public:
}
};
-/// MachineSDNode - An SDNode that represents everything that will be needed
+/// This is a base class used to represent
+/// MGATHER and MSCATTER nodes
+///
+class MaskedGatherScatterSDNode : public MemSDNode {
+ // Operands
+ SDUse Ops[5];
+public:
+ friend class SelectionDAG;
+ MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl,
+ ArrayRef<SDValue> Operands, SDVTList VTs, EVT MemVT,
+ MachineMemOperand *MMO)
+ : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
+ assert(Operands.size() == 5 && "Incompatible number of operands");
+ InitOperands(Ops, Operands.data(), Operands.size());
+ }
+
+ // In the both nodes address is Op1, mask is Op2:
+ // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value
+ // MaskedScatterSDNode (Chain, value, mask, base, index)
+ // Mask is a vector of i1 elements
+ const SDValue &getBasePtr() const { return getOperand(3); }
+ const SDValue &getIndex() const { return getOperand(4); }
+ const SDValue &getMask() const { return getOperand(2); }
+ const SDValue &getValue() const { return getOperand(1); }
+
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::MGATHER ||
+ N->getOpcode() == ISD::MSCATTER;
+ }
+};
+
+/// This class is used to represent an MGATHER node
+///
+class MaskedGatherSDNode : public MaskedGatherScatterSDNode {
+public:
+ friend class SelectionDAG;
+ MaskedGatherSDNode(unsigned Order, DebugLoc dl, ArrayRef<SDValue> Operands,
+ SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
+ : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, Operands, VTs, MemVT,
+ MMO) {
+ assert(getValue().getValueType() == getValueType(0) &&
+ "Incompatible type of the PathThru value in MaskedGatherSDNode");
+ assert(getMask().getValueType().getVectorNumElements() ==
+ getValueType(0).getVectorNumElements() &&
+ "Vector width mismatch between mask and data");
+ assert(getMask().getValueType().getScalarType() == MVT::i1 &&
+ "Vector width mismatch between mask and data");
+ }
+
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::MGATHER;
+ }
+};
+
+/// This class is used to represent an MSCATTER node
+///
+class MaskedScatterSDNode : public MaskedGatherScatterSDNode {
+
+public:
+ friend class SelectionDAG;
+ MaskedScatterSDNode(unsigned Order, DebugLoc dl,ArrayRef<SDValue> Operands,
+ SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
+ : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, Operands, VTs, MemVT,
+ MMO) {
+ assert(getMask().getValueType().getVectorNumElements() ==
+ getValue().getValueType().getVectorNumElements() &&
+ "Vector width mismatch between mask and data");
+ assert(getMask().getValueType().getScalarType() == MVT::i1 &&
+ "Vector width mismatch between mask and data");
+ }
+
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::MSCATTER;
+ }
+};
+
+/// An SDNode that represents everything that will be needed
/// to construct a MachineInstr. These nodes are created during the
/// instruction selection proper phase.
-///
class MachineSDNode : public SDNode {
public:
typedef MachineMemOperand **mmo_iterator;
@@ -2025,11 +2118,11 @@ private:
MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc DL, SDVTList VTs)
: SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {}
- /// LocalOperands - Operands for this instruction, if they fit here. If
+ /// Operands for this instruction, if they fit here. If
/// they don't, this field is unused.
SDUse LocalOperands[4];
- /// MemRefs - Memory reference descriptions for this instruction.
+ /// Memory reference descriptions for this instruction.
mmo_iterator MemRefs;
mmo_iterator MemRefsEnd;
@@ -2038,7 +2131,7 @@ public:
mmo_iterator memoperands_end() const { return MemRefsEnd; }
bool memoperands_empty() const { return MemRefsEnd == MemRefs; }
- /// setMemRefs - Assign this MachineSDNodes's memory reference descriptor
+ /// Assign this MachineSDNodes's memory reference descriptor
/// list. This does not transfer ownership.
void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) {
for (mmo_iterator MMI = NewMemRefs, MME = NewMemRefsEnd; MMI != MME; ++MMI)
@@ -2064,12 +2157,6 @@ public:
}
bool operator!=(const SDNodeIterator& x) const { return !operator==(x); }
- const SDNodeIterator &operator=(const SDNodeIterator &I) {
- assert(I.Node == Node && "Cannot assign iterators to two different nodes!");
- Operand = I.Operand;
- return *this;
- }
-
pointer operator*() const {
return Node->getOperand(Operand).getNode();
}
@@ -2109,60 +2196,51 @@ template <> struct GraphTraits<SDNode*> {
}
};
-/// LargestSDNode - The largest SDNode class.
-///
-typedef AtomicSDNode LargestSDNode;
+/// The largest SDNode class.
+typedef MaskedGatherScatterSDNode LargestSDNode;
-/// MostAlignedSDNode - The SDNode class with the greatest alignment
-/// requirement.
-///
+/// The SDNode class with the greatest alignment requirement.
typedef GlobalAddressSDNode MostAlignedSDNode;
namespace ISD {
- /// isNormalLoad - Returns true if the specified node is a non-extending
- /// and unindexed load.
+ /// Returns true if the specified node is a non-extending and unindexed load.
inline bool isNormalLoad(const SDNode *N) {
const LoadSDNode *Ld = dyn_cast<LoadSDNode>(N);
return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD &&
Ld->getAddressingMode() == ISD::UNINDEXED;
}
- /// isNON_EXTLoad - Returns true if the specified node is a non-extending
- /// load.
+ /// Returns true if the specified node is a non-extending load.
inline bool isNON_EXTLoad(const SDNode *N) {
return isa<LoadSDNode>(N) &&
cast<LoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD;
}
- /// isEXTLoad - Returns true if the specified node is a EXTLOAD.
- ///
+ /// Returns true if the specified node is a EXTLOAD.
inline bool isEXTLoad(const SDNode *N) {
return isa<LoadSDNode>(N) &&
cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD;
}
- /// isSEXTLoad - Returns true if the specified node is a SEXTLOAD.
- ///
+ /// Returns true if the specified node is a SEXTLOAD.
inline bool isSEXTLoad(const SDNode *N) {
return isa<LoadSDNode>(N) &&
cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD;
}
- /// isZEXTLoad - Returns true if the specified node is a ZEXTLOAD.
- ///
+ /// Returns true if the specified node is a ZEXTLOAD.
inline bool isZEXTLoad(const SDNode *N) {
return isa<LoadSDNode>(N) &&
cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD;
}
- /// isUNINDEXEDLoad - Returns true if the specified node is an unindexed load.
- ///
+ /// Returns true if the specified node is an unindexed load.
inline bool isUNINDEXEDLoad(const SDNode *N) {
return isa<LoadSDNode>(N) &&
cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;
}
- /// isNormalStore - Returns true if the specified node is a non-truncating
+ /// Returns true if the specified node is a non-truncating
/// and unindexed store.
inline bool isNormalStore(const SDNode *N) {
const StoreSDNode *St = dyn_cast<StoreSDNode>(N);
@@ -2170,20 +2248,17 @@ namespace ISD {
St->getAddressingMode() == ISD::UNINDEXED;
}
- /// isNON_TRUNCStore - Returns true if the specified node is a non-truncating
- /// store.
+ /// Returns true if the specified node is a non-truncating store.
inline bool isNON_TRUNCStore(const SDNode *N) {
return isa<StoreSDNode>(N) && !cast<StoreSDNode>(N)->isTruncatingStore();
}
- /// isTRUNCStore - Returns true if the specified node is a truncating
- /// store.
+ /// Returns true if the specified node is a truncating store.
inline bool isTRUNCStore(const SDNode *N) {
return isa<StoreSDNode>(N) && cast<StoreSDNode>(N)->isTruncatingStore();
}
- /// isUNINDEXEDStore - Returns true if the specified node is an
- /// unindexed store.
+ /// Returns true if the specified node is an unindexed store.
inline bool isUNINDEXEDStore(const SDNode *N) {
return isa<StoreSDNode>(N) &&
cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;
diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h
index 00bb22b91d32..9d6d6f5b1be0 100644
--- a/include/llvm/CodeGen/SlotIndexes.h
+++ b/include/llvm/CodeGen/SlotIndexes.h
@@ -162,7 +162,7 @@ namespace llvm {
}
/// Return true for a valid index.
- LLVM_EXPLICIT operator bool() const { return isValid(); }
+ explicit operator bool() const { return isValid(); }
/// Print this index to the given raw_ostream.
void print(raw_ostream &os) const;
diff --git a/include/llvm/CodeGen/StackMapLivenessAnalysis.h b/include/llvm/CodeGen/StackMapLivenessAnalysis.h
deleted file mode 100644
index f67a6e95191d..000000000000
--- a/include/llvm/CodeGen/StackMapLivenessAnalysis.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//===--- StackMapLivenessAnalysis - StackMap Liveness Analysis --*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass calculates the liveness for each basic block in a function and
-// attaches the register live-out information to a patchpoint intrinsic (if
-// present).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H
-#define LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H
-
-#include "llvm/CodeGen/LivePhysRegs.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-
-
-namespace llvm {
-
-/// \brief This pass calculates the liveness information for each basic block in
-/// a function and attaches the register live-out information to a patchpoint
-/// intrinsic if present.
-///
-/// This pass can be disabled via the -enable-patchpoint-liveness=false flag.
-/// The pass skips functions that don't have any patchpoint intrinsics. The
-/// information provided by this pass is optional and not required by the
-/// aformentioned intrinsic to function.
-class StackMapLiveness : public MachineFunctionPass {
- MachineFunction *MF;
- const TargetRegisterInfo *TRI;
- LivePhysRegs LiveRegs;
-public:
- static char ID;
-
- /// \brief Default construct and initialize the pass.
- StackMapLiveness();
-
- /// \brief Tell the pass manager which passes we depend on and what
- /// information we preserve.
- void getAnalysisUsage(AnalysisUsage &AU) const override;
-
- /// \brief Calculate the liveness information for the given machine function.
- bool runOnMachineFunction(MachineFunction &MF) override;
-
-private:
- /// \brief Performs the actual liveness calculation for the function.
- bool calculateLiveness();
-
- /// \brief Add the current register live set to the instruction.
- void addLiveOutSetToMI(MachineInstr &MI);
-
- /// \brief Create a register mask and initialize it with the registers from
- /// the register live set.
- uint32_t *createRegisterMask() const;
-};
-
-} // llvm namespace
-
-#endif
diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h
index 4e48afe14004..46a773f74aac 100644
--- a/include/llvm/CodeGen/StackMaps.h
+++ b/include/llvm/CodeGen/StackMaps.h
@@ -14,6 +14,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Support/Debug.h"
#include <map>
#include <vector>
@@ -84,15 +85,23 @@ public:
/// MI-level Statepoint operands
///
/// Statepoint operands take the form:
-/// <num call arguments>, <call target>, [call arguments],
-/// <StackMaps::ConstantOp>, <flags>,
+/// <id>, <num patch bytes >, <num call arguments>, <call target>,
+/// [call arguments], <StackMaps::ConstantOp>, <calling convention>,
+/// <StackMaps::ConstantOp>, <statepoint flags>,
/// <StackMaps::ConstantOp>, <num other args>, [other args],
/// [gc values]
class StatepointOpers {
private:
+ // These values are aboolute offsets into the operands of the statepoint
+ // instruction.
+ enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd };
+
+ // These values are relative offests from the start of the statepoint meta
+ // arguments (i.e. the end of the call arguments).
enum {
- NCallArgsPos = 0,
- CallTargetPos = 1
+ CCOffset = 1,
+ FlagsOffset = 3,
+ NumVMSArgsOffset = 5
};
public:
@@ -100,22 +109,17 @@ public:
MI(MI) { }
/// Get starting index of non call related arguments
- /// (statepoint flags, vm state and gc state).
+ /// (calling convention, statepoint flags, vm state and gc state).
unsigned getVarIdx() const {
- return MI->getOperand(NCallArgsPos).getImm() + 2;
+ return MI->getOperand(NCallArgsPos).getImm() + MetaEnd;
}
- /// Returns the index of the operand containing the number of non-gc non-call
- /// arguments.
- unsigned getNumVMSArgsIdx() const {
- return getVarIdx() + 3;
- }
+ /// Return the ID for the given statepoint.
+ uint64_t getID() const { return MI->getOperand(IDPos).getImm(); }
- /// 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();
+ /// Return the number of patchable bytes the given statepoint should emit.
+ uint32_t getNumPatchBytes() const {
+ return MI->getOperand(NBytesPos).getImm();
}
/// Returns the target of the underlying call.
@@ -245,7 +249,10 @@ private:
void emitConstantPoolEntries(MCStreamer &OS);
/// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call.
- void emitCallsiteEntries(MCStreamer &OS, const TargetRegisterInfo *TRI);
+ void emitCallsiteEntries(MCStreamer &OS);
+
+ void print(raw_ostream &OS);
+ void debug() { print(dbgs()); }
};
}
diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 9209e1c67c1b..9a1b63f91bd4 100644
--- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -34,25 +34,34 @@ namespace llvm {
class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
bool UseInitArray;
+ mutable unsigned NextUniqueID = 0;
public:
- virtual ~TargetLoweringObjectFileELF() {}
+ TargetLoweringObjectFileELF() : UseInitArray(false) {}
+
+ ~TargetLoweringObjectFileELF() override {}
void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM,
const MCSymbol *Sym) const override;
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
- const MCSection *getSectionForConstant(SectionKind Kind,
- const Constant *C) const override;
+ MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const override;
+
+ MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler &Mang,
+ const TargetMachine &TM) const override;
+
+ MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler &Mang,
+ const TargetMachine &TM) const override;
- const MCSection *getExplicitSectionGlobal(const GlobalValue *GV,
- SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM) const override;
+ MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang,
+ const TargetMachine &TM) const override;
- const MCSection *SelectSectionForGlobal(const GlobalValue *GV,
- SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM) const override;
+ bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
+ const Function &F) const override;
/// Return an MCExpr to use for a reference to the specified type info global
/// variable from exception handling information.
@@ -68,17 +77,18 @@ public:
MachineModuleInfo *MMI) const override;
void InitializeELF(bool UseInitArray_);
- const MCSection *getStaticCtorSection(unsigned Priority,
- const MCSymbol *KeySym) const override;
- const MCSection *getStaticDtorSection(unsigned Priority,
- const MCSymbol *KeySym) const override;
+ MCSection *getStaticCtorSection(unsigned Priority,
+ const MCSymbol *KeySym) const override;
+ MCSection *getStaticDtorSection(unsigned Priority,
+ const MCSymbol *KeySym) const override;
};
class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {
public:
- virtual ~TargetLoweringObjectFileMachO() {}
+ ~TargetLoweringObjectFileMachO() override {}
+ TargetLoweringObjectFileMachO();
/// Extract the dependent library name from a linker option string. Returns
/// StringRef() if the option does not specify a library.
@@ -89,18 +99,16 @@ public:
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
Mangler &Mang, const TargetMachine &TM) const override;
- const MCSection *
- SelectSectionForGlobal(const GlobalValue *GV,
- SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM) const override;
+ MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler &Mang,
+ const TargetMachine &TM) const override;
- const MCSection *
- getExplicitSectionGlobal(const GlobalValue *GV,
- SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM) const override;
+ MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler &Mang,
+ const TargetMachine &TM) const override;
- const MCSection *getSectionForConstant(SectionKind Kind,
- const Constant *C) const override;
+ MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const override;
/// The mach-o version of this method defaults to returning a stub reference.
const MCExpr *
@@ -113,23 +121,34 @@ public:
MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang,
const TargetMachine &TM,
MachineModuleInfo *MMI) const override;
+
+ /// Get MachO PC relative GOT entry relocation
+ const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
+ const MCValue &MV, int64_t Offset,
+ MachineModuleInfo *MMI,
+ MCStreamer &Streamer) const override;
};
class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
public:
- virtual ~TargetLoweringObjectFileCOFF() {}
+ ~TargetLoweringObjectFileCOFF() override {}
+
+ MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler &Mang,
+ const TargetMachine &TM) const override;
+
+ MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler &Mang,
+ const TargetMachine &TM) const override;
- const MCSection *
- getExplicitSectionGlobal(const GlobalValue *GV,
- SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM) const override;
+ void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV,
+ bool CannotUsePrivateLabel, Mangler &Mang,
+ const TargetMachine &TM) const override;
- const MCSection *
- SelectSectionForGlobal(const GlobalValue *GV,
- SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM) const override;
+ MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang,
+ const TargetMachine &TM) const override;
/// Extract the dependent library name from a linker option string. Returns
/// StringRef() if the option does not specify a library.
@@ -141,10 +160,10 @@ public:
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
Mangler &Mang, const TargetMachine &TM) const override;
- const MCSection *getStaticCtorSection(unsigned Priority,
- const MCSymbol *KeySym) const override;
- const MCSection *getStaticDtorSection(unsigned Priority,
- const MCSymbol *KeySym) const override;
+ MCSection *getStaticCtorSection(unsigned Priority,
+ const MCSymbol *KeySym) const override;
+ MCSection *getStaticDtorSection(unsigned Priority,
+ const MCSymbol *KeySym) const override;
};
} // end namespace llvm
diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h
index b6136665b968..751fac411ce6 100644
--- a/include/llvm/CodeGen/TargetSchedule.h
+++ b/include/llvm/CodeGen/TargetSchedule.h
@@ -40,6 +40,9 @@ class TargetSchedModel {
SmallVector<unsigned, 16> ResourceFactors;
unsigned MicroOpFactor; // Multiply to normalize microops to resource units.
unsigned ResourceLCM; // Resource units per cycle. Latency normalization factor.
+
+ unsigned computeInstrLatency(const MCSchedClassDesc &SCDesc) const;
+
public:
TargetSchedModel(): SchedModel(MCSchedModel::GetDefaultSchedModel()), STI(nullptr), TII(nullptr) {}
diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h
index 4e93940e223e..e1a9fd38290b 100644
--- a/include/llvm/CodeGen/ValueTypes.h
+++ b/include/llvm/CodeGen/ValueTypes.h
@@ -34,10 +34,9 @@ namespace llvm {
Type *LLVMTy;
public:
- EVT() : V((MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE)),
- LLVMTy(nullptr) {}
- EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(nullptr) { }
- EVT(MVT S) : V(S), LLVMTy(nullptr) {}
+ LLVM_CONSTEXPR EVT() : V(MVT::INVALID_SIMPLE_VALUE_TYPE), LLVMTy(nullptr) {}
+ LLVM_CONSTEXPR EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(nullptr) {}
+ LLVM_CONSTEXPR EVT(MVT S) : V(S), LLVMTy(nullptr) {}
bool operator==(EVT VT) const {
return !(*this != VT);
diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td
index b5fa0e8c6a23..2b30f14f902c 100644
--- a/include/llvm/CodeGen/ValueTypes.td
+++ b/include/llvm/CodeGen/ValueTypes.td
@@ -62,25 +62,26 @@ def v2i64 : ValueType<128, 38>; // 2 x i64 vector value
def v4i64 : ValueType<256, 39>; // 4 x i64 vector value
def v8i64 : ValueType<512, 40>; // 8 x i64 vector value
def v16i64 : ValueType<1024,41>; // 16 x i64 vector value
+def v1i128 : ValueType<128, 42>; // 1 x i128 vector value
-def v2f16 : ValueType<32 , 42>; // 2 x f16 vector value
-def v4f16 : ValueType<64 , 43>; // 4 x f16 vector value
-def v8f16 : ValueType<128, 44>; // 8 x f16 vector value
-def v1f32 : ValueType<32 , 45>; // 1 x f32 vector value
-def v2f32 : ValueType<64 , 46>; // 2 x f32 vector value
-def v4f32 : ValueType<128, 47>; // 4 x f32 vector value
-def v8f32 : ValueType<256, 48>; // 8 x f32 vector value
-def v16f32 : ValueType<512, 49>; // 16 x f32 vector value
-def v1f64 : ValueType<64, 50>; // 1 x f64 vector value
-def v2f64 : ValueType<128, 51>; // 2 x f64 vector value
-def v4f64 : ValueType<256, 52>; // 4 x f64 vector value
-def v8f64 : ValueType<512, 53>; // 8 x f64 vector value
+def v2f16 : ValueType<32 , 43>; // 2 x f16 vector value
+def v4f16 : ValueType<64 , 44>; // 4 x f16 vector value
+def v8f16 : ValueType<128, 45>; // 8 x f16 vector value
+def v1f32 : ValueType<32 , 46>; // 1 x f32 vector value
+def v2f32 : ValueType<64 , 47>; // 2 x f32 vector value
+def v4f32 : ValueType<128, 48>; // 4 x f32 vector value
+def v8f32 : ValueType<256, 49>; // 8 x f32 vector value
+def v16f32 : ValueType<512, 50>; // 16 x f32 vector value
+def v1f64 : ValueType<64, 51>; // 1 x f64 vector value
+def v2f64 : ValueType<128, 52>; // 2 x f64 vector value
+def v4f64 : ValueType<256, 53>; // 4 x f64 vector value
+def v8f64 : ValueType<512, 54>; // 8 x f64 vector value
-def x86mmx : ValueType<64 , 54>; // X86 MMX value
-def FlagVT : ValueType<0 , 55>; // Pre-RA sched glue
-def isVoid : ValueType<0 , 56>; // Produces no value
-def untyped: ValueType<8 , 57>; // Produces an untyped value
+def x86mmx : ValueType<64 , 55>; // X86 MMX value
+def FlagVT : ValueType<0 , 56>; // Pre-RA sched glue
+def isVoid : ValueType<0 , 57>; // Produces no value
+def untyped: ValueType<8 , 58>; // Produces an untyped value
def MetadataVT: ValueType<0, 250>; // Metadata
// Pseudo valuetype mapped to the current pointer size to any address space.
@@ -98,3 +99,6 @@ def iAny : ValueType<0 , 254>;
// Pseudo valuetype mapped to the current pointer size.
def iPTR : ValueType<0 , 255>;
+
+// Pseudo valuetype to represent "any type of any size".
+def Any : ValueType<0 , 256>;
diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h
index eceb8755763e..d7e92094877d 100644
--- a/include/llvm/CodeGen/VirtRegMap.h
+++ b/include/llvm/CodeGen/VirtRegMap.h
@@ -63,8 +63,8 @@ namespace llvm {
/// createSpillSlot - Allocate a spill slot for RC from MFI.
unsigned createSpillSlot(const TargetRegisterClass *RC);
- VirtRegMap(const VirtRegMap&) LLVM_DELETED_FUNCTION;
- void operator=(const VirtRegMap&) LLVM_DELETED_FUNCTION;
+ VirtRegMap(const VirtRegMap&) = delete;
+ void operator=(const VirtRegMap&) = delete;
public:
static char ID;
diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h
new file mode 100644
index 000000000000..e2644edd4d12
--- /dev/null
+++ b/include/llvm/CodeGen/WinEHFuncInfo.h
@@ -0,0 +1,157 @@
+//===-- llvm/CodeGen/WinEHFuncInfo.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Data structures and associated state for Windows exception handling schemes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_WINEHFUNCINFO_H
+#define LLVM_CODEGEN_WINEHFUNCINFO_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+class BasicBlock;
+class Constant;
+class Function;
+class GlobalVariable;
+class IntrinsicInst;
+class LandingPadInst;
+class MCSymbol;
+class Value;
+
+enum ActionType { Catch, Cleanup };
+
+class ActionHandler {
+public:
+ ActionHandler(BasicBlock *BB, ActionType Type)
+ : StartBB(BB), Type(Type), EHState(-1), HandlerBlockOrFunc(nullptr) {}
+
+ ActionType getType() const { return Type; }
+ BasicBlock *getStartBlock() const { return StartBB; }
+
+ bool hasBeenProcessed() { return HandlerBlockOrFunc != nullptr; }
+
+ void setHandlerBlockOrFunc(Constant *F) { HandlerBlockOrFunc = F; }
+ Constant *getHandlerBlockOrFunc() { return HandlerBlockOrFunc; }
+
+ void setEHState(int State) { EHState = State; }
+ int getEHState() const { return EHState; }
+
+private:
+ BasicBlock *StartBB;
+ ActionType Type;
+ int EHState;
+
+ // Can be either a BlockAddress or a Function depending on the EH personality.
+ Constant *HandlerBlockOrFunc;
+};
+
+class CatchHandler : public ActionHandler {
+public:
+ CatchHandler(BasicBlock *BB, Constant *Selector, BasicBlock *NextBB)
+ : ActionHandler(BB, ActionType::Catch), Selector(Selector),
+ NextBB(NextBB), ExceptionObjectVar(nullptr),
+ ExceptionObjectIndex(-1) {}
+
+ // Method for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const ActionHandler *H) {
+ return H->getType() == ActionType::Catch;
+ }
+
+ Constant *getSelector() const { return Selector; }
+ BasicBlock *getNextBB() const { return NextBB; }
+
+ const Value *getExceptionVar() { return ExceptionObjectVar; }
+ TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; }
+
+ void setExceptionVar(const Value *Val) { ExceptionObjectVar = Val; }
+ void setExceptionVarIndex(int Index) { ExceptionObjectIndex = Index; }
+ int getExceptionVarIndex() const { return ExceptionObjectIndex; }
+ void setReturnTargets(TinyPtrVector<BasicBlock *> &Targets) {
+ ReturnTargets = Targets;
+ }
+
+private:
+ Constant *Selector;
+ BasicBlock *NextBB;
+ // While catch handlers are being outlined the ExceptionObjectVar field will
+ // be populated with the instruction in the parent frame that corresponds
+ // to the exception object (or nullptr if the catch does not use an
+ // exception object) and the ExceptionObjectIndex field will be -1.
+ // When the parseEHActions function is called to populate a vector of
+ // instances of this class, the ExceptionObjectVar field will be nullptr
+ // and the ExceptionObjectIndex will be the index of the exception object in
+ // the parent function's frameescape block.
+ const Value *ExceptionObjectVar;
+ int ExceptionObjectIndex;
+ TinyPtrVector<BasicBlock *> ReturnTargets;
+};
+
+class CleanupHandler : public ActionHandler {
+public:
+ CleanupHandler(BasicBlock *BB) : ActionHandler(BB, ActionType::Cleanup) {}
+
+ // Method for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const ActionHandler *H) {
+ return H->getType() == ActionType::Cleanup;
+ }
+};
+
+void parseEHActions(const IntrinsicInst *II,
+ SmallVectorImpl<std::unique_ptr<ActionHandler>> &Actions);
+
+// The following structs respresent the .xdata for functions using C++
+// exceptions on Windows.
+
+struct WinEHUnwindMapEntry {
+ int ToState;
+ Function *Cleanup;
+};
+
+struct WinEHHandlerType {
+ int Adjectives;
+ GlobalVariable *TypeDescriptor;
+ int CatchObjRecoverIdx;
+ Function *Handler;
+};
+
+struct WinEHTryBlockMapEntry {
+ int TryLow;
+ int TryHigh;
+ SmallVector<WinEHHandlerType, 1> HandlerArray;
+};
+
+struct WinEHFuncInfo {
+ DenseMap<const Function *, const LandingPadInst *> RootLPad;
+ DenseMap<const Function *, const InvokeInst *> LastInvoke;
+ DenseMap<const Function *, int> HandlerEnclosedState;
+ DenseMap<const Function *, bool> LastInvokeVisited;
+ DenseMap<const LandingPadInst *, int> LandingPadStateMap;
+ DenseMap<const Function *, int> CatchHandlerParentFrameObjIdx;
+ DenseMap<const Function *, int> CatchHandlerParentFrameObjOffset;
+ DenseMap<const Function *, int> CatchHandlerMaxState;
+ DenseMap<const Function *, int> HandlerBaseState;
+ SmallVector<WinEHUnwindMapEntry, 4> UnwindMap;
+ SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap;
+ SmallVector<std::pair<MCSymbol *, int>, 4> IPToStateList;
+ int UnwindHelpFrameIdx;
+ int UnwindHelpFrameOffset;
+
+ unsigned NumIPToStateFuncsVisited;
+
+ WinEHFuncInfo()
+ : UnwindHelpFrameIdx(INT_MAX), UnwindHelpFrameOffset(-1),
+ NumIPToStateFuncsVisited(0) {}
+};
+
+}
+#endif // LLVM_CODEGEN_WINEHFUNCINFO_H
diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake
index 5c512f6bca6c..bd50d6ee1d6b 100644
--- a/include/llvm/Config/config.h.cmake
+++ b/include/llvm/Config/config.h.cmake
@@ -33,9 +33,6 @@
/* Define to 1 if you have the `bcopy' function. */
#undef HAVE_BCOPY
-/* Define to 1 if you have the `ceilf' function. */
-#cmakedefine HAVE_CEILF ${HAVE_CEILF}
-
/* Define to 1 if you have the `closedir' function. */
#cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR}
@@ -52,6 +49,9 @@
don't. */
#cmakedefine01 HAVE_DECL_STRERROR_S
+/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */
+#cmakedefine HAVE_DIA_SDK ${HAVE_DIA_SDK}
+
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#cmakedefine HAVE_DIRENT_H ${HAVE_DIRENT_H}
@@ -92,33 +92,6 @@
/* Define to 1 if you have the <ffi.h> header file. */
#cmakedefine HAVE_FFI_H ${HAVE_FFI_H}
-/* Set to 1 if the finite function is found in <ieeefp.h> */
-#cmakedefine HAVE_FINITE_IN_IEEEFP_H ${HAVE_FINITE_IN_IEEEFP_H}
-
-/* Define to 1 if you have the `floorf' function. */
-#cmakedefine HAVE_FLOORF ${HAVE_FLOORF}
-
-/* Define to 1 if you have the `log' function. */
-#cmakedefine HAVE_LOG ${HAVE_LOG}
-
-/* Define to 1 if you have the `log2' function. */
-#cmakedefine HAVE_LOG2 ${HAVE_LOG2}
-
-/* Define to 1 if you have the `log10' function. */
-#cmakedefine HAVE_LOG10 ${HAVE_LOG10}
-
-/* Define to 1 if you have the `exp' function. */
-#cmakedefine HAVE_EXP ${HAVE_EXP}
-
-/* Define to 1 if you have the `exp2' function. */
-#cmakedefine HAVE_EXP2 ${HAVE_EXP2}
-
-/* Define to 1 if you have the `exp10' function. */
-#cmakedefine HAVE_EXP10 ${HAVE_EXP10}
-
-/* Define to 1 if you have the `fmodf' function. */
-#cmakedefine HAVE_FMODF ${HAVE_FMODF}
-
/* Define to 1 if you have the `futimes' function. */
#cmakedefine HAVE_FUTIMES ${HAVE_FUTIMES}
@@ -149,18 +122,6 @@
/* Define to 1 if you have the `isatty' function. */
#cmakedefine HAVE_ISATTY 1
-/* Set to 1 if the isinf function is found in <cmath> */
-#cmakedefine HAVE_ISINF_IN_CMATH ${HAVE_ISINF_IN_CMATH}
-
-/* Set to 1 if the isinf function is found in <math.h> */
-#cmakedefine HAVE_ISINF_IN_MATH_H ${HAVE_ISINF_IN_MATH_H}
-
-/* Set to 1 if the isnan function is found in <cmath> */
-#cmakedefine HAVE_ISNAN_IN_CMATH ${HAVE_ISNAN_IN_CMATH}
-
-/* Set to 1 if the isnan function is found in <math.h> */
-#cmakedefine HAVE_ISNAN_IN_MATH_H ${HAVE_ISNAN_IN_MATH_H}
-
/* Define if you have the libdl library or equivalent. */
#cmakedefine HAVE_LIBDL ${HAVE_LIBDL}
@@ -219,6 +180,9 @@
/* Define to 1 if you have the `malloc_zone_statistics' function. */
#cmakedefine HAVE_MALLOC_ZONE_STATISTICS ${HAVE_MALLOC_ZONE_STATISTICS}
+/* Define to 1 if you have the `mallctl` function. */
+#cmakedefine HAVE_MALLCTL ${HAVE_MALLCTL}
+
/* Define to 1 if you have the `mkdtemp' function. */
#cmakedefine HAVE_MKDTEMP ${HAVE_MKDTEMP}
@@ -241,18 +205,12 @@
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#cmakedefine HAVE_NDIR_H ${HAVE_NDIR_H}
-/* Define to 1 if you have the `nearbyintf' function. */
-#cmakedefine HAVE_NEARBYINTF ${HAVE_NEARBYINTF}
-
/* Define to 1 if you have the `opendir' function. */
#cmakedefine HAVE_OPENDIR ${HAVE_OPENDIR}
/* Define to 1 if you have the `posix_spawn' function. */
#cmakedefine HAVE_POSIX_SPAWN ${HAVE_POSIX_SPAWN}
-/* Define to 1 if you have the `powf' function. */
-#cmakedefine HAVE_POWF ${HAVE_POWF}
-
/* Define to 1 if you have the `pread' function. */
#cmakedefine HAVE_PREAD ${HAVE_PREAD}
@@ -283,15 +241,6 @@
/* Define to 1 if you have the `realpath' function. */
#cmakedefine HAVE_REALPATH ${HAVE_REALPATH}
-/* Define to 1 if you have the `rintf' function. */
-#undef HAVE_RINTF
-
-/* Define to 1 if you have the `round' function. */
-#cmakedefine HAVE_ROUND ${HAVE_ROUND}
-
-/* Define to 1 if you have the `roundf' function. */
-#undef HAVE_ROUNDF
-
/* Define to 1 if you have the `sbrk' function. */
#cmakedefine HAVE_SBRK ${HAVE_SBRK}
@@ -334,9 +283,6 @@
/* Define to 1 if you have the `strerror_r' function. */
#cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R}
-/* Define to 1 if you have the `strtof' function. */
-#cmakedefine HAVE_STRTOF ${HAVE_STRTOF}
-
/* Define to 1 if you have the `strtoll' function. */
#cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL}
diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in
index c68c77aa6076..67d7c8485a40 100644
--- a/include/llvm/Config/config.h.in
+++ b/include/llvm/Config/config.h.in
@@ -39,9 +39,6 @@
/* Define to 1 if you have the `backtrace' function. */
#undef HAVE_BACKTRACE
-/* Define to 1 if you have the `ceilf' function. */
-#undef HAVE_CEILF
-
/* Define to 1 if you have the <CrashReporterClient.h> header file. */
#undef HAVE_CRASHREPORTERCLIENT_H
@@ -86,12 +83,6 @@
/* Define to 1 if you have the <execinfo.h> header file. */
#undef HAVE_EXECINFO_H
-/* Define to 1 if you have the `exp' function. */
-#undef HAVE_EXP
-
-/* Define to 1 if you have the `exp2' function. */
-#undef HAVE_EXP2
-
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
@@ -107,15 +98,6 @@
/* Define to 1 if you have the <ffi.h> header file. */
#undef HAVE_FFI_H
-/* Set to 1 if the finite function is found in <ieeefp.h> */
-#undef HAVE_FINITE_IN_IEEEFP_H
-
-/* Define to 1 if you have the `floorf' function. */
-#undef HAVE_FLOORF
-
-/* Define to 1 if you have the `fmodf' function. */
-#undef HAVE_FMODF
-
/* Define to 1 if you have the `futimens' function. */
#undef HAVE_FUTIMENS
@@ -146,18 +128,6 @@
/* Define to 1 if you have the `isatty' function. */
#undef HAVE_ISATTY
-/* Set to 1 if the isinf function is found in <cmath> */
-#undef HAVE_ISINF_IN_CMATH
-
-/* Set to 1 if the isinf function is found in <math.h> */
-#undef HAVE_ISINF_IN_MATH_H
-
-/* Set to 1 if the isnan function is found in <cmath> */
-#undef HAVE_ISNAN_IN_CMATH
-
-/* Set to 1 if the isnan function is found in <math.h> */
-#undef HAVE_ISNAN_IN_MATH_H
-
/* Define if libedit is available on this platform. */
#undef HAVE_LIBEDIT
@@ -189,15 +159,6 @@
the current directory to the dynamic linker search path. */
#undef HAVE_LINK_R
-/* Define to 1 if you have the `log' function. */
-#undef HAVE_LOG
-
-/* Define to 1 if you have the `log10' function. */
-#undef HAVE_LOG10
-
-/* Define to 1 if you have the `log2' function. */
-#undef HAVE_LOG2
-
/* Define to 1 if you have the `longjmp' function. */
#undef HAVE_LONGJMP
@@ -241,15 +202,9 @@
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
-/* Define to 1 if you have the `nearbyintf' function. */
-#undef HAVE_NEARBYINTF
-
/* Define to 1 if you have the `posix_spawn' function. */
#undef HAVE_POSIX_SPAWN
-/* Define to 1 if you have the `powf' function. */
-#undef HAVE_POWF
-
/* Define to 1 if you have the `pread' function. */
#undef HAVE_PREAD
@@ -274,15 +229,6 @@
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
-/* Define to 1 if you have the `rintf' function. */
-#undef HAVE_RINTF
-
-/* Define to 1 if you have the `round' function. */
-#undef HAVE_ROUND
-
-/* Define to 1 if you have the `roundf' function. */
-#undef HAVE_ROUNDF
-
/* Define to 1 if you have the `sbrk' function. */
#undef HAVE_SBRK
@@ -313,12 +259,6 @@
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
-/* Set to 1 if the std::isinf function is found in <cmath> */
-#undef HAVE_STD_ISINF_IN_CMATH
-
-/* Set to 1 if the std::isnan function is found in <cmath> */
-#undef HAVE_STD_ISNAN_IN_CMATH
-
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
@@ -331,9 +271,6 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
-/* Define to 1 if you have the `strtof' function. */
-#undef HAVE_STRTOF
-
/* Define to 1 if you have the `strtoll' function. */
#undef HAVE_STRTOLL
@@ -480,6 +417,9 @@
/* Installation directory for documentation */
#undef LLVM_DOCSDIR
+/* Define to enable checks that alter the LLVM C++ ABI */
+#undef LLVM_ENABLE_ABI_BREAKING_CHECKS
+
/* Define if threads enabled */
#undef LLVM_ENABLE_THREADS
diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake
index d54003d993a9..bb7dc067ea00 100644
--- a/include/llvm/Config/llvm-config.h.cmake
+++ b/include/llvm/Config/llvm-config.h.cmake
@@ -101,4 +101,8 @@
/* Define if we link Polly to the tools */
#cmakedefine LINK_POLLY_INTO_TOOLS
+/* Define if LLVM is built with asserts and checks that change the layout of
+ client-visible data structures. */
+#cmakedefine LLVM_ENABLE_ABI_BREAKING_CHECKS
+
#endif
diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in
index 25a929544832..03e482ac1752 100644
--- a/include/llvm/Config/llvm-config.h.in
+++ b/include/llvm/Config/llvm-config.h.in
@@ -98,4 +98,7 @@
/* LLVM version string */
#undef LLVM_VERSION_STRING
+/* Define to enable checks that alter the LLVM C++ ABI */
+#undef LLVM_ENABLE_ABI_BREAKING_CHECKS
+
#endif
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index 622aa699c435..dddc7faa73e8 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -113,25 +113,16 @@ enum DIDumpType {
DIDT_AppleObjC
};
-// In place of applying the relocations to the data we've read from disk we use
-// a separate mapping table to the side and checking that at locations in the
-// dwarf where we expect relocated values. This adds a bit of complexity to the
-// dwarf parsing/extraction at the benefit of not allocating memory for the
-// entire size of the debug info sections.
-typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
-
class DIContext {
public:
enum DIContextKind {
- CK_DWARF
+ CK_DWARF,
+ CK_PDB
};
DIContextKind getKind() const { return Kind; }
DIContext(DIContextKind K) : Kind(K) {}
- virtual ~DIContext();
-
- /// getDWARFContext - get a context for binary DWARF data.
- static DIContext *getDWARFContext(const object::ObjectFile &Obj);
+ virtual ~DIContext() {}
virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0;
@@ -145,6 +136,43 @@ private:
const DIContextKind Kind;
};
+/// An inferface for inquiring the load address of a loaded object file
+/// to be used by the DIContext implementations when applying relocations
+/// on the fly.
+class LoadedObjectInfo {
+public:
+ LoadedObjectInfo() {}
+ virtual ~LoadedObjectInfo() {}
+
+ /// Obtain the Load Address of a section by Name.
+ ///
+ /// Calculate the address of the section identified by the passed in Name.
+ /// The section need not be present in the local address space. The addresses
+ /// need to be consistent with the addresses used to query the DIContext and
+ /// the output of this function should be deterministic, i.e. repeated calls with
+ /// the same Name should give the same address.
+ virtual uint64_t getSectionLoadAddress(StringRef Name) const = 0;
+
+ /// If conveniently available, return the content of the given Section.
+ ///
+ /// When the section is available in the local address space, in relocated (loaded)
+ /// form, e.g. because it was relocated by a JIT for execution, this function
+ /// should provide the contents of said section in `Data`. If the loaded section
+ /// is not available, or the cost of retrieving it would be prohibitive, this
+ /// function should return false. In that case, relocations will be read from the
+ /// local (unrelocated) object file and applied on the fly. Note that this method
+ /// is used purely for optimzation purposes in the common case of JITting in the
+ /// local address space, so returning false should always be correct.
+ virtual bool getLoadedSectionContents(StringRef Name, StringRef &Data) const {
+ return false;
+ }
+
+ /// Obtain a copy of this LoadedObjectInfo.
+ ///
+ /// The caller is responsible for deallocation once the copy is no longer required.
+ virtual LoadedObjectInfo *clone() const = 0;
+};
+
}
#endif
diff --git a/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
index bb05c302be9a..6ab5d5ce6f6e 100644
--- a/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
@@ -18,18 +18,14 @@ namespace llvm {
class raw_ostream;
class DWARFAbbreviationDeclaration {
- uint32_t Code;
- uint32_t Tag;
- bool HasChildren;
-
+public:
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; }
@@ -53,6 +49,12 @@ public:
private:
void clear();
+
+ uint32_t Code;
+ uint32_t Tag;
+ bool HasChildren;
+
+ AttributeSpecVector AttributeSpecs;
};
}
diff --git a/include/llvm/DebugInfo/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 3fbc1c3b3c79..47dbf5fd4f56 100644
--- a/include/llvm/DebugInfo/DWARFAcceleratorTable.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -7,9 +7,12 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIB_DEBUGINFO_DWARFACCELERATORTABLE_H
+#define LLVM_LIB_DEBUGINFO_DWARFACCELERATORTABLE_H
+
#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/DWARFFormValue.h"
-#include "llvm/DebugInfo/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include <cstdint>
namespace llvm {
@@ -47,3 +50,5 @@ public:
};
}
+
+#endif
diff --git a/include/llvm/DebugInfo/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
index dbf777cc71aa..743f9c696e9e 100644
--- a/include/llvm/DebugInfo/DWARFCompileUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
@@ -10,7 +10,7 @@
#ifndef LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H
#define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H
-#include "llvm/DebugInfo/DWARFUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
namespace llvm {
diff --git a/include/llvm/DebugInfo/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 82b5bb088477..423c0d32f1b5 100644
--- a/include/llvm/DebugInfo/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -13,18 +13,25 @@
#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 "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include <vector>
namespace llvm {
+// In place of applying the relocations to the data we've read from disk we use
+// a separate mapping table to the side and checking that at locations in the
+// dwarf where we expect relocated values. This adds a bit of complexity to the
+// dwarf parsing/extraction at the benefit of not allocating memory for the
+// entire size of the debug info sections.
+typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
+
/// DWARFContext
/// This data structure is the top level entity that deals with dwarf debug
/// information parsing. The actual data is supplied through pure virtual
@@ -44,8 +51,8 @@ class DWARFContext : public DIContext {
std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
std::unique_ptr<DWARFDebugLocDWO> LocDWO;
- DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION;
- DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION;
+ DWARFContext(DWARFContext &) = delete;
+ DWARFContext &operator=(DWARFContext &) = delete;
/// Read compile units from the debug_info section (if necessary)
/// and store them in CUs.
@@ -248,7 +255,8 @@ class DWARFContextInMemory : public DWARFContext {
SmallVector<SmallString<32>, 4> UncompressedSections;
public:
- DWARFContextInMemory(const object::ObjectFile &Obj);
+ DWARFContextInMemory(const object::ObjectFile &Obj,
+ const LoadedObjectInfo *L = nullptr);
bool isLittleEndian() const override { return IsLittleEndian; }
uint8_t getAddressSize() const override { return AddressSize; }
const DWARFSection &getInfoSection() override { return InfoSection; }
diff --git a/include/llvm/DebugInfo/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
index 6752df9cd728..21142089da6b 100644
--- a/include/llvm/DebugInfo/DWARFDebugAbbrev.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
@@ -10,7 +10,7 @@
#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H
#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H
-#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include <list>
#include <map>
#include <vector>
diff --git a/include/llvm/DebugInfo/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
index 837a8e63469e..837a8e63469e 100644
--- a/include/llvm/DebugInfo/DWARFDebugArangeSet.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
diff --git a/include/llvm/DebugInfo/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
index 791f010a8892..791f010a8892 100644
--- a/include/llvm/DebugInfo/DWARFDebugAranges.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
diff --git a/include/llvm/DebugInfo/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index be925cbe7519..be925cbe7519 100644
--- a/include/llvm/DebugInfo/DWARFDebugFrame.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
diff --git a/include/llvm/DebugInfo/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
index f05d64b6f34b..f29d5fe9ecde 100644
--- a/include/llvm/DebugInfo/DWARFDebugInfoEntry.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
@@ -12,8 +12,8 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h"
-#include "llvm/DebugInfo/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
diff --git a/include/llvm/DebugInfo/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
index c5ee76e39682..37b22c2e82f6 100644
--- a/include/llvm/DebugInfo/DWARFDebugLine.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -11,7 +11,7 @@
#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H
#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/DataExtractor.h"
#include <map>
#include <string>
diff --git a/include/llvm/DebugInfo/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
index a6135a0c9291..bd44c2e5aab9 100644
--- a/include/llvm/DebugInfo/DWARFDebugLoc.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -11,7 +11,7 @@
#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/DataExtractor.h"
namespace llvm {
diff --git a/include/llvm/DebugInfo/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index 4ee3bdad3299..c930bd603d4d 100644
--- a/include/llvm/DebugInfo/DWARFDebugRangeList.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -66,6 +66,8 @@ public:
void clear();
void dump(raw_ostream &OS) const;
bool extract(DataExtractor data, uint32_t *offset_ptr);
+ const std::vector<RangeListEntry> &getEntries() { return Entries; }
+
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
/// list. Has to be passed base address of the compile unit referencing this
/// range list.
diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 5bb6d1b9ddb0..7ddcc0d81d59 100644
--- a/include/llvm/DebugInfo/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -63,7 +63,7 @@ public:
/// 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.
+ /// \returns whether the extraction succeeded.
bool extractValue(DataExtractor data, uint32_t *offset_ptr,
const DWARFUnit *u);
bool isInlinedCStr() const {
@@ -74,6 +74,7 @@ public:
/// DWARFFormValue has form class is suitable for representing Foo.
Optional<uint64_t> getAsReference(const DWARFUnit *U) const;
Optional<uint64_t> getAsUnsignedConstant() const;
+ Optional<int64_t> getAsSignedConstant() const;
Optional<const char *> getAsCString(const DWARFUnit *U) const;
Optional<uint64_t> getAsAddress(const DWARFUnit *U) const;
Optional<uint64_t> getAsSectionOffset() const;
@@ -86,6 +87,8 @@ public:
static ArrayRef<uint8_t> getFixedFormSizes(uint8_t AddrSize,
uint16_t Version);
+private:
+ void dumpString(raw_ostream &OS, const DWARFUnit *U) const;
};
}
diff --git a/include/llvm/DebugInfo/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
index d7fe3032e505..d7fe3032e505 100644
--- a/include/llvm/DebugInfo/DWARFRelocMap.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
diff --git a/include/llvm/DebugInfo/DWARFSection.h b/include/llvm/DebugInfo/DWARF/DWARFSection.h
index 5f09d9e37d81..3e27b529e97b 100644
--- a/include/llvm/DebugInfo/DWARFSection.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFSection.h
@@ -10,7 +10,8 @@
#ifndef LLVM_LIB_DEBUGINFO_DWARFSECTION_H
#define LLVM_LIB_DEBUGINFO_DWARFSECTION_H
-#include "llvm/DebugInfo/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/ADT/StringRef.h"
namespace llvm {
diff --git a/include/llvm/DebugInfo/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
index 213b54139e04..f24e27819da2 100644
--- a/include/llvm/DebugInfo/DWARFTypeUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -10,7 +10,7 @@
#ifndef LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H
#define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H
-#include "llvm/DebugInfo/DWARFUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
namespace llvm {
diff --git a/include/llvm/DebugInfo/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index d71a1b60b731..5604b93f2205 100644
--- a/include/llvm/DebugInfo/DWARFUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -10,11 +10,12 @@
#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 "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include <vector>
namespace llvm {
@@ -45,7 +46,7 @@ protected:
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
StringRef SOS, StringRef AOS, bool isLittleEndian) = 0;
- ~DWARFUnitSectionBase() {}
+ ~DWARFUnitSectionBase() = default;
};
/// Concrete instance of DWARFUnitSection, specialized for one Unit type.
@@ -194,9 +195,8 @@ public:
BaseAddr = base_addr;
}
- const DWARFDebugInfoEntryMinimal *
- getCompileUnitDIE(bool extract_cu_die_only = true) {
- extractDIEsIfNeeded(extract_cu_die_only);
+ const DWARFDebugInfoEntryMinimal *getUnitDIE(bool ExtractUnitDIEOnly = true) {
+ extractDIEsIfNeeded(ExtractUnitDIEOnly);
return DieArray.empty() ? nullptr : &DieArray[0];
}
@@ -213,6 +213,45 @@ public:
/// getUnitSection - Return the DWARFUnitSection containing this unit.
const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; }
+ /// \brief Returns the number of DIEs in the unit. Parses the unit
+ /// if necessary.
+ unsigned getNumDIEs() {
+ extractDIEsIfNeeded(false);
+ return DieArray.size();
+ }
+
+ /// \brief Return the index of a DIE inside the unit's DIE vector.
+ ///
+ /// It is illegal to call this method with a DIE that hasn't be
+ /// created by this unit. In other word, it's illegal to call this
+ /// method on a DIE that isn't accessible by following
+ /// children/sibling links starting from this unit's getUnitDIE().
+ uint32_t getDIEIndex(const DWARFDebugInfoEntryMinimal *DIE) {
+ assert(!DieArray.empty() && DIE >= &DieArray[0] &&
+ DIE < &DieArray[0] + DieArray.size());
+ return DIE - &DieArray[0];
+ }
+
+ /// \brief Return the DIE object at the given index.
+ const DWARFDebugInfoEntryMinimal *getDIEAtIndex(unsigned Index) const {
+ assert(Index < DieArray.size());
+ return &DieArray[Index];
+ }
+
+ /// \brief Return the DIE object for a given offset inside the
+ /// unit's DIE vector.
+ ///
+ /// The unit needs to have his DIEs extracted for this method to work.
+ const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) const {
+ assert(!DieArray.empty());
+ auto it = std::lower_bound(
+ DieArray.begin(), DieArray.end(), Offset,
+ [=](const DWARFDebugInfoEntryMinimal &LHS, uint32_t Offset) {
+ return LHS.getOffset() < Offset;
+ });
+ return it == DieArray.end() ? nullptr : &*it;
+ }
+
private:
/// Size in bytes of the .debug_info data associated with this compile unit.
size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); }
diff --git a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
new file mode 100644
index 000000000000..b5fa8c33414d
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
@@ -0,0 +1,59 @@
+//===- ConcreteSymbolEnumerator.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H
+#define LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H
+
+#include "IPDBEnumChildren.h"
+#include "llvm/Support/Casting.h"
+#include <memory>
+
+namespace llvm {
+
+template <typename ChildType>
+class ConcreteSymbolEnumerator : public IPDBEnumChildren<ChildType> {
+public:
+ ConcreteSymbolEnumerator(std::unique_ptr<IPDBEnumSymbols> SymbolEnumerator)
+ : Enumerator(std::move(SymbolEnumerator)) {}
+
+ ~ConcreteSymbolEnumerator() override {}
+
+ uint32_t getChildCount() const override {
+ return Enumerator->getChildCount();
+ }
+
+ std::unique_ptr<ChildType> getChildAtIndex(uint32_t Index) const override {
+ std::unique_ptr<PDBSymbol> Child = Enumerator->getChildAtIndex(Index);
+ return make_concrete_child(std::move(Child));
+ }
+
+ std::unique_ptr<ChildType> getNext() override {
+ std::unique_ptr<PDBSymbol> Child = Enumerator->getNext();
+ return make_concrete_child(std::move(Child));
+ }
+
+ void reset() override { Enumerator->reset(); }
+
+ ConcreteSymbolEnumerator<ChildType> *clone() const override {
+ std::unique_ptr<IPDBEnumSymbols> WrappedClone(Enumerator->clone());
+ return new ConcreteSymbolEnumerator<ChildType>(std::move(WrappedClone));
+ }
+
+private:
+ std::unique_ptr<ChildType>
+ make_concrete_child(std::unique_ptr<PDBSymbol> Child) const {
+ ChildType *ConcreteChild = dyn_cast_or_null<ChildType>(Child.release());
+ return std::unique_ptr<ChildType>(ConcreteChild);
+ }
+
+ std::unique_ptr<IPDBEnumSymbols> Enumerator;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h
new file mode 100644
index 000000000000..7b2bc146b32d
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h
@@ -0,0 +1,33 @@
+//===- DIADataStream.h - DIA implementation of IPDBDataStream ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBDataStream.h"
+
+namespace llvm {
+class DIADataStream : public IPDBDataStream {
+public:
+ explicit DIADataStream(CComPtr<IDiaEnumDebugStreamData> DiaStreamData);
+
+ uint32_t getRecordCount() const override;
+ std::string getName() const override;
+ llvm::Optional<RecordType> getItemAtIndex(uint32_t Index) const override;
+ bool getNext(RecordType &Record) override;
+ void reset() override;
+ DIADataStream *clone() const override;
+
+private:
+ CComPtr<IDiaEnumDebugStreamData> StreamData;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h
new file mode 100644
index 000000000000..375bcdd7e3bd
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h
@@ -0,0 +1,35 @@
+//==- DIAEnumDebugStreams.h - DIA Debug Stream Enumerator impl ---*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+
+namespace llvm {
+
+class IPDBDataStream;
+
+class DIAEnumDebugStreams : public IPDBEnumChildren<IPDBDataStream> {
+public:
+ explicit DIAEnumDebugStreams(CComPtr<IDiaEnumDebugStreams> DiaEnumerator);
+
+ uint32_t getChildCount() const override;
+ ChildTypePtr getChildAtIndex(uint32_t Index) const override;
+ ChildTypePtr getNext() override;
+ void reset() override;
+ DIAEnumDebugStreams *clone() const override;
+
+private:
+ CComPtr<IDiaEnumDebugStreams> Enumerator;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h
new file mode 100644
index 000000000000..4cc85eda477f
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h
@@ -0,0 +1,35 @@
+//==- DIAEnumLineNumbers.h - DIA Line Number Enumerator impl -----*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+
+namespace llvm {
+
+class IPDBLineNumber;
+
+class DIAEnumLineNumbers : public IPDBEnumChildren<IPDBLineNumber> {
+public:
+ explicit DIAEnumLineNumbers(CComPtr<IDiaEnumLineNumbers> DiaEnumerator);
+
+ uint32_t getChildCount() const override;
+ ChildTypePtr getChildAtIndex(uint32_t Index) const override;
+ ChildTypePtr getNext() override;
+ void reset() override;
+ DIAEnumLineNumbers *clone() const override;
+
+private:
+ CComPtr<IDiaEnumLineNumbers> Enumerator;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h
new file mode 100644
index 000000000000..88625f64e49e
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h
@@ -0,0 +1,37 @@
+//==- DIAEnumSourceFiles.h - DIA Source File Enumerator impl -----*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+
+namespace llvm {
+
+class DIASession;
+
+class DIAEnumSourceFiles : public IPDBEnumChildren<IPDBSourceFile> {
+public:
+ explicit DIAEnumSourceFiles(const DIASession &PDBSession,
+ CComPtr<IDiaEnumSourceFiles> DiaEnumerator);
+
+ uint32_t getChildCount() const override;
+ ChildTypePtr getChildAtIndex(uint32_t Index) const override;
+ ChildTypePtr getNext() override;
+ void reset() override;
+ DIAEnumSourceFiles *clone() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaEnumSourceFiles> Enumerator;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h
new file mode 100644
index 000000000000..fe343f778aad
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h
@@ -0,0 +1,37 @@
+//==- DIAEnumSymbols.h - DIA Symbol Enumerator impl --------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+
+namespace llvm {
+
+class DIASession;
+
+class DIAEnumSymbols : public IPDBEnumChildren<PDBSymbol> {
+public:
+ explicit DIAEnumSymbols(const DIASession &Session,
+ CComPtr<IDiaEnumSymbols> DiaEnumerator);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+ DIAEnumSymbols *clone() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaEnumSymbols> Enumerator;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h
new file mode 100644
index 000000000000..5950a0d3835f
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h
@@ -0,0 +1,39 @@
+//===- DIALineNumber.h - DIA implementation of IPDBLineNumber ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+
+namespace llvm {
+class DIALineNumber : public IPDBLineNumber {
+public:
+ explicit DIALineNumber(CComPtr<IDiaLineNumber> DiaLineNumber);
+
+ uint32_t getLineNumber() const override;
+ uint32_t getLineNumberEnd() const override;
+ uint32_t getColumnNumber() const override;
+ uint32_t getColumnNumberEnd() const override;
+ uint32_t getAddressSection() const override;
+ uint32_t getAddressOffset() const override;
+ uint32_t getRelativeVirtualAddress() const override;
+ uint64_t getVirtualAddress() const override;
+ uint32_t getLength() const override;
+ uint32_t getSourceFileId() const override;
+ uint32_t getCompilandId() const override;
+ bool isStatement() const override;
+
+private:
+ CComPtr<IDiaLineNumber> LineNumber;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
new file mode 100644
index 000000000000..9308b8e82657
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
@@ -0,0 +1,206 @@
+//===- DIARawSymbol.h - DIA implementation of IPDBRawSymbol ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+
+namespace llvm {
+class DIASession;
+class DIARawSymbol : public IPDBRawSymbol {
+public:
+ DIARawSymbol(const DIASession &PDBSession, CComPtr<IDiaSymbol> DiaSymbol);
+
+ void dump(raw_ostream &OS, int Indent) const override;
+
+ CComPtr<IDiaSymbol> getDiaSymbol() const { return Symbol; }
+
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
+ uint32_t RVA) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByRVA(uint32_t RVA) const override;
+
+ void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const override;
+ void getFrontEndVersion(VersionInfo &Version) const override;
+ void getBackEndVersion(VersionInfo &Version) const override;
+ PDB_MemberAccess getAccess() const override;
+ uint32_t getAddressOffset() const override;
+ uint32_t getAddressSection() const override;
+ uint32_t getAge() const override;
+ uint32_t getArrayIndexTypeId() const override;
+ uint32_t getBaseDataOffset() const override;
+ uint32_t getBaseDataSlot() const override;
+ uint32_t getBaseSymbolId() const override;
+ PDB_BuiltinType getBuiltinType() const override;
+ uint32_t getBitPosition() const override;
+ PDB_CallingConv getCallingConvention() const override;
+ uint32_t getClassParentId() const override;
+ std::string getCompilerName() const override;
+ uint32_t getCount() const override;
+ uint32_t getCountLiveRanges() const override;
+ PDB_Lang getLanguage() const override;
+ uint32_t getLexicalParentId() const override;
+ std::string getLibraryName() const override;
+ uint32_t getLiveRangeStartAddressOffset() const override;
+ uint32_t getLiveRangeStartAddressSection() const override;
+ uint32_t getLiveRangeStartRelativeVirtualAddress() const override;
+ PDB_RegisterId getLocalBasePointerRegisterId() const override;
+ uint32_t getLowerBoundId() const override;
+ uint32_t getMemorySpaceKind() const override;
+ std::string getName() const override;
+ uint32_t getNumberOfAcceleratorPointerTags() const override;
+ uint32_t getNumberOfColumns() const override;
+ uint32_t getNumberOfModifiers() const override;
+ uint32_t getNumberOfRegisterIndices() const override;
+ uint32_t getNumberOfRows() const override;
+ std::string getObjectFileName() const override;
+ uint32_t getOemId() const override;
+ uint32_t getOemSymbolId() const override;
+ uint32_t getOffsetInUdt() const override;
+ PDB_Cpu getPlatform() const override;
+ uint32_t getRank() const override;
+ PDB_RegisterId getRegisterId() const override;
+ uint32_t getRegisterType() const override;
+ uint32_t getRelativeVirtualAddress() const override;
+ uint32_t getSamplerSlot() const override;
+ uint32_t getSignature() const override;
+ uint32_t getSizeInUdt() const override;
+ uint32_t getSlot() const override;
+ std::string getSourceFileName() const override;
+ uint32_t getStride() const override;
+ uint32_t getSubTypeId() const override;
+ std::string getSymbolsFileName() const override;
+ uint32_t getSymIndexId() const override;
+ uint32_t getTargetOffset() const override;
+ uint32_t getTargetRelativeVirtualAddress() const override;
+ uint64_t getTargetVirtualAddress() const override;
+ uint32_t getTargetSection() const override;
+ uint32_t getTextureSlot() const override;
+ uint32_t getTimeStamp() const override;
+ uint32_t getToken() const override;
+ uint32_t getTypeId() const override;
+ uint32_t getUavSlot() const override;
+ std::string getUndecoratedName() const override;
+ uint32_t getUnmodifiedTypeId() const override;
+ uint32_t getUpperBoundId() const override;
+ Variant getValue() const override;
+ uint32_t getVirtualBaseDispIndex() const override;
+ uint32_t getVirtualBaseOffset() const override;
+ uint32_t getVirtualTableShapeId() const override;
+ PDB_DataKind getDataKind() const override;
+ PDB_SymType getSymTag() const override;
+ PDB_UniqueId getGuid() const override;
+ int32_t getOffset() const override;
+ int32_t getThisAdjust() const override;
+ int32_t getVirtualBasePointerOffset() const override;
+ PDB_LocType getLocationType() const override;
+ PDB_Machine getMachineType() const override;
+ PDB_ThunkOrdinal getThunkOrdinal() const override;
+ uint64_t getLength() const override;
+ uint64_t getLiveRangeLength() const override;
+ uint64_t getVirtualAddress() const override;
+ PDB_UdtType getUdtKind() const override;
+ bool hasConstructor() const override;
+ bool hasCustomCallingConvention() const override;
+ bool hasFarReturn() const override;
+ bool isCode() const override;
+ bool isCompilerGenerated() const override;
+ bool isConstType() const override;
+ bool isEditAndContinueEnabled() const override;
+ bool isFunction() const override;
+ bool getAddressTaken() const override;
+ bool getNoStackOrdering() const override;
+ bool hasAlloca() const override;
+ bool hasAssignmentOperator() const override;
+ bool hasCTypes() const override;
+ bool hasCastOperator() const override;
+ bool hasDebugInfo() const override;
+ bool hasEH() const override;
+ bool hasEHa() const override;
+ bool hasInlAsm() const override;
+ bool hasInlineAttribute() const override;
+ bool hasInterruptReturn() const override;
+ bool hasFramePointer() const override;
+ bool hasLongJump() const override;
+ bool hasManagedCode() const override;
+ bool hasNestedTypes() const override;
+ bool hasNoInlineAttribute() const override;
+ bool hasNoReturnAttribute() const override;
+ bool hasOptimizedCodeDebugInfo() const override;
+ bool hasOverloadedOperator() const override;
+ bool hasSEH() const override;
+ bool hasSecurityChecks() const override;
+ bool hasSetJump() const override;
+ bool hasStrictGSCheck() const override;
+ bool isAcceleratorGroupSharedLocal() const override;
+ bool isAcceleratorPointerTagLiveRange() const override;
+ bool isAcceleratorStubFunction() const override;
+ bool isAggregated() const override;
+ bool isIntroVirtualFunction() const override;
+ bool isCVTCIL() const override;
+ bool isConstructorVirtualBase() const override;
+ bool isCxxReturnUdt() const override;
+ bool isDataAligned() const override;
+ bool isHLSLData() const override;
+ bool isHotpatchable() const override;
+ bool isIndirectVirtualBaseClass() const override;
+ bool isInterfaceUdt() const override;
+ bool isIntrinsic() const override;
+ bool isLTCG() const override;
+ bool isLocationControlFlowDependent() const override;
+ bool isMSILNetmodule() const override;
+ bool isMatrixRowMajor() const override;
+ bool isManagedCode() const override;
+ bool isMSILCode() const override;
+ bool isMultipleInheritance() const override;
+ bool isNaked() const override;
+ bool isNested() const override;
+ bool isOptimizedAway() const override;
+ bool isPacked() const override;
+ bool isPointerBasedOnSymbolValue() const override;
+ bool isPointerToDataMember() const override;
+ bool isPointerToMemberFunction() const override;
+ bool isPureVirtual() const override;
+ bool isRValueReference() const override;
+ bool isRefUdt() const override;
+ bool isReference() const override;
+ bool isRestrictedType() const override;
+ bool isReturnValue() const override;
+ bool isSafeBuffers() const override;
+ bool isScoped() const override;
+ bool isSdl() const override;
+ bool isSingleInheritance() const override;
+ bool isSplitted() const override;
+ bool isStatic() const override;
+ bool hasPrivateSymbols() const override;
+ bool isUnalignedType() const override;
+ bool isUnreached() const override;
+ bool isValueUdt() const override;
+ bool isVirtual() const override;
+ bool isVirtualBaseClass() const override;
+ bool isVirtualInheritance() const override;
+ bool isVolatileType() const override;
+ bool wasInlined() const override;
+ std::string getUnused() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaSymbol> Symbol;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h
new file mode 100644
index 000000000000..9a8600fb85ec
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h
@@ -0,0 +1,51 @@
+//===- DIASession.h - DIA implementation of IPDBSession ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H
+
+#include "DIASupport.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+
+namespace llvm {
+class DIASession : public IPDBSession {
+public:
+ explicit DIASession(CComPtr<IDiaSession> DiaSession);
+
+ static PDB_ErrorCode createFromPdb(StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+ static PDB_ErrorCode createFromExe(StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+
+ uint64_t getLoadAddress() const override;
+ void setLoadAddress(uint64_t Address) override;
+ std::unique_ptr<PDBSymbolExe> getGlobalScope() const override;
+ std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
+
+ std::unique_ptr<PDBSymbol>
+ findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override;
+
+ std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override;
+ std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland(
+ const PDBSymbolCompiland &Compiland) const override;
+ std::unique_ptr<IPDBSourceFile>
+ getSourceFileById(uint32_t FileId) const override;
+
+ std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override;
+
+private:
+ CComPtr<IDiaSession> Session;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h
new file mode 100644
index 000000000000..c424e27493c1
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h
@@ -0,0 +1,36 @@
+//===- DIASourceFile.h - DIA implementation of IPDBSourceFile ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+
+namespace llvm {
+class DIASession;
+
+class DIASourceFile : public IPDBSourceFile {
+public:
+ explicit DIASourceFile(const DIASession &Session,
+ CComPtr<IDiaSourceFile> DiaSourceFile);
+
+ std::string getFileName() const override;
+ uint32_t getUniqueId() const override;
+ std::string getChecksum() const override;
+ PDB_Checksum getChecksumType() const override;
+ std::unique_ptr<IPDBEnumSymbols> getCompilands() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaSourceFile> SourceFile;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h
new file mode 100644
index 000000000000..407a34551cc7
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h
@@ -0,0 +1,33 @@
+//===- DIASupport.h - Common header includes for DIA ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Common defines and header includes for all LLVMDebugInfoPDBDIA. The
+// definitions here configure the necessary #defines and include system headers
+// in the proper order for using DIA.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H
+
+// Require at least Vista
+#define NTDDI_VERSION NTDDI_VISTA
+#define _WIN32_WINNT _WIN32_WINNT_VISTA
+#define WINVER _WIN32_WINNT_VISTA
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+// atlbase.h has to come before windows.h
+#include <atlbase.h>
+#include <windows.h>
+
+// DIA headers must come after windows headers.
+#include <cvconst.h>
+#include <dia2.h>
+
+#endif // LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H
diff --git a/include/llvm/DebugInfo/PDB/IPDBDataStream.h b/include/llvm/DebugInfo/PDB/IPDBDataStream.h
new file mode 100644
index 000000000000..808a0f3ec3a9
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/IPDBDataStream.h
@@ -0,0 +1,37 @@
+//===- IPDBDataStream.h - base interface for child enumerator -*- C++ ---*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H
+#define LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H
+
+#include "PDBTypes.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+/// IPDBDataStream defines an interface used to represent a stream consisting
+/// of a name and a series of records whose formats depend on the particular
+/// stream type.
+class IPDBDataStream {
+public:
+ typedef llvm::SmallVector<uint8_t, 32> RecordType;
+
+ virtual ~IPDBDataStream();
+
+ virtual uint32_t getRecordCount() const = 0;
+ virtual std::string getName() const = 0;
+ virtual llvm::Optional<RecordType> getItemAtIndex(uint32_t Index) const = 0;
+ virtual bool getNext(RecordType &Record) = 0;
+ virtual void reset() = 0;
+ virtual IPDBDataStream *clone() const = 0;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h
new file mode 100644
index 000000000000..645ac96e23a5
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h
@@ -0,0 +1,33 @@
+//===- IPDBEnumChildren.h - base interface for child enumerator -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H
+#define LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H
+
+#include "PDBTypes.h"
+#include <memory>
+
+namespace llvm {
+
+template <typename ChildType> class IPDBEnumChildren {
+public:
+ typedef std::unique_ptr<ChildType> ChildTypePtr;
+ typedef IPDBEnumChildren<ChildType> MyType;
+
+ virtual ~IPDBEnumChildren() {}
+
+ virtual uint32_t getChildCount() const = 0;
+ virtual ChildTypePtr getChildAtIndex(uint32_t Index) const = 0;
+ virtual ChildTypePtr getNext() = 0;
+ virtual void reset() = 0;
+ virtual MyType *clone() const = 0;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBLineNumber.h b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h
new file mode 100644
index 000000000000..92cd58d86649
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h
@@ -0,0 +1,36 @@
+//===- IPDBLineNumber.h - base interface for PDB line no. info ---*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H
+#define LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H
+
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class IPDBLineNumber {
+public:
+ virtual ~IPDBLineNumber();
+
+ virtual uint32_t getLineNumber() const = 0;
+ virtual uint32_t getLineNumberEnd() const = 0;
+ virtual uint32_t getColumnNumber() const = 0;
+ virtual uint32_t getColumnNumberEnd() const = 0;
+ virtual uint32_t getAddressSection() const = 0;
+ virtual uint32_t getAddressOffset() const = 0;
+ virtual uint32_t getRelativeVirtualAddress() const = 0;
+ virtual uint64_t getVirtualAddress() const = 0;
+ virtual uint32_t getLength() const = 0;
+ virtual uint32_t getSourceFileId() const = 0;
+ virtual uint32_t getCompilandId() const = 0;
+ virtual bool isStatement() const = 0;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
new file mode 100644
index 000000000000..139bff56fd5d
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
@@ -0,0 +1,211 @@
+//===- IPDBRawSymbol.h - base interface for PDB symbol types ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H
+
+#include "PDBTypes.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace llvm {
+
+class raw_ostream;
+
+/// IPDBRawSymbol defines an interface used to represent an arbitrary symbol.
+/// It exposes a monolithic interface consisting of accessors for the union of
+/// all properties that are valid for any symbol type. This interface is then
+/// wrapped by a concrete class which exposes only those set of methods valid
+/// for this particular symbol type. See PDBSymbol.h for more details.
+class IPDBRawSymbol {
+public:
+ virtual ~IPDBRawSymbol();
+
+ virtual void dump(raw_ostream &OS, int Indent) const = 0;
+
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type) const = 0;
+
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const = 0;
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
+ uint32_t RVA) const = 0;
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByRVA(uint32_t RVA) const = 0;
+
+ virtual void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const = 0;
+ virtual void getBackEndVersion(VersionInfo &Version) const = 0;
+ virtual PDB_MemberAccess getAccess() const = 0;
+ virtual uint32_t getAddressOffset() const = 0;
+ virtual uint32_t getAddressSection() const = 0;
+ virtual uint32_t getAge() const = 0;
+ virtual uint32_t getArrayIndexTypeId() const = 0;
+ virtual uint32_t getBaseDataOffset() const = 0;
+ virtual uint32_t getBaseDataSlot() const = 0;
+ virtual uint32_t getBaseSymbolId() const = 0;
+ virtual PDB_BuiltinType getBuiltinType() const = 0;
+ virtual uint32_t getBitPosition() const = 0;
+ virtual PDB_CallingConv getCallingConvention() const = 0;
+ virtual uint32_t getClassParentId() const = 0;
+ virtual std::string getCompilerName() const = 0;
+ virtual uint32_t getCount() const = 0;
+ virtual uint32_t getCountLiveRanges() const = 0;
+ virtual void getFrontEndVersion(VersionInfo &Version) const = 0;
+ virtual PDB_Lang getLanguage() const = 0;
+ virtual uint32_t getLexicalParentId() const = 0;
+ virtual std::string getLibraryName() const = 0;
+ virtual uint32_t getLiveRangeStartAddressOffset() const = 0;
+ virtual uint32_t getLiveRangeStartAddressSection() const = 0;
+ virtual uint32_t getLiveRangeStartRelativeVirtualAddress() const = 0;
+ virtual PDB_RegisterId getLocalBasePointerRegisterId() const = 0;
+ virtual uint32_t getLowerBoundId() const = 0;
+ virtual uint32_t getMemorySpaceKind() const = 0;
+ virtual std::string getName() const = 0;
+ virtual uint32_t getNumberOfAcceleratorPointerTags() const = 0;
+ virtual uint32_t getNumberOfColumns() const = 0;
+ virtual uint32_t getNumberOfModifiers() const = 0;
+ virtual uint32_t getNumberOfRegisterIndices() const = 0;
+ virtual uint32_t getNumberOfRows() const = 0;
+ virtual std::string getObjectFileName() const = 0;
+ virtual uint32_t getOemId() const = 0;
+ virtual uint32_t getOemSymbolId() const = 0;
+ virtual uint32_t getOffsetInUdt() const = 0;
+ virtual PDB_Cpu getPlatform() const = 0;
+ virtual uint32_t getRank() const = 0;
+ virtual PDB_RegisterId getRegisterId() const = 0;
+ virtual uint32_t getRegisterType() const = 0;
+ virtual uint32_t getRelativeVirtualAddress() const = 0;
+ virtual uint32_t getSamplerSlot() const = 0;
+ virtual uint32_t getSignature() const = 0;
+ virtual uint32_t getSizeInUdt() const = 0;
+ virtual uint32_t getSlot() const = 0;
+ virtual std::string getSourceFileName() const = 0;
+ virtual uint32_t getStride() const = 0;
+ virtual uint32_t getSubTypeId() const = 0;
+ virtual std::string getSymbolsFileName() const = 0;
+ virtual uint32_t getSymIndexId() const = 0;
+ virtual uint32_t getTargetOffset() const = 0;
+ virtual uint32_t getTargetRelativeVirtualAddress() const = 0;
+ virtual uint64_t getTargetVirtualAddress() const = 0;
+ virtual uint32_t getTargetSection() const = 0;
+ virtual uint32_t getTextureSlot() const = 0;
+ virtual uint32_t getTimeStamp() const = 0;
+ virtual uint32_t getToken() const = 0;
+ virtual uint32_t getTypeId() const = 0;
+ virtual uint32_t getUavSlot() const = 0;
+ virtual std::string getUndecoratedName() const = 0;
+ virtual uint32_t getUnmodifiedTypeId() const = 0;
+ virtual uint32_t getUpperBoundId() const = 0;
+ virtual Variant getValue() const = 0;
+ virtual uint32_t getVirtualBaseDispIndex() const = 0;
+ virtual uint32_t getVirtualBaseOffset() const = 0;
+ virtual uint32_t getVirtualTableShapeId() const = 0;
+ virtual PDB_DataKind getDataKind() const = 0;
+ virtual PDB_SymType getSymTag() const = 0;
+ virtual PDB_UniqueId getGuid() const = 0;
+ virtual int32_t getOffset() const = 0;
+ virtual int32_t getThisAdjust() const = 0;
+ virtual int32_t getVirtualBasePointerOffset() const = 0;
+ virtual PDB_LocType getLocationType() const = 0;
+ virtual PDB_Machine getMachineType() const = 0;
+ virtual PDB_ThunkOrdinal getThunkOrdinal() const = 0;
+ virtual uint64_t getLength() const = 0;
+ virtual uint64_t getLiveRangeLength() const = 0;
+ virtual uint64_t getVirtualAddress() const = 0;
+ virtual PDB_UdtType getUdtKind() const = 0;
+ virtual bool hasConstructor() const = 0;
+ virtual bool hasCustomCallingConvention() const = 0;
+ virtual bool hasFarReturn() const = 0;
+ virtual bool isCode() const = 0;
+ virtual bool isCompilerGenerated() const = 0;
+ virtual bool isConstType() const = 0;
+ virtual bool isEditAndContinueEnabled() const = 0;
+ virtual bool isFunction() const = 0;
+ virtual bool getAddressTaken() const = 0;
+ virtual bool getNoStackOrdering() const = 0;
+ virtual bool hasAlloca() const = 0;
+ virtual bool hasAssignmentOperator() const = 0;
+ virtual bool hasCTypes() const = 0;
+ virtual bool hasCastOperator() const = 0;
+ virtual bool hasDebugInfo() const = 0;
+ virtual bool hasEH() const = 0;
+ virtual bool hasEHa() const = 0;
+ virtual bool hasFramePointer() const = 0;
+ virtual bool hasInlAsm() const = 0;
+ virtual bool hasInlineAttribute() const = 0;
+ virtual bool hasInterruptReturn() const = 0;
+ virtual bool hasLongJump() const = 0;
+ virtual bool hasManagedCode() const = 0;
+ virtual bool hasNestedTypes() const = 0;
+ virtual bool hasNoInlineAttribute() const = 0;
+ virtual bool hasNoReturnAttribute() const = 0;
+ virtual bool hasOptimizedCodeDebugInfo() const = 0;
+ virtual bool hasOverloadedOperator() const = 0;
+ virtual bool hasSEH() const = 0;
+ virtual bool hasSecurityChecks() const = 0;
+ virtual bool hasSetJump() const = 0;
+ virtual bool hasStrictGSCheck() const = 0;
+ virtual bool isAcceleratorGroupSharedLocal() const = 0;
+ virtual bool isAcceleratorPointerTagLiveRange() const = 0;
+ virtual bool isAcceleratorStubFunction() const = 0;
+ virtual bool isAggregated() const = 0;
+ virtual bool isIntroVirtualFunction() const = 0;
+ virtual bool isCVTCIL() const = 0;
+ virtual bool isConstructorVirtualBase() const = 0;
+ virtual bool isCxxReturnUdt() const = 0;
+ virtual bool isDataAligned() const = 0;
+ virtual bool isHLSLData() const = 0;
+ virtual bool isHotpatchable() const = 0;
+ virtual bool isIndirectVirtualBaseClass() const = 0;
+ virtual bool isInterfaceUdt() const = 0;
+ virtual bool isIntrinsic() const = 0;
+ virtual bool isLTCG() const = 0;
+ virtual bool isLocationControlFlowDependent() const = 0;
+ virtual bool isMSILNetmodule() const = 0;
+ virtual bool isMatrixRowMajor() const = 0;
+ virtual bool isManagedCode() const = 0;
+ virtual bool isMSILCode() const = 0;
+ virtual bool isMultipleInheritance() const = 0;
+ virtual bool isNaked() const = 0;
+ virtual bool isNested() const = 0;
+ virtual bool isOptimizedAway() const = 0;
+ virtual bool isPacked() const = 0;
+ virtual bool isPointerBasedOnSymbolValue() const = 0;
+ virtual bool isPointerToDataMember() const = 0;
+ virtual bool isPointerToMemberFunction() const = 0;
+ virtual bool isPureVirtual() const = 0;
+ virtual bool isRValueReference() const = 0;
+ virtual bool isRefUdt() const = 0;
+ virtual bool isReference() const = 0;
+ virtual bool isRestrictedType() const = 0;
+ virtual bool isReturnValue() const = 0;
+ virtual bool isSafeBuffers() const = 0;
+ virtual bool isScoped() const = 0;
+ virtual bool isSdl() const = 0;
+ virtual bool isSingleInheritance() const = 0;
+ virtual bool isSplitted() const = 0;
+ virtual bool isStatic() const = 0;
+ virtual bool hasPrivateSymbols() const = 0;
+ virtual bool isUnalignedType() const = 0;
+ virtual bool isUnreached() const = 0;
+ virtual bool isValueUdt() const = 0;
+ virtual bool isVirtual() const = 0;
+ virtual bool isVirtualBaseClass() const = 0;
+ virtual bool isVirtualInheritance() const = 0;
+ virtual bool isVolatileType() const = 0;
+ virtual bool wasInlined() const = 0;
+ virtual std::string getUnused() const = 0;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h
new file mode 100644
index 000000000000..a130a38a6538
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/IPDBSession.h
@@ -0,0 +1,61 @@
+//===- IPDBSession.h - base interface for a PDB symbol context --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_IPDBSESSION_H
+#define LLVM_DEBUGINFO_PDB_IPDBSESSION_H
+
+#include "PDBTypes.h"
+#include "llvm/Support/Casting.h"
+#include <memory>
+
+namespace llvm {
+
+class PDBSymbolCompiland;
+class PDBSymbolExe;
+
+/// IPDBSession defines an interface used to provide a context for querying
+/// debug information from a debug data source (for example, a PDB).
+class IPDBSession {
+public:
+ virtual ~IPDBSession();
+
+ virtual uint64_t getLoadAddress() const = 0;
+ virtual void setLoadAddress(uint64_t Address) = 0;
+ virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() const = 0;
+ virtual std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const = 0;
+
+ template <typename T>
+ std::unique_ptr<T> getConcreteSymbolById(uint32_t SymbolId) const {
+ auto Symbol(getSymbolById(SymbolId));
+ if (!Symbol)
+ return nullptr;
+
+ T *ConcreteSymbol = dyn_cast<T>(Symbol.get());
+ if (!ConcreteSymbol)
+ return nullptr;
+ Symbol.release();
+ return std::unique_ptr<T>(ConcreteSymbol);
+ }
+
+ virtual std::unique_ptr<PDBSymbol>
+ findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0;
+ virtual std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0;
+
+ virtual std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const = 0;
+ virtual std::unique_ptr<IPDBEnumSourceFiles>
+ getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0;
+ virtual std::unique_ptr<IPDBSourceFile>
+ getSourceFileById(uint32_t FileId) const = 0;
+
+ virtual std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const = 0;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/IPDBSourceFile.h b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h
new file mode 100644
index 000000000000..55000eff02f0
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h
@@ -0,0 +1,37 @@
+//===- IPDBSourceFile.h - base interface for a PDB source file --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H
+#define LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H
+
+#include "PDBTypes.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+/// IPDBSourceFile defines an interface used to represent source files whose
+/// information are stored in the PDB.
+class IPDBSourceFile {
+public:
+ virtual ~IPDBSourceFile();
+
+ void dump(raw_ostream &OS, int Indent) const;
+
+ virtual std::string getFileName() const = 0;
+ virtual uint32_t getUniqueId() const = 0;
+ virtual std::string getChecksum() const = 0;
+ virtual PDB_Checksum getChecksumType() const = 0;
+ virtual std::unique_ptr<IPDBEnumSymbols> getCompilands() const = 0;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h
new file mode 100644
index 000000000000..5df3be85e381
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDB.h
@@ -0,0 +1,26 @@
+//===- PDB.h - base header file for creating a PDB reader -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDB_H
+#define LLVM_DEBUGINFO_PDB_PDB_H
+
+#include "PDBTypes.h"
+#include <memory>
+
+namespace llvm {
+class StringRef;
+
+PDB_ErrorCode loadDataForPDB(PDB_ReaderType Type, StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+
+PDB_ErrorCode loadDataForEXE(PDB_ReaderType Type, StringRef Path,
+ std::unique_ptr<IPDBSession> &Session);
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBContext.h b/include/llvm/DebugInfo/PDB/PDBContext.h
new file mode 100644
index 000000000000..2bb97463f90d
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBContext.h
@@ -0,0 +1,60 @@
+//===-- PDBContext.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===/
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBCONTEXT_H
+#define LLVM_DEBUGINFO_PDB_PDBCONTEXT_H
+
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+
+namespace llvm {
+
+namespace object {
+class COFFObjectFile;
+}
+
+/// PDBContext
+/// This data structure is the top level entity that deals with PDB debug
+/// information parsing. This data structure exists only when there is a
+/// need for a transparent interface to different debug information formats
+/// (e.g. PDB and DWARF). More control and power over the debug information
+/// access can be had by using the PDB interfaces directly.
+class PDBContext : public DIContext {
+
+ PDBContext(PDBContext &) = delete;
+ PDBContext &operator=(PDBContext &) = delete;
+
+public:
+ PDBContext(const object::COFFObjectFile &Object,
+ std::unique_ptr<IPDBSession> PDBSession,
+ bool RelativeAddress);
+
+ static bool classof(const DIContext *DICtx) {
+ return DICtx->getKind() == CK_PDB;
+ }
+
+ void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override;
+
+ 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;
+
+private:
+ std::string getFunctionName(uint64_t Address, DINameKind NameKind) const;
+ std::unique_ptr<IPDBSession> Session;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBExtras.h b/include/llvm/DebugInfo/PDB/PDBExtras.h
new file mode 100644
index 000000000000..48ce1c127196
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBExtras.h
@@ -0,0 +1,38 @@
+//===- PDBExtras.h - helper functions and classes for PDBs -------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBEXTRAS_H
+#define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H
+
+#include "PDBTypes.h"
+#include "llvm/Support/raw_ostream.h"
+#include <unordered_map>
+
+namespace llvm {
+typedef std::unordered_map<PDB_SymType, int> TagStats;
+
+raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_DataKind &Data);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_RegisterId &Reg);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_LocType &Loc);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_ThunkOrdinal &Thunk);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id);
+
+raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
+raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version);
+raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats);
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBSymDumper.h b/include/llvm/DebugInfo/PDB/PDBSymDumper.h
new file mode 100644
index 000000000000..65110f39366f
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymDumper.h
@@ -0,0 +1,61 @@
+//===- PDBSymDumper.h - base interface for PDB symbol dumper *- C++ -----*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H
+
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymDumper {
+public:
+ PDBSymDumper(bool ShouldRequireImpl);
+ virtual ~PDBSymDumper();
+
+ virtual void dump(const PDBSymbolAnnotation &Symbol);
+ virtual void dump(const PDBSymbolBlock &Symbol);
+ virtual void dump(const PDBSymbolCompiland &Symbol);
+ virtual void dump(const PDBSymbolCompilandDetails &Symbol);
+ virtual void dump(const PDBSymbolCompilandEnv &Symbol);
+ virtual void dump(const PDBSymbolCustom &Symbol);
+ virtual void dump(const PDBSymbolData &Symbol);
+ virtual void dump(const PDBSymbolExe &Symbol);
+ virtual void dump(const PDBSymbolFunc &Symbol);
+ virtual void dump(const PDBSymbolFuncDebugEnd &Symbol);
+ virtual void dump(const PDBSymbolFuncDebugStart &Symbol);
+ virtual void dump(const PDBSymbolLabel &Symbol);
+ virtual void dump(const PDBSymbolPublicSymbol &Symbol);
+ virtual void dump(const PDBSymbolThunk &Symbol);
+ virtual void dump(const PDBSymbolTypeArray &Symbol);
+ virtual void dump(const PDBSymbolTypeBaseClass &Symbol);
+ virtual void dump(const PDBSymbolTypeBuiltin &Symbol);
+ virtual void dump(const PDBSymbolTypeCustom &Symbol);
+ virtual void dump(const PDBSymbolTypeDimension &Symbol);
+ virtual void dump(const PDBSymbolTypeEnum &Symbol);
+ virtual void dump(const PDBSymbolTypeFriend &Symbol);
+ virtual void dump(const PDBSymbolTypeFunctionArg &Symbol);
+ virtual void dump(const PDBSymbolTypeFunctionSig &Symbol);
+ virtual void dump(const PDBSymbolTypeManaged &Symbol);
+ virtual void dump(const PDBSymbolTypePointer &Symbol);
+ virtual void dump(const PDBSymbolTypeTypedef &Symbol);
+ virtual void dump(const PDBSymbolTypeUDT &Symbol);
+ virtual void dump(const PDBSymbolTypeVTable &Symbol);
+ virtual void dump(const PDBSymbolTypeVTableShape &Symbol);
+ virtual void dump(const PDBSymbolUnknown &Symbol);
+ virtual void dump(const PDBSymbolUsingNamespace &Symbol);
+
+private:
+ bool RequireImpl;
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h
new file mode 100644
index 000000000000..4360c5431e69
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h
@@ -0,0 +1,97 @@
+//===- PDBSymbol.h - base class for user-facing symbol types -----*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H
+
+#include "ConcreteSymbolEnumerator.h"
+#include "IPDBRawSymbol.h"
+#include "PDBExtras.h"
+#include "PDBTypes.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <unordered_map>
+
+#define FORWARD_SYMBOL_METHOD(MethodName) \
+ auto MethodName() const->decltype(RawSymbol->MethodName()) { \
+ return RawSymbol->MethodName(); \
+ }
+
+namespace llvm {
+
+class IPDBRawSymbol;
+class raw_ostream;
+
+#define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \
+ static const PDB_SymType Tag = TagValue; \
+ static bool classof(const PDBSymbol *S) { return S->getSymTag() == Tag; }
+
+/// PDBSymbol defines the base of the inheritance hierarchy for concrete symbol
+/// types (e.g. functions, executables, vtables, etc). All concrete symbol
+/// types inherit from PDBSymbol and expose the exact set of methods that are
+/// valid for that particular symbol type, as described in the Microsoft
+/// reference "Lexical and Class Hierarchy of Symbol Types":
+/// https://msdn.microsoft.com/en-us/library/370hs6k4.aspx
+class PDBSymbol {
+protected:
+ PDBSymbol(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol);
+
+public:
+ static std::unique_ptr<PDBSymbol>
+ create(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ virtual ~PDBSymbol();
+
+ /// Dumps the contents of a symbol a raw_ostream. By default this will just
+ /// call dump() on the underlying RawSymbol, which allows us to discover
+ /// unknown properties, but individual implementations of PDBSymbol may
+ /// override the behavior to only dump known fields.
+ virtual void dump(PDBSymDumper &Dumper) const = 0;
+ void defaultDump(raw_ostream &OS, int Indent) const;
+
+ PDB_SymType getSymTag() const;
+
+ template <typename T> std::unique_ptr<T> findOneChild() const {
+ auto Enumerator(findAllChildren<T>());
+ return Enumerator->getNext();
+ }
+
+ template <typename T>
+ std::unique_ptr<ConcreteSymbolEnumerator<T>> findAllChildren() const {
+ auto BaseIter = RawSymbol->findChildren(T::Tag);
+ return llvm::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter));
+ }
+ std::unique_ptr<IPDBEnumSymbols> findAllChildren(PDB_SymType Type) const;
+ std::unique_ptr<IPDBEnumSymbols> findAllChildren() const;
+
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const;
+ std::unique_ptr<IPDBEnumSymbols> findChildrenByRVA(PDB_SymType Type,
+ StringRef Name,
+ PDB_NameSearchFlags Flags,
+ uint32_t RVA) const;
+ std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const;
+
+ const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; }
+ IPDBRawSymbol &getRawSymbol() { return *RawSymbol; }
+
+ const IPDBSession &getSession() const { return Session; }
+
+ std::unique_ptr<IPDBEnumSymbols> getChildStats(TagStats &Stats) const;
+
+protected:
+ const IPDBSession &Session;
+ const std::unique_ptr<IPDBRawSymbol> RawSymbol;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h
new file mode 100644
index 000000000000..c055dd7f3d49
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h
@@ -0,0 +1,39 @@
+//===- PDBSymbolAnnotation.h - Accessors for querying PDB annotations ---*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+#include <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolAnnotation : public PDBSymbol {
+public:
+ PDBSymbolAnnotation(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Annotation)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(getDataKind)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ // FORWARD_SYMBOL_METHOD(getValue)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+};
+}
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
new file mode 100644
index 000000000000..2ca12501d9f6
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
@@ -0,0 +1,41 @@
+//===- PDBSymbolBlock.h - Accessors for querying PDB blocks -------------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+#include <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolBlock : public PDBSymbol {
+public:
+ PDBSymbolBlock(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Block)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getLocationType)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+};
+}
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
new file mode 100644
index 000000000000..f8c796ae5bdc
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
@@ -0,0 +1,38 @@
+//===- PDBSymbolCompiland.h - Accessors for querying PDB compilands -----*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+#include <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolCompiland : public PDBSymbol {
+public:
+ PDBSymbolCompiland(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> CompilandSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Compiland)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getLibraryName)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSourceFileName)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+};
+}
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
new file mode 100644
index 000000000000..7f29d6bde990
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
@@ -0,0 +1,55 @@
+//===- PDBSymbolCompilandDetails.h - PDB compiland details ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolCompilandDetails : public PDBSymbol {
+public:
+ PDBSymbolCompilandDetails(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandDetails)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ void getFrontEndVersion(VersionInfo &Version) const {
+ RawSymbol->getFrontEndVersion(Version);
+ }
+
+ void getBackEndVersion(VersionInfo &Version) const {
+ RawSymbol->getBackEndVersion(Version);
+ }
+
+ FORWARD_SYMBOL_METHOD(getCompilerName)
+ FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled)
+ FORWARD_SYMBOL_METHOD(hasDebugInfo)
+ FORWARD_SYMBOL_METHOD(hasManagedCode)
+ FORWARD_SYMBOL_METHOD(hasSecurityChecks)
+ FORWARD_SYMBOL_METHOD(isCVTCIL)
+ FORWARD_SYMBOL_METHOD(isDataAligned)
+ FORWARD_SYMBOL_METHOD(isHotpatchable)
+ FORWARD_SYMBOL_METHOD(isLTCG)
+ FORWARD_SYMBOL_METHOD(isMSILNetmodule)
+ FORWARD_SYMBOL_METHOD(getLanguage)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getPlatform)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBFUNCTION_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
new file mode 100644
index 000000000000..7e2ea9018edb
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
@@ -0,0 +1,37 @@
+//===- PDBSymbolCompilandEnv.h - compiland environment variables *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolCompilandEnv : public PDBSymbol {
+public:
+ PDBSymbolCompilandEnv(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandEnv)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ std::string getValue() const;
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h
new file mode 100644
index 000000000000..86bfd5707a31
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h
@@ -0,0 +1,39 @@
+//===- PDBSymbolCustom.h - compiler-specific types --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+/// PDBSymbolCustom represents symbols that are compiler-specific and do not
+/// fit anywhere else in the lexical hierarchy.
+/// https://msdn.microsoft.com/en-us/library/d88sf09h.aspx
+class PDBSymbolCustom : public PDBSymbol {
+public:
+ PDBSymbolCustom(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> CustomSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Custom)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes);
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/include/llvm/DebugInfo/PDB/PDBSymbolData.h
new file mode 100644
index 000000000000..79cbbf0e1683
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolData.h
@@ -0,0 +1,61 @@
+//===- PDBSymbolData.h - PDB data (e.g. variable) accessors -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolData : public PDBSymbol {
+public:
+ PDBSymbolData(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> DataSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data)
+
+ std::unique_ptr<PDBSymbol> getType() const;
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAccess)
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(getAddressTaken)
+ FORWARD_SYMBOL_METHOD(getBitPosition)
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(isCompilerGenerated)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(getDataKind)
+ FORWARD_SYMBOL_METHOD(isAggregated)
+ FORWARD_SYMBOL_METHOD(isSplitted)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getLocationType)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getOffset)
+ FORWARD_SYMBOL_METHOD(getRegisterId)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getSlot)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getToken)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(getValue)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
new file mode 100644
index 000000000000..7c5f302ad634
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
@@ -0,0 +1,46 @@
+//===- PDBSymbolExe.h - Accessors for querying executables in a PDB ----*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+#include <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolExe : public PDBSymbol {
+public:
+ PDBSymbolExe(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> ExeSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Exe)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAge)
+ FORWARD_SYMBOL_METHOD(getGuid)
+ FORWARD_SYMBOL_METHOD(hasCTypes)
+ FORWARD_SYMBOL_METHOD(hasPrivateSymbols)
+ FORWARD_SYMBOL_METHOD(getMachineType)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSignature)
+ FORWARD_SYMBOL_METHOD(getSymbolsFileName)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+
+private:
+ void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType,
+ int Indent) const;
+};
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
new file mode 100644
index 000000000000..9db41d53532a
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
@@ -0,0 +1,80 @@
+//===- PDBSymbolFunc.h - class representing a function instance -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolFunc : public PDBSymbol {
+public:
+ PDBSymbolFunc(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> FuncSymbol);
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ std::unique_ptr<PDBSymbolTypeFunctionSig> getSignature() const;
+ std::unique_ptr<PDBSymbolTypeUDT> getClassParent() const;
+ std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> getArguments() const;
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function)
+
+ FORWARD_SYMBOL_METHOD(getAccess)
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(isCompilerGenerated)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(hasCustomCallingConvention)
+ FORWARD_SYMBOL_METHOD(hasFarReturn)
+ FORWARD_SYMBOL_METHOD(hasAlloca)
+ FORWARD_SYMBOL_METHOD(hasEH)
+ FORWARD_SYMBOL_METHOD(hasEHa)
+ FORWARD_SYMBOL_METHOD(hasInlAsm)
+ FORWARD_SYMBOL_METHOD(hasLongJump)
+ FORWARD_SYMBOL_METHOD(hasSEH)
+ FORWARD_SYMBOL_METHOD(hasSecurityChecks)
+ FORWARD_SYMBOL_METHOD(hasSetJump)
+ FORWARD_SYMBOL_METHOD(hasInterruptReturn)
+ FORWARD_SYMBOL_METHOD(isIntroVirtualFunction)
+ FORWARD_SYMBOL_METHOD(hasInlineAttribute)
+ FORWARD_SYMBOL_METHOD(isNaked)
+ FORWARD_SYMBOL_METHOD(isStatic)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getLocalBasePointerRegisterId)
+ FORWARD_SYMBOL_METHOD(getLocationType)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(hasFramePointer)
+ FORWARD_SYMBOL_METHOD(hasNoInlineAttribute)
+ FORWARD_SYMBOL_METHOD(hasNoReturnAttribute)
+ FORWARD_SYMBOL_METHOD(isUnreached)
+ FORWARD_SYMBOL_METHOD(getNoStackOrdering)
+ FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo)
+ FORWARD_SYMBOL_METHOD(isPureVirtual)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getToken)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(getUndecoratedName)
+ FORWARD_SYMBOL_METHOD(isVirtual)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getVirtualBaseOffset)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
new file mode 100644
index 000000000000..34d551cda74c
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
@@ -0,0 +1,49 @@
+//===- PDBSymbolFuncDebugEnd.h - function end bounds info -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolFuncDebugEnd : public PDBSymbol {
+public:
+ PDBSymbolFuncDebugEnd(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> FuncDebugEndSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugEnd)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(hasCustomCallingConvention)
+ FORWARD_SYMBOL_METHOD(hasFarReturn)
+ FORWARD_SYMBOL_METHOD(hasInterruptReturn)
+ FORWARD_SYMBOL_METHOD(isStatic)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getLocationType)
+ FORWARD_SYMBOL_METHOD(hasNoInlineAttribute)
+ FORWARD_SYMBOL_METHOD(hasNoReturnAttribute)
+ FORWARD_SYMBOL_METHOD(isUnreached)
+ FORWARD_SYMBOL_METHOD(getOffset)
+ FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
new file mode 100644
index 000000000000..7671be480dac
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
@@ -0,0 +1,49 @@
+//===- PDBSymbolFuncDebugStart.h - function start bounds info ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolFuncDebugStart : public PDBSymbol {
+public:
+ PDBSymbolFuncDebugStart(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> FuncDebugStartSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugStart)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(hasCustomCallingConvention)
+ FORWARD_SYMBOL_METHOD(hasFarReturn)
+ FORWARD_SYMBOL_METHOD(hasInterruptReturn)
+ FORWARD_SYMBOL_METHOD(isStatic)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getLocationType)
+ FORWARD_SYMBOL_METHOD(hasNoInlineAttribute)
+ FORWARD_SYMBOL_METHOD(hasNoReturnAttribute)
+ FORWARD_SYMBOL_METHOD(isUnreached)
+ FORWARD_SYMBOL_METHOD(getOffset)
+ FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
new file mode 100644
index 000000000000..9d9903a11b0c
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
@@ -0,0 +1,49 @@
+//===- PDBSymbolLabel.h - label info ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolLabel : public PDBSymbol {
+public:
+ PDBSymbolLabel(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> LabelSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Label)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(hasCustomCallingConvention)
+ FORWARD_SYMBOL_METHOD(hasFarReturn)
+ FORWARD_SYMBOL_METHOD(hasInterruptReturn)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getLocationType)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(hasNoInlineAttribute)
+ FORWARD_SYMBOL_METHOD(hasNoReturnAttribute)
+ FORWARD_SYMBOL_METHOD(isUnreached)
+ FORWARD_SYMBOL_METHOD(getOffset)
+ FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
new file mode 100644
index 000000000000..70dfcb5ddf4c
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
@@ -0,0 +1,47 @@
+//===- PDBSymbolPublicSymbol.h - public symbol info -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolPublicSymbol : public PDBSymbol {
+public:
+ PDBSymbolPublicSymbol(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> PublicSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PublicSymbol)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(isCode)
+ FORWARD_SYMBOL_METHOD(isFunction)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getLocationType)
+ FORWARD_SYMBOL_METHOD(isManagedCode)
+ FORWARD_SYMBOL_METHOD(isMSILCode)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getUndecoratedName)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
new file mode 100644
index 000000000000..bd5a9b2aa8b3
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
@@ -0,0 +1,57 @@
+//===- PDBSymbolThunk.h - Support for querying PDB thunks ---------------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+#include <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolThunk : public PDBSymbol {
+public:
+ PDBSymbolThunk(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> ThunkSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Thunk)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAccess)
+ FORWARD_SYMBOL_METHOD(getAddressOffset)
+ FORWARD_SYMBOL_METHOD(getAddressSection)
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(isIntroVirtualFunction)
+ FORWARD_SYMBOL_METHOD(isStatic)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(isPureVirtual)
+ FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTargetOffset)
+ FORWARD_SYMBOL_METHOD(getTargetRelativeVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getTargetVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getTargetSection)
+ FORWARD_SYMBOL_METHOD(getThunkOrdinal)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(isVirtual)
+ FORWARD_SYMBOL_METHOD(getVirtualAddress)
+ FORWARD_SYMBOL_METHOD(getVirtualBaseOffset)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
new file mode 100644
index 000000000000..513a9ec05ff8
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
@@ -0,0 +1,45 @@
+//===- PDBSymbolTypeArray.h - array type information ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeArray : public PDBSymbol {
+public:
+ PDBSymbolTypeArray(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> ArrayTypeSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType)
+
+ std::unique_ptr<PDBSymbol> getElementType() const;
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getArrayIndexTypeId)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(getCount)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getRank)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
new file mode 100644
index 000000000000..2a9a8a0788a8
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
@@ -0,0 +1,60 @@
+//===- PDBSymbolTypeBaseClass.h - base class type information ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeBaseClass : public PDBSymbol {
+public:
+ PDBSymbolTypeBaseClass(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BaseClass)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getAccess)
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(hasConstructor)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(hasAssignmentOperator)
+ FORWARD_SYMBOL_METHOD(hasCastOperator)
+ FORWARD_SYMBOL_METHOD(hasNestedTypes)
+ FORWARD_SYMBOL_METHOD(isIndirectVirtualBaseClass)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(isNested)
+ FORWARD_SYMBOL_METHOD(getOffset)
+ FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
+ FORWARD_SYMBOL_METHOD(isPacked)
+ FORWARD_SYMBOL_METHOD(isScoped)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(getUdtKind)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+
+ FORWARD_SYMBOL_METHOD(isVirtualBaseClass)
+ FORWARD_SYMBOL_METHOD(getVirtualBaseDispIndex)
+ FORWARD_SYMBOL_METHOD(getVirtualBasePointerOffset)
+ // FORWARD_SYMBOL_METHOD(getVirtualBaseTableType)
+ FORWARD_SYMBOL_METHOD(getVirtualTableShapeId)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
new file mode 100644
index 000000000000..69a2028a1b1d
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
@@ -0,0 +1,40 @@
+//===- PDBSymbolTypeBuiltin.h - builtin type information --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeBuiltin : public PDBSymbol {
+public:
+ PDBSymbolTypeBuiltin(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BuiltinType)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getBuiltinType)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h
new file mode 100644
index 000000000000..c41c48933e0d
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h
@@ -0,0 +1,36 @@
+//===- PDBSymbolTypeCustom.h - custom compiler type information -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeCustom : public PDBSymbol {
+public:
+ PDBSymbolTypeCustom(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CustomType)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getOemId)
+ FORWARD_SYMBOL_METHOD(getOemSymbolId)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h
new file mode 100644
index 000000000000..3f22ed8d731e
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h
@@ -0,0 +1,36 @@
+//===- PDBSymbolTypeDimension.h - array dimension type info -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeDimension : public PDBSymbol {
+public:
+ PDBSymbolTypeDimension(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Dimension)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getLowerBoundId)
+ FORWARD_SYMBOL_METHOD(getUpperBoundId)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
new file mode 100644
index 000000000000..3188c711915c
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
@@ -0,0 +1,55 @@
+//===- PDBSymbolTypeEnum.h - enum type info ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeEnum : public PDBSymbol {
+public:
+ PDBSymbolTypeEnum(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> EnumTypeSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Enum)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ std::unique_ptr<PDBSymbolTypeUDT> getClassParent() const;
+ std::unique_ptr<PDBSymbolTypeBuiltin> getUnderlyingType() const;
+
+ FORWARD_SYMBOL_METHOD(getBuiltinType)
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId)
+ FORWARD_SYMBOL_METHOD(hasConstructor)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(hasAssignmentOperator)
+ FORWARD_SYMBOL_METHOD(hasCastOperator)
+ FORWARD_SYMBOL_METHOD(hasNestedTypes)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(isNested)
+ FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
+ FORWARD_SYMBOL_METHOD(isPacked)
+ FORWARD_SYMBOL_METHOD(isScoped)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
new file mode 100644
index 000000000000..4d393d7b6c5c
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
@@ -0,0 +1,37 @@
+//===- PDBSymbolTypeFriend.h - friend type info -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeFriend : public PDBSymbol {
+public:
+ PDBSymbolTypeFriend(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Friend)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
new file mode 100644
index 000000000000..14f79d99b6f8
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
@@ -0,0 +1,37 @@
+//===- PDBSymbolTypeFunctionArg.h - function arg type info ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeFunctionArg : public PDBSymbol {
+public:
+ PDBSymbolTypeFunctionArg(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionArg)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
new file mode 100644
index 000000000000..4bb4265a22f6
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
@@ -0,0 +1,50 @@
+//===- PDBSymbolTypeFunctionSig.h - function signature type info *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeFunctionSig : public PDBSymbol {
+public:
+ PDBSymbolTypeFunctionSig(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig)
+
+ std::unique_ptr<PDBSymbol> getReturnType() const;
+ std::unique_ptr<IPDBEnumSymbols> getArguments() const;
+ std::unique_ptr<PDBSymbol> getClassParent() const;
+
+ void dump(PDBSymDumper &Dumper) const override;
+ void dumpArgList(raw_ostream &OS) const;
+
+ FORWARD_SYMBOL_METHOD(getCallingConvention)
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(getCount)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ // FORWARD_SYMBOL_METHOD(getObjectPointerType)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getThisAdjust)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h
new file mode 100644
index 000000000000..cbfcec82a637
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h
@@ -0,0 +1,35 @@
+//===- PDBSymbolTypeManaged.h - managed type info ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeManaged : public PDBSymbol {
+public:
+ PDBSymbolTypeManaged(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ManagedType)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
new file mode 100644
index 000000000000..33578bad0245
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
@@ -0,0 +1,43 @@
+//===- PDBSymbolTypePointer.h - pointer type info ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypePointer : public PDBSymbol {
+public:
+ PDBSymbolTypePointer(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType)
+
+ std::unique_ptr<PDBSymbol> getPointeeType() const;
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(isReference)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
new file mode 100644
index 000000000000..5ad83bb1ec26
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
@@ -0,0 +1,54 @@
+//===- PDBSymbolTypeTypedef.h - typedef type info ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeTypedef : public PDBSymbol {
+public:
+ PDBSymbolTypeTypedef(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Typedef)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getBuiltinType)
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(hasConstructor)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(hasAssignmentOperator)
+ FORWARD_SYMBOL_METHOD(hasCastOperator)
+ FORWARD_SYMBOL_METHOD(hasNestedTypes)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(isNested)
+ FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
+ FORWARD_SYMBOL_METHOD(isPacked)
+ FORWARD_SYMBOL_METHOD(isReference)
+ FORWARD_SYMBOL_METHOD(isScoped)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(getUdtKind)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(getVirtualTableShapeId)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
new file mode 100644
index 000000000000..99cc307a83e3
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
@@ -0,0 +1,52 @@
+//===- PDBSymbolTypeUDT.h - UDT type info -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeUDT : public PDBSymbol {
+public:
+ PDBSymbolTypeUDT(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> UDTSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId)
+ FORWARD_SYMBOL_METHOD(hasConstructor)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(hasAssignmentOperator)
+ FORWARD_SYMBOL_METHOD(hasCastOperator)
+ FORWARD_SYMBOL_METHOD(hasNestedTypes)
+ FORWARD_SYMBOL_METHOD(getLength)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(isNested)
+ FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
+ FORWARD_SYMBOL_METHOD(isPacked)
+ FORWARD_SYMBOL_METHOD(isScoped)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getUdtKind)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(getVirtualTableShapeId)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
new file mode 100644
index 000000000000..6efc549f0cb7
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
@@ -0,0 +1,40 @@
+//===- PDBSymbolTypeVTable.h - VTable type info -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeVTable : public PDBSymbol {
+public:
+ PDBSymbolTypeVTable(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> VtblSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTable)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
new file mode 100644
index 000000000000..f407595a4cc8
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
@@ -0,0 +1,39 @@
+//===- PDBSymbolTypeVTableShape.h - VTable shape info -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolTypeVTableShape : public PDBSymbol {
+public:
+ PDBSymbolTypeVTableShape(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> VtblShapeSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTableShape)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(isConstType)
+ FORWARD_SYMBOL_METHOD(getCount)
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+ FORWARD_SYMBOL_METHOD(isUnalignedType)
+ FORWARD_SYMBOL_METHOD(isVolatileType)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h
new file mode 100644
index 000000000000..94bd2c14079f
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h
@@ -0,0 +1,34 @@
+//===- PDBSymbolUnknown.h - unknown symbol type -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H
+
+#include "PDBSymbol.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolUnknown : public PDBSymbol {
+public:
+ PDBSymbolUnknown(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> UnknownSymbol);
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ static bool classof(const PDBSymbol *S) {
+ return (S->getSymTag() == PDB_SymType::None ||
+ S->getSymTag() >= PDB_SymType::Max);
+ }
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
new file mode 100644
index 000000000000..7072f342bef3
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
@@ -0,0 +1,36 @@
+//===- PDBSymbolUsingNamespace.h - using namespace info ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolUsingNamespace : public PDBSymbol {
+public:
+ PDBSymbolUsingNamespace(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UsingNamespace)
+
+ void dump(PDBSymDumper &Dumper) const override;
+
+ FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_METHOD(getName)
+ FORWARD_SYMBOL_METHOD(getSymIndexId)
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H
diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h
new file mode 100644
index 000000000000..2d19e792d3d0
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/PDBTypes.h
@@ -0,0 +1,516 @@
+//===- PDBTypes.h - Defines enums for various fields contained in PDB ---*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_PDBTYPES_H
+#define LLVM_DEBUGINFO_PDB_PDBTYPES_H
+
+#include "llvm/Config/llvm-config.h"
+#include <functional>
+#include <stdint.h>
+
+namespace llvm {
+
+class PDBSymDumper;
+class PDBSymbol;
+
+class IPDBDataStream;
+template <class T> class IPDBEnumChildren;
+class IPDBLineNumber;
+class IPDBRawSymbol;
+class IPDBSession;
+class IPDBSourceFile;
+
+typedef IPDBEnumChildren<PDBSymbol> IPDBEnumSymbols;
+typedef IPDBEnumChildren<IPDBSourceFile> IPDBEnumSourceFiles;
+typedef IPDBEnumChildren<IPDBDataStream> IPDBEnumDataStreams;
+typedef IPDBEnumChildren<IPDBLineNumber> IPDBEnumLineNumbers;
+
+class PDBSymbolExe;
+class PDBSymbolCompiland;
+class PDBSymbolCompilandDetails;
+class PDBSymbolCompilandEnv;
+class PDBSymbolFunc;
+class PDBSymbolBlock;
+class PDBSymbolData;
+class PDBSymbolAnnotation;
+class PDBSymbolLabel;
+class PDBSymbolPublicSymbol;
+class PDBSymbolTypeUDT;
+class PDBSymbolTypeEnum;
+class PDBSymbolTypeFunctionSig;
+class PDBSymbolTypePointer;
+class PDBSymbolTypeArray;
+class PDBSymbolTypeBuiltin;
+class PDBSymbolTypeTypedef;
+class PDBSymbolTypeBaseClass;
+class PDBSymbolTypeFriend;
+class PDBSymbolTypeFunctionArg;
+class PDBSymbolFuncDebugStart;
+class PDBSymbolFuncDebugEnd;
+class PDBSymbolUsingNamespace;
+class PDBSymbolTypeVTableShape;
+class PDBSymbolTypeVTable;
+class PDBSymbolCustom;
+class PDBSymbolThunk;
+class PDBSymbolTypeCustom;
+class PDBSymbolTypeManaged;
+class PDBSymbolTypeDimension;
+class PDBSymbolUnknown;
+
+/// Specifies which PDB reader implementation is to be used. Only a value
+/// of PDB_ReaderType::DIA is supported.
+enum class PDB_ReaderType {
+ DIA = 0,
+};
+
+/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but
+/// is abstracted here for the purposes of non-Windows platforms that don't have
+/// the GUID structure defined.
+struct PDB_UniqueId {
+ uint64_t HighPart;
+ uint64_t LowPart;
+};
+
+/// An enumeration indicating the type of data contained in this table.
+enum class PDB_TableType {
+ Symbols,
+ SourceFiles,
+ LineNumbers,
+ SectionContribs,
+ Segments,
+ InjectedSources,
+ FrameData
+};
+
+/// Defines flags used for enumerating child symbols. This corresponds to the
+/// NameSearchOptions enumeration which is documented here:
+/// https://msdn.microsoft.com/en-us/library/yat28ads.aspx
+enum PDB_NameSearchFlags {
+ NS_Default = 0x0,
+ NS_CaseSensitive = 0x1,
+ NS_CaseInsensitive = 0x2,
+ NS_FileNameExtMatch = 0x4,
+ NS_Regex = 0x8,
+ NS_UndecoratedName = 0x10
+};
+
+/// Specifies the hash algorithm that a source file from a PDB was hashed with.
+/// This corresponds to the CV_SourceChksum_t enumeration and are documented
+/// here: https://msdn.microsoft.com/en-us/library/e96az21x.aspx
+enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2 };
+
+/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
+enum class PDB_Cpu {
+ Intel8080 = 0x0,
+ Intel8086 = 0x1,
+ Intel80286 = 0x2,
+ Intel80386 = 0x3,
+ Intel80486 = 0x4,
+ Pentium = 0x5,
+ PentiumPro = 0x6,
+ Pentium3 = 0x7,
+ MIPS = 0x10,
+ MIPS16 = 0x11,
+ MIPS32 = 0x12,
+ MIPS64 = 0x13,
+ MIPSI = 0x14,
+ MIPSII = 0x15,
+ MIPSIII = 0x16,
+ MIPSIV = 0x17,
+ MIPSV = 0x18,
+ M68000 = 0x20,
+ M68010 = 0x21,
+ M68020 = 0x22,
+ M68030 = 0x23,
+ M68040 = 0x24,
+ Alpha = 0x30,
+ Alpha21164 = 0x31,
+ Alpha21164A = 0x32,
+ Alpha21264 = 0x33,
+ Alpha21364 = 0x34,
+ PPC601 = 0x40,
+ PPC603 = 0x41,
+ PPC604 = 0x42,
+ PPC620 = 0x43,
+ PPCFP = 0x44,
+ PPCBE = 0x45,
+ SH3 = 0x50,
+ SH3E = 0x51,
+ SH3DSP = 0x52,
+ SH4 = 0x53,
+ SHMedia = 0x54,
+ ARM3 = 0x60,
+ ARM4 = 0x61,
+ ARM4T = 0x62,
+ ARM5 = 0x63,
+ ARM5T = 0x64,
+ ARM6 = 0x65,
+ ARM_XMAC = 0x66,
+ ARM_WMMX = 0x67,
+ ARM7 = 0x68,
+ Omni = 0x70,
+ Ia64 = 0x80,
+ Ia64_2 = 0x81,
+ CEE = 0x90,
+ AM33 = 0xa0,
+ M32R = 0xb0,
+ TriCore = 0xc0,
+ X64 = 0xd0,
+ EBC = 0xe0,
+ Thumb = 0xf0,
+ ARMNT = 0xf4,
+ D3D11_Shader = 0x100,
+};
+
+enum class PDB_Machine {
+ Invalid = 0xffff,
+ Unknown = 0x0,
+ Am33 = 0x13,
+ Amd64 = 0x8664,
+ Arm = 0x1C0,
+ ArmNT = 0x1C4,
+ Ebc = 0xEBC,
+ x86 = 0x14C,
+ Ia64 = 0x200,
+ M32R = 0x9041,
+ Mips16 = 0x266,
+ MipsFpu = 0x366,
+ MipsFpu16 = 0x466,
+ PowerPC = 0x1F0,
+ PowerPCFP = 0x1F1,
+ R4000 = 0x166,
+ SH3 = 0x1A2,
+ SH3DSP = 0x1A3,
+ SH4 = 0x1A6,
+ SH5 = 0x1A8,
+ Thumb = 0x1C2,
+ WceMipsV2 = 0x169
+};
+
+/// These values correspond to the CV_call_e enumeration, and are documented
+/// at the following locations:
+/// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx
+/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680207(v=vs.85).aspx
+///
+enum class PDB_CallingConv {
+ NearCdecl = 0x00,
+ FarCdecl = 0x01,
+ NearPascal = 0x02,
+ FarPascal = 0x03,
+ NearFastcall = 0x04,
+ FarFastcall = 0x05,
+ Skipped = 0x06,
+ NearStdcall = 0x07,
+ FarStdcall = 0x08,
+ NearSyscall = 0x09,
+ FarSyscall = 0x0a,
+ Thiscall = 0x0b,
+ MipsCall = 0x0c,
+ Generic = 0x0d,
+ Alphacall = 0x0e,
+ Ppccall = 0x0f,
+ SuperHCall = 0x10,
+ Armcall = 0x11,
+ AM33call = 0x12,
+ Tricall = 0x13,
+ Sh5call = 0x14,
+ M32R = 0x15,
+ Clrcall = 0x16,
+ Inline = 0x17,
+ NearVectorcall = 0x18,
+ Reserved = 0x19,
+};
+
+/// These values correspond to the CV_CFL_LANG enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx
+enum class PDB_Lang {
+ C = 0x00,
+ Cpp = 0x01,
+ Fortran = 0x02,
+ Masm = 0x03,
+ Pascal = 0x04,
+ Basic = 0x05,
+ Cobol = 0x06,
+ Link = 0x07,
+ Cvtres = 0x08,
+ Cvtpgd = 0x09,
+ CSharp = 0x0a,
+ VB = 0x0b,
+ ILAsm = 0x0c,
+ Java = 0x0d,
+ JScript = 0x0e,
+ MSIL = 0x0f,
+ HLSL = 0x10
+};
+
+/// These values correspond to the DataKind enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/b2x2t313.aspx
+enum class PDB_DataKind {
+ Unknown,
+ Local,
+ StaticLocal,
+ Param,
+ ObjectPtr,
+ FileStatic,
+ Global,
+ Member,
+ StaticMember,
+ Constant
+};
+
+/// These values correspond to the SymTagEnum enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/bkedss5f.aspx
+enum class PDB_SymType {
+ None,
+ Exe,
+ Compiland,
+ CompilandDetails,
+ CompilandEnv,
+ Function,
+ Block,
+ Data,
+ Annotation,
+ Label,
+ PublicSymbol,
+ UDT,
+ Enum,
+ FunctionSig,
+ PointerType,
+ ArrayType,
+ BuiltinType,
+ Typedef,
+ BaseClass,
+ Friend,
+ FunctionArg,
+ FuncDebugStart,
+ FuncDebugEnd,
+ UsingNamespace,
+ VTableShape,
+ VTable,
+ Custom,
+ Thunk,
+ CustomType,
+ ManagedType,
+ Dimension,
+ Max
+};
+
+/// These values correspond to the LocationType enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/f57kaez3.aspx
+enum class PDB_LocType {
+ Null,
+ Static,
+ TLS,
+ RegRel,
+ ThisRel,
+ Enregistered,
+ BitField,
+ Slot,
+ IlRel,
+ MetaData,
+ Constant,
+ Max
+};
+
+/// These values correspond to the THUNK_ORDINAL enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/dh0k8hft.aspx
+enum class PDB_ThunkOrdinal {
+ Standard,
+ ThisAdjustor,
+ Vcall,
+ Pcode,
+ UnknownLoad,
+ TrampIncremental,
+ BranchIsland
+};
+
+/// These values correspond to the UdtKind enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/wcstk66t.aspx
+enum class PDB_UdtType { Struct, Class, Union, Interface };
+
+/// These values correspond to the StackFrameTypeEnum enumeration, and are
+/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx.
+enum class PDB_StackFrameType { FPO, KernelTrap, KernelTSS, EBP, FrameData };
+
+/// These values correspond to the StackFrameTypeEnum enumeration, and are
+/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx.
+enum class PDB_MemoryType { Code, Data, Stack, HeapCode };
+
+/// These values correspond to the Basictype enumeration, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx
+enum class PDB_BuiltinType {
+ None = 0,
+ Void = 1,
+ Char = 2,
+ WCharT = 3,
+ Int = 6,
+ UInt = 7,
+ Float = 8,
+ BCD = 9,
+ Bool = 10,
+ Long = 13,
+ ULong = 14,
+ Currency = 25,
+ Date = 26,
+ Variant = 27,
+ Complex = 28,
+ Bitfield = 29,
+ BSTR = 30,
+ HResult = 31
+};
+
+enum class PDB_RegisterId {
+ Unknown = 0,
+ VFrame = 30006,
+ AL = 1,
+ CL = 2,
+ DL = 3,
+ BL = 4,
+ AH = 5,
+ CH = 6,
+ DH = 7,
+ BH = 8,
+ AX = 9,
+ CX = 10,
+ DX = 11,
+ BX = 12,
+ SP = 13,
+ BP = 14,
+ SI = 15,
+ DI = 16,
+ EAX = 17,
+ ECX = 18,
+ EDX = 19,
+ EBX = 20,
+ ESP = 21,
+ EBP = 22,
+ ESI = 23,
+ EDI = 24,
+ ES = 25,
+ CS = 26,
+ SS = 27,
+ DS = 28,
+ FS = 29,
+ GS = 30,
+ IP = 31,
+ RAX = 328,
+ RBX = 329,
+ RCX = 330,
+ RDX = 331,
+ RSI = 332,
+ RDI = 333,
+ RBP = 334,
+ RSP = 335,
+ R8 = 336,
+ R9 = 337,
+ R10 = 338,
+ R11 = 339,
+ R12 = 340,
+ R13 = 341,
+ R14 = 342,
+ R15 = 343,
+};
+
+enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 };
+
+enum class PDB_ErrorCode {
+ Success,
+ NoPdbImpl,
+ InvalidPath,
+ InvalidFileFormat,
+ InvalidParameter,
+ AlreadyLoaded,
+ UnknownError,
+ NoMemory,
+ DebugInfoMismatch
+};
+
+struct VersionInfo {
+ uint32_t Major;
+ uint32_t Minor;
+ uint32_t Build;
+ uint32_t QFE;
+};
+
+enum PDB_VariantType {
+ Empty,
+ Unknown,
+ Int8,
+ Int16,
+ Int32,
+ Int64,
+ Single,
+ Double,
+ UInt8,
+ UInt16,
+ UInt32,
+ UInt64,
+ Bool,
+};
+
+struct Variant {
+ Variant()
+ : Type(PDB_VariantType::Empty) {
+ }
+
+ PDB_VariantType Type;
+ union {
+ bool Bool;
+ int8_t Int8;
+ int16_t Int16;
+ int32_t Int32;
+ int64_t Int64;
+ float Single;
+ double Double;
+ uint8_t UInt8;
+ uint16_t UInt16;
+ uint32_t UInt32;
+ uint64_t UInt64;
+ };
+#define VARIANT_EQUAL_CASE(Enum) \
+ case PDB_VariantType::Enum: \
+ return Enum == Other.Enum;
+ bool operator==(const Variant &Other) const {
+ if (Type != Other.Type)
+ return false;
+ switch (Type) {
+ VARIANT_EQUAL_CASE(Bool)
+ VARIANT_EQUAL_CASE(Int8)
+ VARIANT_EQUAL_CASE(Int16)
+ VARIANT_EQUAL_CASE(Int32)
+ VARIANT_EQUAL_CASE(Int64)
+ VARIANT_EQUAL_CASE(Single)
+ VARIANT_EQUAL_CASE(Double)
+ VARIANT_EQUAL_CASE(UInt8)
+ VARIANT_EQUAL_CASE(UInt16)
+ VARIANT_EQUAL_CASE(UInt32)
+ VARIANT_EQUAL_CASE(UInt64)
+ default:
+ return true;
+ }
+ }
+#undef VARIANT_EQUAL_CASE
+ bool operator!=(const Variant &Other) const { return !(*this == Other); }
+};
+
+} // namespace llvm
+
+namespace std {
+template <> struct hash<llvm::PDB_SymType> {
+ typedef llvm::PDB_SymType argument_type;
+ typedef std::size_t result_type;
+
+ result_type operator()(const argument_type &Arg) const {
+ return std::hash<int>()(static_cast<int>(Arg));
+ }
+};
+}
+
+#endif
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index d79bd3c4dfc8..4b2add8bf5df 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -15,6 +15,7 @@
#ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H
#define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H
+#include "RuntimeDyld.h"
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -42,6 +43,7 @@ class GlobalVariable;
class GlobalValue;
class JITEventListener;
class MachineCodeInfo;
+class MCJITMemoryManager;
class MutexGuard;
class ObjectCache;
class RTDyldMemoryManager;
@@ -57,46 +59,34 @@ namespace object {
/// table. Access to this class should be serialized under a mutex.
class ExecutionEngineState {
public:
- struct AddressMapConfig : public ValueMapConfig<const GlobalValue*> {
- typedef ExecutionEngineState *ExtraData;
- static sys::Mutex *getMutex(ExecutionEngineState *EES);
- static void onDelete(ExecutionEngineState *EES, const GlobalValue *Old);
- static void onRAUW(ExecutionEngineState *, const GlobalValue *,
- const GlobalValue *);
- };
-
- typedef ValueMap<const GlobalValue *, void *, AddressMapConfig>
- GlobalAddressMapTy;
+ typedef StringMap<uint64_t> GlobalAddressMapTy;
private:
- ExecutionEngine &EE;
- /// GlobalAddressMap - A mapping between LLVM global values and their
- /// actualized version...
+ /// GlobalAddressMap - A mapping between LLVM global symbol names values and
+ /// their actualized version...
GlobalAddressMapTy GlobalAddressMap;
/// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap,
/// used to convert raw addresses into the LLVM global value that is emitted
/// at the address. This map is not computed unless getGlobalValueAtAddress
/// is called at some point.
- std::map<void *, AssertingVH<const GlobalValue> > GlobalAddressReverseMap;
+ std::map<uint64_t, std::string> GlobalAddressReverseMap;
public:
- ExecutionEngineState(ExecutionEngine &EE);
GlobalAddressMapTy &getGlobalAddressMap() {
return GlobalAddressMap;
}
- std::map<void*, AssertingVH<const GlobalValue> > &
- getGlobalAddressReverseMap() {
+ std::map<uint64_t, std::string> &getGlobalAddressReverseMap() {
return GlobalAddressReverseMap;
}
/// \brief Erase an entry from the mapping table.
///
/// \returns The address that \p ToUnmap was happed to.
- void *RemoveMapping(const GlobalValue *ToUnmap);
+ uint64_t RemoveMapping(StringRef Name);
};
/// \brief Abstract interface for implementation execution of LLVM modules,
@@ -139,10 +129,18 @@ protected:
virtual char *getMemoryForGV(const GlobalVariable *GV);
static ExecutionEngine *(*MCJITCtor)(
- std::unique_ptr<Module> M,
- std::string *ErrorStr,
- std::unique_ptr<RTDyldMemoryManager> MCJMM,
- std::unique_ptr<TargetMachine> TM);
+ std::unique_ptr<Module> M,
+ std::string *ErrorStr,
+ std::shared_ptr<MCJITMemoryManager> MM,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> SR,
+ std::unique_ptr<TargetMachine> TM);
+
+ static ExecutionEngine *(*OrcMCJITReplacementCtor)(
+ std::string *ErrorStr,
+ std::shared_ptr<MCJITMemoryManager> MM,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> SR,
+ std::unique_ptr<TargetMachine> TM);
+
static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr);
@@ -151,6 +149,9 @@ protected:
/// abort.
void *(*LazyFunctionCreator)(const std::string &);
+ /// getMangledName - Get mangled name.
+ std::string getMangledName(const GlobalValue *GV);
+
public:
/// lock - This lock protects the ExecutionEngine and MCJIT classes. It must
/// be held while changing the internal state of any of those classes.
@@ -222,7 +223,8 @@ public:
/// Map the address of a JIT section as returned from the memory manager
/// to the address in the target process as the running code will see it.
/// This is the address which will be used for relocation resolution.
- virtual void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) {
+ virtual void mapSectionAddress(const void *LocalAddress,
+ uint64_t TargetAddress) {
llvm_unreachable("Re-mapping of section addresses not supported with this "
"EE!");
}
@@ -280,6 +282,7 @@ public:
/// existing data in memory. Mappings are automatically removed when their
/// GlobalValue is destroyed.
void addGlobalMapping(const GlobalValue *GV, void *Addr);
+ void addGlobalMapping(StringRef Name, uint64_t Addr);
/// clearAllGlobalMappings - Clear all global mappings and start over again,
/// for use in dynamic compilation scenarios to move globals.
@@ -293,14 +296,17 @@ public:
/// address. This updates both maps as required. If "Addr" is null, the
/// entry for the global is removed from the mappings. This returns the old
/// value of the pointer, or null if it was not in the map.
- void *updateGlobalMapping(const GlobalValue *GV, void *Addr);
+ uint64_t updateGlobalMapping(const GlobalValue *GV, void *Addr);
+ uint64_t updateGlobalMapping(StringRef Name, uint64_t Addr);
+
+ /// getAddressToGlobalIfAvailable - This returns the address of the specified
+ /// global symbol.
+ uint64_t getAddressToGlobalIfAvailable(StringRef S);
/// getPointerToGlobalIfAvailable - This returns the address of the specified
/// global value if it is has already been codegen'd, otherwise it returns
/// null.
- ///
- /// This function is deprecated for the MCJIT execution engine. It doesn't
- /// seem to be needed in that case, but an equivalent can be added if it is.
+ void *getPointerToGlobalIfAvailable(StringRef S);
void *getPointerToGlobalIfAvailable(const GlobalValue *GV);
/// getPointerToGlobal - This returns the address of the specified global
@@ -464,6 +470,7 @@ public:
}
protected:
+ ExecutionEngine() {}
explicit ExecutionEngine(std::unique_ptr<Module> M);
void emitGlobals();
@@ -493,7 +500,8 @@ private:
EngineKind::Kind WhichEngine;
std::string *ErrorStr;
CodeGenOpt::Level OptLevel;
- std::unique_ptr<RTDyldMemoryManager> MCJMM;
+ std::shared_ptr<MCJITMemoryManager> MemMgr;
+ std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver;
TargetOptions Options;
Reloc::Model RelocModel;
CodeModel::Model CMModel;
@@ -501,11 +509,12 @@ private:
std::string MCPU;
SmallVector<std::string, 4> MAttrs;
bool VerifyModules;
-
- /// InitEngine - Does the common initialization of default options.
- void InitEngine();
+ bool UseOrcMCJITReplacement;
public:
+ /// Default constructor for EngineBuilder.
+ EngineBuilder();
+
/// Constructor for EngineBuilder.
EngineBuilder(std::unique_ptr<Module> M);
@@ -527,6 +536,12 @@ public:
/// memory manager. This option defaults to NULL.
EngineBuilder &setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
+ EngineBuilder&
+ setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
+
+ EngineBuilder&
+ setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
+
/// setErrorStr - Set the error string to write to on error. This option
/// defaults to NULL.
EngineBuilder &setErrorStr(std::string *e) {
@@ -590,6 +605,11 @@ public:
return *this;
}
+ // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default.
+ void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) {
+ this->UseOrcMCJITReplacement = UseOrcMCJITReplacement;
+ }
+
TargetMachine *selectTarget();
/// selectTarget - Pick a target either via -march or by guessing the native
diff --git a/include/llvm/ExecutionEngine/JITSymbolFlags.h b/include/llvm/ExecutionEngine/JITSymbolFlags.h
new file mode 100644
index 000000000000..450e9481fa00
--- /dev/null
+++ b/include/llvm/ExecutionEngine/JITSymbolFlags.h
@@ -0,0 +1,81 @@
+//===------ JITSymbolFlags.h - Flags for symbols in the JIT -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Symbol flags for symbols in the JIT (e.g. weak, exported).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITSYMBOLFLAGS_H
+#define LLVM_EXECUTIONENGINE_JITSYMBOLFLAGS_H
+
+#include "llvm/IR/GlobalValue.h"
+
+namespace llvm {
+
+/// @brief Flags for symbols in the JIT.
+enum class JITSymbolFlags : char {
+ None = 0,
+ Weak = 1U << 0,
+ Exported = 1U << 1
+};
+
+inline JITSymbolFlags operator|(JITSymbolFlags LHS, JITSymbolFlags RHS) {
+ typedef std::underlying_type<JITSymbolFlags>::type UT;
+ return static_cast<JITSymbolFlags>(
+ static_cast<UT>(LHS) | static_cast<UT>(RHS));
+}
+
+inline JITSymbolFlags& operator |=(JITSymbolFlags &LHS, JITSymbolFlags RHS) {
+ LHS = LHS | RHS;
+ return LHS;
+}
+
+inline JITSymbolFlags operator&(JITSymbolFlags LHS, JITSymbolFlags RHS) {
+ typedef std::underlying_type<JITSymbolFlags>::type UT;
+ return static_cast<JITSymbolFlags>(
+ static_cast<UT>(LHS) & static_cast<UT>(RHS));
+}
+
+inline JITSymbolFlags& operator &=(JITSymbolFlags &LHS, JITSymbolFlags RHS) {
+ LHS = LHS & RHS;
+ return LHS;
+}
+
+/// @brief Base class for symbols in the JIT.
+class JITSymbolBase {
+public:
+ JITSymbolBase(JITSymbolFlags Flags) : Flags(Flags) {}
+
+ JITSymbolFlags getFlags() const { return Flags; }
+
+ bool isWeak() const {
+ return (Flags & JITSymbolFlags::Weak) == JITSymbolFlags::Weak;
+ }
+
+ bool isExported() const {
+ return (Flags & JITSymbolFlags::Exported) == JITSymbolFlags::Exported;
+ }
+
+ static JITSymbolFlags flagsFromGlobalValue(const GlobalValue &GV) {
+ JITSymbolFlags Flags = JITSymbolFlags::None;
+ if (GV.hasWeakLinkage())
+ Flags |= JITSymbolFlags::Weak;
+ if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())
+ Flags |= JITSymbolFlags::Exported;
+ return Flags;
+
+ }
+
+private:
+ JITSymbolFlags Flags;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h b/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h
new file mode 100644
index 000000000000..b07561152ec0
--- /dev/null
+++ b/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h
@@ -0,0 +1,63 @@
+//===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a wrapper class to hold the memory into which an
+// object will be generated.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
+#define LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+/// \brief SmallVector-backed MemoryBuffer instance.
+///
+/// This class enables efficient construction of MemoryBuffers from SmallVector
+/// instances. This is useful for MCJIT and Orc, where object files are streamed
+/// into SmallVectors, then inspected using ObjectFile (which takes a
+/// MemoryBuffer).
+class ObjectMemoryBuffer : public MemoryBuffer {
+public:
+
+ /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value.
+ ///
+ /// FIXME: It'd be nice for this to be a non-templated constructor taking a
+ /// SmallVectorImpl here instead of a templated one taking a SmallVector<N>,
+ /// but SmallVector's move-construction/assignment currently only take
+ /// SmallVectors. If/when that is fixed we can simplify this constructor and
+ /// the following one.
+ ObjectMemoryBuffer(SmallVectorImpl<char> &&SV)
+ : SV(std::move(SV)), BufferName("<in-memory object>") {
+ init(this->SV.begin(), this->SV.end(), false);
+ }
+
+ /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector
+ /// r-value and StringRef.
+ ObjectMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name)
+ : SV(std::move(SV)), BufferName(Name) {
+ init(this->SV.begin(), this->SV.end(), false);
+ }
+
+ const char* getBufferIdentifier() const override { return BufferName.c_str(); }
+
+ BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
+
+private:
+ SmallVector<char, 0> SV;
+ std::string BufferName;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
new file mode 100644
index 000000000000..719adbc562c2
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -0,0 +1,547 @@
+//===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// JIT layer for breaking up modules and inserting callbacks to allow
+// individual functions to be compiled on demand.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
+
+//#include "CloneSubModule.h"
+#include "IndirectionUtils.h"
+#include "LambdaResolver.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include <list>
+#include <set>
+
+#include "llvm/Support/Debug.h"
+
+namespace llvm {
+namespace orc {
+
+/// @brief Compile-on-demand layer.
+///
+/// When a module is added to this layer a stub is created for each of its
+/// function definitions. The stubs and other global values are immediately
+/// added to the layer below. When a stub is called it triggers the extraction
+/// of the function body from the original module. The extracted body is then
+/// compiled and executed.
+template <typename BaseLayerT, typename CompileCallbackMgrT>
+class CompileOnDemandLayer {
+private:
+
+ // Utility class for MapValue. Only materializes declarations for global
+ // variables.
+ class GlobalDeclMaterializer : public ValueMaterializer {
+ public:
+ GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {}
+ Value* materializeValueFor(Value *V) final {
+ if (auto *GV = dyn_cast<GlobalVariable>(V))
+ return cloneGlobalVariableDecl(Dst, *GV);
+ else if (auto *F = dyn_cast<Function>(V))
+ return cloneFunctionDecl(Dst, *F);
+ // Else.
+ return nullptr;
+ }
+ private:
+ Module &Dst;
+ };
+
+ typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
+ class UncompiledPartition;
+
+ // Logical module.
+ //
+ // This struct contains the handles for the global values and stubs (which
+ // cover the external symbols of the original module), plus the handes for
+ // each of the extracted partitions. These handleds are used for lookup (only
+ // the globals/stubs module is searched) and memory management. The actual
+ // searching and resource management are handled by the LogicalDylib that owns
+ // the LogicalModule.
+ struct LogicalModule {
+ LogicalModule() {}
+
+ LogicalModule(LogicalModule &&Other)
+ : SrcM(std::move(Other.SrcM)),
+ GVsAndStubsHandle(std::move(Other.GVsAndStubsHandle)),
+ ImplHandles(std::move(Other.ImplHandles)) {}
+
+ std::unique_ptr<Module> SrcM;
+ BaseLayerModuleSetHandleT GVsAndStubsHandle;
+ std::vector<BaseLayerModuleSetHandleT> ImplHandles;
+ };
+
+ // Logical dylib.
+ //
+ // This class handles symbol resolution and resource management for a set of
+ // modules that were added together as a logical dylib.
+ //
+ // A logical dylib contains one-or-more LogicalModules plus a set of
+ // UncompiledPartitions. LogicalModules support symbol resolution and resource
+ // management for for code that has already been emitted. UncompiledPartitions
+ // represent code that has not yet been compiled.
+ class LogicalDylib {
+ private:
+ friend class UncompiledPartition;
+ typedef std::list<LogicalModule> LogicalModuleList;
+ public:
+
+ typedef unsigned UncompiledPartitionID;
+ typedef typename LogicalModuleList::iterator LMHandle;
+
+ // Construct a logical dylib.
+ LogicalDylib(CompileOnDemandLayer &CODLayer) : CODLayer(CODLayer) { }
+
+ // Delete this logical dylib, release logical module resources.
+ virtual ~LogicalDylib() {
+ releaseLogicalModuleResources();
+ }
+
+ // Get a reference to the containing layer.
+ CompileOnDemandLayer& getCODLayer() { return CODLayer; }
+
+ // Get a reference to the base layer.
+ BaseLayerT& getBaseLayer() { return CODLayer.BaseLayer; }
+
+ // Start a new context for a single logical module.
+ LMHandle createLogicalModule() {
+ LogicalModules.push_back(LogicalModule());
+ return std::prev(LogicalModules.end());
+ }
+
+ // Set the global-values-and-stubs module handle for this logical module.
+ void setGVsAndStubsHandle(LMHandle LMH, BaseLayerModuleSetHandleT H) {
+ LMH->GVsAndStubsHandle = H;
+ }
+
+ // Return the global-values-and-stubs module handle for this logical module.
+ BaseLayerModuleSetHandleT getGVsAndStubsHandle(LMHandle LMH) {
+ return LMH->GVsAndStubsHandle;
+ }
+
+ // Add a handle to a module containing lazy function bodies to the given
+ // logical module.
+ void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) {
+ LMH->ImplHandles.push_back(H);
+ }
+
+ // Create an UncompiledPartition attached to this LogicalDylib.
+ UncompiledPartition& createUncompiledPartition(LMHandle LMH,
+ std::shared_ptr<Module> SrcM);
+
+ // Take ownership of the given UncompiledPartition from the logical dylib.
+ std::unique_ptr<UncompiledPartition>
+ takeUPOwnership(UncompiledPartitionID ID);
+
+ // Look up a symbol in this context.
+ JITSymbol findSymbolInternally(LMHandle LMH, const std::string &Name) {
+ if (auto Symbol = getBaseLayer().findSymbolIn(LMH->GVsAndStubsHandle,
+ Name, false))
+ return Symbol;
+
+ for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
+ ++I)
+ if (I != LMH)
+ if (auto Symbol = getBaseLayer().findSymbolIn(I->GVsAndStubsHandle,
+ Name, false))
+ return Symbol;
+
+ return nullptr;
+ }
+
+ JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ for (auto &LM : LogicalModules)
+ if (auto Symbol = getBaseLayer().findSymbolIn(LM.GVsAndStubsHandle,
+ Name,
+ ExportedSymbolsOnly))
+ return Symbol;
+ return nullptr;
+ }
+
+ // Find an external symbol (via the user supplied SymbolResolver).
+ virtual RuntimeDyld::SymbolInfo
+ findSymbolExternally(const std::string &Name) const = 0;
+
+ private:
+
+ void releaseLogicalModuleResources() {
+ for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
+ ++I) {
+ getBaseLayer().removeModuleSet(I->GVsAndStubsHandle);
+ for (auto H : I->ImplHandles)
+ getBaseLayer().removeModuleSet(H);
+ }
+ }
+
+ CompileOnDemandLayer &CODLayer;
+ LogicalModuleList LogicalModules;
+ std::vector<std::unique_ptr<UncompiledPartition>> UncompiledPartitions;
+ };
+
+ template <typename ResolverPtrT>
+ class LogicalDylibImpl : public LogicalDylib {
+ public:
+ LogicalDylibImpl(CompileOnDemandLayer &CODLayer, ResolverPtrT Resolver)
+ : LogicalDylib(CODLayer), Resolver(std::move(Resolver)) {}
+
+ RuntimeDyld::SymbolInfo
+ findSymbolExternally(const std::string &Name) const override {
+ return Resolver->findSymbol(Name);
+ }
+
+ private:
+ ResolverPtrT Resolver;
+ };
+
+ template <typename ResolverPtrT>
+ static std::unique_ptr<LogicalDylib>
+ createLogicalDylib(CompileOnDemandLayer &CODLayer,
+ ResolverPtrT Resolver) {
+ typedef LogicalDylibImpl<ResolverPtrT> Impl;
+ return llvm::make_unique<Impl>(CODLayer, std::move(Resolver));
+ }
+
+ // Uncompiled partition.
+ //
+ // Represents one as-yet uncompiled portion of a module.
+ class UncompiledPartition {
+ public:
+
+ struct PartitionEntry {
+ PartitionEntry(Function *F, TargetAddress CallbackID)
+ : F(F), CallbackID(CallbackID) {}
+ Function *F;
+ TargetAddress CallbackID;
+ };
+
+ typedef std::vector<PartitionEntry> PartitionEntryList;
+
+ // Creates an uncompiled partition with the list of functions that make up
+ // this partition.
+ UncompiledPartition(LogicalDylib &LD, typename LogicalDylib::LMHandle LMH,
+ std::shared_ptr<Module> SrcM)
+ : LD(LD), LMH(LMH), SrcM(std::move(SrcM)), ID(~0U) {}
+
+ ~UncompiledPartition() {
+ // FIXME: When we want to support threaded lazy compilation we'll need to
+ // lock the callback manager here.
+ auto &CCMgr = LD.getCODLayer().CompileCallbackMgr;
+ for (auto PEntry : PartitionEntries)
+ CCMgr.releaseCompileCallback(PEntry.CallbackID);
+ }
+
+ // Set the ID for this partition.
+ void setID(typename LogicalDylib::UncompiledPartitionID ID) {
+ this->ID = ID;
+ }
+
+ // Set the function set and callbacks for this partition.
+ void setPartitionEntries(PartitionEntryList PartitionEntries) {
+ this->PartitionEntries = std::move(PartitionEntries);
+ }
+
+ // Handle a compile callback for the function at index FnIdx.
+ TargetAddress compile(unsigned FnIdx) {
+ // Take ownership of self. This will ensure we delete the partition and
+ // free all its resources once we're done compiling.
+ std::unique_ptr<UncompiledPartition> This = LD.takeUPOwnership(ID);
+
+ // Release all other compile callbacks for this partition.
+ // We skip the callback for this function because that's the one that
+ // called us, and the callback manager will already have removed it.
+ auto &CCMgr = LD.getCODLayer().CompileCallbackMgr;
+ for (unsigned I = 0; I < PartitionEntries.size(); ++I)
+ if (I != FnIdx)
+ CCMgr.releaseCompileCallback(PartitionEntries[I].CallbackID);
+
+ // Grab the name of the function being called here.
+ Function *F = PartitionEntries[FnIdx].F;
+ std::string CalledFnName = Mangle(F->getName(), SrcM->getDataLayout());
+
+ // Extract the function and add it to the base layer.
+ auto PartitionImplH = emitPartition();
+ LD.addToLogicalModule(LMH, PartitionImplH);
+
+ // Update body pointers.
+ // FIXME: When we start supporting remote lazy jitting this will need to
+ // be replaced with a user-supplied callback for updating the
+ // remote pointers.
+ TargetAddress CalledAddr = 0;
+ for (unsigned I = 0; I < PartitionEntries.size(); ++I) {
+ auto F = PartitionEntries[I].F;
+ std::string FName(F->getName());
+ auto FnBodySym =
+ LD.getBaseLayer().findSymbolIn(PartitionImplH,
+ Mangle(FName, SrcM->getDataLayout()),
+ false);
+ auto FnPtrSym =
+ LD.getBaseLayer().findSymbolIn(LD.getGVsAndStubsHandle(LMH),
+ Mangle(FName + "$orc_addr",
+ SrcM->getDataLayout()),
+ false);
+ assert(FnBodySym && "Couldn't find function body.");
+ assert(FnPtrSym && "Couldn't find function body pointer.");
+
+ auto FnBodyAddr = FnBodySym.getAddress();
+ void *FnPtrAddr = reinterpret_cast<void*>(
+ static_cast<uintptr_t>(FnPtrSym.getAddress()));
+
+ // If this is the function we're calling record the address so we can
+ // return it from this function.
+ if (I == FnIdx)
+ CalledAddr = FnBodyAddr;
+
+ memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
+ }
+
+ // Finally, clear the partition structure so we don't try to
+ // double-release the callbacks in the UncompiledPartition destructor.
+ PartitionEntries.clear();
+
+ return CalledAddr;
+ }
+
+ private:
+
+ BaseLayerModuleSetHandleT emitPartition() {
+ // Create the module.
+ std::string NewName(SrcM->getName());
+ for (auto &PEntry : PartitionEntries) {
+ NewName += ".";
+ NewName += PEntry.F->getName();
+ }
+ auto PM = llvm::make_unique<Module>(NewName, SrcM->getContext());
+ PM->setDataLayout(SrcM->getDataLayout());
+ ValueToValueMapTy VMap;
+ GlobalDeclMaterializer GDM(*PM);
+
+ // Create decls in the new module.
+ for (auto &PEntry : PartitionEntries)
+ cloneFunctionDecl(*PM, *PEntry.F, &VMap);
+
+ // Move the function bodies.
+ for (auto &PEntry : PartitionEntries)
+ moveFunctionBody(*PEntry.F, VMap);
+
+ // Create memory manager and symbol resolver.
+ auto MemMgr = llvm::make_unique<SectionMemoryManager>();
+ auto Resolver = createLambdaResolver(
+ [this](const std::string &Name) {
+ if (auto Symbol = LD.findSymbolInternally(LMH, Name))
+ return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+ Symbol.getFlags());
+ return LD.findSymbolExternally(Name);
+ },
+ [this](const std::string &Name) {
+ if (auto Symbol = LD.findSymbolInternally(LMH, Name))
+ return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+ Symbol.getFlags());
+ return RuntimeDyld::SymbolInfo(nullptr);
+ });
+ std::vector<std::unique_ptr<Module>> PartMSet;
+ PartMSet.push_back(std::move(PM));
+ return LD.getBaseLayer().addModuleSet(std::move(PartMSet),
+ std::move(MemMgr),
+ std::move(Resolver));
+ }
+
+ LogicalDylib &LD;
+ typename LogicalDylib::LMHandle LMH;
+ std::shared_ptr<Module> SrcM;
+ typename LogicalDylib::UncompiledPartitionID ID;
+ PartitionEntryList PartitionEntries;
+ };
+
+ typedef std::list<std::unique_ptr<LogicalDylib>> LogicalDylibList;
+
+public:
+ /// @brief Handle to a set of loaded modules.
+ typedef typename LogicalDylibList::iterator ModuleSetHandleT;
+
+ /// @brief Construct a compile-on-demand layer instance.
+ CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr)
+ : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {}
+
+ /// @brief Add a module to the compile-on-demand layer.
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ModuleSetHandleT addModuleSet(ModuleSetT Ms,
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+
+ assert(MemMgr == nullptr &&
+ "User supplied memory managers not supported with COD yet.");
+
+ LogicalDylibs.push_back(createLogicalDylib(*this, std::move(Resolver)));
+
+ // Process each of the modules in this module set.
+ for (auto &M : Ms) {
+ std::vector<std::vector<Function*>> Partitioning;
+ for (auto &F : *M) {
+ if (F.isDeclaration())
+ continue;
+ Partitioning.push_back(std::vector<Function*>());
+ Partitioning.back().push_back(&F);
+ }
+ addLogicalModule(*LogicalDylibs.back(),
+ std::shared_ptr<Module>(std::move(M)),
+ std::move(Partitioning));
+ }
+
+ return std::prev(LogicalDylibs.end());
+ }
+
+ /// @brief Remove the module represented by the given handle.
+ ///
+ /// This will remove all modules in the layers below that were derived from
+ /// the module represented by H.
+ void removeModuleSet(ModuleSetHandleT H) {
+ LogicalDylibs.erase(H);
+ }
+
+ /// @brief Search for the given named symbol.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it exists.
+ JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+ return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
+ }
+
+ /// @brief Get the address of a symbol provided by this layer, or some layer
+ /// below this one.
+ JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ return (*H)->findSymbol(Name, ExportedSymbolsOnly);
+ }
+
+private:
+
+ void addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcM,
+ std::vector<std::vector<Function*>> Partitions) {
+
+ // Bump the linkage and rename any anonymous/privote members in SrcM to
+ // ensure that everything will resolve properly after we partition SrcM.
+ makeAllSymbolsExternallyAccessible(*SrcM);
+
+ // Create a logical module handle for SrcM within the logical dylib.
+ auto LMH = LD.createLogicalModule();
+
+ // Create the GVs-and-stubs module.
+ auto GVsAndStubsM = llvm::make_unique<Module>(
+ (SrcM->getName() + ".globals_and_stubs").str(),
+ SrcM->getContext());
+ GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
+ ValueToValueMapTy VMap;
+
+ // Process partitions and create stubs.
+ // We create the stubs before copying the global variables as we know the
+ // stubs won't refer to any globals (they only refer to their implementation
+ // pointer) so there's no ordering/value-mapping issues.
+ for (auto& Partition : Partitions) {
+ auto &UP = LD.createUncompiledPartition(LMH, SrcM);
+ typename UncompiledPartition::PartitionEntryList PartitionEntries;
+ for (auto &F : Partition) {
+ assert(!F->isDeclaration() &&
+ "Partition should only contain definitions");
+ unsigned FnIdx = PartitionEntries.size();
+ auto CCI = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
+ PartitionEntries.push_back(
+ typename UncompiledPartition::PartitionEntry(F, CCI.getAddress()));
+ Function *StubF = cloneFunctionDecl(*GVsAndStubsM, *F, &VMap);
+ GlobalVariable *FnBodyPtr =
+ createImplPointer(*StubF->getType(), *StubF->getParent(),
+ StubF->getName() + "$orc_addr",
+ createIRTypedAddress(*StubF->getFunctionType(),
+ CCI.getAddress()));
+ makeStub(*StubF, *FnBodyPtr);
+ CCI.setCompileAction([&UP, FnIdx]() { return UP.compile(FnIdx); });
+ }
+
+ UP.setPartitionEntries(std::move(PartitionEntries));
+ }
+
+ // Now clone the global variable declarations.
+ GlobalDeclMaterializer GDMat(*GVsAndStubsM);
+ for (auto &GV : SrcM->globals())
+ if (!GV.isDeclaration())
+ cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap);
+
+ // Then clone the initializers.
+ for (auto &GV : SrcM->globals())
+ if (!GV.isDeclaration())
+ moveGlobalVariableInitializer(GV, VMap, &GDMat);
+
+ // Build a resolver for the stubs module and add it to the base layer.
+ auto GVsAndStubsResolver = createLambdaResolver(
+ [&LD](const std::string &Name) {
+ if (auto Symbol = LD.findSymbol(Name, false))
+ return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+ Symbol.getFlags());
+ return LD.findSymbolExternally(Name);
+ },
+ [&LD](const std::string &Name) {
+ return RuntimeDyld::SymbolInfo(nullptr);
+ });
+
+ std::vector<std::unique_ptr<Module>> GVsAndStubsMSet;
+ GVsAndStubsMSet.push_back(std::move(GVsAndStubsM));
+ auto GVsAndStubsH =
+ BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
+ llvm::make_unique<SectionMemoryManager>(),
+ std::move(GVsAndStubsResolver));
+ LD.setGVsAndStubsHandle(LMH, GVsAndStubsH);
+ }
+
+ static std::string Mangle(StringRef Name, const DataLayout &DL) {
+ Mangler M(&DL);
+ std::string MangledName;
+ {
+ raw_string_ostream MangledNameStream(MangledName);
+ M.getNameWithPrefix(MangledNameStream, Name);
+ }
+ return MangledName;
+ }
+
+ BaseLayerT &BaseLayer;
+ CompileCallbackMgrT &CompileCallbackMgr;
+ LogicalDylibList LogicalDylibs;
+};
+
+template <typename BaseLayerT, typename CompileCallbackMgrT>
+typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::
+ UncompiledPartition&
+CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib::
+ createUncompiledPartition(LMHandle LMH, std::shared_ptr<Module> SrcM) {
+ UncompiledPartitions.push_back(
+ llvm::make_unique<UncompiledPartition>(*this, LMH, std::move(SrcM)));
+ UncompiledPartitions.back()->setID(UncompiledPartitions.size() - 1);
+ return *UncompiledPartitions.back();
+}
+
+template <typename BaseLayerT, typename CompileCallbackMgrT>
+std::unique_ptr<typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::
+ UncompiledPartition>
+CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib::
+ takeUPOwnership(UncompiledPartitionID ID) {
+
+ std::swap(UncompiledPartitions[ID], UncompiledPartitions.back());
+ UncompiledPartitions[ID]->setID(ID);
+ auto UP = std::move(UncompiledPartitions.back());
+ UncompiledPartitions.pop_back();
+ return UP;
+}
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
diff --git a/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/include/llvm/ExecutionEngine/Orc/CompileUtils.h
new file mode 100644
index 000000000000..49a1fbadb295
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -0,0 +1,62 @@
+//===-- CompileUtils.h - Utilities for compiling IR in the JIT --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains utilities for compiling IR to object files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
+#define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
+
+#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+namespace orc {
+
+/// @brief Simple compile functor: Takes a single IR module and returns an
+/// ObjectFile.
+class SimpleCompiler {
+public:
+ /// @brief Construct a simple compile functor with the given target.
+ SimpleCompiler(TargetMachine &TM) : TM(TM) {}
+
+ /// @brief Compile a Module to an ObjectFile.
+ object::OwningBinary<object::ObjectFile> operator()(Module &M) const {
+ SmallVector<char, 0> ObjBufferSV;
+ raw_svector_ostream ObjStream(ObjBufferSV);
+
+ legacy::PassManager PM;
+ MCContext *Ctx;
+ if (TM.addPassesToEmitMC(PM, Ctx, ObjStream))
+ llvm_unreachable("Target does not support MC emission.");
+ PM.run(M);
+ ObjStream.flush();
+ std::unique_ptr<MemoryBuffer> ObjBuffer(
+ new ObjectMemoryBuffer(std::move(ObjBufferSV)));
+ ErrorOr<std::unique_ptr<object::ObjectFile>> Obj =
+ object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
+ // TODO: Actually report errors helpfully.
+ typedef object::OwningBinary<object::ObjectFile> OwningObj;
+ if (Obj)
+ return OwningObj(std::move(*Obj), std::move(ObjBuffer));
+ return OwningObj(nullptr, nullptr);
+ }
+
+private:
+ TargetMachine &TM;
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
diff --git a/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
new file mode 100644
index 000000000000..c10508cc8a62
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -0,0 +1,182 @@
+//===-- ExecutionUtils.h - Utilities for executing code in Orc --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains utilities for executing code in Orc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
+#define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
+
+#include "JITSymbol.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include <vector>
+
+namespace llvm {
+
+class ConstantArray;
+class GlobalVariable;
+class Function;
+class Module;
+class Value;
+
+namespace orc {
+
+/// @brief This iterator provides a convenient way to iterate over the elements
+/// of an llvm.global_ctors/llvm.global_dtors instance.
+///
+/// The easiest way to get hold of instances of this class is to use the
+/// getConstructors/getDestructors functions.
+class CtorDtorIterator {
+public:
+
+ /// @brief Accessor for an element of the global_ctors/global_dtors array.
+ ///
+ /// This class provides a read-only view of the element with any casts on
+ /// the function stripped away.
+ struct Element {
+ Element(unsigned Priority, const Function *Func, const Value *Data)
+ : Priority(Priority), Func(Func), Data(Data) {}
+
+ unsigned Priority;
+ const Function *Func;
+ const Value *Data;
+ };
+
+ /// @brief Construct an iterator instance. If End is true then this iterator
+ /// acts as the end of the range, otherwise it is the beginning.
+ CtorDtorIterator(const GlobalVariable *GV, bool End);
+
+ /// @brief Test iterators for equality.
+ bool operator==(const CtorDtorIterator &Other) const;
+
+ /// @brief Test iterators for inequality.
+ bool operator!=(const CtorDtorIterator &Other) const;
+
+ /// @brief Pre-increment iterator.
+ CtorDtorIterator& operator++();
+
+ /// @brief Post-increment iterator.
+ CtorDtorIterator operator++(int);
+
+ /// @brief Dereference iterator. The resulting value provides a read-only view
+ /// of this element of the global_ctors/global_dtors list.
+ Element operator*() const;
+
+private:
+ const ConstantArray *InitList;
+ unsigned I;
+};
+
+/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// array.
+iterator_range<CtorDtorIterator> getConstructors(const Module &M);
+
+/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// array.
+iterator_range<CtorDtorIterator> getDestructors(const Module &M);
+
+/// @brief Convenience class for recording constructor/destructor names for
+/// later execution.
+template <typename JITLayerT>
+class CtorDtorRunner {
+public:
+
+ /// @brief Construct a CtorDtorRunner for the given range using the given
+ /// name mangling function.
+ CtorDtorRunner(std::vector<std::string> CtorDtorNames,
+ typename JITLayerT::ModuleSetHandleT H)
+ : CtorDtorNames(std::move(CtorDtorNames)), H(H) {}
+
+ /// @brief Run the recorded constructors/destructors through the given JIT
+ /// layer.
+ bool runViaLayer(JITLayerT &JITLayer) const {
+ typedef void (*CtorDtorTy)();
+
+ bool Error = false;
+ for (const auto &CtorDtorName : CtorDtorNames)
+ if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) {
+ CtorDtorTy CtorDtor =
+ reinterpret_cast<CtorDtorTy>(
+ static_cast<uintptr_t>(CtorDtorSym.getAddress()));
+ CtorDtor();
+ } else
+ Error = true;
+ return !Error;
+ }
+
+private:
+ std::vector<std::string> CtorDtorNames;
+ typename JITLayerT::ModuleSetHandleT H;
+};
+
+/// @brief Support class for static dtor execution. For hosted (in-process) JITs
+/// only!
+///
+/// If a __cxa_atexit function isn't found C++ programs that use static
+/// destructors will fail to link. However, we don't want to use the host
+/// process's __cxa_atexit, because it will schedule JIT'd destructors to run
+/// after the JIT has been torn down, which is no good. This class makes it easy
+/// to override __cxa_atexit (and the related __dso_handle).
+///
+/// To use, clients should manually call searchOverrides from their symbol
+/// resolver. This should generally be done after attempting symbol resolution
+/// inside the JIT, but before searching the host process's symbol table. When
+/// the client determines that destructors should be run (generally at JIT
+/// teardown or after a return from main), the runDestructors method should be
+/// called.
+class LocalCXXRuntimeOverrides {
+public:
+
+ /// Create a runtime-overrides class.
+ template <typename MangleFtorT>
+ LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) {
+ addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
+ addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
+ }
+
+ /// Search overrided symbols.
+ RuntimeDyld::SymbolInfo searchOverrides(const std::string &Name) {
+ auto I = CXXRuntimeOverrides.find(Name);
+ if (I != CXXRuntimeOverrides.end())
+ return RuntimeDyld::SymbolInfo(I->second, JITSymbolFlags::Exported);
+ return nullptr;
+ }
+
+ /// Run any destructors recorded by the overriden __cxa_atexit function
+ /// (CXAAtExitOverride).
+ void runDestructors();
+
+private:
+
+ template <typename PtrTy>
+ TargetAddress toTargetAddress(PtrTy* P) {
+ return static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(P));
+ }
+
+ void addOverride(const std::string &Name, TargetAddress Addr) {
+ CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
+ }
+
+ StringMap<TargetAddress> CXXRuntimeOverrides;
+
+ typedef void (*DestructorPtr)(void*);
+ typedef std::pair<DestructorPtr, void*> CXXDestructorDataPair;
+ typedef std::vector<CXXDestructorDataPair> CXXDestructorDataPairList;
+ CXXDestructorDataPairList DSOHandleOverride;
+ static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
+ void *DSOHandle);
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
new file mode 100644
index 000000000000..637902200786
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -0,0 +1,148 @@
+//===------ IRCompileLayer.h -- Eagerly compile IR for JIT ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains the definition for a basic, eagerly compiling layer of the JIT.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
+
+#include "JITSymbol.h"
+#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/Object/ObjectFile.h"
+#include <memory>
+
+namespace llvm {
+namespace orc {
+
+/// @brief Eager IR compiling layer.
+///
+/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It
+/// immediately compiles each IR module to an object file (each IR Module is
+/// compiled separately). The resulting set of object files is then added to
+/// the layer below, which must implement the object layer concept.
+template <typename BaseLayerT> class IRCompileLayer {
+public:
+ typedef std::function<object::OwningBinary<object::ObjectFile>(Module &)>
+ CompileFtor;
+
+private:
+ typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;
+
+ typedef std::vector<std::unique_ptr<object::ObjectFile>> OwningObjectVec;
+ typedef std::vector<std::unique_ptr<MemoryBuffer>> OwningBufferVec;
+
+public:
+ /// @brief Handle to a set of compiled modules.
+ typedef ObjSetHandleT ModuleSetHandleT;
+
+ /// @brief Construct an IRCompileLayer with the given BaseLayer, which must
+ /// implement the ObjectLayer concept.
+ IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile)
+ : BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {}
+
+ /// @brief Set an ObjectCache to query before compiling.
+ void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
+
+ /// @brief Compile each module in the given module set, then add the resulting
+ /// set of objects to the base layer along with the memory manager and
+ /// symbol resolver.
+ ///
+ /// @return A handle for the added modules.
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ModuleSetHandleT addModuleSet(ModuleSetT Ms,
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ OwningObjectVec Objects;
+ OwningBufferVec Buffers;
+
+ for (const auto &M : Ms) {
+ std::unique_ptr<object::ObjectFile> Object;
+ std::unique_ptr<MemoryBuffer> Buffer;
+
+ if (ObjCache)
+ std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary();
+
+ if (!Object) {
+ std::tie(Object, Buffer) = Compile(*M).takeBinary();
+ if (ObjCache)
+ ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef());
+ }
+
+ Objects.push_back(std::move(Object));
+ Buffers.push_back(std::move(Buffer));
+ }
+
+ ModuleSetHandleT H =
+ BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver));
+
+ BaseLayer.takeOwnershipOfBuffers(H, std::move(Buffers));
+
+ return H;
+ }
+
+ /// @brief Remove the module set associated with the handle H.
+ void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); }
+
+ /// @brief Search for the given named symbol.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it exists.
+ JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
+ }
+
+ /// @brief Get the address of the given symbol in the context of the set of
+ /// compiled modules represented by the handle H. This call is
+ /// forwarded to the base layer's implementation.
+ /// @param H The handle for the module set to search in.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it is found in the
+ /// given module set.
+ JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
+ }
+
+ /// @brief Immediately emit and finalize the moduleOB set represented by the
+ /// given handle.
+ /// @param H Handle for module set to emit/finalize.
+ void emitAndFinalize(ModuleSetHandleT H) {
+ BaseLayer.emitAndFinalize(H);
+ }
+
+private:
+ object::OwningBinary<object::ObjectFile>
+ tryToLoadFromObjectCache(const Module &M) {
+ std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M);
+ if (!ObjBuffer)
+ return object::OwningBinary<object::ObjectFile>();
+
+ ErrorOr<std::unique_ptr<object::ObjectFile>> Obj =
+ object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
+ if (!Obj)
+ return object::OwningBinary<object::ObjectFile>();
+
+ return object::OwningBinary<object::ObjectFile>(std::move(*Obj),
+ std::move(ObjBuffer));
+ }
+
+ BaseLayerT &BaseLayer;
+ CompileFtor Compile;
+ ObjectCache *ObjCache;
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H
diff --git a/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
new file mode 100644
index 000000000000..4dabb9a41494
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
@@ -0,0 +1,101 @@
+//===----- IRTransformLayer.h - Run all IR through a functor ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Run all IR passed in through a user supplied functor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
+
+#include "JITSymbol.h"
+
+namespace llvm {
+namespace orc {
+
+/// @brief IR mutating layer.
+///
+/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It
+/// immediately applies the user supplied functor to each module, then adds
+/// the set of transformed modules to the layer below.
+template <typename BaseLayerT, typename TransformFtor>
+class IRTransformLayer {
+public:
+ /// @brief Handle to a set of added modules.
+ typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT;
+
+ /// @brief Construct an IRTransformLayer with the given BaseLayer
+ IRTransformLayer(BaseLayerT &BaseLayer,
+ TransformFtor Transform = TransformFtor())
+ : BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
+
+ /// @brief Apply the transform functor to each module in the module set, then
+ /// add the resulting set of modules to the base layer, along with the
+ /// memory manager and symbol resolver.
+ ///
+ /// @return A handle for the added modules.
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ModuleSetHandleT addModuleSet(ModuleSetT Ms,
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+
+ for (auto I = Ms.begin(), E = Ms.end(); I != E; ++I)
+ *I = Transform(std::move(*I));
+
+ return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
+ std::move(Resolver));
+ }
+
+ /// @brief Remove the module set associated with the handle H.
+ void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); }
+
+ /// @brief Search for the given named symbol.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it exists.
+ JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
+ }
+
+ /// @brief Get the address of the given symbol in the context of the set of
+ /// modules represented by the handle H. This call is forwarded to the
+ /// base layer's implementation.
+ /// @param H The handle for the module set to search in.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it is found in the
+ /// given module set.
+ JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
+ }
+
+ /// @brief Immediately emit and finalize the module set represented by the
+ /// given handle.
+ /// @param H Handle for module set to emit/finalize.
+ void emitAndFinalize(ModuleSetHandleT H) {
+ BaseLayer.emitAndFinalize(H);
+ }
+
+ /// @brief Access the transform functor directly.
+ TransformFtor& getTransform() { return Transform; }
+
+ /// @brief Access the mumate functor directly.
+ const TransformFtor& getTransform() const { return Transform; }
+
+private:
+ BaseLayerT &BaseLayer;
+ TransformFtor Transform;
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
new file mode 100644
index 000000000000..4b7fc5e84b9c
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -0,0 +1,295 @@
+//===-- IndirectionUtils.h - Utilities for adding indirections --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains utilities for adding indirections and breaking up modules.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
+#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
+
+#include "JITSymbol.h"
+#include "LambdaResolver.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Transforms/Utils/ValueMapper.h"
+#include <sstream>
+
+namespace llvm {
+namespace orc {
+
+/// @brief Base class for JITLayer independent aspects of
+/// JITCompileCallbackManager.
+class JITCompileCallbackManagerBase {
+public:
+
+ typedef std::function<TargetAddress()> CompileFtor;
+
+ /// @brief Handle to a newly created compile callback. Can be used to get an
+ /// IR constant representing the address of the trampoline, and to set
+ /// the compile action for the callback.
+ class CompileCallbackInfo {
+ public:
+ CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile)
+ : Addr(Addr), Compile(Compile) {}
+
+ TargetAddress getAddress() const { return Addr; }
+ void setCompileAction(CompileFtor Compile) {
+ this->Compile = std::move(Compile);
+ }
+ private:
+ TargetAddress Addr;
+ CompileFtor &Compile;
+ };
+
+ /// @brief Construct a JITCompileCallbackManagerBase.
+ /// @param ErrorHandlerAddress The address of an error handler in the target
+ /// process to be used if a compile callback fails.
+ /// @param NumTrampolinesPerBlock Number of trampolines to emit if there is no
+ /// available trampoline when getCompileCallback is
+ /// called.
+ JITCompileCallbackManagerBase(TargetAddress ErrorHandlerAddress,
+ unsigned NumTrampolinesPerBlock)
+ : ErrorHandlerAddress(ErrorHandlerAddress),
+ NumTrampolinesPerBlock(NumTrampolinesPerBlock) {}
+
+ virtual ~JITCompileCallbackManagerBase() {}
+
+ /// @brief Execute the callback for the given trampoline id. Called by the JIT
+ /// to compile functions on demand.
+ TargetAddress executeCompileCallback(TargetAddress TrampolineAddr) {
+ auto I = ActiveTrampolines.find(TrampolineAddr);
+ // FIXME: Also raise an error in the Orc error-handler when we finally have
+ // one.
+ if (I == ActiveTrampolines.end())
+ return ErrorHandlerAddress;
+
+ // Found a callback handler. Yank this trampoline out of the active list and
+ // put it back in the available trampolines list, then try to run the
+ // handler's compile and update actions.
+ // Moving the trampoline ID back to the available list first means there's at
+ // least one available trampoline if the compile action triggers a request for
+ // a new one.
+ auto Compile = std::move(I->second);
+ ActiveTrampolines.erase(I);
+ AvailableTrampolines.push_back(TrampolineAddr);
+
+ if (auto Addr = Compile())
+ return Addr;
+
+ return ErrorHandlerAddress;
+ }
+
+ /// @brief Reserve a compile callback.
+ virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0;
+
+ /// @brief Get a CompileCallbackInfo for an existing callback.
+ CompileCallbackInfo getCompileCallbackInfo(TargetAddress TrampolineAddr) {
+ auto I = ActiveTrampolines.find(TrampolineAddr);
+ assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
+ return CompileCallbackInfo(I->first, I->second);
+ }
+
+ /// @brief Release a compile callback.
+ ///
+ /// Note: Callbacks are auto-released after they execute. This method should
+ /// only be called to manually release a callback that is not going to
+ /// execute.
+ void releaseCompileCallback(TargetAddress TrampolineAddr) {
+ auto I = ActiveTrampolines.find(TrampolineAddr);
+ assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
+ ActiveTrampolines.erase(I);
+ AvailableTrampolines.push_back(TrampolineAddr);
+ }
+
+protected:
+ TargetAddress ErrorHandlerAddress;
+ unsigned NumTrampolinesPerBlock;
+
+ typedef std::map<TargetAddress, CompileFtor> TrampolineMapT;
+ TrampolineMapT ActiveTrampolines;
+ std::vector<TargetAddress> AvailableTrampolines;
+};
+
+/// @brief Manage compile callbacks.
+template <typename JITLayerT, typename TargetT>
+class JITCompileCallbackManager : public JITCompileCallbackManagerBase {
+public:
+
+ /// @brief Construct a JITCompileCallbackManager.
+ /// @param JIT JIT layer to emit callback trampolines, etc. into.
+ /// @param Context LLVMContext to use for trampoline & resolve block modules.
+ /// @param ErrorHandlerAddress The address of an error handler in the target
+ /// process to be used if a compile callback fails.
+ /// @param NumTrampolinesPerBlock Number of trampolines to allocate whenever
+ /// there is no existing callback trampoline.
+ /// (Trampolines are allocated in blocks for
+ /// efficiency.)
+ JITCompileCallbackManager(JITLayerT &JIT, RuntimeDyld::MemoryManager &MemMgr,
+ LLVMContext &Context,
+ TargetAddress ErrorHandlerAddress,
+ unsigned NumTrampolinesPerBlock)
+ : JITCompileCallbackManagerBase(ErrorHandlerAddress,
+ NumTrampolinesPerBlock),
+ JIT(JIT), MemMgr(MemMgr) {
+ emitResolverBlock(Context);
+ }
+
+ /// @brief Get/create a compile callback with the given signature.
+ CompileCallbackInfo getCompileCallback(LLVMContext &Context) final {
+ TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context);
+ auto &Compile = this->ActiveTrampolines[TrampolineAddr];
+ return CompileCallbackInfo(TrampolineAddr, Compile);
+ }
+
+private:
+
+ std::vector<std::unique_ptr<Module>>
+ SingletonSet(std::unique_ptr<Module> M) {
+ std::vector<std::unique_ptr<Module>> Ms;
+ Ms.push_back(std::move(M));
+ return Ms;
+ }
+
+ void emitResolverBlock(LLVMContext &Context) {
+ std::unique_ptr<Module> M(new Module("resolver_block_module",
+ Context));
+ TargetT::insertResolverBlock(*M, *this);
+ auto NonResolver =
+ createLambdaResolver(
+ [](const std::string &Name) -> RuntimeDyld::SymbolInfo {
+ llvm_unreachable("External symbols in resolver block?");
+ },
+ [](const std::string &Name) -> RuntimeDyld::SymbolInfo {
+ llvm_unreachable("Dylib symbols in resolver block?");
+ });
+ auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr,
+ std::move(NonResolver));
+ JIT.emitAndFinalize(H);
+ auto ResolverBlockSymbol =
+ JIT.findSymbolIn(H, TargetT::ResolverBlockName, false);
+ assert(ResolverBlockSymbol && "Failed to insert resolver block");
+ ResolverBlockAddr = ResolverBlockSymbol.getAddress();
+ }
+
+ TargetAddress getAvailableTrampolineAddr(LLVMContext &Context) {
+ if (this->AvailableTrampolines.empty())
+ grow(Context);
+ assert(!this->AvailableTrampolines.empty() &&
+ "Failed to grow available trampolines.");
+ TargetAddress TrampolineAddr = this->AvailableTrampolines.back();
+ this->AvailableTrampolines.pop_back();
+ return TrampolineAddr;
+ }
+
+ void grow(LLVMContext &Context) {
+ assert(this->AvailableTrampolines.empty() && "Growing prematurely?");
+ std::unique_ptr<Module> M(new Module("trampoline_block", Context));
+ auto GetLabelName =
+ TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr,
+ this->NumTrampolinesPerBlock,
+ this->ActiveTrampolines.size());
+ auto NonResolver =
+ createLambdaResolver(
+ [](const std::string &Name) -> RuntimeDyld::SymbolInfo {
+ llvm_unreachable("External symbols in trampoline block?");
+ },
+ [](const std::string &Name) -> RuntimeDyld::SymbolInfo {
+ llvm_unreachable("Dylib symbols in trampoline block?");
+ });
+ auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr,
+ std::move(NonResolver));
+ JIT.emitAndFinalize(H);
+ for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) {
+ std::string Name = GetLabelName(I);
+ auto TrampolineSymbol = JIT.findSymbolIn(H, Name, false);
+ assert(TrampolineSymbol && "Failed to emit trampoline.");
+ this->AvailableTrampolines.push_back(TrampolineSymbol.getAddress());
+ }
+ }
+
+ JITLayerT &JIT;
+ RuntimeDyld::MemoryManager &MemMgr;
+ TargetAddress ResolverBlockAddr;
+};
+
+/// @brief Build a function pointer of FunctionType with the given constant
+/// address.
+///
+/// Usage example: Turn a trampoline address into a function pointer constant
+/// for use in a stub.
+Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr);
+
+/// @brief Create a function pointer with the given type, name, and initializer
+/// in the given Module.
+GlobalVariable* createImplPointer(PointerType &PT, Module &M,
+ const Twine &Name, Constant *Initializer);
+
+/// @brief Turn a function declaration into a stub function that makes an
+/// indirect call using the given function pointer.
+void makeStub(Function &F, GlobalVariable &ImplPointer);
+
+/// @brief Raise linkage types and rename as necessary to ensure that all
+/// symbols are accessible for other modules.
+///
+/// This should be called before partitioning a module to ensure that the
+/// partitions retain access to each other's symbols.
+void makeAllSymbolsExternallyAccessible(Module &M);
+
+/// @brief Clone a function declaration into a new module.
+///
+/// This function can be used as the first step towards creating a callback
+/// stub (see makeStub), or moving a function body (see moveFunctionBody).
+///
+/// If the VMap argument is non-null, a mapping will be added between F and
+/// the new declaration, and between each of F's arguments and the new
+/// declaration's arguments. This map can then be passed in to moveFunction to
+/// move the function body if required. Note: When moving functions between
+/// modules with these utilities, all decls should be cloned (and added to a
+/// single VMap) before any bodies are moved. This will ensure that references
+/// between functions all refer to the versions in the new module.
+Function* cloneFunctionDecl(Module &Dst, const Function &F,
+ ValueToValueMapTy *VMap = nullptr);
+
+/// @brief Move the body of function 'F' to a cloned function declaration in a
+/// different module (See related cloneFunctionDecl).
+///
+/// If the target function declaration is not supplied via the NewF parameter
+/// then it will be looked up via the VMap.
+///
+/// This will delete the body of function 'F' from its original parent module,
+/// but leave its declaration.
+void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
+ ValueMaterializer *Materializer = nullptr,
+ Function *NewF = nullptr);
+
+/// @brief Clone a global variable declaration into a new module.
+GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
+ ValueToValueMapTy *VMap = nullptr);
+
+/// @brief Move global variable GV from its parent module to cloned global
+/// declaration in a different module.
+///
+/// If the target global declaration is not supplied via the NewGV parameter
+/// then it will be looked up via the VMap.
+///
+/// This will delete the initializer of GV from its original parent module,
+/// but leave its declaration.
+void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
+ ValueToValueMapTy &VMap,
+ ValueMaterializer *Materializer = nullptr,
+ GlobalVariable *NewGV = nullptr);
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h
new file mode 100644
index 000000000000..422a3761837c
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h
@@ -0,0 +1,77 @@
+//===----------- JITSymbol.h - JIT symbol abstraction -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstraction for target process addresses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H
+#define LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H
+
+#include "llvm/ExecutionEngine/JITSymbolFlags.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <functional>
+
+namespace llvm {
+namespace orc {
+
+/// @brief Represents an address in the target process's address space.
+typedef uint64_t TargetAddress;
+
+/// @brief Represents a symbol in the JIT.
+class JITSymbol : public JITSymbolBase {
+public:
+
+ typedef std::function<TargetAddress()> GetAddressFtor;
+
+ /// @brief Create a 'null' symbol that represents failure to find a symbol
+ /// definition.
+ JITSymbol(std::nullptr_t)
+ : JITSymbolBase(JITSymbolFlags::None), CachedAddr(0) {}
+
+ /// @brief Create a symbol for a definition with a known address.
+ JITSymbol(TargetAddress Addr, JITSymbolFlags Flags)
+ : JITSymbolBase(Flags), CachedAddr(Addr) {}
+
+ /// @brief Create a symbol for a definition that doesn't have a known address
+ /// yet.
+ /// @param GetAddress A functor to materialize a definition (fixing the
+ /// address) on demand.
+ ///
+ /// This constructor allows a JIT layer to provide a reference to a symbol
+ /// definition without actually materializing the definition up front. The
+ /// user can materialize the definition at any time by calling the getAddress
+ /// method.
+ JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
+ : JITSymbolBase(Flags), GetAddress(std::move(GetAddress)), CachedAddr(0) {}
+
+ /// @brief Returns true if the symbol exists, false otherwise.
+ explicit operator bool() const { return CachedAddr || GetAddress; }
+
+ /// @brief Get the address of the symbol in the target address space. Returns
+ /// '0' if the symbol does not exist.
+ TargetAddress getAddress() {
+ if (GetAddress) {
+ CachedAddr = GetAddress();
+ assert(CachedAddr && "Symbol could not be materialized.");
+ GetAddress = nullptr;
+ }
+ return CachedAddr;
+ }
+
+private:
+ GetAddressFtor GetAddress;
+ TargetAddress CachedAddr;
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H
diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
new file mode 100644
index 000000000000..faa23658524f
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
@@ -0,0 +1,62 @@
+//===-- LambdaResolverMM - Redirect symbol lookup via a functor -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied
+// functor for symbol resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
+#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+template <typename ExternalLookupFtorT, typename DylibLookupFtorT>
+class LambdaResolver : public RuntimeDyld::SymbolResolver {
+public:
+
+ LambdaResolver(ExternalLookupFtorT ExternalLookupFtor,
+ DylibLookupFtorT DylibLookupFtor)
+ : ExternalLookupFtor(ExternalLookupFtor),
+ DylibLookupFtor(DylibLookupFtor) {}
+
+ RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) final {
+ return ExternalLookupFtor(Name);
+ }
+
+ RuntimeDyld::SymbolInfo
+ findSymbolInLogicalDylib(const std::string &Name) final {
+ return DylibLookupFtor(Name);
+ }
+
+private:
+ ExternalLookupFtorT ExternalLookupFtor;
+ DylibLookupFtorT DylibLookupFtor;
+};
+
+template <typename ExternalLookupFtorT,
+ typename DylibLookupFtorT>
+std::unique_ptr<LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT>>
+createLambdaResolver(ExternalLookupFtorT ExternalLookupFtor,
+ DylibLookupFtorT DylibLookupFtor) {
+ typedef LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT> LR;
+ return make_unique<LR>(std::move(ExternalLookupFtor),
+ std::move(DylibLookupFtor));
+}
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
new file mode 100644
index 000000000000..71c83f7e05f6
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
@@ -0,0 +1,304 @@
+//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains the definition for a lazy-emitting layer for the JIT.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
+
+#include "JITSymbol.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Module.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include <list>
+
+namespace llvm {
+namespace orc {
+
+/// @brief Lazy-emitting IR layer.
+///
+/// This layer accepts sets of LLVM IR Modules (via addModuleSet), but does
+/// not immediately emit them the layer below. Instead, emissing to the base
+/// layer is deferred until the first time the client requests the address
+/// (via JITSymbol::getAddress) for a symbol contained in this layer.
+template <typename BaseLayerT> class LazyEmittingLayer {
+public:
+ typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
+
+private:
+ class EmissionDeferredSet {
+ public:
+ EmissionDeferredSet() : EmitState(NotEmitted) {}
+ virtual ~EmissionDeferredSet() {}
+
+ JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
+ switch (EmitState) {
+ case NotEmitted:
+ if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
+ // Create a std::string version of Name to capture here - the argument
+ // (a StringRef) may go away before the lambda is executed.
+ // FIXME: Use capture-init when we move to C++14.
+ std::string PName = Name;
+ JITSymbolFlags Flags = JITSymbolBase::flagsFromGlobalValue(*GV);
+ auto GetAddress =
+ [this, ExportedSymbolsOnly, PName, &B]() -> TargetAddress {
+ if (this->EmitState == Emitting)
+ return 0;
+ else if (this->EmitState == NotEmitted) {
+ this->EmitState = Emitting;
+ Handle = this->emitToBaseLayer(B);
+ this->EmitState = Emitted;
+ }
+ auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly);
+ return Sym.getAddress();
+ };
+ return JITSymbol(std::move(GetAddress), Flags);
+ } else
+ return nullptr;
+ case Emitting:
+ // Calling "emit" can trigger external symbol lookup (e.g. to check for
+ // pre-existing definitions of common-symbol), but it will never find in
+ // this module that it would not have found already, so return null from
+ // here.
+ return nullptr;
+ case Emitted:
+ return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
+ }
+ llvm_unreachable("Invalid emit-state.");
+ }
+
+ void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
+ if (EmitState != NotEmitted)
+ BaseLayer.removeModuleSet(Handle);
+ }
+
+ void emitAndFinalize(BaseLayerT &BaseLayer) {
+ assert(EmitState != Emitting &&
+ "Cannot emitAndFinalize while already emitting");
+ if (EmitState == NotEmitted) {
+ EmitState = Emitting;
+ Handle = emitToBaseLayer(BaseLayer);
+ EmitState = Emitted;
+ }
+ BaseLayer.emitAndFinalize(Handle);
+ }
+
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ static std::unique_ptr<EmissionDeferredSet>
+ create(BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver);
+
+ protected:
+ virtual const GlobalValue* searchGVs(StringRef Name,
+ bool ExportedSymbolsOnly) const = 0;
+ virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0;
+
+ private:
+ enum { NotEmitted, Emitting, Emitted } EmitState;
+ BaseLayerHandleT Handle;
+ };
+
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ class EmissionDeferredSetImpl : public EmissionDeferredSet {
+ public:
+ EmissionDeferredSetImpl(ModuleSetT Ms,
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver)
+ : Ms(std::move(Ms)), MemMgr(std::move(MemMgr)),
+ Resolver(std::move(Resolver)) {}
+
+ protected:
+
+ const GlobalValue* searchGVs(StringRef Name,
+ bool ExportedSymbolsOnly) const override {
+ // FIXME: We could clean all this up if we had a way to reliably demangle
+ // names: We could just demangle name and search, rather than
+ // mangling everything else.
+
+ // If we have already built the mangled name set then just search it.
+ if (MangledSymbols) {
+ auto VI = MangledSymbols->find(Name);
+ if (VI == MangledSymbols->end())
+ return nullptr;
+ auto GV = VI->second;
+ if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
+ return GV;
+ return nullptr;
+ }
+
+ // If we haven't built the mangled name set yet, try to build it. As an
+ // optimization this will leave MangledNames set to nullptr if we find
+ // Name in the process of building the set.
+ return buildMangledSymbols(Name, ExportedSymbolsOnly);
+ }
+
+ BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override {
+ // We don't need the mangled names set any more: Once we've emitted this
+ // to the base layer we'll just look for symbols there.
+ MangledSymbols.reset();
+ return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
+ std::move(Resolver));
+ }
+
+ private:
+ // If the mangled name of the given GlobalValue matches the given search
+ // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
+ // return the symbol. Otherwise, add the mangled name to the Names map and
+ // return nullptr.
+ const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
+ const GlobalValue &GV,
+ const Mangler &Mang, StringRef SearchName,
+ bool ExportedSymbolsOnly) const {
+ // Modules don't "provide" decls or common symbols.
+ if (GV.isDeclaration() || GV.hasCommonLinkage())
+ return nullptr;
+
+ // Mangle the GV name.
+ std::string MangledName;
+ {
+ raw_string_ostream MangledNameStream(MangledName);
+ Mang.getNameWithPrefix(MangledNameStream, &GV, false);
+ }
+
+ // Check whether this is the name we were searching for, and if it is then
+ // bail out early.
+ if (MangledName == SearchName)
+ if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
+ return &GV;
+
+ // Otherwise add this to the map for later.
+ Names[MangledName] = &GV;
+ return nullptr;
+ }
+
+ // Build the MangledSymbols map. Bails out early (with MangledSymbols left set
+ // to nullptr) if the given SearchName is found while building the map.
+ const GlobalValue* buildMangledSymbols(StringRef SearchName,
+ bool ExportedSymbolsOnly) const {
+ assert(!MangledSymbols && "Mangled symbols map already exists?");
+
+ auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
+
+ for (const auto &M : Ms) {
+ Mangler Mang(&M->getDataLayout());
+
+ for (const auto &V : M->globals())
+ if (auto GV = addGlobalValue(*Symbols, V, Mang, SearchName,
+ ExportedSymbolsOnly))
+ return GV;
+
+ for (const auto &F : *M)
+ if (auto GV = addGlobalValue(*Symbols, F, Mang, SearchName,
+ ExportedSymbolsOnly))
+ return GV;
+ }
+
+ MangledSymbols = std::move(Symbols);
+ return nullptr;
+ }
+
+ ModuleSetT Ms;
+ MemoryManagerPtrT MemMgr;
+ SymbolResolverPtrT Resolver;
+ mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
+ };
+
+ typedef std::list<std::unique_ptr<EmissionDeferredSet>> ModuleSetListT;
+
+ BaseLayerT &BaseLayer;
+ ModuleSetListT ModuleSetList;
+
+public:
+ /// @brief Handle to a set of loaded modules.
+ typedef typename ModuleSetListT::iterator ModuleSetHandleT;
+
+ /// @brief Construct a lazy emitting layer.
+ LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
+
+ /// @brief Add the given set of modules to the lazy emitting layer.
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ModuleSetHandleT addModuleSet(ModuleSetT Ms,
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ return ModuleSetList.insert(
+ ModuleSetList.end(),
+ EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MemMgr),
+ std::move(Resolver)));
+ }
+
+ /// @brief Remove the module set represented by the given handle.
+ ///
+ /// This method will free the memory associated with the given module set,
+ /// both in this layer, and the base layer.
+ void removeModuleSet(ModuleSetHandleT H) {
+ (*H)->removeModulesFromBaseLayer(BaseLayer);
+ ModuleSetList.erase(H);
+ }
+
+ /// @brief Search for the given named symbol.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it exists.
+ JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ // Look for the symbol among existing definitions.
+ if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
+ return Symbol;
+
+ // If not found then search the deferred sets. If any of these contain a
+ // definition of 'Name' then they will return a JITSymbol that will emit
+ // the corresponding module when the symbol address is requested.
+ for (auto &DeferredSet : ModuleSetList)
+ if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer))
+ return Symbol;
+
+ // If no definition found anywhere return a null symbol.
+ return nullptr;
+ }
+
+ /// @brief Get the address of the given symbol in the context of the set of
+ /// compiled modules represented by the handle H.
+ JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer);
+ }
+
+ /// @brief Immediately emit and finalize the moduleOB set represented by the
+ /// given handle.
+ /// @param H Handle for module set to emit/finalize.
+ void emitAndFinalize(ModuleSetHandleT H) {
+ (*H)->emitAndFinalize(BaseLayer);
+ }
+
+};
+
+template <typename BaseLayerT>
+template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
+LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
+ BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ typedef EmissionDeferredSetImpl<ModuleSetT, MemoryManagerPtrT, SymbolResolverPtrT>
+ EDS;
+ return llvm::make_unique<EDS>(std::move(Ms), std::move(MemMgr),
+ std::move(Resolver));
+}
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
new file mode 100644
index 000000000000..f3094dafae3c
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -0,0 +1,284 @@
+//===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains the definition for the object layer of the JIT.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
+
+#include "JITSymbol.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include <list>
+#include <memory>
+
+namespace llvm {
+namespace orc {
+
+class ObjectLinkingLayerBase {
+protected:
+
+ /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
+ ///
+ /// An instance of this class will be created for each set of objects added
+ /// via JITObjectLayer::addObjectSet. Deleting the instance (via
+ /// removeObjectSet) frees its memory, removing all symbol definitions that
+ /// had been provided by this instance. Higher level layers are responsible
+ /// for taking any action required to handle the missing symbols.
+ class LinkedObjectSet {
+ LinkedObjectSet(const LinkedObjectSet&) = delete;
+ void operator=(const LinkedObjectSet&) = delete;
+ public:
+ LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
+ State(Raw) {}
+
+ virtual ~LinkedObjectSet() {}
+
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
+ addObject(const object::ObjectFile &Obj) {
+ return RTDyld->loadObject(Obj);
+ }
+
+ RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {
+ return RTDyld->getSymbol(Name);
+ }
+
+ bool NeedsFinalization() const { return (State == Raw); }
+
+ virtual void Finalize() = 0;
+
+ void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
+ assert((State != Finalized) &&
+ "Attempting to remap sections for finalized objects.");
+ RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
+ }
+
+ void takeOwnershipOfBuffer(std::unique_ptr<MemoryBuffer> B) {
+ OwnedBuffers.push_back(std::move(B));
+ }
+
+ protected:
+ std::unique_ptr<RuntimeDyld> RTDyld;
+ enum { Raw, Finalizing, Finalized } State;
+
+ // FIXME: This ownership hack only exists because RuntimeDyldELF still
+ // wants to be able to inspect the original object when resolving
+ // relocations. As soon as that can be fixed this should be removed.
+ std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers;
+ };
+
+ typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
+
+public:
+ /// @brief Handle to a set of loaded objects.
+ typedef LinkedObjectSetListT::iterator ObjSetHandleT;
+
+ // Ownership hack.
+ // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without
+ // referencing the original object.
+ template <typename OwningMBSet>
+ void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) {
+ for (auto &MB : MBs)
+ (*H)->takeOwnershipOfBuffer(std::move(MB));
+ }
+
+};
+
+/// @brief Default (no-op) action to perform when loading objects.
+class DoNothingOnNotifyLoaded {
+public:
+ template <typename ObjSetT, typename LoadResult>
+ void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
+ const LoadResult &) {}
+};
+
+/// @brief Bare bones object linking layer.
+///
+/// This class is intended to be used as the base layer for a JIT. It allows
+/// object files to be loaded into memory, linked, and the addresses of their
+/// symbols queried. All objects added to this layer can see each other's
+/// symbols.
+template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
+class ObjectLinkingLayer : public ObjectLinkingLayerBase {
+private:
+
+ template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
+ class ConcreteLinkedObjectSet : public LinkedObjectSet {
+ public:
+ ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver)
+ : LinkedObjectSet(*MemMgr, *Resolver), MemMgr(std::move(MemMgr)),
+ Resolver(std::move(Resolver)) { }
+
+ void Finalize() override {
+ State = Finalizing;
+ RTDyld->resolveRelocations();
+ RTDyld->registerEHFrames();
+ MemMgr->finalizeMemory();
+ OwnedBuffers.clear();
+ State = Finalized;
+ }
+
+ private:
+ MemoryManagerPtrT MemMgr;
+ SymbolResolverPtrT Resolver;
+ };
+
+ template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
+ std::unique_ptr<LinkedObjectSet>
+ createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) {
+ typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
+ return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver));
+ }
+
+public:
+
+ /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
+ /// RuntimeDyld::LoadedObjectInfo instances.
+ typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
+ LoadedObjInfoList;
+
+ /// @brief Functor for receiving finalization notifications.
+ typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
+
+ /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
+ /// and NotifyFinalized functors.
+ ObjectLinkingLayer(
+ NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
+ NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
+ : NotifyLoaded(std::move(NotifyLoaded)),
+ NotifyFinalized(std::move(NotifyFinalized)) {}
+
+ /// @brief Add a set of objects (or archives) that will be treated as a unit
+ /// for the purposes of symbol lookup and memory management.
+ ///
+ /// @return A pair containing (1) A handle that can be used to free the memory
+ /// allocated for the objects, and (2) a LoadedObjInfoList containing
+ /// one LoadedObjInfo instance for each object at the corresponding
+ /// index in the Objects list.
+ ///
+ /// This version of this method allows the client to pass in an
+ /// RTDyldMemoryManager instance that will be used to allocate memory and look
+ /// up external symbol addresses for the given objects.
+ template <typename ObjSetT,
+ typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ObjSetHandleT addObjectSet(const ObjSetT &Objects,
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ ObjSetHandleT Handle =
+ LinkedObjSetList.insert(
+ LinkedObjSetList.end(),
+ createLinkedObjectSet(std::move(MemMgr), std::move(Resolver)));
+
+ LinkedObjectSet &LOS = **Handle;
+ LoadedObjInfoList LoadedObjInfos;
+
+ for (auto &Obj : Objects)
+ LoadedObjInfos.push_back(LOS.addObject(*Obj));
+
+ NotifyLoaded(Handle, Objects, LoadedObjInfos);
+
+ return Handle;
+ }
+
+ /// @brief Remove the set of objects associated with handle H.
+ ///
+ /// All memory allocated for the objects will be freed, and the sections and
+ /// symbols they provided will no longer be available. No attempt is made to
+ /// re-emit the missing symbols, and any use of these symbols (directly or
+ /// indirectly) will result in undefined behavior. If dependence tracking is
+ /// required to detect or resolve such issues it should be added at a higher
+ /// layer.
+ void removeObjectSet(ObjSetHandleT H) {
+ // How do we invalidate the symbols in H?
+ LinkedObjSetList.erase(H);
+ }
+
+ /// @brief Search for the given named symbol.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it exists.
+ JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+ for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
+ ++I)
+ if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
+ return Symbol;
+
+ return nullptr;
+ }
+
+ /// @brief Search for the given named symbol in the context of the set of
+ /// loaded objects represented by the handle H.
+ /// @param H The handle for the object set to search in.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it is found in the
+ /// given object set.
+ JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
+ bool ExportedSymbolsOnly) {
+ if (auto Sym = (*H)->getSymbol(Name)) {
+ if (Sym.isExported() || !ExportedSymbolsOnly) {
+ auto Addr = Sym.getAddress();
+ auto Flags = Sym.getFlags();
+ if (!(*H)->NeedsFinalization()) {
+ // If this instance has already been finalized then we can just return
+ // the address.
+ return JITSymbol(Addr, Flags);
+ } else {
+ // If this instance needs finalization return a functor that will do
+ // it. The functor still needs to double-check whether finalization is
+ // required, in case someone else finalizes this set before the
+ // functor is called.
+ auto GetAddress =
+ [this, Addr, H]() {
+ if ((*H)->NeedsFinalization()) {
+ (*H)->Finalize();
+ if (NotifyFinalized)
+ NotifyFinalized(H);
+ }
+ return Addr;
+ };
+ return JITSymbol(std::move(GetAddress), Flags);
+ }
+ }
+ }
+ return nullptr;
+ }
+
+ /// @brief Map section addresses for the objects associated with the handle H.
+ void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
+ TargetAddress TargetAddr) {
+ (*H)->mapSectionAddress(LocalAddress, TargetAddr);
+ }
+
+ /// @brief Immediately emit and finalize the object set represented by the
+ /// given handle.
+ /// @param H Handle for object set to emit/finalize.
+ void emitAndFinalize(ObjSetHandleT H) {
+ (*H)->Finalize();
+ if (NotifyFinalized)
+ NotifyFinalized(H);
+ }
+
+private:
+ LinkedObjectSetListT LinkedObjSetList;
+ NotifyLoadedFtor NotifyLoaded;
+ NotifyFinalizedFtor NotifyFinalized;
+};
+
+} // End namespace orc.
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
diff --git a/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h
new file mode 100644
index 000000000000..309f5a96090e
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h
@@ -0,0 +1,53 @@
+//===-- OrcTargetSupport.h - Code to support specific targets --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Target specific code for Orc, e.g. callback assembly.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H
+#define LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H
+
+#include "IndirectionUtils.h"
+
+namespace llvm {
+namespace orc {
+
+class OrcX86_64 {
+public:
+ static const char *ResolverBlockName;
+
+ /// @brief Insert module-level inline callback asm into module M for the
+ /// symbols managed by JITResolveCallbackHandler J.
+ static void insertResolverBlock(Module &M,
+ JITCompileCallbackManagerBase &JCBM);
+
+ /// @brief Get a label name from the given index.
+ typedef std::function<std::string(unsigned)> LabelNameFtor;
+
+ /// @brief Insert the requested number of trampolines into the given module.
+ /// @param M Module to insert the call block into.
+ /// @param NumCalls Number of calls to create in the call block.
+ /// @param StartIndex Optional argument specifying the index suffix to start
+ /// with.
+ /// @return A functor that provides the symbol name for each entry in the call
+ /// block.
+ ///
+ static LabelNameFtor insertCompileCallbackTrampolines(
+ Module &M,
+ TargetAddress TrampolineAddr,
+ unsigned NumCalls,
+ unsigned StartIndex = 0);
+
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H
diff --git a/include/llvm/ExecutionEngine/OrcMCJITReplacement.h b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h
new file mode 100644
index 000000000000..4cd5648b2fc2
--- /dev/null
+++ b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h
@@ -0,0 +1,38 @@
+//===---- OrcMCJITReplacement.h - Orc-based MCJIT replacement ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file forces OrcMCJITReplacement to link in on certain operating systems.
+// (Windows).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H
+#define LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H
+
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include <cstdlib>
+
+extern "C" void LLVMLinkInOrcMCJITReplacement();
+
+namespace {
+ struct ForceOrcMCJITReplacementLinking {
+ ForceOrcMCJITReplacementLinking() {
+ // We must reference OrcMCJITReplacement in such a way that compilers will
+ // not delete it all as dead code, even with whole program optimization,
+ // yet is effectively a NO-OP. As the compiler isn't smart enough to know
+ // that getenv() never returns -1, this will do the job.
+ if (std::getenv("bar") != (char*) -1)
+ return;
+
+ LLVMLinkInOrcMCJITReplacement();
+ }
+ } ForceOrcMCJITReplacementLinking;
+}
+
+#endif
diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
index ef81cd328bdb..207bad06c239 100644
--- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
+++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
@@ -14,6 +14,7 @@
#ifndef LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H
#define LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H
+#include "RuntimeDyld.h"
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CBindingWrapping.h"
@@ -27,68 +28,91 @@ class ExecutionEngine;
class ObjectFile;
}
+class MCJITMemoryManager : public RuntimeDyld::MemoryManager {
+public:
+ /// This method is called after an object has been loaded into memory but
+ /// before relocations are applied to the loaded sections. The object load
+ /// may have been initiated by MCJIT to resolve an external symbol for another
+ /// object that is being finalized. In that case, the object about which
+ /// the memory manager is being notified will be finalized immediately after
+ /// the memory manager returns from this call.
+ ///
+ /// Memory managers which are preparing code for execution in an external
+ /// address space can use this call to remap the section addresses for the
+ /// newly loaded object.
+ virtual void notifyObjectLoaded(ExecutionEngine *EE,
+ const object::ObjectFile &) {}
+};
+
// RuntimeDyld clients often want to handle the memory management of
// what gets placed where. For JIT clients, this is the subset of
// JITMemoryManager required for dynamic loading of binaries.
//
// FIXME: As the RuntimeDyld fills out, additional routines will be needed
// for the varying types of objects to be allocated.
-class RTDyldMemoryManager {
- RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION;
- void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION;
+class RTDyldMemoryManager : public MCJITMemoryManager,
+ public RuntimeDyld::SymbolResolver {
+ RTDyldMemoryManager(const RTDyldMemoryManager&) = delete;
+ void operator=(const RTDyldMemoryManager&) = delete;
public:
RTDyldMemoryManager() {}
- virtual ~RTDyldMemoryManager();
-
- /// Allocate a memory block of (at least) the given size suitable for
- /// executable code. The SectionID is a unique identifier assigned by the JIT
- /// engine, and optionally recorded by the memory manager to access a loaded
- /// section.
- virtual uint8_t *allocateCodeSection(
- uintptr_t Size, unsigned Alignment, unsigned SectionID,
- StringRef SectionName) = 0;
-
- /// Allocate a memory block of (at least) the given size suitable for data.
- /// The SectionID is a unique identifier assigned by the JIT engine, and
- /// optionally recorded by the memory manager to access a loaded section.
- virtual uint8_t *allocateDataSection(
- uintptr_t Size, unsigned Alignment, unsigned SectionID,
- StringRef SectionName, bool IsReadOnly) = 0;
-
- /// Inform the memory manager about the total amount of memory required to
- /// allocate all sections to be loaded:
- /// \p CodeSize - the total size of all code sections
- /// \p DataSizeRO - the total size of all read-only data sections
- /// \p DataSizeRW - the total size of all read-write data sections
- ///
- /// Note that by default the callback is disabled. To enable it
- /// redefine the method needsToReserveAllocationSpace to return true.
- virtual void reserveAllocationSpace(
- uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { }
-
- /// Override to return true to enable the reserveAllocationSpace callback.
- virtual bool needsToReserveAllocationSpace() { return false; }
-
- /// Register the EH frames with the runtime so that c++ exceptions work.
- ///
- /// \p Addr parameter provides the local address of the EH frame section
- /// data, while \p LoadAddr provides the address of the data in the target
- /// address space. If the section has not been remapped (which will usually
- /// be the case for local execution) these two values will be the same.
- virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size);
+ ~RTDyldMemoryManager() override;
- virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size);
+ void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
+ void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
/// This method returns the address of the specified function or variable in
/// the current process.
static uint64_t getSymbolAddressInProcess(const std::string &Name);
+ /// Legacy symbol lookup - DEPRECATED! Please override findSymbol instead.
+ ///
/// 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) {
return getSymbolAddressInProcess(Name);
}
+ /// This method returns a RuntimeDyld::SymbolInfo for the specified function
+ /// or variable. It is used to resolve symbols during module linking.
+ ///
+ /// By default this falls back on the legacy lookup method:
+ /// 'getSymbolAddress'. The address returned by getSymbolAddress is treated as
+ /// a strong, exported symbol, consistent with historical treatment by
+ /// RuntimeDyld.
+ ///
+ /// Clients writing custom RTDyldMemoryManagers are encouraged to override
+ /// this method and return a SymbolInfo with the flags set correctly. This is
+ /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols.
+ RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override {
+ return RuntimeDyld::SymbolInfo(getSymbolAddress(Name),
+ JITSymbolFlags::Exported);
+ }
+
+ /// Legacy symbol lookup -- DEPRECATED! Please override
+ /// findSymbolInLogicalDylib instead.
+ ///
+ /// Default to treating all modules as separate.
+ virtual uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) {
+ return 0;
+ }
+
+ /// Default to treating all modules as separate.
+ ///
+ /// By default this falls back on the legacy lookup method:
+ /// 'getSymbolAddressInLogicalDylib'. The address returned by
+ /// getSymbolAddressInLogicalDylib is treated as a strong, exported symbol,
+ /// consistent with historical treatment by RuntimeDyld.
+ ///
+ /// Clients writing custom RTDyldMemoryManagers are encouraged to override
+ /// this method and return a SymbolInfo with the flags set correctly. This is
+ /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols.
+ RuntimeDyld::SymbolInfo
+ findSymbolInLogicalDylib(const std::string &Name) override {
+ return RuntimeDyld::SymbolInfo(getSymbolAddressInLogicalDylib(Name),
+ JITSymbolFlags::Exported);
+ }
+
/// This method returns the address of the specified function. As such it is
/// only useful for resolving library symbols, not code generated symbols.
///
@@ -100,30 +124,6 @@ public:
/// MCJIT or RuntimeDyld. Use getSymbolAddress instead.
virtual void *getPointerToNamedFunction(const std::string &Name,
bool AbortOnFailure = true);
-
- /// This method is called after an object has been loaded into memory but
- /// before relocations are applied to the loaded sections. The object load
- /// may have been initiated by MCJIT to resolve an external symbol for another
- /// object that is being finalized. In that case, the object about which
- /// the memory manager is being notified will be finalized immediately after
- /// the memory manager returns from this call.
- ///
- /// Memory managers which are preparing code for execution in an external
- /// address space can use this call to remap the section addresses for the
- /// newly loaded object.
- virtual void notifyObjectLoaded(ExecutionEngine *EE,
- const 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
- /// to decide whether or not to act on this method. The memory manager will
- /// typically allocate all sections as read-write and then apply specific
- /// permissions when this method is called. Code sections cannot be executed
- /// until this function has been called. In addition, any cache coherency
- /// operations needed to reliably use the memory are also performed.
- ///
- /// Returns true if an error occurred, false otherwise.
- virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0;
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
@@ -132,4 +132,5 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(
} // namespace llvm
+
#endif
diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h
index 799fc34eb659..ac0151aa7ec1 100644
--- a/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -14,9 +14,10 @@
#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
+#include "JITSymbolFlags.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Support/Memory.h"
+#include "llvm/DebugInfo/DIContext.h"
#include <memory>
namespace llvm {
@@ -32,30 +33,36 @@ class RuntimeDyldCheckerImpl;
class RuntimeDyld {
friend class RuntimeDyldCheckerImpl;
- RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
- void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
+ RuntimeDyld(const RuntimeDyld &) = delete;
+ void operator=(const RuntimeDyld &) = delete;
- // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public
- // interface.
- 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 a named symbol.
+ class SymbolInfo : public JITSymbolBase {
+ public:
+ SymbolInfo(std::nullptr_t) : JITSymbolBase(JITSymbolFlags::None), Address(0) {}
+ SymbolInfo(uint64_t Address, JITSymbolFlags Flags)
+ : JITSymbolBase(Flags), Address(Address) {}
+ explicit operator bool() const { return Address != 0; }
+ uint64_t getAddress() const { return Address; }
+ private:
+ uint64_t Address;
+ };
+
/// \brief Information about the loaded object.
- class LoadedObjectInfo {
+ class LoadedObjectInfo : public llvm::LoadedObjectInfo {
friend class RuntimeDyldImpl;
public:
LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
unsigned EndIdx)
: RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { }
- virtual ~LoadedObjectInfo() {}
+ virtual ~LoadedObjectInfo() = default;
virtual object::OwningBinary<object::ObjectFile>
getObjectForDebug(const object::ObjectFile &Obj) const = 0;
@@ -69,7 +76,110 @@ public:
unsigned BeginIdx, EndIdx;
};
- RuntimeDyld(RTDyldMemoryManager *);
+ template <typename Derived> struct LoadedObjectInfoHelper : LoadedObjectInfo {
+ LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
+ unsigned EndIdx)
+ : LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
+ llvm::LoadedObjectInfo *clone() const override {
+ return new Derived(static_cast<const Derived &>(*this));
+ }
+ };
+
+ /// \brief Memory Management.
+ class MemoryManager {
+ public:
+ virtual ~MemoryManager() {};
+
+ /// Allocate a memory block of (at least) the given size suitable for
+ /// executable code. The SectionID is a unique identifier assigned by the
+ /// RuntimeDyld instance, and optionally recorded by the memory manager to
+ /// access a loaded section.
+ virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName) = 0;
+
+ /// Allocate a memory block of (at least) the given size suitable for data.
+ /// The SectionID is a unique identifier assigned by the JIT engine, and
+ /// optionally recorded by the memory manager to access a loaded section.
+ virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName,
+ bool IsReadOnly) = 0;
+
+ /// Inform the memory manager about the total amount of memory required to
+ /// allocate all sections to be loaded:
+ /// \p CodeSize - the total size of all code sections
+ /// \p DataSizeRO - the total size of all read-only data sections
+ /// \p DataSizeRW - the total size of all read-write data sections
+ ///
+ /// Note that by default the callback is disabled. To enable it
+ /// redefine the method needsToReserveAllocationSpace to return true.
+ virtual void reserveAllocationSpace(uintptr_t CodeSize,
+ uintptr_t DataSizeRO,
+ uintptr_t DataSizeRW) {}
+
+ /// Override to return true to enable the reserveAllocationSpace callback.
+ virtual bool needsToReserveAllocationSpace() { return false; }
+
+ /// Register the EH frames with the runtime so that c++ exceptions work.
+ ///
+ /// \p Addr parameter provides the local address of the EH frame section
+ /// data, while \p LoadAddr provides the address of the data in the target
+ /// address space. If the section has not been remapped (which will usually
+ /// be the case for local execution) these two values will be the same.
+ virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) = 0;
+ virtual void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr,
+ size_t Size) = 0;
+
+ /// This method is called when object loading is complete and section page
+ /// permissions can be applied. It is up to the memory manager implementation
+ /// to decide whether or not to act on this method. The memory manager will
+ /// typically allocate all sections as read-write and then apply specific
+ /// permissions when this method is called. Code sections cannot be executed
+ /// until this function has been called. In addition, any cache coherency
+ /// operations needed to reliably use the memory are also performed.
+ ///
+ /// Returns true if an error occurred, false otherwise.
+ virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0;
+
+ private:
+ virtual void anchor();
+ };
+
+ /// \brief Symbol resolution.
+ class SymbolResolver {
+ public:
+ virtual ~SymbolResolver() {};
+
+ /// This method returns the address of the specified function or variable.
+ /// It is used to resolve symbols during module linking.
+ virtual SymbolInfo findSymbol(const std::string &Name) = 0;
+
+ /// This method returns the address of the specified symbol if it exists
+ /// within the logical dynamic library represented by this
+ /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this
+ /// interface should return addresses for hidden symbols.
+ ///
+ /// This is of particular importance for the Orc JIT APIs, which support lazy
+ /// compilation by breaking up modules: Each of those broken out modules
+ /// must be able to resolve hidden symbols provided by the others. Clients
+ /// writing memory managers for MCJIT can usually ignore this method.
+ ///
+ /// This method will be queried by RuntimeDyld when checking for previous
+ /// definitions of common symbols. It will *not* be queried by default when
+ /// resolving external symbols (this minimises the link-time overhead for
+ /// MCJIT clients who don't care about Orc features). If you are writing a
+ /// RTDyldMemoryManager for Orc and want "external" symbol resolution to
+ /// search the logical dylib, you should override your getSymbolAddress
+ /// method call this method directly.
+ virtual SymbolInfo findSymbolInLogicalDylib(const std::string &Name) = 0;
+ private:
+ virtual void anchor();
+ };
+
+ /// \brief Construct a RuntimeDyld instance.
+ RuntimeDyld(MemoryManager &MemMgr, SymbolResolver &Resolver);
~RuntimeDyld();
/// Add the referenced object file to the list of objects to be loaded and
@@ -79,11 +189,11 @@ public:
/// Get the address of our local copy of the symbol. This may or may not
/// be the address used for relocation (clients can copy the data around
/// and resolve relocatons based on where they put it).
- void *getSymbolAddress(StringRef Name) const;
+ void *getSymbolLocalAddress(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) const;
+ /// Get the target address and flags for the named symbol.
+ /// This address is the one used for relocation.
+ SymbolInfo getSymbol(StringRef Name) const;
/// Resolve the relocations for all symbols we currently know about.
void resolveRelocations();
@@ -118,6 +228,15 @@ public:
assert(!Dyld && "setProcessAllSections must be called before loadObject.");
this->ProcessAllSections = ProcessAllSections;
}
+
+private:
+ // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public
+ // interface.
+ std::unique_ptr<RuntimeDyldImpl> Dyld;
+ MemoryManager &MemMgr;
+ SymbolResolver &Resolver;
+ bool ProcessAllSections;
+ RuntimeDyldCheckerImpl *Checker;
};
} // end namespace llvm
diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index 35ceba27596c..31ce151c56a3 100644
--- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -52,6 +52,7 @@ class raw_ostream;
///
/// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
/// | 'next_pc' '(' symbol ')'
+/// | 'stub_addr' '(' file-name ',' section-name ',' symbol ')'
/// | symbol
///
/// binary_expr = expr '+' expr
@@ -85,12 +86,12 @@ public:
/// \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
+ /// if 'LocalAddress' is true, this returns the address of the section
+ /// within the linker's memory. If 'LocalAddress' 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 LocalAddress);
private:
std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h
index 136856390b21..0b0dcb021f14 100644
--- a/include/llvm/ExecutionEngine/SectionMemoryManager.h
+++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h
@@ -16,7 +16,7 @@
#define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Memory.h"
@@ -35,12 +35,12 @@ namespace llvm {
/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory
/// directly. Clients of MCJIT should call MCJIT::finalizeObject.
class SectionMemoryManager : public RTDyldMemoryManager {
- SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION;
- void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION;
+ SectionMemoryManager(const SectionMemoryManager&) = delete;
+ void operator=(const SectionMemoryManager&) = delete;
public:
SectionMemoryManager() { }
- virtual ~SectionMemoryManager();
+ ~SectionMemoryManager() override;
/// \brief Allocates a memory block of (at least) the given size suitable for
/// executable code.
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h
index dd76a90aa5ea..fc04fe71cbf0 100644
--- a/include/llvm/IR/Argument.h
+++ b/include/llvm/IR/Argument.h
@@ -64,6 +64,11 @@ public:
/// containing function, return the number of bytes known to be
/// dereferenceable. Otherwise, zero is returned.
uint64_t getDereferenceableBytes() const;
+
+ /// \brief If this argument has the dereferenceable_or_null attribute on
+ /// it in its containing function, return the number of bytes known to be
+ /// dereferenceable. Otherwise, zero is returned.
+ uint64_t getDereferenceableOrNullBytes() const;
/// \brief Return true if this argument has the byval attribute on it in its
/// containing function.
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h
index 5ff48d688918..e2a0a7ee395a 100644
--- a/include/llvm/IR/Attributes.h
+++ b/include/llvm/IR/Attributes.h
@@ -73,6 +73,7 @@ public:
ByVal, ///< Pass structure by value
InAlloca, ///< Pass structure in an alloca
Cold, ///< Marks function as being in a cold path.
+ Convergent, ///< Can only be moved to control-equivalent blocks
InlineHint, ///< Source said inlining was desirable
InReg, ///< Force argument to be passed in register
JumpTable, ///< Build jump-instruction tables and replace refs.
@@ -89,6 +90,7 @@ public:
///< often, so lazy binding isn't worthwhile
NonNull, ///< Pointer is known to be not null
Dereferenceable, ///< Pointer is known to be dereferenceable
+ DereferenceableOrNull, ///< Pointer is either null or dereferenceable
NoRedZone, ///< Disable redzone
NoReturn, ///< Mark the function as not returning
NoUnwind, ///< Function doesn't unwind stack
@@ -136,6 +138,8 @@ public:
static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align);
static Attribute getWithDereferenceableBytes(LLVMContext &Context,
uint64_t Bytes);
+ static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context,
+ uint64_t Bytes);
//===--------------------------------------------------------------------===//
// Attribute Accessors
@@ -185,6 +189,10 @@ public:
/// dereferenceable attribute (or zero if unknown).
uint64_t getDereferenceableBytes() const;
+ /// \brief Returns the number of dereferenceable_or_null bytes from the
+ /// dereferenceable_or_null attribute (or zero if unknown).
+ uint64_t getDereferenceableOrNullBytes() const;
+
/// \brief The Attribute is converted to a string of equivalent mnemonic. This
/// is, presumably, for writing out the mnemonics for the assembly writer.
std::string getAsString(bool InAttrGrp = false) const;
@@ -253,35 +261,52 @@ public:
ArrayRef<Attribute::AttrKind> Kind);
static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B);
- /// \brief Add an attribute to the attribute set at the given index. Since
+ /// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet addAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Attr) const;
- /// \brief Add an attribute to the attribute set at the given index. Since
+ /// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet addAttribute(LLVMContext &C, unsigned Index,
StringRef Kind) const;
AttributeSet addAttribute(LLVMContext &C, unsigned Index,
StringRef Kind, StringRef Value) const;
- /// \brief Add attributes to the attribute set at the given index. Since
+ /// \brief Add attributes to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet addAttributes(LLVMContext &C, unsigned Index,
AttributeSet Attrs) const;
/// \brief Remove the specified attribute at the specified index from this
- /// attribute list. Since attribute lists are immutable, this returns the new
- /// list.
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Attr) const;
/// \brief Remove the specified attributes at the specified index from this
- /// attribute list. Since attribute lists are immutable, this returns the new
- /// list.
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
AttributeSet removeAttributes(LLVMContext &C, unsigned Index,
AttributeSet Attrs) const;
+ /// \brief Remove the specified attributes at the specified index from this
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
+ AttributeSet removeAttributes(LLVMContext &C, unsigned Index,
+ const AttrBuilder &Attrs) const;
+
+ /// \brief Add the dereferenceable attribute to the attribute set at the given
+ /// index. Because attribute sets are immutable, this returns a new set.
+ AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index,
+ uint64_t Bytes) const;
+
+ /// \brief Add the dereferenceable_or_null attribute to the attribute set at
+ /// the given index. Because attribute sets are immutable, this returns a new
+ /// set.
+ AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
+ uint64_t Bytes) const;
+
//===--------------------------------------------------------------------===//
// AttributeSet Accessors
//===--------------------------------------------------------------------===//
@@ -326,6 +351,10 @@ public:
/// \brief Get the number of dereferenceable bytes (or zero if unknown).
uint64_t getDereferenceableBytes(unsigned Index) const;
+ /// \brief Get the number of dereferenceable_or_null bytes (or zero if
+ /// unknown).
+ uint64_t getDereferenceableOrNullBytes(unsigned Index) const;
+
/// \brief Return the attributes at the index as a string.
std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
@@ -406,14 +435,19 @@ class AttrBuilder {
uint64_t Alignment;
uint64_t StackAlignment;
uint64_t DerefBytes;
+ uint64_t DerefOrNullBytes;
public:
- AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {}
+ AttrBuilder()
+ : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+ DerefOrNullBytes(0) {}
explicit AttrBuilder(uint64_t Val)
- : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {
+ : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+ DerefOrNullBytes(0) {
addRawValue(Val);
}
AttrBuilder(const Attribute &A)
- : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {
+ : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+ DerefOrNullBytes(0) {
addAttribute(A);
}
AttrBuilder(AttributeSet AS, unsigned Idx);
@@ -441,6 +475,13 @@ public:
/// \brief Add the attributes from the builder.
AttrBuilder &merge(const AttrBuilder &B);
+ /// \brief Remove the attributes from the builder.
+ AttrBuilder &remove(const AttrBuilder &B);
+
+ /// \brief Return true if the builder has any attribute that's in the
+ /// specified builder.
+ bool overlaps(const AttrBuilder &B) const;
+
/// \brief Return true if the builder has the specified attribute.
bool contains(Attribute::AttrKind A) const {
assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
@@ -471,6 +512,10 @@ public:
/// attribute exists (zero is returned otherwise).
uint64_t getDereferenceableBytes() const { return DerefBytes; }
+ /// \brief Retrieve the number of dereferenceable_or_null bytes, if the
+ /// dereferenceable_or_null attribute exists (zero is returned otherwise).
+ uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; }
+
/// \brief This turns an int alignment (which must be a power of 2) into the
/// form used internally in Attribute.
AttrBuilder &addAlignmentAttr(unsigned Align);
@@ -483,6 +528,10 @@ public:
/// internally in Attribute.
AttrBuilder &addDereferenceableAttr(uint64_t Bytes);
+ /// \brief This turns the number of dereferenceable_or_null bytes into the
+ /// form used internally in Attribute.
+ AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes);
+
/// \brief Return true if the builder contains no target-independent
/// attributes.
bool empty() const { return Attrs.none(); }
@@ -521,7 +570,7 @@ public:
namespace AttributeFuncs {
/// \brief Which attributes cannot be applied to a type.
-AttributeSet typeIncompatible(Type *Ty, uint64_t Index);
+AttrBuilder typeIncompatible(const Type *Ty);
} // end AttributeFuncs namespace
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index 7c7dd2ca5643..66581bfedbe6 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -28,33 +28,25 @@ class LandingPadInst;
class TerminatorInst;
class LLVMContext;
class BlockAddress;
+class Function;
-template<> struct ilist_traits<Instruction>
- : public SymbolTableListTraits<Instruction, BasicBlock> {
+// Traits for intrusive list of basic blocks...
+template<> struct ilist_traits<BasicBlock>
+ : public SymbolTableListTraits<BasicBlock, Function> {
- /// \brief Return a node that marks the end of a list.
- ///
- /// The sentinel is relative to this instance, so we use a non-static
- /// method.
- Instruction *createSentinel() const {
- // Since i(p)lists always publicly derive from their corresponding traits,
- // placing a data member in this class will augment the i(p)list. But since
- // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>,
- // there is a legal viable downcast from it to NodeTy. We use this trick to
- // superimpose an 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<Instruction*>(&Sentinel);
- }
- static void destroySentinel(Instruction*) {}
+ BasicBlock *createSentinel() const;
+ static void destroySentinel(BasicBlock*) {}
- Instruction *provideInitialHead() const { return createSentinel(); }
- Instruction *ensureHead(Instruction*) const { return createSentinel(); }
- static void noteHead(Instruction*, Instruction*) {}
+ BasicBlock *provideInitialHead() const { return createSentinel(); }
+ BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); }
+ static void noteHead(BasicBlock*, BasicBlock*) {}
+
+ static ValueSymbolTable *getSymTab(Function *ItemParent);
private:
- mutable ilist_half_node<Instruction> Sentinel;
+ mutable ilist_half_node<BasicBlock> Sentinel;
};
+
/// \brief LLVM Basic Block Representation
///
/// This represents a single basic block in LLVM. A basic block is simply a
@@ -82,8 +74,8 @@ private:
void setParent(Function *parent);
friend class SymbolTableListTraits<BasicBlock, Function>;
- BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION;
- void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION;
+ BasicBlock(const BasicBlock &) = delete;
+ void operator=(const BasicBlock &) = delete;
/// \brief Constructor.
///
@@ -113,13 +105,18 @@ public:
BasicBlock *InsertBefore = nullptr) {
return new BasicBlock(Context, Name, Parent, InsertBefore);
}
- ~BasicBlock();
+ ~BasicBlock() override;
/// \brief Return the enclosing method, or null if none.
const Function *getParent() const { return Parent; }
Function *getParent() { return Parent; }
- const DataLayout *getDataLayout() const;
+ /// \brief Return the module owning the function this basic block belongs to,
+ /// or nullptr it the function does not have a module.
+ ///
+ /// Note: this is undefined behavior if the block does not have a parent.
+ const Module *getModule() const;
+ Module *getModule();
/// \brief Returns the terminator instruction if the block is well formed or
/// null if the block is not well formed.
@@ -172,7 +169,9 @@ public:
void removeFromParent();
/// \brief Unlink 'this' from the containing function and delete it.
- void eraseFromParent();
+ ///
+ // \returns an iterator pointing to the element after the erased one.
+ iplist<BasicBlock>::iterator eraseFromParent();
/// \brief Unlink this basic block from its current function and insert it
/// into the function that \p MovePos lives in, right before \p MovePos.
@@ -208,6 +207,24 @@ public:
return const_cast<BasicBlock*>(this)->getUniquePredecessor();
}
+ /// \brief Return the successor of this block if it has a single successor.
+ /// Otherwise return a null pointer.
+ ///
+ /// This method is analogous to getSinglePredecessor above.
+ BasicBlock *getSingleSuccessor();
+ const BasicBlock *getSingleSuccessor() const {
+ return const_cast<BasicBlock*>(this)->getSingleSuccessor();
+ }
+
+ /// \brief Return the successor of this block if it has a unique successor.
+ /// Otherwise return a null pointer.
+ ///
+ /// This method is analogous to getUniquePredecessor above.
+ BasicBlock *getUniqueSuccessor();
+ const BasicBlock *getUniqueSuccessor() const {
+ return const_cast<BasicBlock*>(this)->getUniqueSuccessor();
+ }
+
//===--------------------------------------------------------------------===//
/// Instruction iterator methods
///
@@ -320,6 +337,12 @@ private:
}
};
+// createSentinel is used to get hold of the node that marks the end of the
+// list... (same trick used here as in ilist_traits<Instruction>)
+inline BasicBlock *ilist_traits<BasicBlock>::createSentinel() const {
+ return static_cast<BasicBlock*>(&Sentinel);
+}
+
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef)
diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h
index 5400d2384868..f78220a52033 100644
--- a/include/llvm/IR/CFG.h
+++ b/include/llvm/IR/CFG.h
@@ -16,6 +16,7 @@
#define LLVM_IR_CFG_H
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
@@ -84,6 +85,8 @@ public:
typedef PredIterator<BasicBlock, Value::user_iterator> pred_iterator;
typedef PredIterator<const BasicBlock,
Value::const_user_iterator> const_pred_iterator;
+typedef llvm::iterator_range<pred_iterator> pred_range;
+typedef llvm::iterator_range<const_pred_iterator> pred_const_range;
inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); }
inline const_pred_iterator pred_begin(const BasicBlock *BB) {
@@ -96,8 +99,12 @@ inline const_pred_iterator pred_end(const BasicBlock *BB) {
inline bool pred_empty(const BasicBlock *BB) {
return pred_begin(BB) == pred_end(BB);
}
-
-
+inline pred_range predecessors(BasicBlock *BB) {
+ return pred_range(pred_begin(BB), pred_end(BB));
+}
+inline pred_const_range predecessors(const BasicBlock *BB) {
+ return pred_const_range(pred_begin(BB), pred_end(BB));
+}
//===----------------------------------------------------------------------===//
// BasicBlock succ_iterator definition
@@ -114,7 +121,7 @@ public:
typedef typename super::reference reference;
private:
- const Term_ Term;
+ Term_ Term;
unsigned idx;
typedef SuccIterator<Term_, BB_> Self;
@@ -129,6 +136,8 @@ private:
public:
explicit SuccessorProxy(const Self &it) : it(it) {}
+ SuccessorProxy(const SuccessorProxy&) = default;
+
SuccessorProxy &operator=(SuccessorProxy r) {
*this = reference(r);
return *this;
@@ -158,12 +167,6 @@ public:
idx = 0;
}
- inline const Self &operator=(const Self &I) {
- assert(Term == I.Term &&"Cannot assign iterators to two different blocks!");
- idx = I.idx;
- return *this;
- }
-
/// getSuccessorIndex - This is used to interface between code that wants to
/// operate on terminator instructions directly.
unsigned getSuccessorIndex() const { return idx; }
@@ -247,6 +250,8 @@ public:
typedef SuccIterator<TerminatorInst*, BasicBlock> succ_iterator;
typedef SuccIterator<const TerminatorInst*,
const BasicBlock> succ_const_iterator;
+typedef llvm::iterator_range<succ_iterator> succ_range;
+typedef llvm::iterator_range<succ_const_iterator> succ_const_range;
inline succ_iterator succ_begin(BasicBlock *BB) {
return succ_iterator(BB->getTerminator());
@@ -263,6 +268,13 @@ inline succ_const_iterator succ_end(const BasicBlock *BB) {
inline bool succ_empty(const BasicBlock *BB) {
return succ_begin(BB) == succ_end(BB);
}
+inline succ_range successors(BasicBlock *BB) {
+ return succ_range(succ_begin(BB), succ_end(BB));
+}
+inline succ_const_range successors(const BasicBlock *BB) {
+ return succ_const_range(succ_begin(BB), succ_end(BB));
+}
+
template <typename T, typename U> struct isPodLike<SuccIterator<T, U> > {
static const bool value = isPodLike<T>::value;
diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h
index df082577a0e2..170d263dfc79 100644
--- a/include/llvm/IR/CallSite.h
+++ b/include/llvm/IR/CallSite.h
@@ -46,12 +46,13 @@ template <typename FunTy = const Function,
class CallSiteBase {
protected:
PointerIntPair<InstrTy*, 1, bool> I;
-public:
+
CallSiteBase() : I(nullptr, false) {}
CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); }
CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); }
- CallSiteBase(ValTy *II) { *this = get(II); }
-protected:
+ explicit CallSiteBase(ValTy *II) { *this = get(II); }
+
+private:
/// CallSiteBase::get - This static method is sort of like a constructor. It
/// will create an appropriate call site for a Call or Invoke instruction, but
/// it can also create a null initialized CallSiteBase object for something
@@ -78,7 +79,7 @@ public:
InstrTy *getInstruction() const { return I.getPointer(); }
InstrTy *operator->() const { return I.getPointer(); }
- LLVM_EXPLICIT operator bool() const { return I.getPointer(); }
+ explicit operator bool() const { return I.getPointer(); }
/// getCalledValue - Return the pointer to function that is being called.
///
@@ -151,7 +152,7 @@ public:
IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); }
bool arg_empty() const { return arg_end() == arg_begin(); }
unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); }
-
+
/// getType - Return the type of the instruction that generated this call site
///
Type *getType() const { return (*this)->getType(); }
@@ -193,6 +194,14 @@ public:
CALLSITE_DELEGATE_SETTER(setCallingConv(CC));
}
+ FunctionType *getFunctionType() const {
+ CALLSITE_DELEGATE_GETTER(getFunctionType());
+ }
+
+ void mutateFunctionType(FunctionType *Ty) const {
+ CALLSITE_DELEGATE_SETTER(mutateFunctionType(Ty));
+ }
+
/// getAttributes/setAttributes - get or set the parameter attributes of
/// the call.
const AttributeSet &getAttributes() const {
@@ -222,7 +231,13 @@ public:
uint64_t getDereferenceableBytes(uint16_t i) const {
CALLSITE_DELEGATE_GETTER(getDereferenceableBytes(i));
}
-
+
+ /// @brief Extract the number of dereferenceable_or_null bytes for a call or
+ /// parameter (0=unknown).
+ uint64_t getDereferenceableOrNullBytes(uint16_t i) const {
+ CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i));
+ }
+
/// \brief Return true if the call should not be treated as a call to a
/// builtin.
bool isNoBuiltin() const {
@@ -349,15 +364,13 @@ private:
class CallSite : public CallSiteBase<Function, Value, User, Instruction,
CallInst, InvokeInst, User::op_iterator> {
- typedef CallSiteBase<Function, Value, User, Instruction,
- CallInst, InvokeInst, User::op_iterator> Base;
public:
CallSite() {}
- CallSite(Base B) : Base(B) {}
- CallSite(Value* V) : Base(V) {}
- CallSite(CallInst *CI) : Base(CI) {}
- CallSite(InvokeInst *II) : Base(II) {}
- CallSite(Instruction *II) : Base(II) {}
+ CallSite(CallSiteBase B) : CallSiteBase(B) {}
+ CallSite(CallInst *CI) : CallSiteBase(CI) {}
+ CallSite(InvokeInst *II) : CallSiteBase(II) {}
+ explicit CallSite(Instruction *II) : CallSiteBase(II) {}
+ explicit CallSite(Value *V) : CallSiteBase(V) {}
bool operator==(const CallSite &CS) const { return I == CS.I; }
bool operator!=(const CallSite &CS) const { return I != CS.I; }
@@ -371,13 +384,13 @@ private:
/// ImmutableCallSite - establish a view to a call site for examination
class ImmutableCallSite : public CallSiteBase<> {
- typedef CallSiteBase<> Base;
public:
- ImmutableCallSite(const Value* V) : Base(V) {}
- ImmutableCallSite(const CallInst *CI) : Base(CI) {}
- ImmutableCallSite(const InvokeInst *II) : Base(II) {}
- ImmutableCallSite(const Instruction *II) : Base(II) {}
- ImmutableCallSite(CallSite CS) : Base(CS.getInstruction()) {}
+ ImmutableCallSite() {}
+ ImmutableCallSite(const CallInst *CI) : CallSiteBase(CI) {}
+ ImmutableCallSite(const InvokeInst *II) : CallSiteBase(II) {}
+ explicit ImmutableCallSite(const Instruction *II) : CallSiteBase(II) {}
+ explicit ImmutableCallSite(const Value *V) : CallSiteBase(V) {}
+ ImmutableCallSite(CallSite CS) : CallSiteBase(CS.getInstruction()) {}
};
} // End llvm namespace
diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h
index 3e77a7709d5c..4d4c15fb68cd 100644
--- a/include/llvm/IR/Comdat.h
+++ b/include/llvm/IR/Comdat.h
@@ -49,7 +49,7 @@ private:
friend class Module;
Comdat();
Comdat(SelectionKind SK, StringMapEntry<Comdat> *Name);
- Comdat(const Comdat &) LLVM_DELETED_FUNCTION;
+ Comdat(const Comdat &) = delete;
// Points to the map in Module.
StringMapEntry<Comdat> *Name;
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index d26991eaab75..75499e0a4db3 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -39,8 +39,8 @@ namespace llvm {
/// don't have to worry about the lifetime of the objects.
/// @brief LLVM Constant Representation
class Constant : public User {
- void operator=(const Constant &) LLVM_DELETED_FUNCTION;
- Constant(const Constant &) LLVM_DELETED_FUNCTION;
+ void operator=(const Constant &) = delete;
+ Constant(const Constant &) = delete;
void anchor() override;
protected:
diff --git a/include/llvm/IR/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h
index e271a1482117..fb6ca3b3184c 100644
--- a/include/llvm/IR/ConstantFolder.h
+++ b/include/llvm/IR/ConstantFolder.h
@@ -118,34 +118,35 @@ public:
// Memory Instructions
//===--------------------------------------------------------------------===//
- Constant *CreateGetElementPtr(Constant *C,
+ Constant *CreateGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) const {
- return ConstantExpr::getGetElementPtr(C, IdxList);
+ return ConstantExpr::getGetElementPtr(Ty, C, IdxList);
}
- Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const {
+ Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
- return ConstantExpr::getGetElementPtr(C, Idx);
+ return ConstantExpr::getGetElementPtr(Ty, C, Idx);
}
- Constant *CreateGetElementPtr(Constant *C,
+ Constant *CreateGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) const {
- return ConstantExpr::getGetElementPtr(C, IdxList);
+ return ConstantExpr::getGetElementPtr(Ty, C, IdxList);
}
- Constant *CreateInBoundsGetElementPtr(Constant *C,
+ Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) const {
- return ConstantExpr::getInBoundsGetElementPtr(C, IdxList);
+ return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList);
}
- Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const {
+ Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
+ Constant *Idx) const {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
- return ConstantExpr::getInBoundsGetElementPtr(C, Idx);
+ return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx);
}
- Constant *CreateInBoundsGetElementPtr(Constant *C,
+ Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) const {
- return ConstantExpr::getInBoundsGetElementPtr(C, IdxList);
+ return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList);
}
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h
index 5e8cd34c4d69..9ded3ca36a70 100644
--- a/include/llvm/IR/ConstantRange.h
+++ b/include/llvm/IR/ConstantRange.h
@@ -33,6 +33,7 @@
#define LLVM_IR_CONSTANTRANGE_H
#include "llvm/ADT/APInt.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@@ -59,15 +60,27 @@ public:
/// assert out if the two APInt's are not the same bit width.
ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper);
- /// Produce the smallest range that contains all values that
- /// might satisfy the comparison specified by Pred when compared to any value
- /// contained within Other.
+ /// Produce the smallest range such that all values that may satisfy the given
+ /// predicate with any value contained within Other is contained in the
+ /// returned range. Formally, this returns a superset of
+ /// 'union over all y in Other . { x : icmp op x y is true }'. If the exact
+ /// answer is not representable as a ConstantRange, the return value will be a
+ /// proper superset of the above.
///
- /// Solves for range X in 'for all x in X, there exists a y in Y such that
- /// icmp op x, y is true'. Every value that might make the comparison true
- /// is included in the resulting range.
- static ConstantRange makeICmpRegion(unsigned Pred,
- const ConstantRange &Other);
+ /// Example: Pred = ult and Other = i8 [2, 5) returns Result = [0, 4)
+ static ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred,
+ const ConstantRange &Other);
+
+ /// Produce the largest range such that all values in the returned range
+ /// satisfy the given predicate with all values contained within Other.
+ /// Formally, this returns a subset of
+ /// 'intersection over all y in Other . { x : icmp op x y is true }'. If the
+ /// exact answer is not representable as a ConstantRange, the return value
+ /// will be a proper subset of the above.
+ ///
+ /// Example: Pred = ult and Other = i8 [2, 5) returns [0, 2)
+ static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
+ const ConstantRange &Other);
/// Return the lower value for this range.
///
@@ -208,8 +221,8 @@ public:
ConstantRange sub(const ConstantRange &Other) const;
/// 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.
+ /// from a multiplication of a value in this range and a value in \p Other,
+ /// treating both this and \p Other as unsigned ranges.
ConstantRange multiply(const ConstantRange &Other) const;
/// Return a new range representing the possible values resulting
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index 5b098b4f51d6..e97bda54e8f0 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -12,7 +12,7 @@
/// which represent the different flavors of constant values that live in LLVM.
/// Note that Constants are immutable (once created they never change) and are
/// fully shared by structural equivalence. This means that two structurally
-/// equivalent constants will always have the same address. Constant's are
+/// equivalent constants will always have the same address. Constants are
/// created on demand as needed and never deleted: thus clients don't have to
/// worry about the lifetime of the objects.
//
@@ -46,8 +46,8 @@ template <class ConstantClass> struct ConstantAggrKeyType;
/// @brief Class for constant integers.
class ConstantInt : public Constant {
void anchor() override;
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ ConstantInt(const ConstantInt &) = delete;
ConstantInt(IntegerType *Ty, const APInt& V);
APInt Val;
protected:
@@ -228,8 +228,8 @@ public:
class ConstantFP : public Constant {
APFloat Val;
void anchor() override;
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ ConstantFP(const ConstantFP &) = delete;
friend class LLVMContextImpl;
protected:
ConstantFP(Type *Ty, const APFloat& V);
@@ -251,6 +251,7 @@ public:
static Constant *get(Type* Ty, double V);
static Constant *get(Type* Ty, StringRef Str);
static ConstantFP *get(LLVMContext &Context, const APFloat &V);
+ static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0);
static Constant *getNegativeZero(Type *Ty);
static Constant *getInfinity(Type *Ty, bool Negative = false);
@@ -294,8 +295,8 @@ public:
/// ConstantAggregateZero - All zero aggregate value
///
class ConstantAggregateZero : public Constant {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ ConstantAggregateZero(const ConstantAggregateZero &) = delete;
protected:
explicit ConstantAggregateZero(Type *ty)
: Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {}
@@ -341,7 +342,7 @@ public:
///
class ConstantArray : public Constant {
friend struct ConstantAggrKeyType<ConstantArray>;
- ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION;
+ ConstantArray(const ConstantArray &) = delete;
protected:
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
public:
@@ -383,7 +384,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant)
//
class ConstantStruct : public Constant {
friend struct ConstantAggrKeyType<ConstantStruct>;
- ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION;
+ ConstantStruct(const ConstantStruct &) = delete;
protected:
ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
public:
@@ -442,7 +443,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant)
///
class ConstantVector : public Constant {
friend struct ConstantAggrKeyType<ConstantVector>;
- ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION;
+ ConstantVector(const ConstantVector &) = delete;
protected:
ConstantVector(VectorType *T, ArrayRef<Constant *> Val);
public:
@@ -491,8 +492,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant)
/// ConstantPointerNull - a constant pointer value that points to null
///
class ConstantPointerNull : public Constant {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ ConstantPointerNull(const ConstantPointerNull &) = delete;
protected:
explicit ConstantPointerNull(PointerType *T)
: Constant(T,
@@ -542,12 +543,12 @@ class ConstantDataSequential : public Constant {
/// element array of i8, or a 1-element array of i32. They'll both end up in
/// the same StringMap bucket, linked up.
ConstantDataSequential *Next;
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ ConstantDataSequential(const ConstantDataSequential &) = delete;
protected:
explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data)
: Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {}
- ~ConstantDataSequential() { delete Next; }
+ ~ConstantDataSequential() override { delete Next; }
static Constant *getImpl(StringRef Bytes, Type *Ty);
@@ -653,8 +654,8 @@ private:
/// operands because it stores all of the elements of the constant as densely
/// packed data, instead of as Value*'s.
class ConstantDataArray : public ConstantDataSequential {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ ConstantDataArray(const ConstantDataArray &) = delete;
void anchor() override;
friend class ConstantDataSequential;
explicit ConstantDataArray(Type *ty, const char *Data)
@@ -676,6 +677,15 @@ public:
static Constant *get(LLVMContext &Context, ArrayRef<float> Elts);
static Constant *get(LLVMContext &Context, ArrayRef<double> Elts);
+ /// getFP() constructors - Return a constant with array type with an element
+ /// count and element type of float with precision matching the number of
+ /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits,
+ /// double for 64bits) Note that this can return a ConstantAggregateZero
+ /// object.
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint16_t> Elts);
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts);
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> Elts);
+
/// getString - This method constructs a CDS and initializes it with a text
/// string. The default behavior (AddNull==true) causes a null terminator to
/// be placed at the end of the array (increasing the length of the string by
@@ -705,8 +715,8 @@ public:
/// operands because it stores all of the elements of the constant as densely
/// packed data, instead of as Value*'s.
class ConstantDataVector : public ConstantDataSequential {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ ConstantDataVector(const ConstantDataVector &) = delete;
void anchor() override;
friend class ConstantDataSequential;
explicit ConstantDataVector(Type *ty, const char *Data)
@@ -728,6 +738,15 @@ public:
static Constant *get(LLVMContext &Context, ArrayRef<float> Elts);
static Constant *get(LLVMContext &Context, ArrayRef<double> Elts);
+ /// getFP() constructors - Return a constant with vector type with an element
+ /// count and element type of float with the precision matching the number of
+ /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits,
+ /// double for 64bits) Note that this can return a ConstantAggregateZero
+ /// object.
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint16_t> Elts);
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts);
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> Elts);
+
/// getSplat - Return a ConstantVector with the specified constant in each
/// element. The specified constant has to be a of a compatible type (i8/i16/
/// i32/i64/float/double) and must be a ConstantFP or ConstantInt.
@@ -756,7 +775,7 @@ public:
/// BlockAddress - The address of a basic block.
///
class BlockAddress : public Constant {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
void *operator new(size_t s) { return User::operator new(s, 2); }
BlockAddress(Function *F, BasicBlock *BB);
public:
@@ -1036,44 +1055,46 @@ public:
bool OnlyIfReduced = false);
/// Getelementptr form. Value* is only accepted for convenience;
- /// all elements must be Constant's.
+ /// all elements must be Constants.
///
/// \param OnlyIfReducedTy see \a getWithOperands() docs.
- static Constant *getGetElementPtr(Constant *C, ArrayRef<Constant *> IdxList,
+ static Constant *getGetElementPtr(Type *Ty, Constant *C,
+ ArrayRef<Constant *> IdxList,
bool InBounds = false,
Type *OnlyIfReducedTy = nullptr) {
return getGetElementPtr(
- C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()),
+ Ty, C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()),
InBounds, OnlyIfReducedTy);
}
- static Constant *getGetElementPtr(Constant *C, Constant *Idx,
+ static Constant *getGetElementPtr(Type *Ty, 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, OnlyIfReducedTy);
+ return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, OnlyIfReducedTy);
}
- static Constant *getGetElementPtr(Constant *C, ArrayRef<Value *> IdxList,
+ static Constant *getGetElementPtr(Type *Ty, 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.
- static Constant *getInBoundsGetElementPtr(Constant *C,
+ static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) {
- return getGetElementPtr(C, IdxList, true);
+ return getGetElementPtr(Ty, C, IdxList, true);
}
- static Constant *getInBoundsGetElementPtr(Constant *C,
+ static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C,
Constant *Idx) {
// 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, Idx, true);
+ return getGetElementPtr(Ty, C, Idx, true);
}
- static Constant *getInBoundsGetElementPtr(Constant *C,
+ static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) {
- return getGetElementPtr(C, IdxList, true);
+ return getGetElementPtr(Ty, C, IdxList, true);
}
static Constant *getExtractElement(Constant *Vec, Constant *Idx,
@@ -1125,8 +1146,9 @@ public:
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.
+ /// getAsInstruction - Returns an Instruction which implements the same
+ /// operation as this ConstantExpr. The instruction is not linked to any basic
+ /// block.
///
/// A better approach to this could be to have a constructor for Instruction
/// which would take a ConstantExpr parameter, but that would have spread
@@ -1168,8 +1190,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant)
/// LangRef.html#undefvalues for details.
///
class UndefValue : public Constant {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ UndefValue(const UndefValue &) = delete;
protected:
explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {}
protected:
diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h
index ae1ac650a9ec..997113191d19 100644
--- a/include/llvm/IR/DIBuilder.h
+++ b/include/llvm/IR/DIBuilder.h
@@ -30,38 +30,17 @@ namespace llvm {
class Value;
class Constant;
class LLVMContext;
- class MDNode;
class StringRef;
- class DIBasicType;
- class DICompileUnit;
- class DICompositeType;
- class DIDerivedType;
- class DIDescriptor;
- class DIFile;
- class DIEnumerator;
- class DIType;
- class DIGlobalVariable;
- class DIImportedEntity;
- class DINameSpace;
- class DIVariable;
- class DISubrange;
- class DILexicalBlockFile;
- class DILexicalBlock;
- class DIScope;
- class DISubprogram;
- class DITemplateTypeParameter;
- class DITemplateValueParameter;
- class DIObjCProperty;
class DIBuilder {
Module &M;
LLVMContext &VMContext;
- MDNode *TempEnumTypes;
- MDNode *TempRetainTypes;
- MDNode *TempSubprograms;
- MDNode *TempGVs;
- MDNode *TempImportedModules;
+ TempMDTuple TempEnumTypes;
+ TempMDTuple TempRetainTypes;
+ TempMDTuple TempSubprograms;
+ TempMDTuple TempGVs;
+ TempMDTuple TempImportedModules;
Function *DeclareFn; // llvm.dbg.declare
Function *ValueFn; // llvm.dbg.value
@@ -80,12 +59,12 @@ namespace llvm {
/// 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;
+ DIBuilder(const DIBuilder &) = delete;
+ void operator=(const DIBuilder &) = delete;
/// \brief Create a temporary.
///
- /// Create an \a MDNodeFwdDecl and track it in \a UnresolvedNodes.
+ /// Create an \a temporary node and track it in \a UnresolvedNodes.
void trackIfUnresolved(MDNode *N);
public:
@@ -116,6 +95,7 @@ namespace llvm {
/// @param SplitName The name of the file that we'll split debug info out
/// into.
/// @param Kind The kind of debug information to generate.
+ /// @param DWOId The DWOId if this is a split skeleton compile unit.
/// @param EmitDebugInfo A boolean flag which indicates whether debug
/// information should be written to the final
/// output or not. When this is false, debug
@@ -125,26 +105,25 @@ namespace llvm {
/// source location information in the back end
/// without actually changing the output (e.g.,
/// when using optimization remarks).
- DICompileUnit createCompileUnit(unsigned Lang, StringRef File,
- StringRef Dir, StringRef Producer,
- bool isOptimized, StringRef Flags,
- unsigned RV,
- StringRef SplitName = StringRef(),
- DebugEmissionKind Kind = FullDebug,
- bool EmitDebugInfo = true);
+ DICompileUnit *
+ createCompileUnit(unsigned Lang, StringRef File, StringRef Dir,
+ StringRef Producer, bool isOptimized, StringRef Flags,
+ unsigned RV, StringRef SplitName = StringRef(),
+ DebugEmissionKind Kind = FullDebug, uint64_t DWOId = 0,
+ bool EmitDebugInfo = true);
/// createFile - Create a file descriptor to hold debugging information
/// for a file.
- DIFile createFile(StringRef Filename, StringRef Directory);
+ DIFile *createFile(StringRef Filename, StringRef Directory);
/// createEnumerator - Create a single enumerator value.
- DIEnumerator createEnumerator(StringRef Name, int64_t Val);
+ DIEnumerator *createEnumerator(StringRef Name, int64_t Val);
/// \brief Create a DWARF unspecified type.
- DIBasicType createUnspecifiedType(StringRef Name);
+ DIBasicType *createUnspecifiedType(StringRef Name);
/// \brief Create C++11 nullptr type.
- DIBasicType createNullPtrType();
+ DIBasicType *createNullPtrType();
/// createBasicType - Create debugging information entry for a basic
/// type.
@@ -152,36 +131,36 @@ namespace llvm {
/// @param SizeInBits Size of the type.
/// @param AlignInBits Type alignment.
/// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float.
- DIBasicType createBasicType(StringRef Name, uint64_t SizeInBits,
- uint64_t AlignInBits, unsigned Encoding);
+ DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits,
+ uint64_t AlignInBits, unsigned Encoding);
/// createQualifiedType - Create debugging information entry for a qualified
/// type, e.g. 'const int'.
/// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type
/// @param FromTy Base Type.
- DIDerivedType createQualifiedType(unsigned Tag, DIType FromTy);
+ DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy);
/// createPointerType - Create debugging information entry for a pointer.
/// @param PointeeTy Type pointed by this pointer.
/// @param SizeInBits Size.
/// @param AlignInBits Alignment. (optional)
/// @param Name Pointer type name. (optional)
- DIDerivedType
- createPointerType(DIType PointeeTy, uint64_t SizeInBits,
- uint64_t AlignInBits = 0, StringRef Name = StringRef());
+ DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits,
+ uint64_t AlignInBits = 0,
+ StringRef Name = "");
/// \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,
- uint64_t SizeInBits,
- uint64_t AlignInBits = 0);
+ 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.
- DIDerivedType createReferenceType(unsigned Tag, DIType RTy);
+ DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy);
/// createTypedef - Create debugging information entry for a typedef.
/// @param Ty Original type.
@@ -189,11 +168,11 @@ namespace llvm {
/// @param File File where this type is defined.
/// @param LineNo Line number.
/// @param Context The surrounding context for the typedef.
- DIDerivedType createTypedef(DIType Ty, StringRef Name, DIFile File,
- unsigned LineNo, DIDescriptor Context);
+ DIDerivedType *createTypedef(DIType *Ty, StringRef Name, DIFile *File,
+ unsigned LineNo, DIScope *Context);
/// createFriend - Create debugging information entry for a 'friend'.
- DIDerivedType createFriend(DIType Ty, DIType FriendTy);
+ DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy);
/// createInheritance - Create debugging information entry to establish
/// inheritance relationship between two types.
@@ -202,8 +181,8 @@ namespace llvm {
/// @param BaseOffset Base offset.
/// @param Flags Flags to describe inheritance attribute,
/// e.g. private
- DIDerivedType createInheritance(DIType Ty, DIType BaseTy,
- uint64_t BaseOffset, unsigned Flags);
+ DIDerivedType *createInheritance(DIType *Ty, DIType *BaseTy,
+ uint64_t BaseOffset, unsigned Flags);
/// createMemberType - Create debugging information entry for a member.
/// @param Scope Member scope.
@@ -215,10 +194,11 @@ namespace llvm {
/// @param OffsetInBits Member offset.
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Ty Parent type.
- DIDerivedType
- createMemberType(DIDescriptor Scope, StringRef Name, DIFile File,
- unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits,
- uint64_t OffsetInBits, unsigned Flags, DIType Ty);
+ DIDerivedType *createMemberType(DIScope *Scope, StringRef Name,
+ DIFile *File, unsigned LineNo,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ DIType *Ty);
/// createStaticMemberType - Create debugging information entry for a
/// C++ static data member.
@@ -229,10 +209,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::Constant *Val);
+ DIDerivedType *createStaticMemberType(DIScope *Scope, StringRef Name,
+ DIFile *File, unsigned LineNo,
+ DIType *Ty, unsigned Flags,
+ llvm::Constant *Val);
/// createObjCIVar - Create debugging information entry for Objective-C
/// instance variable.
@@ -245,11 +225,10 @@ namespace llvm {
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Ty Parent type.
/// @param PropertyNode Property associated with this ivar.
- DIDerivedType createObjCIVar(StringRef Name, DIFile File,
- unsigned LineNo, uint64_t SizeInBits,
- uint64_t AlignInBits, uint64_t OffsetInBits,
- unsigned Flags, DIType Ty,
- MDNode *PropertyNode);
+ DIDerivedType *createObjCIVar(StringRef Name, DIFile *File, unsigned LineNo,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ DIType *Ty, MDNode *PropertyNode);
/// createObjCProperty - Create debugging information entry for Objective-C
/// property.
@@ -260,12 +239,11 @@ namespace llvm {
/// @param SetterName Name of the Objective C property setter selector.
/// @param PropertyAttributes Objective C property attributes.
/// @param Ty Type.
- DIObjCProperty createObjCProperty(StringRef Name,
- DIFile File, unsigned LineNumber,
- StringRef GetterName,
- StringRef SetterName,
- unsigned PropertyAttributes,
- DIType Ty);
+ DIObjCProperty *createObjCProperty(StringRef Name, DIFile *File,
+ unsigned LineNumber,
+ StringRef GetterName,
+ StringRef SetterName,
+ unsigned PropertyAttributes, DIType *Ty);
/// createClassType - Create debugging information entry for a class.
/// @param Scope Scope in which this class is defined.
@@ -283,14 +261,14 @@ namespace llvm {
/// for more info.
/// @param TemplateParms Template type parameters.
/// @param UniqueIdentifier A unique identifier for the class.
- DICompositeType createClassType(DIDescriptor Scope, StringRef Name,
- DIFile File, unsigned LineNumber,
- uint64_t SizeInBits, uint64_t AlignInBits,
- uint64_t OffsetInBits, unsigned Flags,
- DIType DerivedFrom, DIArray Elements,
- DIType VTableHolder = DIType(),
- MDNode *TemplateParms = nullptr,
- StringRef UniqueIdentifier = StringRef());
+ DICompositeType *createClassType(DIScope *Scope, StringRef Name,
+ DIFile *File, unsigned LineNumber,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ DIType *DerivedFrom, DINodeArray Elements,
+ DIType *VTableHolder = nullptr,
+ MDNode *TemplateParms = nullptr,
+ StringRef UniqueIdentifier = "");
/// createStructType - Create debugging information entry for a struct.
/// @param Scope Scope in which this struct is defined.
@@ -303,13 +281,11 @@ namespace llvm {
/// @param Elements Struct elements.
/// @param RunTimeLang Optional parameter, Objective-C runtime version.
/// @param UniqueIdentifier A unique identifier for the struct.
- DICompositeType createStructType(DIDescriptor Scope, StringRef Name,
- DIFile File, unsigned LineNumber,
- uint64_t SizeInBits, uint64_t AlignInBits,
- unsigned Flags, DIType DerivedFrom,
- DIArray Elements, unsigned RunTimeLang = 0,
- DIType VTableHolder = DIType(),
- StringRef UniqueIdentifier = StringRef());
+ DICompositeType *createStructType(
+ DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
+ uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags,
+ DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0,
+ DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = "");
/// createUnionType - Create debugging information entry for an union.
/// @param Scope Scope in which this union is defined.
@@ -322,24 +298,20 @@ namespace llvm {
/// @param Elements Union elements.
/// @param RunTimeLang Optional parameter, Objective-C runtime version.
/// @param UniqueIdentifier A unique identifier for the union.
- DICompositeType createUnionType(
- DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber,
- uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags,
- DIArray Elements, unsigned RunTimeLang = 0,
- StringRef UniqueIdentifier = StringRef());
+ DICompositeType *createUnionType(DIScope *Scope, StringRef Name,
+ DIFile *File, unsigned LineNumber,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ unsigned Flags, DINodeArray Elements,
+ unsigned RunTimeLang = 0,
+ StringRef UniqueIdentifier = "");
/// createTemplateTypeParameter - Create debugging information for template
/// type parameter.
/// @param Scope Scope in which this type is defined.
/// @param Name Type parameter name.
/// @param Ty Parameter type.
- /// @param File File where this type parameter is defined.
- /// @param LineNo Line number.
- /// @param ColumnNo Column Number.
- DITemplateTypeParameter
- createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
- MDNode *File = nullptr, unsigned LineNo = 0,
- unsigned ColumnNo = 0);
+ DITemplateTypeParameter *
+ createTemplateTypeParameter(DIScope *Scope, StringRef Name, DIType *Ty);
/// createTemplateValueParameter - Create debugging information for template
/// value parameter.
@@ -347,56 +319,46 @@ namespace llvm {
/// @param Name Value parameter name.
/// @param Ty Parameter type.
/// @param Val Constant parameter value.
- /// @param File File where this type parameter is defined.
- /// @param LineNo Line number.
- /// @param ColumnNo Column Number.
- DITemplateValueParameter
- createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
- Constant *Val, MDNode *File = nullptr,
- unsigned LineNo = 0, unsigned ColumnNo = 0);
+ DITemplateValueParameter *createTemplateValueParameter(DIScope *Scope,
+ StringRef Name,
+ DIType *Ty,
+ Constant *Val);
/// \brief Create debugging information for a template template parameter.
/// @param Scope Scope in which this type is defined.
/// @param Name Value parameter name.
/// @param Ty Parameter type.
/// @param Val The fully qualified name of the template.
- /// @param File File where this type parameter is defined.
- /// @param LineNo Line number.
- /// @param ColumnNo Column Number.
- DITemplateValueParameter
- createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name,
- DIType Ty, StringRef Val,
- MDNode *File = nullptr, unsigned LineNo = 0,
- unsigned ColumnNo = 0);
+ DITemplateValueParameter *createTemplateTemplateParameter(DIScope *Scope,
+ StringRef Name,
+ DIType *Ty,
+ StringRef Val);
/// \brief Create debugging information for a template parameter pack.
/// @param Scope Scope in which this type is defined.
/// @param Name Value parameter name.
/// @param Ty Parameter type.
/// @param Val An array of types in the pack.
- /// @param File File where this type parameter is defined.
- /// @param LineNo Line number.
- /// @param ColumnNo Column Number.
- DITemplateValueParameter
- createTemplateParameterPack(DIDescriptor Scope, StringRef Name,
- DIType Ty, DIArray Val, MDNode *File = nullptr,
- unsigned LineNo = 0, unsigned ColumnNo = 0);
+ DITemplateValueParameter *createTemplateParameterPack(DIScope *Scope,
+ StringRef Name,
+ DIType *Ty,
+ DINodeArray Val);
/// createArrayType - Create debugging information entry for an array.
/// @param Size Array size.
/// @param AlignInBits Alignment.
/// @param Ty Element type.
/// @param Subscripts Subscripts.
- DICompositeType createArrayType(uint64_t Size, uint64_t AlignInBits,
- DIType Ty, DIArray Subscripts);
+ DICompositeType *createArrayType(uint64_t Size, uint64_t AlignInBits,
+ DIType *Ty, DINodeArray Subscripts);
/// createVectorType - Create debugging information entry for a vector type.
/// @param Size Array size.
/// @param AlignInBits Alignment.
/// @param Ty Element type.
/// @param Subscripts Subscripts.
- DICompositeType createVectorType(uint64_t Size, uint64_t AlignInBits,
- DIType Ty, DIArray Subscripts);
+ DICompositeType *createVectorType(uint64_t Size, uint64_t AlignInBits,
+ DIType *Ty, DINodeArray Subscripts);
/// createEnumerationType - Create debugging information entry for an
/// enumeration.
@@ -409,10 +371,10 @@ namespace llvm {
/// @param Elements Enumeration elements.
/// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum.
/// @param UniqueIdentifier A unique identifier for the enum.
- DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name,
- DIFile File, unsigned LineNumber, uint64_t SizeInBits,
- uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType,
- StringRef UniqueIdentifier = StringRef());
+ DICompositeType *createEnumerationType(
+ DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
+ uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements,
+ DIType *UnderlyingType, StringRef UniqueIdentifier = "");
/// createSubroutineType - Create subroutine type.
/// @param File File in which this subroutine is defined.
@@ -420,49 +382,49 @@ namespace llvm {
/// includes return type at 0th index.
/// @param Flags E.g.: LValueReference.
/// These flags are used to emit dwarf attributes.
- DISubroutineType createSubroutineType(DIFile File,
- DITypeArray ParameterTypes,
- unsigned Flags = 0);
+ DISubroutineType *createSubroutineType(DIFile *File,
+ DITypeRefArray ParameterTypes,
+ unsigned Flags = 0);
- /// createArtificialType - Create a new DIType with "artificial" flag set.
- DIType createArtificialType(DIType Ty);
+ /// createArtificialType - Create a new DIType* with "artificial" flag set.
+ DIType *createArtificialType(DIType *Ty);
- /// createObjectPointerType - Create a new DIType with the "object pointer"
+ /// createObjectPointerType - Create a new DIType* with the "object pointer"
/// flag set.
- DIType createObjectPointerType(DIType Ty);
+ DIType *createObjectPointerType(DIType *Ty);
/// \brief Create a permanent forward-declared type.
- DICompositeType createForwardDecl(unsigned Tag, StringRef Name,
- DIDescriptor Scope, DIFile F,
- unsigned Line, unsigned RuntimeLang = 0,
- uint64_t SizeInBits = 0,
- uint64_t AlignInBits = 0,
- StringRef UniqueIdentifier = StringRef());
+ DICompositeType *createForwardDecl(unsigned Tag, StringRef Name,
+ DIScope *Scope, DIFile *F, unsigned Line,
+ unsigned RuntimeLang = 0,
+ uint64_t SizeInBits = 0,
+ uint64_t AlignInBits = 0,
+ StringRef UniqueIdentifier = "");
/// \brief Create a temporary forward-declared type.
- DICompositeType createReplaceableForwardDecl(
- unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F,
- unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0,
- uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef());
+ DICompositeType *createReplaceableCompositeType(
+ unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line,
+ unsigned RuntimeLang = 0, uint64_t SizeInBits = 0,
+ uint64_t AlignInBits = 0, unsigned Flags = DINode::FlagFwdDecl,
+ StringRef UniqueIdentifier = "");
- /// retainType - Retain DIType in a module even if it is not referenced
+ /// retainType - Retain DIType* in a module even if it is not referenced
/// through debug info anchors.
- void retainType(DIType T);
+ void retainType(DIType *T);
/// createUnspecifiedParameter - Create unspecified parameter type
/// for a subroutine type.
- DIBasicType createUnspecifiedParameter();
+ DIBasicType *createUnspecifiedParameter();
- /// getOrCreateArray - Get a DIArray, create one if required.
- DIArray getOrCreateArray(ArrayRef<Metadata *> Elements);
+ /// getOrCreateArray - Get a DINodeArray, create one if required.
+ DINodeArray getOrCreateArray(ArrayRef<Metadata *> Elements);
- /// getOrCreateTypeArray - Get a DITypeArray, create one if required.
- DITypeArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements);
+ /// getOrCreateTypeArray - Get a DITypeRefArray, create one if required.
+ DITypeRefArray 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);
-
+ DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count);
/// createGlobalVariable - Create a new descriptor for the specified
/// variable.
@@ -476,19 +438,19 @@ namespace llvm {
/// externally visible or not.
/// @param Val llvm::Value of the variable.
/// @param Decl Reference to the corresponding declaration.
- DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name,
- StringRef LinkageName, DIFile File,
- unsigned LineNo, DITypeRef Ty,
- bool isLocalToUnit,
- llvm::Constant *Val,
- MDNode *Decl = nullptr);
+ DIGlobalVariable *createGlobalVariable(DIScope *Context, StringRef Name,
+ StringRef LinkageName, DIFile *File,
+ unsigned LineNo, DIType *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);
+ DIGlobalVariable *createTempGlobalVariableFwdDecl(
+ DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File,
+ unsigned LineNo, DIType *Ty, bool isLocalToUnit, llvm::Constant *Val,
+ MDNode *Decl = nullptr);
/// createLocalVariable - Create a new descriptor for the specified
/// local variable.
@@ -504,28 +466,29 @@ namespace llvm {
/// @param Flags Flags, e.g. artificial variable.
/// @param ArgNo If this variable is an argument then this argument's
/// number. 1 indicates 1st argument.
- DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope,
- StringRef Name,
- DIFile File, unsigned LineNo,
- DITypeRef Ty, bool AlwaysPreserve = false,
- unsigned Flags = 0,
- unsigned ArgNo = 0);
+ DILocalVariable *createLocalVariable(unsigned Tag, DIScope *Scope,
+ StringRef Name, DIFile *File,
+ unsigned LineNo, DIType *Ty,
+ bool AlwaysPreserve = false,
+ unsigned Flags = 0,
+ unsigned ArgNo = 0);
/// createExpression - Create a new descriptor for the specified
/// variable which has a complex address expression for its address.
/// @param Addr An array of complex address operations.
- DIExpression createExpression(ArrayRef<int64_t> Addr = None);
+ DIExpression *createExpression(ArrayRef<uint64_t> Addr = None);
+ DIExpression *createExpression(ArrayRef<int64_t> Addr);
- /// createPieceExpression - Create a descriptor to describe one part
+ /// createBitPieceExpression - Create a descriptor to describe one part
/// of aggregate variable that is fragmented across multiple Values.
///
- /// @param OffsetInBytes Offset of the piece in bytes.
- /// @param SizeInBytes Size of the piece in bytes.
- DIExpression createPieceExpression(unsigned OffsetInBytes,
- unsigned SizeInBytes);
+ /// @param OffsetInBits Offset of the piece in bits.
+ /// @param SizeInBits Size of the piece in bits.
+ DIExpression *createBitPieceExpression(unsigned OffsetInBits,
+ unsigned SizeInBits);
/// createFunction - Create a new descriptor for the specified subprogram.
- /// See comments in DISubprogram for descriptions of these fields.
+ /// See comments in DISubprogram* for descriptions of these fields.
/// @param Scope Function scope.
/// @param Name Function name.
/// @param LinkageName Mangled function name.
@@ -540,49 +503,35 @@ namespace llvm {
/// @param isOptimized True if optimization is ON.
/// @param Fn llvm::Function pointer.
/// @param TParam Function template parameters.
- DISubprogram createFunction(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);
+ DISubprogram *
+ createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName,
+ DIFile *File, unsigned LineNo, DISubroutineType *Ty,
+ bool isLocalToUnit, bool isDefinition, unsigned ScopeLine,
+ unsigned Flags = 0, bool isOptimized = false,
+ Function *Fn = nullptr, 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);
-
+ DISubprogram *createTempFunctionFwdDecl(
+ DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File,
+ unsigned LineNo, DISubroutineType *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,
- 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);
+ DISubprogram *
+ createFunction(DIScopeRef Scope, StringRef Name, StringRef LinkageName,
+ DIFile *File, unsigned LineNo, DISubroutineType *Ty,
+ bool isLocalToUnit, bool isDefinition, unsigned ScopeLine,
+ unsigned Flags = 0, bool isOptimized = false,
+ Function *Fn = nullptr, MDNode *TParam = nullptr,
+ MDNode *Decl = nullptr);
/// createMethod - Create a new descriptor for the specified C++ method.
- /// See comments in DISubprogram for descriptions of these fields.
+ /// See comments in DISubprogram* for descriptions of these fields.
/// @param Scope Function scope.
/// @param Name Function name.
/// @param LinkageName Mangled function name.
@@ -600,17 +549,13 @@ namespace llvm {
/// @param isOptimized True if optimization is ON.
/// @param Fn llvm::Function pointer.
/// @param TParam Function template parameters.
- DISubprogram createMethod(DIDescriptor Scope, StringRef Name,
- StringRef LinkageName,
- DIFile File, unsigned LineNo,
- DICompositeType Ty, bool isLocalToUnit,
- bool isDefinition,
- unsigned Virtuality = 0, unsigned VTableIndex = 0,
- DIType VTableHolder = DIType(),
- unsigned Flags = 0,
- bool isOptimized = false,
- Function *Fn = nullptr,
- MDNode *TParam = nullptr);
+ DISubprogram *
+ createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName,
+ DIFile *File, unsigned LineNo, DISubroutineType *Ty,
+ bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0,
+ unsigned VTableIndex = 0, DIType *VTableHolder = nullptr,
+ unsigned Flags = 0, bool isOptimized = false,
+ Function *Fn = nullptr, MDNode *TParam = nullptr);
/// createNameSpace - This creates new descriptor for a namespace
/// with the specified parent scope.
@@ -618,9 +563,8 @@ namespace llvm {
/// @param Name Name of this namespace
/// @param File Source file
/// @param LineNo Line number
- DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name,
- DIFile File, unsigned LineNo);
-
+ DINamespace *createNameSpace(DIScope *Scope, StringRef Name, DIFile *File,
+ unsigned LineNo);
/// createLexicalBlockFile - This creates a descriptor for a lexical
/// block with a new file attached. This merely extends the existing
@@ -628,8 +572,8 @@ namespace llvm {
/// @param Scope Lexical block.
/// @param File Source file.
/// @param Discriminator DWARF path discriminator value.
- DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File,
- unsigned Discriminator = 0);
+ DILexicalBlockFile *createLexicalBlockFile(DIScope *Scope, DIFile *File,
+ unsigned Discriminator = 0);
/// createLexicalBlock - This creates a descriptor for a lexical block
/// with the specified parent context.
@@ -637,60 +581,63 @@ namespace llvm {
/// @param File Source file.
/// @param Line Line number.
/// @param Col Column number.
- DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File,
- unsigned Line, unsigned Col);
+ DILexicalBlock *createLexicalBlock(DIScope *Scope, DIFile *File,
+ unsigned Line, unsigned Col);
/// \brief Create a descriptor for an imported module.
/// @param Context The scope this module is imported into
/// @param NS The namespace being imported here
/// @param Line Line number
- DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS,
- unsigned Line);
+ DIImportedEntity *createImportedModule(DIScope *Context, DINamespace *NS,
+ unsigned Line);
/// \brief Create a descriptor for an imported module.
/// @param Context The scope this module is imported into
/// @param NS An aliased namespace
/// @param Line Line number
- DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS,
- unsigned Line);
+ DIImportedEntity *createImportedModule(DIScope *Context,
+ DIImportedEntity *NS, unsigned Line);
/// \brief Create a descriptor for an imported function.
/// @param Context The scope this module is imported into
/// @param Decl The declaration (or definition) of a function, type, or
/// variable
/// @param Line Line number
- DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl,
- unsigned Line,
- StringRef Name = StringRef());
- DIImportedEntity createImportedDeclaration(DIScope Context,
- DIImportedEntity NS,
- unsigned Line,
- StringRef Name = StringRef());
+ DIImportedEntity *createImportedDeclaration(DIScope *Context, DINode *Decl,
+ unsigned Line,
+ StringRef Name = "");
/// 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 DL Debug info location.
/// @param InsertAtEnd Location for the new intrinsic.
- Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
- DIExpression Expr, BasicBlock *InsertAtEnd);
+ Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo,
+ DIExpression *Expr, const DILocation *DL,
+ 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 DL Debug info location.
/// @param InsertBefore Location for the new intrinsic.
- Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
- DIExpression Expr, Instruction *InsertBefore);
+ Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo,
+ DIExpression *Expr, const DILocation *DL,
+ 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 DL Debug info location.
/// @param InsertAtEnd Location for the new intrinsic.
Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
- DIVariable VarInfo, DIExpression Expr,
+ DILocalVariable *VarInfo,
+ DIExpression *Expr,
+ const DILocation *DL,
BasicBlock *InsertAtEnd);
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
@@ -698,24 +645,45 @@ namespace llvm {
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
/// @param Expr A complex location expression.
+ /// @param DL Debug info location.
/// @param InsertBefore Location for the new intrinsic.
Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
- DIVariable VarInfo, DIExpression Expr,
+ DILocalVariable *VarInfo,
+ DIExpression *Expr,
+ const DILocation *DL,
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);
+ 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());
+ void replaceArrays(DICompositeType *&T, DINodeArray Elements,
+ DINodeArray TParems = DINodeArray());
+
+ /// \brief Replace a temporary node.
+ ///
+ /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c
+ /// Replacement.
+ ///
+ /// If \c Replacement is the same as \c N.get(), instead call \a
+ /// MDNode::replaceWithUniqued(). In this case, the uniqued node could
+ /// have a different address, so we return the final address.
+ template <class NodeTy>
+ NodeTy *replaceTemporary(TempMDNode &&N, NodeTy *Replacement) {
+ if (N.get() == Replacement)
+ return cast<NodeTy>(MDNode::replaceWithUniqued(std::move(N)));
+
+ N->replaceAllUsesWith(Replacement);
+ return Replacement;
+ }
};
} // end namespace llvm
diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h
index a9e75955ce74..3e1f9744f9e8 100644
--- a/include/llvm/IR/DataLayout.h
+++ b/include/llvm/IR/DataLayout.h
@@ -53,6 +53,11 @@ enum AlignTypeEnum {
AGGREGATE_ALIGN = 'a'
};
+// FIXME: Currently the DataLayout string carries a "preferred alignment"
+// for types. As the DataLayout is module/global, this should likely be
+// sunk down to an FTTI element that is queried rather than a global
+// preference.
+
/// \brief Layout alignment element.
///
/// Stores the alignment data associated with a given alignment type (integer,
@@ -103,7 +108,14 @@ private:
unsigned StackNaturalAlign;
- enum ManglingModeT { MM_None, MM_ELF, MM_MachO, MM_WINCOFF, MM_Mips };
+ enum ManglingModeT {
+ MM_None,
+ MM_ELF,
+ MM_MachO,
+ MM_WinCOFF,
+ MM_WinCOFFX86,
+ MM_Mips
+ };
ManglingModeT ManglingMode;
SmallVector<unsigned char, 8> LegalIntWidths;
@@ -111,6 +123,9 @@ private:
/// \brief Primitive type alignment data.
SmallVector<LayoutAlignElem, 16> Alignments;
+ /// \brief The string representation used to create this DataLayout
+ std::string StringRepresentation;
+
typedef SmallVector<PointerAlignElem, 8> PointersTy;
PointersTy Pointers;
@@ -180,6 +195,7 @@ public:
DataLayout &operator=(const DataLayout &DL) {
clear();
+ StringRepresentation = DL.StringRepresentation;
BigEndian = DL.isBigEndian();
StackNaturalAlign = DL.StackNaturalAlign;
ManglingMode = DL.ManglingMode;
@@ -204,8 +220,12 @@ public:
/// \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;
+ /// constructor above. This should not be used to compare two DataLayout as
+ /// different string can represent the same layout.
+ std::string getStringRepresentation() const { return StringRepresentation; }
+
+ /// \brief Test if the DataLayout was constructed from an empty string.
+ bool isDefault() const { return StringRepresentation.empty(); }
/// \brief Returns true if the specified type is known to be a native integer
/// type supported by the CPU.
@@ -231,7 +251,7 @@ public:
unsigned getStackAlignment() const { return StackNaturalAlign; }
bool hasMicrosoftFastStdCallMangling() const {
- return ManglingMode == MM_WINCOFF;
+ return ManglingMode == MM_WinCOFFX86;
}
bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; }
@@ -239,7 +259,7 @@ public:
const char *getLinkerPrivateGlobalPrefix() const {
if (ManglingMode == MM_MachO)
return "l";
- return getPrivateGlobalPrefix();
+ return "";
}
char getGlobalPrefix() const {
@@ -247,9 +267,10 @@ public:
case MM_None:
case MM_ELF:
case MM_Mips:
+ case MM_WinCOFF:
return '\0';
case MM_MachO:
- case MM_WINCOFF:
+ case MM_WinCOFFX86:
return '_';
}
llvm_unreachable("invalid mangling mode");
@@ -264,7 +285,8 @@ public:
case MM_Mips:
return "$";
case MM_MachO:
- case MM_WINCOFF:
+ case MM_WinCOFF:
+ case MM_WinCOFFX86:
return "L";
}
llvm_unreachable("invalid mangling mode");
@@ -446,22 +468,6 @@ inline LLVMTargetDataRef wrap(const DataLayout *P) {
return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout *>(P));
}
-class DataLayoutPass : public ImmutablePass {
- DataLayout DL;
-
-public:
- /// This has to exist, because this is a pass, but it should never be used.
- DataLayoutPass();
- ~DataLayoutPass();
-
- const DataLayout &getDataLayout() const { return DL; }
-
- static char ID; // Pass identification, replacement for typeid
-
- bool doFinalization(Module &M) override;
- bool doInitialization(Module &M) override;
-};
-
/// Used to lazily calculate structure layout information for a target machine,
/// based on the DataLayout structure.
class StructLayout {
diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h
index 5c85d6d52824..5429648ade2c 100644
--- a/include/llvm/IR/DebugInfo.h
+++ b/include/llvm/IR/DebugInfo.h
@@ -22,990 +22,30 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
-#include "llvm/IR/Metadata.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include <iterator>
namespace llvm {
-class BasicBlock;
-class Constant;
-class Function;
-class GlobalVariable;
class Module;
-class Type;
-class Value;
class DbgDeclareInst;
class DbgValueInst;
-class Instruction;
-class Metadata;
-class MDNode;
-class MDString;
-class NamedMDNode;
-class LLVMContext;
-class raw_ostream;
-
-class DIFile;
-class DISubprogram;
-class DILexicalBlock;
-class DILexicalBlockFile;
-class DIVariable;
-class DIType;
-class DIScope;
-class DIObjCProperty;
/// \brief Maps from type identifier to the actual MDNode.
-typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap;
-
-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 {
- FlagAccessibility = 1 << 0 | 1 << 1,
- FlagPrivate = 1,
- FlagProtected = 2,
- FlagPublic = 3,
-
- FlagFwdDecl = 1 << 2,
- FlagAppleBlock = 1 << 3,
- FlagBlockByrefStruct = 1 << 4,
- FlagVirtual = 1 << 5,
- FlagArtificial = 1 << 6,
- FlagExplicit = 1 << 7,
- FlagPrototyped = 1 << 8,
- FlagObjcClassComplete = 1 << 9,
- FlagObjectPointer = 1 << 10,
- FlagVector = 1 << 11,
- FlagStaticMember = 1 << 12,
- FlagIndirectVariable = 1 << 13,
- FlagLValueReference = 1 << 14,
- FlagRValueReference = 1 << 15
- };
-
-protected:
- const MDNode *DbgNode;
-
- StringRef getStringField(unsigned Elt) const;
- unsigned getUnsignedField(unsigned Elt) const {
- return (unsigned)getUInt64Field(Elt);
- }
- uint64_t getUInt64Field(unsigned Elt) const;
- int64_t getInt64Field(unsigned Elt) const;
- DIDescriptor getDescriptorField(unsigned Elt) const;
-
- template <typename DescTy> DescTy getFieldAs(unsigned Elt) const {
- return DescTy(getDescriptorField(Elt));
- }
-
- GlobalVariable *getGlobalVariableField(unsigned Elt) const;
- Constant *getConstantField(unsigned Elt) const;
- Function *getFunctionField(unsigned Elt) const;
- void replaceFunctionField(unsigned Elt, Function *F);
-
-public:
- explicit DIDescriptor(const MDNode *N = nullptr) : DbgNode(N) {}
-
- bool Verify() const;
-
- MDNode *get() const { return const_cast<MDNode *>(DbgNode); }
- operator MDNode *() const { return get(); }
- MDNode *operator->() const { return get(); }
-
- // An explicit operator bool so that we can do testing of DI values
- // easily.
- // FIXME: This operator bool isn't actually protecting anything at the
- // moment due to the conversion operator above making DIDescriptor nodes
- // implicitly convertable to bool.
- LLVM_EXPLICIT operator bool() const { return DbgNode != nullptr; }
-
- bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; }
- bool operator!=(DIDescriptor Other) const { return !operator==(Other); }
-
- 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;
- bool isGlobalVariable() const;
- bool isScope() const;
- bool isFile() const;
- bool isCompileUnit() const;
- bool isNameSpace() const;
- bool isLexicalBlockFile() const;
- bool isLexicalBlock() const;
- bool isSubrange() const;
- bool isEnumerator() const;
- bool isType() const;
- bool isTemplateTypeParameter() const;
- bool isTemplateValueParameter() const;
- bool isObjCProperty() const;
- bool isImportedEntity() const;
- bool isExpression() const;
-
- void print(raw_ostream &OS) const;
- void dump() const;
-
- /// \brief Replace all uses of debug info referenced by this descriptor.
- void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D);
- void replaceAllUsesWith(MDNode *D);
-};
-
-/// \brief This is used to represent ranges, for array bounds.
-class DISubrange : public DIDescriptor {
- friend class DIDescriptor;
- void printInternal(raw_ostream &OS) const;
-
-public:
- explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {}
-
- int64_t getLo() const { return getHeaderFieldAs<int64_t>(1); }
- int64_t getCount() const { return getHeaderFieldAs<int64_t>(2); }
- bool Verify() const;
-};
-
-/// \brief This descriptor holds an array of nodes with type T.
-template <typename T> class DITypedArray : public DIDescriptor {
-public:
- 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);
- }
-};
-
-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 {
- friend class DIDescriptor;
- void printInternal(raw_ostream &OS) const;
-
-public:
- explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {}
-
- 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;
-
-/// \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
-/// DIScope's descendants are not a substitutable subtype of
-/// DIScope. The DIDescriptor::isScope() method only is true for
-/// DIScopes that are scopes in the strict lexical scope sense
-/// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType.
-class DIScope : public DIDescriptor {
-protected:
- friend class DIDescriptor;
- void printInternal(raw_ostream &OS) const;
-
-public:
- explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {}
-
- /// \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;
-
- /// \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;
-};
-
-/// \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;
- friend DIScopeRef DIScope::getContext() const;
- friend DIScopeRef DIScope::getRef() const;
- friend class DIType;
-
- /// \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 Metadata *() const { return const_cast<Metadata *>(Val); }
-};
-
-template <typename T>
-T DIRef<T>::resolve(const DITypeIdentifierMap &Map) const {
- if (!Val)
- return T();
-
- if (const MDNode *MD = dyn_cast<MDNode>(Val))
- return T(MD);
-
- const MDString *MS = cast<MDString>(Val);
- // Find the corresponding MDNode.
- DITypeIdentifierMap::const_iterator Iter = Map.find(MS);
- assert(Iter != Map.end() && "Identifier not in the type map?");
- assert(DIDescriptor(Iter->second).isType() &&
- "MDNode in DITypeIdentifierMap should be a DIType.");
- return T(Iter->second);
-}
-
-template <typename T> StringRef DIRef<T>::getName() const {
- if (!Val)
- return StringRef();
-
- if (const MDNode *MD = dyn_cast<MDNode>(Val))
- return T(MD).getName();
-
- const MDString *MS = cast<MDString>(Val);
- return MS->getString();
-}
-
-/// \brief Handle fields that are references to DIScopes.
-template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
-/// \brief Specialize DIRef constructor for DIScopeRef.
-template <> DIRef<DIScope>::DIRef(const Metadata *V);
-
-/// \brief Handle fields that are references to DITypes.
-template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
-/// \brief Specialize DIRef constructor for DITypeRef.
-template <> DIRef<DIType>::DIRef(const Metadata *V);
-
-/// \briefThis is a wrapper for a type.
-///
-/// FIXME: Types should be factored much better so that CV qualifiers and
-/// others do not require a huge and empty descriptor full of zeros.
-class DIType : public DIScope {
-protected:
- friend class DIDescriptor;
- void printInternal(raw_ostream &OS) const;
-
-public:
- explicit DIType(const MDNode *N = nullptr) : DIScope(N) {}
- operator DITypeRef () const {
- assert(isType() &&
- "constructing DITypeRef from an MDNode that is not a type");
- return DITypeRef(&*getRef());
- }
-
- bool Verify() const;
-
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
- StringRef getName() const { return getHeaderField(1); }
- unsigned getLineNumber() const {
- return getHeaderFieldAs<unsigned>(2);
- }
- uint64_t getSizeInBits() const {
- return getHeaderFieldAs<unsigned>(3);
- }
- uint64_t getAlignInBits() const {
- return getHeaderFieldAs<unsigned>(4);
- }
- // FIXME: Offset is only used for DW_TAG_member nodes. Making every type
- // carry this is just plain insane.
- uint64_t getOffsetInBits() const {
- return getHeaderFieldAs<unsigned>(5);
- }
- 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; }
- bool isAppleBlockExtension() const {
- return (getFlags() & FlagAppleBlock) != 0;
- }
- bool isBlockByrefStruct() const {
- return (getFlags() & FlagBlockByrefStruct) != 0;
- }
- bool isVirtual() const { return (getFlags() & FlagVirtual) != 0; }
- bool isArtificial() const { return (getFlags() & FlagArtificial) != 0; }
- bool isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; }
- bool isObjcClassComplete() const {
- return (getFlags() & FlagObjcClassComplete) != 0;
- }
- bool isVector() const { return (getFlags() & FlagVector) != 0; }
- bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; }
- bool isLValueReference() const {
- return (getFlags() & FlagLValueReference) != 0;
- }
- bool isRValueReference() const {
- return (getFlags() & FlagRValueReference) != 0;
- }
- bool isValid() const { return DbgNode && isType(); }
-};
-
-/// \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 getHeaderFieldAs<unsigned>(7); }
-
- bool Verify() const;
-};
-
-/// \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;
-
-public:
- explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {}
-
- DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(3); }
-
- /// \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>(4);
- }
-
- Constant *getConstant() const {
- assert((getTag() == dwarf::DW_TAG_member) && isStaticMember());
- return getConstantField(4);
- }
-
- bool Verify() const;
-};
-
-/// \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 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);
-
-public:
- DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); }
- MDString *getIdentifier() const;
-
- bool Verify() const;
-};
-
-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;
-};
-
-/// \brief A wrapper for a compile unit.
-class DICompileUnit : public DIScope {
- friend class DIDescriptor;
- void printInternal(raw_ostream &OS) const;
-
-public:
- explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {}
-
- dwarf::SourceLanguage getLanguage() const {
- return static_cast<dwarf::SourceLanguage>(getHeaderFieldAs<unsigned>(1));
- }
- StringRef getProducer() const { return getHeaderField(2); }
-
- 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;
- DIArray getSubprograms() const;
- DIArray getGlobalVariables() const;
- DIArray getImportedEntities() const;
-
- void replaceSubprograms(DIArray Subprograms);
- void replaceGlobalVariables(DIArray GlobalVariables);
-
- StringRef getSplitDebugFilename() const { return getHeaderField(6); }
- unsigned getEmissionKind() const { return getHeaderFieldAs<unsigned>(7); }
-
- bool Verify() const;
-};
-
-/// \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;
-
-public:
- explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {}
-
- 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); }
-
- /// \brief Check if this is local (like 'static' in C).
- unsigned isLocalToUnit() const { return getHeaderFieldAs<unsigned>(5); }
- unsigned isDefinition() const { return getHeaderFieldAs<unsigned>(6); }
-
- unsigned getVirtuality() const { return getHeaderFieldAs<unsigned>(7); }
- unsigned getVirtualIndex() const { return getHeaderFieldAs<unsigned>(8); }
-
- unsigned getFlags() const { return getHeaderFieldAs<unsigned>(9); }
-
- unsigned isOptimized() const { return getHeaderFieldAs<bool>(10); }
-
- /// \brief Get the beginning of the scope of the function (not the name).
- unsigned getScopeLineNumber() const { return getHeaderFieldAs<unsigned>(11); }
-
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
- DISubroutineType getType() const { return getFieldAs<DISubroutineType>(3); }
-
- DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(4); }
-
- bool Verify() const;
-
- /// \brief Check if this provides debugging information for the function F.
- bool describes(const Function *F);
-
- 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>(7);
- }
- MDNode *getVariablesNodes() const;
- DIArray getVariables() const;
-
- 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;
- }
-
-};
-
-/// \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 getHeaderFieldAs<unsigned>(1);
- }
- unsigned getColumnNumber() const {
- return getHeaderFieldAs<unsigned>(2);
- }
- bool Verify() const;
-};
-
-/// \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) {}
- DIScope getContext() const {
- if (getScope().isSubprogram())
- return getScope();
- return getScope().getContext();
- }
- unsigned getLineNumber() const { return getScope().getLineNumber(); }
- unsigned getColumnNumber() const { return getScope().getColumnNumber(); }
- DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); }
- unsigned getDiscriminator() const { return getHeaderFieldAs<unsigned>(1); }
- bool Verify() const;
-};
-
-/// \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); }
- bool Verify() const;
-};
-
-/// \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); }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
- StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); }
- StringRef getDirectory() const {
- return getFieldAs<DIFile>(3).getDirectory();
- }
- bool Verify() const;
-};
-
-/// \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); }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
- Metadata *getValue() const;
- StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); }
- StringRef getDirectory() const {
- return getFieldAs<DIFile>(4).getDirectory();
- }
- bool Verify() const;
-};
-
-/// \brief This is a wrapper for a global variable.
-class DIGlobalVariable : public DIDescriptor {
- friend class DIDescriptor;
- void printInternal(raw_ostream &OS) const;
-
-public:
- explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {}
-
- 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>(2).getDirectory();
- }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
-
- GlobalVariable *getGlobal() const { return getGlobalVariableField(4); }
- Constant *getConstant() const { return getConstantField(4); }
- DIDerivedType getStaticDataMemberDeclaration() const {
- return getFieldAs<DIDerivedType>(5);
- }
-
- bool Verify() const;
-};
-
-/// \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;
-
-public:
- explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {}
-
- 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;
- }
- 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); }
-
- /// \brief Return true if this variable is marked as "artificial".
- bool isArtificial() const {
- return (getHeaderFieldAs<unsigned>(3) & FlagArtificial) != 0;
- }
-
- bool isObjectPointer() const {
- return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0;
- }
-
- /// \brief Return true if this variable is represented as a pointer.
- bool isIndirect() const {
- return (getHeaderFieldAs<unsigned>(3) & FlagIndirectVariable) != 0;
- }
-
- /// \brief If this variable is inlined then return inline location.
- MDNode *getInlinedAt() const;
-
- bool Verify() const;
-
- /// \brief Check if this is a "__block" variable (Apple Blocks).
- bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const {
- return (getType().resolve(Map)).isBlockByrefStruct();
- }
-
- /// \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;
-};
-
-/// \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 {
- 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;
- bool atSameLineAs(const DILocation &Other) const {
- return (getLineNumber() == Other.getLineNumber() &&
- getFilename() == Other.getFilename());
- }
- /// \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().isLexicalBlockFile()
- ? DILexicalBlockFile(
- cast<MDNode>(cast<MDLocation>(DbgNode)->getScope()))
- .getDiscriminator()
- : 0;
- }
-
- /// \brief Generate a new discriminator value for this location.
- unsigned computeNewDiscriminator(LLVMContext &Ctx);
-
- /// \brief Return a copy of this location with a different scope.
- DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope);
-};
-
-class DIObjCProperty : public DIDescriptor {
- friend class DIDescriptor;
- void printInternal(raw_ostream &OS) const;
-
-public:
- explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {}
-
- StringRef getObjCPropertyName() const { return getHeaderField(1); }
- DIFile getFile() const { return getFieldAs<DIFile>(1); }
- unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
-
- StringRef getObjCPropertyGetterName() const { return getHeaderField(3); }
- StringRef getObjCPropertySetterName() const { return getHeaderField(4); }
- unsigned getAttributes() const { return getHeaderFieldAs<unsigned>(5); }
- bool isReadOnlyObjCProperty() const {
- return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0;
- }
- bool isReadWriteObjCProperty() const {
- return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0;
- }
- bool isAssignObjCProperty() const {
- return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0;
- }
- bool isRetainObjCProperty() const {
- return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0;
- }
- bool isCopyObjCProperty() const {
- return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0;
- }
- bool isNonAtomicObjCProperty() const {
- return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0;
- }
-
- /// \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>(2); }
-
- bool Verify() const;
-};
-
-/// \brief An imported module (C++ using directive or similar).
-class DIImportedEntity : public DIDescriptor {
- friend class DIDescriptor;
- void printInternal(raw_ostream &OS) const;
-
-public:
- explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {}
- DIScope getContext() const { return getFieldAs<DIScope>(1); }
- DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); }
- unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); }
- StringRef getName() const { return getHeaderField(2); }
- bool Verify() const;
-};
+typedef DenseMap<const MDString *, DIType *> DITypeIdentifierMap;
/// \brief Find subprogram that is enclosing this scope.
-DISubprogram getDISubprogram(const MDNode *Scope);
+DISubprogram *getDISubprogram(const MDNode *Scope);
/// \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);
-
-/// \brief Find underlying composite type.
-DICompositeType getDICompositeType(DIType T);
-
-/// \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);
+/// \returns a valid subprogram, if found. Otherwise, return \c nullptr.
+DISubprogram *getDISubprogram(const Function *F);
-/// \brief Remove inlined scope from the variable.
-DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext);
+/// \brief Find underlying composite type.
+DICompositeTypeBase *getDICompositeType(DIType *T);
/// \brief Generate map by visiting all retained types.
DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes);
@@ -1016,6 +56,7 @@ DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes);
/// metadata for debugging. We also remove debug locations for instructions.
/// Return true if module is modified.
bool StripDebugInfo(Module &M);
+bool stripDebugInfo(Function &F);
/// \brief Return Debug Info Metadata Version by checking module flags.
unsigned getDebugMetadataVersionFromModule(const Module &M);
@@ -1039,8 +80,8 @@ public:
void processDeclare(const Module &M, const DbgDeclareInst *DDI);
/// \brief Process DbgValueInst.
void processValue(const Module &M, const DbgValueInst *DVI);
- /// \brief Process DILocation.
- void processLocation(const Module &M, DILocation Loc);
+ /// \brief Process debug info location.
+ void processLocation(const Module &M, const DILocation *Loc);
/// \brief Clear all lists.
void reset();
@@ -1048,21 +89,23 @@ public:
private:
void InitializeTypeMap(const Module &M);
- void processType(DIType DT);
- void processSubprogram(DISubprogram SP);
- void processScope(DIScope Scope);
- bool addCompileUnit(DICompileUnit CU);
- bool addGlobalVariable(DIGlobalVariable DIG);
- bool addSubprogram(DISubprogram SP);
- bool addType(DIType DT);
- bool addScope(DIScope Scope);
+ void processType(DIType *DT);
+ void processSubprogram(DISubprogram *SP);
+ void processScope(DIScope *Scope);
+ bool addCompileUnit(DICompileUnit *CU);
+ bool addGlobalVariable(DIGlobalVariable *DIG);
+ bool addSubprogram(DISubprogram *SP);
+ bool addType(DIType *DT);
+ bool addScope(DIScope *Scope);
public:
- typedef SmallVectorImpl<DICompileUnit>::const_iterator compile_unit_iterator;
- typedef SmallVectorImpl<DISubprogram>::const_iterator subprogram_iterator;
- typedef SmallVectorImpl<DIGlobalVariable>::const_iterator global_variable_iterator;
- typedef SmallVectorImpl<DIType>::const_iterator type_iterator;
- typedef SmallVectorImpl<DIScope>::const_iterator scope_iterator;
+ typedef SmallVectorImpl<DICompileUnit *>::const_iterator
+ compile_unit_iterator;
+ typedef SmallVectorImpl<DISubprogram *>::const_iterator subprogram_iterator;
+ typedef SmallVectorImpl<DIGlobalVariable *>::const_iterator
+ global_variable_iterator;
+ typedef SmallVectorImpl<DIType *>::const_iterator type_iterator;
+ typedef SmallVectorImpl<DIScope *>::const_iterator scope_iterator;
iterator_range<compile_unit_iterator> compile_units() const {
return iterator_range<compile_unit_iterator>(CUs.begin(), CUs.end());
@@ -1091,19 +134,19 @@ public:
unsigned scope_count() const { return Scopes.size(); }
private:
- SmallVector<DICompileUnit, 8> CUs;
- SmallVector<DISubprogram, 8> SPs;
- SmallVector<DIGlobalVariable, 8> GVs;
- SmallVector<DIType, 8> TYs;
- SmallVector<DIScope, 8> Scopes;
- SmallPtrSet<MDNode *, 64> NodesSeen;
+ SmallVector<DICompileUnit *, 8> CUs;
+ SmallVector<DISubprogram *, 8> SPs;
+ SmallVector<DIGlobalVariable *, 8> GVs;
+ SmallVector<DIType *, 8> TYs;
+ SmallVector<DIScope *, 8> Scopes;
+ SmallPtrSet<const MDNode *, 64> NodesSeen;
DITypeIdentifierMap TypeIdentifierMap;
/// \brief Specify if TypeIdentifierMap is initialized.
bool TypeMapInitialized;
};
-DenseMap<const Function *, DISubprogram> makeSubprogramMap(const Module &M);
+DenseMap<const Function *, DISubprogram *> makeSubprogramMap(const Module &M);
} // end namespace llvm
diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def
new file mode 100644
index 000000000000..d5de8683fd3b
--- /dev/null
+++ b/include/llvm/IR/DebugInfoFlags.def
@@ -0,0 +1,36 @@
+//===- llvm/IR/DebugInfoFlags.def - Debug info flag definitions -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Macros for running through debug info flags.
+//
+//===----------------------------------------------------------------------===//
+
+// TODO: Add other DW-based macros.
+#ifndef HANDLE_DI_FLAG
+#error "Missing macro definition of HANDLE_DI_FLAG"
+#endif
+
+HANDLE_DI_FLAG(1, Private)
+HANDLE_DI_FLAG(2, Protected)
+HANDLE_DI_FLAG(3, Public)
+HANDLE_DI_FLAG((1 << 2), FwdDecl)
+HANDLE_DI_FLAG((1 << 3), AppleBlock)
+HANDLE_DI_FLAG((1 << 4), BlockByrefStruct)
+HANDLE_DI_FLAG((1 << 5), Virtual)
+HANDLE_DI_FLAG((1 << 6), Artificial)
+HANDLE_DI_FLAG((1 << 7), Explicit)
+HANDLE_DI_FLAG((1 << 8), Prototyped)
+HANDLE_DI_FLAG((1 << 9), ObjcClassComplete)
+HANDLE_DI_FLAG((1 << 10), ObjectPointer)
+HANDLE_DI_FLAG((1 << 11), Vector)
+HANDLE_DI_FLAG((1 << 12), StaticMember)
+HANDLE_DI_FLAG((1 << 13), LValueReference)
+HANDLE_DI_FLAG((1 << 14), RValueReference)
+
+#undef HANDLE_DI_FLAG
diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h
new file mode 100644
index 000000000000..0125de5d40f5
--- /dev/null
+++ b/include/llvm/IR/DebugInfoMetadata.h
@@ -0,0 +1,2227 @@
+//===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Declarations for metadata specific to debug info.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_DEBUGINFOMETADATA_H
+#define LLVM_IR_DEBUGINFOMETADATA_H
+
+#include "llvm/IR/Metadata.h"
+#include "llvm/Support/Dwarf.h"
+
+// Helper macros for defining get() overrides.
+#define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__
+#define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS
+#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \
+ static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \
+ return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \
+ } \
+ static CLASS *getIfExists(LLVMContext &Context, \
+ DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \
+ return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \
+ /* ShouldCreate */ false); \
+ } \
+ static CLASS *getDistinct(LLVMContext &Context, \
+ DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \
+ return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \
+ } \
+ static Temp##CLASS getTemporary(LLVMContext &Context, \
+ DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \
+ return Temp##CLASS( \
+ getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \
+ }
+
+namespace llvm {
+
+/// \brief Pointer union between a subclass of DINode and MDString.
+///
+/// \a DICompositeType can be referenced via an \a MDString unique identifier.
+/// This class allows some type safety in the face of that, requiring either a
+/// node of a particular type or an \a MDString.
+template <class T> class TypedDINodeRef {
+ const Metadata *MD = nullptr;
+
+public:
+ TypedDINodeRef() = default;
+ TypedDINodeRef(std::nullptr_t) {}
+
+ /// \brief Construct from a raw pointer.
+ explicit TypedDINodeRef(const Metadata *MD) : MD(MD) {
+ assert((!MD || isa<MDString>(MD) || isa<T>(MD)) && "Expected valid ref");
+ }
+
+ template <class U>
+ TypedDINodeRef(
+ const TypedDINodeRef<U> &X,
+ typename std::enable_if<std::is_convertible<U *, T *>::value>::type * =
+ nullptr)
+ : MD(X) {}
+
+ operator Metadata *() const { return const_cast<Metadata *>(MD); }
+
+ bool operator==(const TypedDINodeRef<T> &X) const { return MD == X.MD; };
+ bool operator!=(const TypedDINodeRef<T> &X) const { return MD != X.MD; };
+
+ /// \brief Create a reference.
+ ///
+ /// Get a reference to \c N, using an \a MDString reference if available.
+ static TypedDINodeRef get(const T *N);
+
+ template <class MapTy> T *resolve(const MapTy &Map) const {
+ if (!MD)
+ return nullptr;
+
+ if (auto *Typed = dyn_cast<T>(MD))
+ return const_cast<T *>(Typed);
+
+ auto *S = cast<MDString>(MD);
+ auto I = Map.find(S);
+ assert(I != Map.end() && "Missing identifier in type map");
+ return cast<T>(I->second);
+ }
+};
+
+typedef TypedDINodeRef<DINode> DINodeRef;
+typedef TypedDINodeRef<DIScope> DIScopeRef;
+typedef TypedDINodeRef<DIType> DITypeRef;
+
+class DITypeRefArray {
+ const MDTuple *N = nullptr;
+
+public:
+ DITypeRefArray(const MDTuple *N) : N(N) {}
+
+ explicit operator bool() const { return get(); }
+ explicit operator MDTuple *() const { return get(); }
+
+ MDTuple *get() const { return const_cast<MDTuple *>(N); }
+ MDTuple *operator->() const { return get(); }
+ MDTuple &operator*() const { return *get(); }
+
+ // FIXME: Fix callers and remove condition on N.
+ unsigned size() const { return N ? N->getNumOperands() : 0u; }
+ DITypeRef operator[](unsigned I) const { return DITypeRef(N->getOperand(I)); }
+
+ class iterator : std::iterator<std::input_iterator_tag, DITypeRef,
+ std::ptrdiff_t, void, DITypeRef> {
+ MDNode::op_iterator I = nullptr;
+
+ public:
+ iterator() = default;
+ explicit iterator(MDNode::op_iterator I) : I(I) {}
+ DITypeRef operator*() const { return DITypeRef(*I); }
+ iterator &operator++() {
+ ++I;
+ return *this;
+ }
+ iterator operator++(int) {
+ iterator Temp(*this);
+ ++I;
+ return Temp;
+ }
+ bool operator==(const iterator &X) const { return I == X.I; }
+ bool operator!=(const iterator &X) const { return I != X.I; }
+ };
+
+ // FIXME: Fix callers and remove condition on N.
+ iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); }
+ iterator end() const { return N ? iterator(N->op_end()) : iterator(); }
+};
+
+/// \brief Tagged DWARF-like metadata node.
+///
+/// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*,
+/// defined in llvm/Support/Dwarf.h). Called \a DINode because it's
+/// potentially used for non-DWARF output.
+class DINode : public MDNode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+protected:
+ DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+ ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None)
+ : MDNode(C, ID, Storage, Ops1, Ops2) {
+ assert(Tag < 1u << 16);
+ SubclassData16 = Tag;
+ }
+ ~DINode() = default;
+
+ template <class Ty> Ty *getOperandAs(unsigned I) const {
+ return cast_or_null<Ty>(getOperand(I));
+ }
+
+ StringRef getStringOperand(unsigned I) const {
+ if (auto *S = getOperandAs<MDString>(I))
+ return S->getString();
+ return StringRef();
+ }
+
+ static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) {
+ if (S.empty())
+ return nullptr;
+ return MDString::get(Context, S);
+ }
+
+public:
+ unsigned getTag() const { return SubclassData16; }
+
+ /// \brief Debug info flags.
+ ///
+ /// The three accessibility flags are mutually exclusive and rolled together
+ /// in the first two bits.
+ enum DIFlags {
+#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID,
+#include "llvm/IR/DebugInfoFlags.def"
+ FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic
+ };
+
+ static unsigned getFlag(StringRef Flag);
+ static const char *getFlagString(unsigned Flag);
+
+ /// \brief Split up a flags bitfield.
+ ///
+ /// Split \c Flags into \c SplitFlags, a vector of its components. Returns
+ /// any remaining (unrecognized) bits.
+ static unsigned splitFlags(unsigned Flags,
+ SmallVectorImpl<unsigned> &SplitFlags);
+
+ DINodeRef getRef() const { return DINodeRef::get(this); }
+
+ static bool classof(const Metadata *MD) {
+ switch (MD->getMetadataID()) {
+ default:
+ return false;
+ case GenericDINodeKind:
+ case DISubrangeKind:
+ case DIEnumeratorKind:
+ case DIBasicTypeKind:
+ case DIDerivedTypeKind:
+ case DICompositeTypeKind:
+ case DISubroutineTypeKind:
+ case DIFileKind:
+ case DICompileUnitKind:
+ case DISubprogramKind:
+ case DILexicalBlockKind:
+ case DILexicalBlockFileKind:
+ case DINamespaceKind:
+ case DITemplateTypeParameterKind:
+ case DITemplateValueParameterKind:
+ case DIGlobalVariableKind:
+ case DILocalVariableKind:
+ case DIObjCPropertyKind:
+ case DIImportedEntityKind:
+ return true;
+ }
+ }
+};
+
+template <class T> struct simplify_type<const TypedDINodeRef<T>> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(const TypedDINodeRef<T> &MD) {
+ return MD;
+ }
+};
+
+template <class T>
+struct simplify_type<TypedDINodeRef<T>>
+ : simplify_type<const TypedDINodeRef<T>> {};
+
+/// \brief Generic tagged DWARF-like metadata node.
+///
+/// An un-specialized DWARF-like metadata node. The first operand is a
+/// (possibly empty) null-separated \a MDString header that contains arbitrary
+/// fields. The remaining operands are \a dwarf_operands(), and are pointers
+/// to other metadata.
+class GenericDINode : public DINode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash,
+ unsigned Tag, ArrayRef<Metadata *> Ops1,
+ ArrayRef<Metadata *> Ops2)
+ : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) {
+ setHash(Hash);
+ }
+ ~GenericDINode() { dropAllReferences(); }
+
+ void setHash(unsigned Hash) { SubclassData32 = Hash; }
+ void recalculateHash();
+
+ static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag,
+ StringRef Header, ArrayRef<Metadata *> DwarfOps,
+ StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(Context, Tag, getCanonicalMDString(Context, Header),
+ DwarfOps, Storage, ShouldCreate);
+ }
+
+ static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag,
+ MDString *Header, ArrayRef<Metadata *> DwarfOps,
+ StorageType Storage, bool ShouldCreate = true);
+
+ TempGenericDINode cloneImpl() const {
+ return getTemporary(
+ getContext(), getTag(), getHeader(),
+ SmallVector<Metadata *, 4>(dwarf_op_begin(), dwarf_op_end()));
+ }
+
+public:
+ unsigned getHash() const { return SubclassData32; }
+
+ DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, StringRef Header,
+ ArrayRef<Metadata *> DwarfOps),
+ (Tag, Header, DwarfOps))
+ DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, MDString *Header,
+ ArrayRef<Metadata *> DwarfOps),
+ (Tag, Header, DwarfOps))
+
+ /// \brief Return a (temporary) clone of this.
+ TempGenericDINode clone() const { return cloneImpl(); }
+
+ unsigned getTag() const { return SubclassData16; }
+ StringRef getHeader() const { return getStringOperand(0); }
+
+ op_iterator dwarf_op_begin() const { return op_begin() + 1; }
+ op_iterator dwarf_op_end() const { return op_end(); }
+ op_range dwarf_operands() const {
+ return op_range(dwarf_op_begin(), dwarf_op_end());
+ }
+
+ unsigned getNumDwarfOperands() const { return getNumOperands() - 1; }
+ const MDOperand &getDwarfOperand(unsigned I) const {
+ return getOperand(I + 1);
+ }
+ void replaceDwarfOperandWith(unsigned I, Metadata *New) {
+ replaceOperandWith(I + 1, New);
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == GenericDINodeKind;
+ }
+};
+
+/// \brief Array subrange.
+///
+/// TODO: Merge into node for DW_TAG_array_type, which should have a custom
+/// type.
+class DISubrange : public DINode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ int64_t Count;
+ int64_t LowerBound;
+
+ DISubrange(LLVMContext &C, StorageType Storage, int64_t Count,
+ int64_t LowerBound)
+ : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None),
+ Count(Count), LowerBound(LowerBound) {}
+ ~DISubrange() = default;
+
+ static DISubrange *getImpl(LLVMContext &Context, int64_t Count,
+ int64_t LowerBound, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDISubrange cloneImpl() const {
+ return getTemporary(getContext(), getCount(), getLowerBound());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0),
+ (Count, LowerBound))
+
+ TempDISubrange clone() const { return cloneImpl(); }
+
+ int64_t getLowerBound() const { return LowerBound; }
+ int64_t getCount() const { return Count; }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DISubrangeKind;
+ }
+};
+
+/// \brief Enumeration value.
+///
+/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no
+/// longer creates a type cycle.
+class DIEnumerator : public DINode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ int64_t Value;
+
+ DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value,
+ ArrayRef<Metadata *> Ops)
+ : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
+ Value(Value) {}
+ ~DIEnumerator() = default;
+
+ static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value,
+ StringRef Name, StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage,
+ ShouldCreate);
+ }
+ static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value,
+ MDString *Name, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDIEnumerator cloneImpl() const {
+ return getTemporary(getContext(), getValue(), getName());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, StringRef Name),
+ (Value, Name))
+ DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, MDString *Name),
+ (Value, Name))
+
+ TempDIEnumerator clone() const { return cloneImpl(); }
+
+ int64_t getValue() const { return Value; }
+ StringRef getName() const { return getStringOperand(0); }
+
+ MDString *getRawName() const { return getOperandAs<MDString>(0); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIEnumeratorKind;
+ }
+};
+
+/// \brief Base class for scope-like contexts.
+///
+/// Base class for lexical scopes and types (which are also declaration
+/// contexts).
+///
+/// TODO: Separate the concepts of declaration contexts and lexical scopes.
+class DIScope : public DINode {
+protected:
+ DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+ ArrayRef<Metadata *> Ops)
+ : DINode(C, ID, Storage, Tag, Ops) {}
+ ~DIScope() = default;
+
+public:
+ DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
+
+ inline StringRef getFilename() const;
+ inline StringRef getDirectory() const;
+
+ StringRef getName() const;
+ DIScopeRef getScope() const;
+
+ /// \brief Return the raw underlying file.
+ ///
+ /// An \a DIFile is an \a DIScope, but it doesn't point at a separate file
+ /// (it\em is the file). If \c this is an \a DIFile, we need to return \c
+ /// this. Otherwise, return the first operand, which is where all other
+ /// subclasses store their file pointer.
+ Metadata *getRawFile() const {
+ return isa<DIFile>(this) ? const_cast<DIScope *>(this)
+ : static_cast<Metadata *>(getOperand(0));
+ }
+
+ DIScopeRef getRef() const { return DIScopeRef::get(this); }
+
+ static bool classof(const Metadata *MD) {
+ switch (MD->getMetadataID()) {
+ default:
+ return false;
+ case DIBasicTypeKind:
+ case DIDerivedTypeKind:
+ case DICompositeTypeKind:
+ case DISubroutineTypeKind:
+ case DIFileKind:
+ case DICompileUnitKind:
+ case DISubprogramKind:
+ case DILexicalBlockKind:
+ case DILexicalBlockFileKind:
+ case DINamespaceKind:
+ return true;
+ }
+ }
+};
+
+/// \brief File.
+///
+/// TODO: Merge with directory/file node (including users).
+/// TODO: Canonicalize paths on creation.
+class DIFile : public DIScope {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DIFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops)
+ : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {}
+ ~DIFile() = default;
+
+ static DIFile *getImpl(LLVMContext &Context, StringRef Filename,
+ StringRef Directory, StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, getCanonicalMDString(Context, Filename),
+ getCanonicalMDString(Context, Directory), Storage,
+ ShouldCreate);
+ }
+ static DIFile *getImpl(LLVMContext &Context, MDString *Filename,
+ MDString *Directory, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDIFile cloneImpl() const {
+ return getTemporary(getContext(), getFilename(), getDirectory());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory),
+ (Filename, Directory))
+ DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory),
+ (Filename, Directory))
+
+ TempDIFile clone() const { return cloneImpl(); }
+
+ StringRef getFilename() const { return getStringOperand(0); }
+ StringRef getDirectory() const { return getStringOperand(1); }
+
+ MDString *getRawFilename() const { return getOperandAs<MDString>(0); }
+ MDString *getRawDirectory() const { return getOperandAs<MDString>(1); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIFileKind;
+ }
+};
+
+StringRef DIScope::getFilename() const {
+ if (auto *F = getFile())
+ return F->getFilename();
+ return "";
+}
+
+StringRef DIScope::getDirectory() const {
+ if (auto *F = getFile())
+ return F->getDirectory();
+ return "";
+}
+
+/// \brief Base class for types.
+///
+/// TODO: Remove the hardcoded name and context, since many types don't use
+/// them.
+/// TODO: Split up flags.
+class DIType : public DIScope {
+ unsigned Line;
+ unsigned Flags;
+ uint64_t SizeInBits;
+ uint64_t AlignInBits;
+ uint64_t OffsetInBits;
+
+protected:
+ DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+ unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops)
+ : DIScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags),
+ SizeInBits(SizeInBits), AlignInBits(AlignInBits),
+ OffsetInBits(OffsetInBits) {}
+ ~DIType() = default;
+
+public:
+ TempDIType clone() const {
+ return TempDIType(cast<DIType>(MDNode::clone().release()));
+ }
+
+ unsigned getLine() const { return Line; }
+ uint64_t getSizeInBits() const { return SizeInBits; }
+ uint64_t getAlignInBits() const { return AlignInBits; }
+ uint64_t getOffsetInBits() const { return OffsetInBits; }
+ unsigned getFlags() const { return Flags; }
+
+ DIScopeRef getScope() const { return DIScopeRef(getRawScope()); }
+ StringRef getName() const { return getStringOperand(2); }
+
+
+ Metadata *getRawScope() const { return getOperand(1); }
+ MDString *getRawName() const { return getOperandAs<MDString>(2); }
+
+ void setFlags(unsigned NewFlags) {
+ assert(!isUniqued() && "Cannot set flags on uniqued nodes");
+ Flags = NewFlags;
+ }
+
+ 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; }
+ bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; }
+ bool isBlockByrefStruct() const { return getFlags() & FlagBlockByrefStruct; }
+ bool isVirtual() const { return getFlags() & FlagVirtual; }
+ bool isArtificial() const { return getFlags() & FlagArtificial; }
+ bool isObjectPointer() const { return getFlags() & FlagObjectPointer; }
+ bool isObjcClassComplete() const {
+ return getFlags() & FlagObjcClassComplete;
+ }
+ bool isVector() const { return getFlags() & FlagVector; }
+ bool isStaticMember() const { return getFlags() & FlagStaticMember; }
+ bool isLValueReference() const { return getFlags() & FlagLValueReference; }
+ bool isRValueReference() const { return getFlags() & FlagRValueReference; }
+
+ DITypeRef getRef() const { return DITypeRef::get(this); }
+
+ static bool classof(const Metadata *MD) {
+ switch (MD->getMetadataID()) {
+ default:
+ return false;
+ case DIBasicTypeKind:
+ case DIDerivedTypeKind:
+ case DICompositeTypeKind:
+ case DISubroutineTypeKind:
+ return true;
+ }
+ }
+};
+
+/// \brief Basic type, like 'int' or 'float'.
+///
+/// TODO: Split out DW_TAG_unspecified_type.
+/// TODO: Drop unused accessors.
+class DIBasicType : public DIType {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Encoding;
+
+ DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag,
+ uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding,
+ ArrayRef<Metadata *> Ops)
+ : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
+ 0, Ops),
+ Encoding(Encoding) {}
+ ~DIBasicType() = default;
+
+ static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
+ StringRef Name, uint64_t SizeInBits,
+ uint64_t AlignInBits, unsigned Encoding,
+ StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
+ SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate);
+ }
+ static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
+ MDString *Name, uint64_t SizeInBits,
+ uint64_t AlignInBits, unsigned Encoding,
+ StorageType Storage, bool ShouldCreate = true);
+
+ TempDIBasicType cloneImpl() const {
+ return getTemporary(getContext(), getTag(), getName(), getSizeInBits(),
+ getAlignInBits(), getEncoding());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name),
+ (Tag, Name, 0, 0, 0))
+ DEFINE_MDNODE_GET(DIBasicType,
+ (unsigned Tag, StringRef Name, uint64_t SizeInBits,
+ uint64_t AlignInBits, unsigned Encoding),
+ (Tag, Name, SizeInBits, AlignInBits, Encoding))
+ DEFINE_MDNODE_GET(DIBasicType,
+ (unsigned Tag, MDString *Name, uint64_t SizeInBits,
+ uint64_t AlignInBits, unsigned Encoding),
+ (Tag, Name, SizeInBits, AlignInBits, Encoding))
+
+ TempDIBasicType clone() const { return cloneImpl(); }
+
+ unsigned getEncoding() const { return Encoding; }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIBasicTypeKind;
+ }
+};
+
+/// \brief Base class for DIDerivedType and DICompositeType.
+///
+/// TODO: Delete; they're not really related.
+class DIDerivedTypeBase : public DIType {
+protected:
+ DIDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage,
+ unsigned Tag, unsigned Line, uint64_t SizeInBits,
+ uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags,
+ ArrayRef<Metadata *> Ops)
+ : DIType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits,
+ Flags, Ops) {}
+ ~DIDerivedTypeBase() = default;
+
+public:
+ DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); }
+ Metadata *getRawBaseType() const { return getOperand(3); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIDerivedTypeKind ||
+ MD->getMetadataID() == DICompositeTypeKind ||
+ MD->getMetadataID() == DISubroutineTypeKind;
+ }
+};
+
+/// \brief Derived types.
+///
+/// This includes qualified types, pointers, references, friends, typedefs, and
+/// class members.
+///
+/// TODO: Split out members (inheritance, fields, methods, etc.).
+class DIDerivedType : public DIDerivedTypeBase {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag,
+ unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops)
+ : DIDerivedTypeBase(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Ops) {}
+ ~DIDerivedType() = default;
+
+ static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
+ StringRef Name, DIFile *File, unsigned Line,
+ DIScopeRef Scope, DITypeRef BaseType,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ Metadata *ExtraData, StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
+ Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
+ Flags, ExtraData, Storage, ShouldCreate);
+ }
+ static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
+ MDString *Name, Metadata *File, unsigned Line,
+ Metadata *Scope, Metadata *BaseType,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ Metadata *ExtraData, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDIDerivedType cloneImpl() const {
+ return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
+ getScope(), getBaseType(), getSizeInBits(),
+ getAlignInBits(), getOffsetInBits(), getFlags(),
+ getExtraData());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIDerivedType,
+ (unsigned Tag, MDString *Name, Metadata *File,
+ unsigned Line, Metadata *Scope, Metadata *BaseType,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ Metadata *ExtraData = nullptr),
+ (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, ExtraData))
+ DEFINE_MDNODE_GET(DIDerivedType,
+ (unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
+ DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits,
+ uint64_t AlignInBits, uint64_t OffsetInBits,
+ unsigned Flags, Metadata *ExtraData = nullptr),
+ (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, ExtraData))
+
+ TempDIDerivedType clone() const { return cloneImpl(); }
+
+ /// \brief Get extra data associated with this derived type.
+ ///
+ /// Class type for pointer-to-members, objective-c property node for ivars,
+ /// or global constant wrapper for static members.
+ ///
+ /// TODO: Separate out types that need this extra operand: pointer-to-member
+ /// types and member fields (static members and ivars).
+ Metadata *getExtraData() const { return getRawExtraData(); }
+ Metadata *getRawExtraData() const { return getOperand(4); }
+
+ /// \brief Get casted version of extra data.
+ /// @{
+ DITypeRef getClassType() const {
+ assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
+ return DITypeRef(getExtraData());
+ }
+ DIObjCProperty *getObjCProperty() const {
+ return dyn_cast_or_null<DIObjCProperty>(getExtraData());
+ }
+ Constant *getConstant() const {
+ assert(getTag() == dwarf::DW_TAG_member && isStaticMember());
+ if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
+ return C->getValue();
+ return nullptr;
+ }
+ /// @}
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIDerivedTypeKind;
+ }
+};
+
+/// \brief Base class for DICompositeType and DISubroutineType.
+///
+/// TODO: Delete; they're not really related.
+class DICompositeTypeBase : public DIDerivedTypeBase {
+ unsigned RuntimeLang;
+
+protected:
+ DICompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage,
+ unsigned Tag, unsigned Line, unsigned RuntimeLang,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ ArrayRef<Metadata *> Ops)
+ : DIDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Ops),
+ RuntimeLang(RuntimeLang) {}
+ ~DICompositeTypeBase() = default;
+
+public:
+ /// \brief Get the elements of the composite type.
+ ///
+ /// \note Calling this is only valid for \a DICompositeType. This assertion
+ /// can be removed once \a DISubroutineType has been separated from
+ /// "composite types".
+ DINodeArray getElements() const {
+ assert(!isa<DISubroutineType>(this) && "no elements for DISubroutineType");
+ return cast_or_null<MDTuple>(getRawElements());
+ }
+ DITypeRef getVTableHolder() const { return DITypeRef(getRawVTableHolder()); }
+ DITemplateParameterArray getTemplateParams() const {
+ return cast_or_null<MDTuple>(getRawTemplateParams());
+ }
+ StringRef getIdentifier() const { return getStringOperand(7); }
+ unsigned getRuntimeLang() const { return RuntimeLang; }
+
+ Metadata *getRawElements() const { return getOperand(4); }
+ Metadata *getRawVTableHolder() const { return getOperand(5); }
+ Metadata *getRawTemplateParams() const { return getOperand(6); }
+ MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); }
+
+ /// \brief Replace operands.
+ ///
+ /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision
+ /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track
+ /// of its movement if necessary.
+ /// @{
+ void replaceElements(DINodeArray Elements) {
+#ifndef NDEBUG
+ for (DINode *Op : getElements())
+ assert(std::find(Elements->op_begin(), Elements->op_end(), Op) &&
+ "Lost a member during member list replacement");
+#endif
+ replaceOperandWith(4, Elements.get());
+ }
+ void replaceVTableHolder(DITypeRef VTableHolder) {
+ replaceOperandWith(5, VTableHolder);
+ }
+ void replaceTemplateParams(DITemplateParameterArray TemplateParams) {
+ replaceOperandWith(6, TemplateParams.get());
+ }
+ /// @}
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DICompositeTypeKind ||
+ MD->getMetadataID() == DISubroutineTypeKind;
+ }
+};
+
+/// \brief Composite types.
+///
+/// TODO: Detach from DerivedTypeBase (split out MDEnumType?).
+/// TODO: Create a custom, unrelated node for DW_TAG_array_type.
+class DICompositeType : public DICompositeTypeBase {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag,
+ unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits,
+ uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags,
+ ArrayRef<Metadata *> Ops)
+ : DICompositeTypeBase(C, DICompositeTypeKind, Storage, Tag, Line,
+ RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
+ Flags, Ops) {}
+ ~DICompositeType() = default;
+
+ static DICompositeType *
+ getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
+ unsigned Line, DIScopeRef Scope, DITypeRef BaseType,
+ uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
+ uint64_t Flags, DINodeArray Elements, unsigned RuntimeLang,
+ DITypeRef VTableHolder, DITemplateParameterArray TemplateParams,
+ StringRef Identifier, StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(
+ Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
+ RuntimeLang, VTableHolder, TemplateParams.get(),
+ getCanonicalMDString(Context, Identifier), Storage, ShouldCreate);
+ }
+ static DICompositeType *
+ getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
+ unsigned Line, Metadata *Scope, Metadata *BaseType,
+ uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
+ unsigned Flags, Metadata *Elements, unsigned RuntimeLang,
+ Metadata *VTableHolder, Metadata *TemplateParams,
+ MDString *Identifier, StorageType Storage, bool ShouldCreate = true);
+
+ TempDICompositeType cloneImpl() const {
+ return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
+ getScope(), getBaseType(), getSizeInBits(),
+ getAlignInBits(), getOffsetInBits(), getFlags(),
+ getElements(), getRuntimeLang(), getVTableHolder(),
+ getTemplateParams(), getIdentifier());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DICompositeType,
+ (unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
+ DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits,
+ uint64_t AlignInBits, uint64_t OffsetInBits,
+ unsigned Flags, DINodeArray Elements, unsigned RuntimeLang,
+ DITypeRef VTableHolder,
+ DITemplateParameterArray TemplateParams = nullptr,
+ StringRef Identifier = ""),
+ (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier))
+ DEFINE_MDNODE_GET(DICompositeType,
+ (unsigned Tag, MDString *Name, Metadata *File,
+ unsigned Line, Metadata *Scope, Metadata *BaseType,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags, Metadata *Elements,
+ unsigned RuntimeLang, Metadata *VTableHolder,
+ Metadata *TemplateParams = nullptr,
+ MDString *Identifier = nullptr),
+ (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier))
+
+ TempDICompositeType clone() const { return cloneImpl(); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DICompositeTypeKind;
+ }
+};
+
+template <class T> TypedDINodeRef<T> TypedDINodeRef<T>::get(const T *N) {
+ if (N)
+ if (auto *Composite = dyn_cast<DICompositeType>(N))
+ if (auto *S = Composite->getRawIdentifier())
+ return TypedDINodeRef<T>(S);
+ return TypedDINodeRef<T>(N);
+}
+
+/// \brief Type array for a subprogram.
+///
+/// TODO: Detach from CompositeType, and fold the array of types in directly
+/// as operands.
+class DISubroutineType : public DICompositeTypeBase {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DISubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags,
+ ArrayRef<Metadata *> Ops)
+ : DICompositeTypeBase(C, DISubroutineTypeKind, Storage,
+ dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags,
+ Ops) {}
+ ~DISubroutineType() = default;
+
+ static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
+ DITypeRefArray TypeArray,
+ StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate);
+ }
+ static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
+ Metadata *TypeArray, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDISubroutineType cloneImpl() const {
+ return getTemporary(getContext(), getFlags(), getTypeArray());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DISubroutineType,
+ (unsigned Flags, DITypeRefArray TypeArray),
+ (Flags, TypeArray))
+ DEFINE_MDNODE_GET(DISubroutineType, (unsigned Flags, Metadata *TypeArray),
+ (Flags, TypeArray))
+
+ TempDISubroutineType clone() const { return cloneImpl(); }
+
+ DITypeRefArray getTypeArray() const {
+ return cast_or_null<MDTuple>(getRawTypeArray());
+ }
+ Metadata *getRawTypeArray() const { return getRawElements(); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DISubroutineTypeKind;
+ }
+};
+
+/// \brief Compile unit.
+class DICompileUnit : public DIScope {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned SourceLanguage;
+ bool IsOptimized;
+ unsigned RuntimeVersion;
+ unsigned EmissionKind;
+ uint64_t DWOId;
+
+ DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage,
+ bool IsOptimized, unsigned RuntimeVersion,
+ unsigned EmissionKind, uint64_t DWOId, ArrayRef<Metadata *> Ops)
+ : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
+ SourceLanguage(SourceLanguage), IsOptimized(IsOptimized),
+ RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind),
+ DWOId(DWOId) {}
+ ~DICompileUnit() = default;
+
+ static DICompileUnit *
+ getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File,
+ StringRef Producer, bool IsOptimized, StringRef Flags,
+ unsigned RuntimeVersion, StringRef SplitDebugFilename,
+ unsigned EmissionKind, DICompositeTypeArray EnumTypes,
+ DITypeArray RetainedTypes, DISubprogramArray Subprograms,
+ DIGlobalVariableArray GlobalVariables,
+ DIImportedEntityArray ImportedEntities, uint64_t DWOId,
+ StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(Context, SourceLanguage, File,
+ getCanonicalMDString(Context, Producer), IsOptimized,
+ getCanonicalMDString(Context, Flags), RuntimeVersion,
+ getCanonicalMDString(Context, SplitDebugFilename),
+ EmissionKind, EnumTypes.get(), RetainedTypes.get(),
+ Subprograms.get(), GlobalVariables.get(),
+ ImportedEntities.get(), DWOId, Storage, ShouldCreate);
+ }
+ static DICompileUnit *
+ getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
+ MDString *Producer, bool IsOptimized, MDString *Flags,
+ unsigned RuntimeVersion, MDString *SplitDebugFilename,
+ unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
+ Metadata *Subprograms, Metadata *GlobalVariables,
+ Metadata *ImportedEntities, uint64_t DWOId, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDICompileUnit cloneImpl() const {
+ return getTemporary(
+ getContext(), getSourceLanguage(), getFile(), getProducer(),
+ isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(),
+ getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(),
+ getGlobalVariables(), getImportedEntities(), DWOId);
+ }
+
+public:
+ DEFINE_MDNODE_GET(DICompileUnit,
+ (unsigned SourceLanguage, DIFile *File, StringRef Producer,
+ bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,
+ StringRef SplitDebugFilename, unsigned EmissionKind,
+ DICompositeTypeArray EnumTypes, DITypeArray RetainedTypes,
+ DISubprogramArray Subprograms,
+ DIGlobalVariableArray GlobalVariables,
+ DIImportedEntityArray ImportedEntities, uint64_t DWOId),
+ (SourceLanguage, File, Producer, IsOptimized, Flags,
+ RuntimeVersion, SplitDebugFilename, EmissionKind,
+ EnumTypes, RetainedTypes, Subprograms, GlobalVariables,
+ ImportedEntities, DWOId))
+ DEFINE_MDNODE_GET(
+ DICompileUnit,
+ (unsigned SourceLanguage, Metadata *File, MDString *Producer,
+ bool IsOptimized, MDString *Flags, unsigned RuntimeVersion,
+ MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes,
+ Metadata *RetainedTypes, Metadata *Subprograms,
+ Metadata *GlobalVariables, Metadata *ImportedEntities, uint64_t DWOId),
+ (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
+ SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms,
+ GlobalVariables, ImportedEntities, DWOId))
+
+ TempDICompileUnit clone() const { return cloneImpl(); }
+
+ unsigned getSourceLanguage() const { return SourceLanguage; }
+ bool isOptimized() const { return IsOptimized; }
+ unsigned getRuntimeVersion() const { return RuntimeVersion; }
+ unsigned getEmissionKind() const { return EmissionKind; }
+ StringRef getProducer() const { return getStringOperand(1); }
+ StringRef getFlags() const { return getStringOperand(2); }
+ StringRef getSplitDebugFilename() const { return getStringOperand(3); }
+ DICompositeTypeArray getEnumTypes() const {
+ return cast_or_null<MDTuple>(getRawEnumTypes());
+ }
+ DITypeArray getRetainedTypes() const {
+ return cast_or_null<MDTuple>(getRawRetainedTypes());
+ }
+ DISubprogramArray getSubprograms() const {
+ return cast_or_null<MDTuple>(getRawSubprograms());
+ }
+ DIGlobalVariableArray getGlobalVariables() const {
+ return cast_or_null<MDTuple>(getRawGlobalVariables());
+ }
+ DIImportedEntityArray getImportedEntities() const {
+ return cast_or_null<MDTuple>(getRawImportedEntities());
+ }
+ unsigned getDWOId() const { return DWOId; }
+
+ MDString *getRawProducer() const { return getOperandAs<MDString>(1); }
+ MDString *getRawFlags() const { return getOperandAs<MDString>(2); }
+ MDString *getRawSplitDebugFilename() const {
+ return getOperandAs<MDString>(3);
+ }
+ Metadata *getRawEnumTypes() const { return getOperand(4); }
+ Metadata *getRawRetainedTypes() const { return getOperand(5); }
+ Metadata *getRawSubprograms() const { return getOperand(6); }
+ Metadata *getRawGlobalVariables() const { return getOperand(7); }
+ Metadata *getRawImportedEntities() const { return getOperand(8); }
+
+ /// \brief Replace arrays.
+ ///
+ /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and
+ /// deleted on a uniquing collision. In practice, uniquing collisions on \a
+ /// DICompileUnit should be fairly rare.
+ /// @{
+ void replaceSubprograms(DISubprogramArray N) {
+ replaceOperandWith(6, N.get());
+ }
+ void replaceGlobalVariables(DIGlobalVariableArray N) {
+ replaceOperandWith(7, N.get());
+ }
+ /// @}
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DICompileUnitKind;
+ }
+};
+
+/// \brief A scope for locals.
+///
+/// A legal scope for lexical blocks, local variables, and debug info
+/// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a
+/// DILexicalBlockFile.
+class DILocalScope : public DIScope {
+protected:
+ DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+ ArrayRef<Metadata *> Ops)
+ : DIScope(C, ID, Storage, Tag, Ops) {}
+ ~DILocalScope() = default;
+
+public:
+ /// \brief Get the subprogram for this scope.
+ ///
+ /// Return this if it's an \a DISubprogram; otherwise, look up the scope
+ /// chain.
+ DISubprogram *getSubprogram() const;
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DISubprogramKind ||
+ MD->getMetadataID() == DILexicalBlockKind ||
+ MD->getMetadataID() == DILexicalBlockFileKind;
+ }
+};
+
+/// \brief Debug location.
+///
+/// A debug location in source code, used for debug info and otherwise.
+class DILocation : public MDNode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
+ unsigned Column, ArrayRef<Metadata *> MDs);
+ ~DILocation() { dropAllReferences(); }
+
+ static DILocation *getImpl(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, StorageType Storage,
+ bool ShouldCreate = true);
+ static DILocation *getImpl(LLVMContext &Context, unsigned Line,
+ unsigned Column, DILocalScope *Scope,
+ DILocation *InlinedAt, StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope),
+ static_cast<Metadata *>(InlinedAt), Storage, ShouldCreate);
+ }
+
+ TempDILocation cloneImpl() const {
+ return getTemporary(getContext(), getLine(), getColumn(), getScope(),
+ getInlinedAt());
+ }
+
+ // Disallow replacing operands.
+ void replaceOperandWith(unsigned I, Metadata *New) = delete;
+
+public:
+ DEFINE_MDNODE_GET(DILocation,
+ (unsigned Line, unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt = nullptr),
+ (Line, Column, Scope, InlinedAt))
+ DEFINE_MDNODE_GET(DILocation,
+ (unsigned Line, unsigned Column, DILocalScope *Scope,
+ DILocation *InlinedAt = nullptr),
+ (Line, Column, Scope, InlinedAt))
+
+ /// \brief Return a (temporary) clone of this.
+ TempDILocation clone() const { return cloneImpl(); }
+
+ unsigned getLine() const { return SubclassData32; }
+ unsigned getColumn() const { return SubclassData16; }
+ DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); }
+ DILocation *getInlinedAt() const {
+ return cast_or_null<DILocation>(getRawInlinedAt());
+ }
+
+ DIFile *getFile() const { return getScope()->getFile(); }
+ StringRef getFilename() const { return getScope()->getFilename(); }
+ StringRef getDirectory() const { return getScope()->getDirectory(); }
+
+ /// \brief Get the scope where this is inlined.
+ ///
+ /// Walk through \a getInlinedAt() and return \a getScope() from the deepest
+ /// location.
+ DILocalScope *getInlinedAtScope() const {
+ if (auto *IA = getInlinedAt())
+ return IA->getInlinedAtScope();
+ return getScope();
+ }
+
+ /// \brief Check whether this can be discriminated from another location.
+ ///
+ /// Check \c this can be discriminated from \c RHS in a linetable entry.
+ /// Scope and inlined-at chains are not recorded in the linetable, so they
+ /// cannot be used to distinguish basic blocks.
+ ///
+ /// The current implementation is weaker than it should be, since it just
+ /// checks filename and line.
+ ///
+ /// FIXME: Add a check for getDiscriminator().
+ /// FIXME: Add a check for getColumn().
+ /// FIXME: Change the getFilename() check to getFile() (or add one for
+ /// getDirectory()).
+ bool canDiscriminate(const DILocation &RHS) const {
+ return getFilename() != RHS.getFilename() || getLine() != RHS.getLine();
+ }
+
+ /// \brief Get the DWARF discriminator.
+ ///
+ /// DWARF discriminators distinguish identical file locations between
+ /// instructions that are on different basic blocks.
+ inline unsigned getDiscriminator() const;
+
+ /// \brief Compute new discriminator in the given context.
+ ///
+ /// This modifies the \a LLVMContext that \c this is in to increment the next
+ /// discriminator for \c this's line/filename combination.
+ ///
+ /// FIXME: Delete this. See comments in implementation and at the only call
+ /// site in \a AddDiscriminators::runOnFunction().
+ unsigned computeNewDiscriminator() const;
+
+ Metadata *getRawScope() const { return getOperand(0); }
+ Metadata *getRawInlinedAt() const {
+ if (getNumOperands() == 2)
+ return getOperand(1);
+ return nullptr;
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DILocationKind;
+ }
+};
+
+/// \brief Subprogram description.
+///
+/// TODO: Remove DisplayName. It's always equal to Name.
+/// TODO: Split up flags.
+class DISubprogram : public DILocalScope {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Line;
+ unsigned ScopeLine;
+ unsigned Virtuality;
+ unsigned VirtualIndex;
+ unsigned Flags;
+ bool IsLocalToUnit;
+ bool IsDefinition;
+ bool IsOptimized;
+
+ DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line,
+ unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex,
+ unsigned Flags, bool IsLocalToUnit, bool IsDefinition,
+ bool IsOptimized, ArrayRef<Metadata *> Ops)
+ : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram,
+ Ops),
+ Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality),
+ VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit),
+ IsDefinition(IsDefinition), IsOptimized(IsOptimized) {}
+ ~DISubprogram() = default;
+
+ static DISubprogram *
+ getImpl(LLVMContext &Context, DIScopeRef Scope, StringRef Name,
+ StringRef LinkageName, DIFile *File, unsigned Line,
+ DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition,
+ unsigned ScopeLine, DITypeRef ContainingType, unsigned Virtuality,
+ unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+ Constant *Function, DITemplateParameterArray TemplateParams,
+ DISubprogram *Declaration, DILocalVariableArray Variables,
+ StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
+ getCanonicalMDString(Context, LinkageName), File, Line, Type,
+ IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
+ Virtuality, VirtualIndex, Flags, IsOptimized,
+ Function ? ConstantAsMetadata::get(Function) : nullptr,
+ TemplateParams.get(), Declaration, Variables.get(), Storage,
+ ShouldCreate);
+ }
+ static DISubprogram *
+ getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
+ MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
+ bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
+ Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
+ unsigned Flags, bool IsOptimized, Metadata *Function,
+ Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
+ StorageType Storage, bool ShouldCreate = true);
+
+ TempDISubprogram cloneImpl() const {
+ return getTemporary(getContext(), getScope(), getName(), getLinkageName(),
+ getFile(), getLine(), getType(), isLocalToUnit(),
+ isDefinition(), getScopeLine(), getContainingType(),
+ getVirtuality(), getVirtualIndex(), getFlags(),
+ isOptimized(), getFunctionConstant(),
+ getTemplateParams(), getDeclaration(), getVariables());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DISubprogram,
+ (DIScopeRef Scope, StringRef Name, StringRef LinkageName,
+ DIFile *File, unsigned Line, DISubroutineType *Type,
+ bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
+ DITypeRef ContainingType, unsigned Virtuality,
+ unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+ Constant *Function = nullptr,
+ DITemplateParameterArray TemplateParams = nullptr,
+ DISubprogram *Declaration = nullptr,
+ DILocalVariableArray Variables = nullptr),
+ (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
+ IsDefinition, ScopeLine, ContainingType, Virtuality,
+ VirtualIndex, Flags, IsOptimized, Function, TemplateParams,
+ Declaration, Variables))
+ DEFINE_MDNODE_GET(
+ DISubprogram,
+ (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File,
+ unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
+ unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality,
+ unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
+ Metadata *Function = nullptr, Metadata *TemplateParams = nullptr,
+ Metadata *Declaration = nullptr, Metadata *Variables = nullptr),
+ (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
+ ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized,
+ Function, TemplateParams, Declaration, Variables))
+
+ TempDISubprogram clone() const { return cloneImpl(); }
+
+public:
+ unsigned getLine() const { return Line; }
+ unsigned getVirtuality() const { return Virtuality; }
+ unsigned getVirtualIndex() const { return VirtualIndex; }
+ unsigned getScopeLine() const { return ScopeLine; }
+ unsigned getFlags() const { return Flags; }
+ bool isLocalToUnit() const { return IsLocalToUnit; }
+ bool isDefinition() const { return IsDefinition; }
+ bool isOptimized() const { return IsOptimized; }
+
+ unsigned isArtificial() const { return getFlags() & FlagArtificial; }
+ bool isPrivate() const {
+ return (getFlags() & FlagAccessibility) == FlagPrivate;
+ }
+ bool isProtected() const {
+ return (getFlags() & FlagAccessibility) == FlagProtected;
+ }
+ bool isPublic() const {
+ return (getFlags() & FlagAccessibility) == FlagPublic;
+ }
+ bool isExplicit() const { return getFlags() & FlagExplicit; }
+ bool isPrototyped() const { return getFlags() & FlagPrototyped; }
+
+ /// \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;
+ }
+
+ /// \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;
+ }
+
+ DIScopeRef getScope() const { return DIScopeRef(getRawScope()); }
+
+ StringRef getName() const { return getStringOperand(2); }
+ StringRef getDisplayName() const { return getStringOperand(3); }
+ StringRef getLinkageName() const { return getStringOperand(4); }
+
+ MDString *getRawName() const { return getOperandAs<MDString>(2); }
+ MDString *getRawLinkageName() const { return getOperandAs<MDString>(4); }
+
+ DISubroutineType *getType() const {
+ return cast_or_null<DISubroutineType>(getRawType());
+ }
+ DITypeRef getContainingType() const {
+ return DITypeRef(getRawContainingType());
+ }
+
+ Constant *getFunctionConstant() const {
+ if (auto *C = cast_or_null<ConstantAsMetadata>(getRawFunction()))
+ return C->getValue();
+ return nullptr;
+ }
+ DITemplateParameterArray getTemplateParams() const {
+ return cast_or_null<MDTuple>(getRawTemplateParams());
+ }
+ DISubprogram *getDeclaration() const {
+ return cast_or_null<DISubprogram>(getRawDeclaration());
+ }
+ DILocalVariableArray getVariables() const {
+ return cast_or_null<MDTuple>(getRawVariables());
+ }
+
+ Metadata *getRawScope() const { return getOperand(1); }
+ Metadata *getRawType() const { return getOperand(5); }
+ Metadata *getRawContainingType() const { return getOperand(6); }
+ Metadata *getRawFunction() const { return getOperand(7); }
+ Metadata *getRawTemplateParams() const { return getOperand(8); }
+ Metadata *getRawDeclaration() const { return getOperand(9); }
+ Metadata *getRawVariables() const { return getOperand(10); }
+
+ /// \brief Get a pointer to the function this subprogram describes.
+ ///
+ /// This dyn_casts \a getFunctionConstant() to \a Function.
+ ///
+ /// FIXME: Should this be looking through bitcasts?
+ Function *getFunction() const;
+
+ /// \brief Replace the function.
+ ///
+ /// If \a isUniqued() and not \a isResolved(), this could node will be
+ /// RAUW'ed and deleted out from under the caller. Use a \a TrackingMDRef if
+ /// that's a problem.
+ /// @{
+ void replaceFunction(Function *F);
+ void replaceFunction(ConstantAsMetadata *MD) { replaceOperandWith(7, MD); }
+ void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); }
+ /// @}
+
+ /// \brief Check if this subprogram decribes the given function.
+ ///
+ /// FIXME: Should this be looking through bitcasts?
+ bool describes(const Function *F) const;
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DISubprogramKind;
+ }
+};
+
+class DILexicalBlockBase : public DILocalScope {
+protected:
+ DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage,
+ ArrayRef<Metadata *> Ops)
+ : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {}
+ ~DILexicalBlockBase() = default;
+
+public:
+ DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); }
+
+ Metadata *getRawScope() const { return getOperand(1); }
+
+ /// \brief Forwarding accessors to LexicalBlock.
+ ///
+ /// TODO: Remove these and update code to use \a DILexicalBlock directly.
+ /// @{
+ inline unsigned getLine() const;
+ inline unsigned getColumn() const;
+ /// @}
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DILexicalBlockKind ||
+ MD->getMetadataID() == DILexicalBlockFileKind;
+ }
+};
+
+class DILexicalBlock : public DILexicalBlockBase {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Line;
+ unsigned Column;
+
+ DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line,
+ unsigned Column, ArrayRef<Metadata *> Ops)
+ : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line),
+ Column(Column) {}
+ ~DILexicalBlock() = default;
+
+ static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope,
+ DIFile *File, unsigned Line, unsigned Column,
+ StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, static_cast<Metadata *>(Scope),
+ static_cast<Metadata *>(File), Line, Column, Storage,
+ ShouldCreate);
+ }
+
+ static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope,
+ Metadata *File, unsigned Line, unsigned Column,
+ StorageType Storage, bool ShouldCreate = true);
+
+ TempDILexicalBlock cloneImpl() const {
+ return getTemporary(getContext(), getScope(), getFile(), getLine(),
+ getColumn());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DILexicalBlock, (DILocalScope * Scope, DIFile *File,
+ unsigned Line, unsigned Column),
+ (Scope, File, Line, Column))
+ DEFINE_MDNODE_GET(DILexicalBlock, (Metadata * Scope, Metadata *File,
+ unsigned Line, unsigned Column),
+ (Scope, File, Line, Column))
+
+ TempDILexicalBlock clone() const { return cloneImpl(); }
+
+ unsigned getLine() const { return Line; }
+ unsigned getColumn() const { return Column; }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DILexicalBlockKind;
+ }
+};
+
+unsigned DILexicalBlockBase::getLine() const {
+ if (auto *N = dyn_cast<DILexicalBlock>(this))
+ return N->getLine();
+ return 0;
+}
+
+unsigned DILexicalBlockBase::getColumn() const {
+ if (auto *N = dyn_cast<DILexicalBlock>(this))
+ return N->getColumn();
+ return 0;
+}
+
+class DILexicalBlockFile : public DILexicalBlockBase {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Discriminator;
+
+ DILexicalBlockFile(LLVMContext &C, StorageType Storage,
+ unsigned Discriminator, ArrayRef<Metadata *> Ops)
+ : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops),
+ Discriminator(Discriminator) {}
+ ~DILexicalBlockFile() = default;
+
+ static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope,
+ DIFile *File, unsigned Discriminator,
+ StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, static_cast<Metadata *>(Scope),
+ static_cast<Metadata *>(File), Discriminator, Storage,
+ ShouldCreate);
+ }
+
+ static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope,
+ Metadata *File, unsigned Discriminator,
+ StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDILexicalBlockFile cloneImpl() const {
+ return getTemporary(getContext(), getScope(), getFile(),
+ getDiscriminator());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DILexicalBlockFile, (DILocalScope * Scope, DIFile *File,
+ unsigned Discriminator),
+ (Scope, File, Discriminator))
+ DEFINE_MDNODE_GET(DILexicalBlockFile,
+ (Metadata * Scope, Metadata *File, unsigned Discriminator),
+ (Scope, File, Discriminator))
+
+ TempDILexicalBlockFile clone() const { return cloneImpl(); }
+
+ // TODO: Remove these once they're gone from DILexicalBlockBase.
+ unsigned getLine() const = delete;
+ unsigned getColumn() const = delete;
+
+ unsigned getDiscriminator() const { return Discriminator; }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DILexicalBlockFileKind;
+ }
+};
+
+unsigned DILocation::getDiscriminator() const {
+ if (auto *F = dyn_cast<DILexicalBlockFile>(getScope()))
+ return F->getDiscriminator();
+ return 0;
+}
+
+class DINamespace : public DIScope {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Line;
+
+ DINamespace(LLVMContext &Context, StorageType Storage, unsigned Line,
+ ArrayRef<Metadata *> Ops)
+ : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace,
+ Ops),
+ Line(Line) {}
+ ~DINamespace() = default;
+
+ static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope,
+ DIFile *File, StringRef Name, unsigned Line,
+ StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name),
+ Line, Storage, ShouldCreate);
+ }
+ static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope,
+ Metadata *File, MDString *Name, unsigned Line,
+ StorageType Storage, bool ShouldCreate = true);
+
+ TempDINamespace cloneImpl() const {
+ return getTemporary(getContext(), getScope(), getFile(), getName(),
+ getLine());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DINamespace, (DIScope * Scope, DIFile *File, StringRef Name,
+ unsigned Line),
+ (Scope, File, Name, Line))
+ DEFINE_MDNODE_GET(DINamespace, (Metadata * Scope, Metadata *File,
+ MDString *Name, unsigned Line),
+ (Scope, File, Name, Line))
+
+ TempDINamespace clone() const { return cloneImpl(); }
+
+ unsigned getLine() const { return Line; }
+ DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
+ StringRef getName() const { return getStringOperand(2); }
+
+ Metadata *getRawScope() const { return getOperand(1); }
+ MDString *getRawName() const { return getOperandAs<MDString>(2); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DINamespaceKind;
+ }
+};
+
+/// \brief Base class for template parameters.
+class DITemplateParameter : public DINode {
+protected:
+ DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage,
+ unsigned Tag, ArrayRef<Metadata *> Ops)
+ : DINode(Context, ID, Storage, Tag, Ops) {}
+ ~DITemplateParameter() = default;
+
+public:
+ StringRef getName() const { return getStringOperand(0); }
+ DITypeRef getType() const { return DITypeRef(getRawType()); }
+
+ MDString *getRawName() const { return getOperandAs<MDString>(0); }
+ Metadata *getRawType() const { return getOperand(1); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DITemplateTypeParameterKind ||
+ MD->getMetadataID() == DITemplateValueParameterKind;
+ }
+};
+
+class DITemplateTypeParameter : public DITemplateParameter {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DITemplateTypeParameter(LLVMContext &Context, StorageType Storage,
+ ArrayRef<Metadata *> Ops)
+ : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage,
+ dwarf::DW_TAG_template_type_parameter, Ops) {}
+ ~DITemplateTypeParameter() = default;
+
+ static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name,
+ DITypeRef Type, StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage,
+ ShouldCreate);
+ }
+ static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name,
+ Metadata *Type, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDITemplateTypeParameter cloneImpl() const {
+ return getTemporary(getContext(), getName(), getType());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DITemplateTypeParameter, (StringRef Name, DITypeRef Type),
+ (Name, Type))
+ DEFINE_MDNODE_GET(DITemplateTypeParameter, (MDString * Name, Metadata *Type),
+ (Name, Type))
+
+ TempDITemplateTypeParameter clone() const { return cloneImpl(); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DITemplateTypeParameterKind;
+ }
+};
+
+class DITemplateValueParameter : public DITemplateParameter {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DITemplateValueParameter(LLVMContext &Context, StorageType Storage,
+ unsigned Tag, ArrayRef<Metadata *> Ops)
+ : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag,
+ Ops) {}
+ ~DITemplateValueParameter() = default;
+
+ static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,
+ StringRef Name, DITypeRef Type,
+ Metadata *Value, StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type,
+ Value, Storage, ShouldCreate);
+ }
+ static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,
+ MDString *Name, Metadata *Type,
+ Metadata *Value, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDITemplateValueParameter cloneImpl() const {
+ return getTemporary(getContext(), getTag(), getName(), getType(),
+ getValue());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, StringRef Name,
+ DITypeRef Type, Metadata *Value),
+ (Tag, Name, Type, Value))
+ DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, MDString *Name,
+ Metadata *Type, Metadata *Value),
+ (Tag, Name, Type, Value))
+
+ TempDITemplateValueParameter clone() const { return cloneImpl(); }
+
+ Metadata *getValue() const { return getOperand(2); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DITemplateValueParameterKind;
+ }
+};
+
+/// \brief Base class for variables.
+///
+/// TODO: Hardcode to DW_TAG_variable.
+class DIVariable : public DINode {
+ unsigned Line;
+
+protected:
+ DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+ unsigned Line, ArrayRef<Metadata *> Ops)
+ : DINode(C, ID, Storage, Tag, Ops), Line(Line) {}
+ ~DIVariable() = default;
+
+public:
+ unsigned getLine() const { return Line; }
+ DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
+ StringRef getName() const { return getStringOperand(1); }
+ DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
+ DITypeRef getType() const { return DITypeRef(getRawType()); }
+
+ StringRef getFilename() const {
+ if (auto *F = getFile())
+ return F->getFilename();
+ return "";
+ }
+ StringRef getDirectory() const {
+ if (auto *F = getFile())
+ return F->getDirectory();
+ return "";
+ }
+
+ Metadata *getRawScope() const { return getOperand(0); }
+ MDString *getRawName() const { return getOperandAs<MDString>(1); }
+ Metadata *getRawFile() const { return getOperand(2); }
+ Metadata *getRawType() const { return getOperand(3); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DILocalVariableKind ||
+ MD->getMetadataID() == DIGlobalVariableKind;
+ }
+};
+
+/// \brief Global variables.
+///
+/// TODO: Remove DisplayName. It's always equal to Name.
+class DIGlobalVariable : public DIVariable {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ bool IsLocalToUnit;
+ bool IsDefinition;
+
+ DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line,
+ bool IsLocalToUnit, bool IsDefinition,
+ ArrayRef<Metadata *> Ops)
+ : DIVariable(C, DIGlobalVariableKind, Storage, dwarf::DW_TAG_variable,
+ Line, Ops),
+ IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {}
+ ~DIGlobalVariable() = default;
+
+ static DIGlobalVariable *
+ getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name,
+ StringRef LinkageName, DIFile *File, unsigned Line, DITypeRef Type,
+ bool IsLocalToUnit, bool IsDefinition, Constant *Variable,
+ DIDerivedType *StaticDataMemberDeclaration, StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
+ getCanonicalMDString(Context, LinkageName), File, Line, Type,
+ IsLocalToUnit, IsDefinition,
+ Variable ? ConstantAsMetadata::get(Variable) : nullptr,
+ StaticDataMemberDeclaration, Storage, ShouldCreate);
+ }
+ static DIGlobalVariable *
+ getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
+ MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
+ bool IsLocalToUnit, bool IsDefinition, Metadata *Variable,
+ Metadata *StaticDataMemberDeclaration, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDIGlobalVariable cloneImpl() const {
+ return getTemporary(getContext(), getScope(), getName(), getLinkageName(),
+ getFile(), getLine(), getType(), isLocalToUnit(),
+ isDefinition(), getVariable(),
+ getStaticDataMemberDeclaration());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIGlobalVariable,
+ (DIScope * Scope, StringRef Name, StringRef LinkageName,
+ DIFile *File, unsigned Line, DITypeRef Type,
+ bool IsLocalToUnit, bool IsDefinition, Constant *Variable,
+ DIDerivedType *StaticDataMemberDeclaration),
+ (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
+ IsDefinition, Variable, StaticDataMemberDeclaration))
+ DEFINE_MDNODE_GET(DIGlobalVariable,
+ (Metadata * Scope, MDString *Name, MDString *LinkageName,
+ Metadata *File, unsigned Line, Metadata *Type,
+ bool IsLocalToUnit, bool IsDefinition, Metadata *Variable,
+ Metadata *StaticDataMemberDeclaration),
+ (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
+ IsDefinition, Variable, StaticDataMemberDeclaration))
+
+ TempDIGlobalVariable clone() const { return cloneImpl(); }
+
+ bool isLocalToUnit() const { return IsLocalToUnit; }
+ bool isDefinition() const { return IsDefinition; }
+ StringRef getDisplayName() const { return getStringOperand(4); }
+ StringRef getLinkageName() const { return getStringOperand(5); }
+ Constant *getVariable() const {
+ if (auto *C = cast_or_null<ConstantAsMetadata>(getRawVariable()))
+ return dyn_cast<Constant>(C->getValue());
+ return nullptr;
+ }
+ DIDerivedType *getStaticDataMemberDeclaration() const {
+ return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration());
+ }
+
+ MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); }
+ Metadata *getRawVariable() const { return getOperand(6); }
+ Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIGlobalVariableKind;
+ }
+};
+
+/// \brief Local variable.
+///
+/// TODO: Split between arguments and otherwise.
+/// TODO: Use \c DW_TAG_variable instead of fake tags.
+/// TODO: Split up flags.
+class DILocalVariable : public DIVariable {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Arg;
+ unsigned Flags;
+
+ DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag,
+ unsigned Line, unsigned Arg, unsigned Flags,
+ ArrayRef<Metadata *> Ops)
+ : DIVariable(C, DILocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg),
+ Flags(Flags) {}
+ ~DILocalVariable() = default;
+
+ static DILocalVariable *getImpl(LLVMContext &Context, unsigned Tag,
+ DIScope *Scope, StringRef Name, DIFile *File,
+ unsigned Line, DITypeRef Type, unsigned Arg,
+ unsigned Flags, StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name),
+ File, Line, Type, Arg, Flags, Storage, ShouldCreate);
+ }
+ static DILocalVariable *
+ getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name,
+ Metadata *File, unsigned Line, Metadata *Type, unsigned Arg,
+ unsigned Flags, StorageType Storage, bool ShouldCreate = true);
+
+ TempDILocalVariable cloneImpl() const {
+ return getTemporary(getContext(), getTag(), getScope(), getName(),
+ getFile(), getLine(), getType(), getArg(), getFlags());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DILocalVariable,
+ (unsigned Tag, DILocalScope *Scope, StringRef Name,
+ DIFile *File, unsigned Line, DITypeRef Type, unsigned Arg,
+ unsigned Flags),
+ (Tag, Scope, Name, File, Line, Type, Arg, Flags))
+ DEFINE_MDNODE_GET(DILocalVariable,
+ (unsigned Tag, Metadata *Scope, MDString *Name,
+ Metadata *File, unsigned Line, Metadata *Type,
+ unsigned Arg, unsigned Flags),
+ (Tag, Scope, Name, File, Line, Type, Arg, Flags))
+
+ TempDILocalVariable clone() const { return cloneImpl(); }
+
+ /// \brief Get the local scope for this variable.
+ ///
+ /// Variables must be defined in a local scope.
+ DILocalScope *getScope() const {
+ return cast<DILocalScope>(DIVariable::getScope());
+ }
+
+ unsigned getArg() const { return Arg; }
+ unsigned getFlags() const { return Flags; }
+
+ bool isArtificial() const { return getFlags() & FlagArtificial; }
+ bool isObjectPointer() const { return getFlags() & FlagObjectPointer; }
+
+ /// \brief Check that a location is valid for this variable.
+ ///
+ /// Check that \c DL exists, is in the same subprogram, and has the same
+ /// inlined-at location as \c this. (Otherwise, it's not a valid attachemnt
+ /// to a \a DbgInfoIntrinsic.)
+ bool isValidLocationForIntrinsic(const DILocation *DL) const {
+ return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram();
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DILocalVariableKind;
+ }
+};
+
+/// \brief DWARF expression.
+///
+/// This is (almost) a DWARF expression that modifies the location of a
+/// variable or (or the location of a single piece of a variable).
+///
+/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const
+/// and have DW_OP_plus consume the topmost elements on the stack.
+///
+/// TODO: Co-allocate the expression elements.
+/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary
+/// storage types.
+class DIExpression : public MDNode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ std::vector<uint64_t> Elements;
+
+ DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements)
+ : MDNode(C, DIExpressionKind, Storage, None),
+ Elements(Elements.begin(), Elements.end()) {}
+ ~DIExpression() = default;
+
+ static DIExpression *getImpl(LLVMContext &Context,
+ ArrayRef<uint64_t> Elements, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDIExpression cloneImpl() const {
+ return getTemporary(getContext(), getElements());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements))
+
+ TempDIExpression clone() const { return cloneImpl(); }
+
+ ArrayRef<uint64_t> getElements() const { return Elements; }
+
+ unsigned getNumElements() const { return Elements.size(); }
+ uint64_t getElement(unsigned I) const {
+ assert(I < Elements.size() && "Index out of range");
+ return Elements[I];
+ }
+
+ /// \brief Return whether this is a piece of an aggregate variable.
+ bool isBitPiece() const;
+
+ /// \brief Return the offset of this piece in bits.
+ uint64_t getBitPieceOffset() const;
+
+ /// \brief Return the size of this piece in bits.
+ uint64_t getBitPieceSize() const;
+
+ typedef ArrayRef<uint64_t>::iterator element_iterator;
+ element_iterator elements_begin() const { return getElements().begin(); }
+ element_iterator elements_end() const { return getElements().end(); }
+
+ /// \brief A lightweight wrapper around an expression operand.
+ ///
+ /// TODO: Store arguments directly and change \a DIExpression to store a
+ /// range of these.
+ class ExprOperand {
+ const uint64_t *Op;
+
+ public:
+ explicit ExprOperand(const uint64_t *Op) : Op(Op) {}
+
+ const uint64_t *get() const { return Op; }
+
+ /// \brief Get the operand code.
+ uint64_t getOp() const { return *Op; }
+
+ /// \brief Get an argument to the operand.
+ ///
+ /// Never returns the operand itself.
+ uint64_t getArg(unsigned I) const { return Op[I + 1]; }
+
+ unsigned getNumArgs() const { return getSize() - 1; }
+
+ /// \brief Return the size of the operand.
+ ///
+ /// Return the number of elements in the operand (1 + args).
+ unsigned getSize() const;
+ };
+
+ /// \brief An iterator for expression operands.
+ class expr_op_iterator
+ : public std::iterator<std::input_iterator_tag, ExprOperand> {
+ ExprOperand Op;
+
+ public:
+ explicit expr_op_iterator(element_iterator I) : Op(I) {}
+
+ element_iterator getBase() const { return Op.get(); }
+ const ExprOperand &operator*() const { return Op; }
+ const ExprOperand *operator->() const { return &Op; }
+
+ expr_op_iterator &operator++() {
+ increment();
+ return *this;
+ }
+ expr_op_iterator operator++(int) {
+ expr_op_iterator T(*this);
+ increment();
+ return T;
+ }
+
+ /// \brief Get the next iterator.
+ ///
+ /// \a std::next() doesn't work because this is technically an
+ /// input_iterator, but it's a perfectly valid operation. This is an
+ /// accessor to provide the same functionality.
+ expr_op_iterator getNext() const { return ++expr_op_iterator(*this); }
+
+ bool operator==(const expr_op_iterator &X) const {
+ return getBase() == X.getBase();
+ }
+ bool operator!=(const expr_op_iterator &X) const {
+ return getBase() != X.getBase();
+ }
+
+ private:
+ void increment() { Op = ExprOperand(getBase() + Op.getSize()); }
+ };
+
+ /// \brief Visit the elements via ExprOperand wrappers.
+ ///
+ /// These range iterators visit elements through \a ExprOperand wrappers.
+ /// This is not guaranteed to be a valid range unless \a isValid() gives \c
+ /// true.
+ ///
+ /// \pre \a isValid() gives \c true.
+ /// @{
+ expr_op_iterator expr_op_begin() const {
+ return expr_op_iterator(elements_begin());
+ }
+ expr_op_iterator expr_op_end() const {
+ return expr_op_iterator(elements_end());
+ }
+ /// @}
+
+ bool isValid() const;
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIExpressionKind;
+ }
+};
+
+class DIObjCProperty : public DINode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Line;
+ unsigned Attributes;
+
+ DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line,
+ unsigned Attributes, ArrayRef<Metadata *> Ops)
+ : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property,
+ Ops),
+ Line(Line), Attributes(Attributes) {}
+ ~DIObjCProperty() = default;
+
+ static DIObjCProperty *
+ getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line,
+ StringRef GetterName, StringRef SetterName, unsigned Attributes,
+ DIType *Type, StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(Context, getCanonicalMDString(Context, Name), File, Line,
+ getCanonicalMDString(Context, GetterName),
+ getCanonicalMDString(Context, SetterName), Attributes, Type,
+ Storage, ShouldCreate);
+ }
+ static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name,
+ Metadata *File, unsigned Line,
+ MDString *GetterName, MDString *SetterName,
+ unsigned Attributes, Metadata *Type,
+ StorageType Storage, bool ShouldCreate = true);
+
+ TempDIObjCProperty cloneImpl() const {
+ return getTemporary(getContext(), getName(), getFile(), getLine(),
+ getGetterName(), getSetterName(), getAttributes(),
+ getType());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIObjCProperty,
+ (StringRef Name, DIFile *File, unsigned Line,
+ StringRef GetterName, StringRef SetterName,
+ unsigned Attributes, DIType *Type),
+ (Name, File, Line, GetterName, SetterName, Attributes,
+ Type))
+ DEFINE_MDNODE_GET(DIObjCProperty,
+ (MDString * Name, Metadata *File, unsigned Line,
+ MDString *GetterName, MDString *SetterName,
+ unsigned Attributes, Metadata *Type),
+ (Name, File, Line, GetterName, SetterName, Attributes,
+ Type))
+
+ TempDIObjCProperty clone() const { return cloneImpl(); }
+
+ unsigned getLine() const { return Line; }
+ unsigned getAttributes() const { return Attributes; }
+ StringRef getName() const { return getStringOperand(0); }
+ DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
+ StringRef getGetterName() const { return getStringOperand(2); }
+ StringRef getSetterName() const { return getStringOperand(3); }
+
+ /// \brief Get the type.
+ ///
+ /// \note Objective-C doesn't have an ODR, so there is no benefit in storing
+ /// a type ref here.
+ DIType *getType() const { return cast_or_null<DIType>(getRawType()); }
+
+ StringRef getFilename() const {
+ if (auto *F = getFile())
+ return F->getFilename();
+ return "";
+ }
+ StringRef getDirectory() const {
+ if (auto *F = getFile())
+ return F->getDirectory();
+ return "";
+ }
+
+ MDString *getRawName() const { return getOperandAs<MDString>(0); }
+ Metadata *getRawFile() const { return getOperand(1); }
+ MDString *getRawGetterName() const { return getOperandAs<MDString>(2); }
+ MDString *getRawSetterName() const { return getOperandAs<MDString>(3); }
+ Metadata *getRawType() const { return getOperand(4); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIObjCPropertyKind;
+ }
+};
+
+/// \brief An imported module (C++ using directive or similar).
+class DIImportedEntity : public DINode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ unsigned Line;
+
+ DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag,
+ unsigned Line, ArrayRef<Metadata *> Ops)
+ : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {}
+ ~DIImportedEntity() = default;
+
+ static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag,
+ DIScope *Scope, DINodeRef Entity,
+ unsigned Line, StringRef Name,
+ StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, Tag, Scope, Entity, Line,
+ getCanonicalMDString(Context, Name), Storage, ShouldCreate);
+ }
+ static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag,
+ Metadata *Scope, Metadata *Entity,
+ unsigned Line, MDString *Name,
+ StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDIImportedEntity cloneImpl() const {
+ return getTemporary(getContext(), getTag(), getScope(), getEntity(),
+ getLine(), getName());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIImportedEntity,
+ (unsigned Tag, DIScope *Scope, DINodeRef Entity,
+ unsigned Line, StringRef Name = ""),
+ (Tag, Scope, Entity, Line, Name))
+ DEFINE_MDNODE_GET(DIImportedEntity,
+ (unsigned Tag, Metadata *Scope, Metadata *Entity,
+ unsigned Line, MDString *Name),
+ (Tag, Scope, Entity, Line, Name))
+
+ TempDIImportedEntity clone() const { return cloneImpl(); }
+
+ unsigned getLine() const { return Line; }
+ DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
+ DINodeRef getEntity() const { return DINodeRef(getRawEntity()); }
+ StringRef getName() const { return getStringOperand(2); }
+
+ Metadata *getRawScope() const { return getOperand(0); }
+ Metadata *getRawEntity() const { return getOperand(1); }
+ MDString *getRawName() const { return getOperandAs<MDString>(2); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIImportedEntityKind;
+ }
+};
+
+} // end namespace llvm
+
+#undef DEFINE_MDNODE_GET_UNPACK_IMPL
+#undef DEFINE_MDNODE_GET_UNPACK
+#undef DEFINE_MDNODE_GET
+
+#endif
diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h
index 86e64417099d..8ea5875e1f85 100644
--- a/include/llvm/IR/DebugLoc.h
+++ b/include/llvm/IR/DebugLoc.h
@@ -22,11 +22,15 @@ namespace llvm {
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 DILocation;
+
+ /// \brief A debug info location.
+ ///
+ /// This class is a wrapper around a tracking reference to an \a DILocation
+ /// pointer.
+ ///
+ /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a
+ /// one based on relatively opaque \a MDNode pointers.
class DebugLoc {
TrackingMDNodeRef Loc;
@@ -43,67 +47,78 @@ namespace llvm {
return *this;
}
+ /// \brief Construct from an \a DILocation.
+ DebugLoc(const DILocation *L);
+
+ /// \brief Construct from an \a MDNode.
+ ///
+ /// Note: if \c N is not an \a DILocation, a verifier check will fail, and
+ /// accessors will crash. However, construction from other nodes is
+ /// supported in order to handle forward references when reading textual
+ /// IR.
+ explicit DebugLoc(const MDNode *N);
+
+ /// \brief Get the underlying \a DILocation.
+ ///
+ /// \pre !*this or \c isa<DILocation>(getAsMDNode()).
+ /// @{
+ DILocation *get() const;
+ operator DILocation *() const { return get(); }
+ DILocation *operator->() const { return get(); }
+ DILocation &operator*() const { return *get(); }
+ /// @}
+
+ /// \brief Check for null.
+ ///
+ /// Check for null in a way that is safe with broken debug info. Unlike
+ /// the conversion to \c DILocation, this doesn't require that \c Loc is of
+ /// the right type. Important for cases like \a llvm::StripDebugInfo() and
+ /// \a Instruction::hasMetadata().
+ explicit operator bool() const { return Loc; }
+
/// \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);
-
- /// getFromDILocation - Translate the DILocation quad into a DebugLoc.
- static DebugLoc getFromDILocation(MDNode *N);
-
- /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc.
- static DebugLoc getFromDILexicalBlock(MDNode *N);
-
- /// isUnknown - Return true if this is an unknown location.
- bool isUnknown() const { return !Loc; }
+ /// \brief Create a new DebugLoc.
+ ///
+ /// Create a new DebugLoc at the specified line/col and scope/inline. This
+ /// forwards to \a DILocation::get().
+ ///
+ /// If \c !Scope, returns a default-constructed \a DebugLoc.
+ ///
+ /// FIXME: Remove this. Users should use DILocation::get().
+ static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope,
+ const MDNode *InlinedAt = nullptr);
unsigned getLine() const;
unsigned getCol() const;
-
- /// getScope - This returns the scope pointer for this DebugLoc, or null if
- /// invalid.
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;
- 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 &) const {
- return getScopeAndInlinedAt(Scope, IA);
- }
-
- /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid.
- 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.
+ DILocation *getInlinedAt() const;
+
+ /// \brief Get the fully inlined-at scope for a DebugLoc.
+ ///
+ /// Gets the inlined-at scope for a DebugLoc.
+ MDNode *getInlinedAtScope() const;
+
+ /// \brief Find the debug info location for the start of the function.
+ ///
+ /// Walk up the scope chain of given debug loc and find line number info
+ /// for the function.
+ ///
+ /// FIXME: Remove this. Users should use DILocation/DILocalScope API to
+ /// find the subprogram, and then DILocation::get().
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;
- MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); }
+ /// \brief Return \c this as a bar \a MDNode.
+ MDNode *getAsMDNode() const { return Loc; }
bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; }
- bool operator!=(const DebugLoc &DL) const { return !(*this == DL); }
+ bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; }
void dump() const;
- void dump(const LLVMContext &) const { dump(); }
+
/// \brief prints source location /path/to/file.exe:line:col @[inlined at]
void print(raw_ostream &OS) const;
- void print(const LLVMContext &, raw_ostream &OS) const { print(OS); }
};
} // end namespace llvm
diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h
index 182015c98aa2..38f1af0d70da 100644
--- a/include/llvm/IR/DerivedTypes.h
+++ b/include/llvm/IR/DerivedTypes.h
@@ -94,8 +94,8 @@ public:
/// FunctionType - Class to represent function types
///
class FunctionType : public Type {
- FunctionType(const FunctionType &) LLVM_DELETED_FUNCTION;
- const FunctionType &operator=(const FunctionType &) LLVM_DELETED_FUNCTION;
+ FunctionType(const FunctionType &) = delete;
+ const FunctionType &operator=(const FunctionType &) = delete;
FunctionType(Type *Result, ArrayRef<Type*> Params, bool IsVarArgs);
public:
@@ -188,8 +188,8 @@ public:
/// generator for a target expects).
///
class StructType : public CompositeType {
- StructType(const StructType &) LLVM_DELETED_FUNCTION;
- const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION;
+ StructType(const StructType &) = delete;
+ const StructType &operator=(const StructType &) = delete;
StructType(LLVMContext &C)
: CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {}
enum {
@@ -308,8 +308,8 @@ public:
///
class SequentialType : public CompositeType {
Type *ContainedType; ///< Storage for the single contained type.
- SequentialType(const SequentialType &) LLVM_DELETED_FUNCTION;
- const SequentialType &operator=(const SequentialType &) LLVM_DELETED_FUNCTION;
+ SequentialType(const SequentialType &) = delete;
+ const SequentialType &operator=(const SequentialType &) = delete;
protected:
SequentialType(TypeID TID, Type *ElType)
@@ -335,8 +335,8 @@ public:
class ArrayType : public SequentialType {
uint64_t NumElements;
- ArrayType(const ArrayType &) LLVM_DELETED_FUNCTION;
- const ArrayType &operator=(const ArrayType &) LLVM_DELETED_FUNCTION;
+ ArrayType(const ArrayType &) = delete;
+ const ArrayType &operator=(const ArrayType &) = delete;
ArrayType(Type *ElType, uint64_t NumEl);
public:
/// ArrayType::get - This static method is the primary way to construct an
@@ -361,8 +361,8 @@ public:
class VectorType : public SequentialType {
unsigned NumElements;
- VectorType(const VectorType &) LLVM_DELETED_FUNCTION;
- const VectorType &operator=(const VectorType &) LLVM_DELETED_FUNCTION;
+ VectorType(const VectorType &) = delete;
+ const VectorType &operator=(const VectorType &) = delete;
VectorType(Type *ElType, unsigned NumEl);
public:
/// VectorType::get - This static method is the primary way to construct an
@@ -446,8 +446,8 @@ public:
/// PointerType - Class to represent pointers.
///
class PointerType : public SequentialType {
- PointerType(const PointerType &) LLVM_DELETED_FUNCTION;
- const PointerType &operator=(const PointerType &) LLVM_DELETED_FUNCTION;
+ PointerType(const PointerType &) = delete;
+ const PointerType &operator=(const PointerType &) = delete;
explicit PointerType(Type *ElType, unsigned AddrSpace);
public:
/// PointerType::get - This constructs a pointer to an object of the specified
@@ -464,6 +464,9 @@ public:
/// element type.
static bool isValidElementType(Type *ElemTy);
+ /// Return true if we can load or store from a pointer to this type.
+ static bool isLoadableOrStorableType(Type *ElemTy);
+
/// @brief Return the address space of the Pointer type.
inline unsigned getAddressSpace() const { return getSubclassData(); }
diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h
index c6a8854e0774..6db5a40c5772 100644
--- a/include/llvm/IR/DiagnosticInfo.h
+++ b/include/llvm/IR/DiagnosticInfo.h
@@ -20,6 +20,7 @@
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
+#include <functional>
namespace llvm {
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index 51403281e964..6c228eae633a 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -19,6 +19,7 @@
#define LLVM_IR_FUNCTION_H
#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
@@ -31,26 +32,6 @@ namespace llvm {
class FunctionType;
class LLVMContext;
-// Traits for intrusive list of basic blocks...
-template<> struct ilist_traits<BasicBlock>
- : public SymbolTableListTraits<BasicBlock, Function> {
-
- // createSentinel is used to get hold of the node that marks the end of the
- // list... (same trick used here as in ilist_traits<Instruction>)
- BasicBlock *createSentinel() const {
- return static_cast<BasicBlock*>(&Sentinel);
- }
- static void destroySentinel(BasicBlock*) {}
-
- BasicBlock *provideInitialHead() const { return createSentinel(); }
- BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); }
- static void noteHead(BasicBlock*, BasicBlock*) {}
-
- static ValueSymbolTable *getSymTab(Function *ItemParent);
-private:
- mutable ilist_half_node<BasicBlock> Sentinel;
-};
-
template<> struct ilist_traits<Argument>
: public SymbolTableListTraits<Argument, Function> {
@@ -86,6 +67,7 @@ private:
mutable ArgumentListType ArgumentList; ///< The formal arguments
ValueSymbolTable *SymTab; ///< Symbol table of args/instructions
AttributeSet AttributeSets; ///< Parameter attributes
+ FunctionType *Ty;
/*
* Value::SubclassData
@@ -96,6 +78,17 @@ private:
* bit 3-6: CallingConvention
*/
+ /// Bits from GlobalObject::GlobalObjectSubclassData.
+ enum {
+ /// Whether this function is materializable.
+ IsMaterializableBit = 1 << 0,
+ HasMetadataHashEntryBit = 1 << 1
+ };
+ void setGlobalObjectBit(unsigned Mask, bool Value) {
+ setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
+ (Value ? Mask : 0u));
+ }
+
friend class SymbolTableListTraits<Function, Module>;
void setParent(Module *parent);
@@ -113,12 +106,8 @@ private:
}
void BuildLazyArguments() const;
- Function(const Function&) LLVM_DELETED_FUNCTION;
- void operator=(const Function&) LLVM_DELETED_FUNCTION;
-
- /// Do the actual lookup of an intrinsic ID when the query could not be
- /// answered from the cache.
- unsigned lookupIntrinsicID() const LLVM_READONLY;
+ Function(const Function&) = delete;
+ void operator=(const Function&) = delete;
/// Function ctor - If the (optional) Module argument is specified, the
/// function is automatically inserted into the end of the function list for
@@ -133,13 +122,13 @@ public:
return new(0) Function(Ty, Linkage, N, M);
}
- ~Function();
+ ~Function() override;
Type *getReturnType() const; // Return the type of the ret val
FunctionType *getFunctionType() const; // Return the FunctionType for me
- /// getContext - Return a pointer to the LLVMContext associated with this
- /// function, or NULL if this function is not bound to a context yet.
+ /// getContext - Return a reference to the LLVMContext associated with this
+ /// function.
LLVMContext &getContext() const;
/// isVarArg - Return true if this function takes a variable number of
@@ -154,13 +143,17 @@ public:
/// intrinsic, or if the pointer is null. This value is always defined to be
/// zero to allow easy checking for whether a function is intrinsic or not.
/// The particular intrinsic functions which correspond to this value are
- /// defined in llvm/Intrinsics.h. Results are cached in the LLVM context,
- /// subsequent requests for the same ID return results much faster from the
- /// cache.
- ///
- unsigned getIntrinsicID() const LLVM_READONLY;
+ /// defined in llvm/Intrinsics.h.
+ Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; }
bool isIntrinsic() const { return getName().startswith("llvm."); }
+ /// \brief Recalculate the ID for this function if it is an Intrinsic defined
+ /// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic
+ /// if the name of this function does not match an intrinsic in that header.
+ /// Note, this method does not need to be called directly, as it is called
+ /// from Value::setName() whenever the name of this function changes.
+ void recalculateIntrinsicID();
+
/// getCallingConv()/setCallingConv(CC) - These method get and set the
/// calling convention of this function. The enum values for the known
/// calling conventions are defined in CallingConv.h.
@@ -202,6 +195,12 @@ public:
AttributeSet::FunctionIndex, Kind, Value));
}
+ /// Set the entry count for this function.
+ void setEntryCount(uint64_t Count);
+
+ /// Get the entry count for this function.
+ Optional<uint64_t> getEntryCount() const;
+
/// @brief Return true if the function has the attribute.
bool hasFnAttribute(Attribute::AttrKind Kind) const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
@@ -218,6 +217,11 @@ public:
return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind);
}
+ /// \brief Return the stack alignment for the function.
+ unsigned getFnStackAlignment() const {
+ return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex);
+ }
+
/// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm
/// to use during code generation.
bool hasGC() const;
@@ -234,6 +238,13 @@ public:
/// @brief removes the attributes from the list of attributes.
void removeAttributes(unsigned i, AttributeSet attr);
+ /// @brief adds the dereferenceable attribute to the list of attributes.
+ void addDereferenceableAttr(unsigned i, uint64_t Bytes);
+
+ /// @brief adds the dereferenceable_or_null attribute to the list of
+ /// attributes.
+ void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
+
/// @brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
return AttributeSets.getParamAlignment(i);
@@ -244,7 +255,13 @@ public:
uint64_t getDereferenceableBytes(unsigned i) const {
return AttributeSets.getDereferenceableBytes(i);
}
-
+
+ /// @brief Extract the number of dereferenceable_or_null bytes for a call or
+ /// parameter (0=unknown).
+ uint64_t getDereferenceableOrNullBytes(unsigned i) const {
+ return AttributeSets.getDereferenceableOrNullBytes(i);
+ }
+
/// @brief Determine if the function does not access memory.
bool doesNotAccessMemory() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
@@ -291,6 +308,16 @@ public:
addFnAttr(Attribute::NoDuplicate);
}
+ /// @brief Determine if the call is convergent.
+ bool isConvergent() const {
+ return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::Convergent);
+ }
+ void setConvergent() {
+ addFnAttr(Attribute::Convergent);
+ }
+
+
/// @brief True if the ABI mandates (or the user requested) that this
/// function be in a unwind table.
bool hasUWTable() const {
@@ -464,6 +491,10 @@ public:
Constant *getPrologueData() const;
void setPrologueData(Constant *PrologueData);
+ /// Print the function to an output stream with an optional
+ /// AssemblyAnnotationWriter.
+ void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr) const;
+
/// 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
@@ -514,12 +545,50 @@ public:
/// setjmp or other function that gcc recognizes as "returning twice".
bool callsFunctionThatReturnsTwice() const;
+ /// \brief Check if this has any metadata.
+ bool hasMetadata() const { return hasMetadataHashEntry(); }
+
+ /// \brief Get the current metadata attachment, if any.
+ ///
+ /// Returns \c nullptr if such an attachment is missing.
+ /// @{
+ MDNode *getMetadata(unsigned KindID) const;
+ MDNode *getMetadata(StringRef Kind) const;
+ /// @}
+
+ /// \brief Set a particular kind of metadata attachment.
+ ///
+ /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
+ /// replacing it if it already exists.
+ /// @{
+ void setMetadata(unsigned KindID, MDNode *MD);
+ void setMetadata(StringRef Kind, MDNode *MD);
+ /// @}
+
+ /// \brief Get all current metadata attachments.
+ void
+ getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
+
+ /// \brief Drop metadata not in the given list.
+ ///
+ /// Drop all metadata from \c this not included in \c KnownIDs.
+ void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
+
private:
// Shadow Value::setValueSubclassData with a private forwarding method so that
// subclasses cannot accidentally use it.
void setValueSubclassData(unsigned short D) {
Value::setValueSubclassData(D);
}
+
+ bool hasMetadataHashEntry() const {
+ return getGlobalObjectSubClassData() & HasMetadataHashEntryBit;
+ }
+ void setHasMetadataHashEntry(bool HasEntry) {
+ setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry);
+ }
+
+ void clearMetadata();
};
inline ValueSymbolTable *
diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h
index 6f57dc2a98a6..1d6c9157f0b8 100644
--- a/include/llvm/IR/GVMaterializer.h
+++ b/include/llvm/IR/GVMaterializer.h
@@ -47,11 +47,14 @@ public:
/// lazily. If the Materializer doesn't support this capability, this method
/// is a noop.
///
- virtual void Dematerialize(GlobalValue *) {}
+ virtual void dematerialize(GlobalValue *) {}
/// Make sure the entire Module has been completely read.
///
- virtual std::error_code MaterializeModule(Module *M) = 0;
+ virtual std::error_code materializeModule(Module *M) = 0;
+
+ virtual std::error_code materializeMetadata() = 0;
+ virtual void setStripDebugInfo() = 0;
virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0;
};
diff --git a/include/llvm/IR/GetElementPtrTypeIterator.h b/include/llvm/IR/GetElementPtrTypeIterator.h
index dcf8e64dbb27..6bba0ae29e98 100644
--- a/include/llvm/IR/GetElementPtrTypeIterator.h
+++ b/include/llvm/IR/GetElementPtrTypeIterator.h
@@ -16,7 +16,9 @@
#define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Operator.h"
#include "llvm/IR/User.h"
+#include "llvm/ADT/PointerIntPair.h"
namespace llvm {
template<typename ItTy = User::const_op_iterator>
@@ -26,19 +28,28 @@ namespace llvm {
Type *, ptrdiff_t> super;
ItTy OpIt;
- Type *CurTy;
+ PointerIntPair<Type *, 1> CurTy;
+ unsigned AddrSpace;
generic_gep_type_iterator() {}
public:
static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
generic_gep_type_iterator I;
- I.CurTy = Ty;
+ I.CurTy.setPointer(Ty);
+ I.OpIt = It;
+ return I;
+ }
+ static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace,
+ ItTy It) {
+ generic_gep_type_iterator I;
+ I.CurTy.setPointer(Ty);
+ I.CurTy.setInt(true);
+ I.AddrSpace = AddrSpace;
I.OpIt = It;
return I;
}
static generic_gep_type_iterator end(ItTy It) {
generic_gep_type_iterator I;
- I.CurTy = nullptr;
I.OpIt = It;
return I;
}
@@ -51,11 +62,15 @@ namespace llvm {
}
Type *operator*() const {
- return CurTy;
+ if (CurTy.getInt())
+ return CurTy.getPointer()->getPointerTo(AddrSpace);
+ return CurTy.getPointer();
}
Type *getIndexedType() const {
- CompositeType *CT = cast<CompositeType>(CurTy);
+ if (CurTy.getInt())
+ return CurTy.getPointer();
+ CompositeType *CT = cast<CompositeType>(CurTy.getPointer());
return CT->getTypeAtIndex(getOperand());
}
@@ -66,10 +81,13 @@ namespace llvm {
Value *getOperand() const { return *OpIt; }
generic_gep_type_iterator& operator++() { // Preincrement
- if (CompositeType *CT = dyn_cast<CompositeType>(CurTy)) {
- CurTy = CT->getTypeAtIndex(getOperand());
+ if (CurTy.getInt()) {
+ CurTy.setInt(false);
+ } else if (CompositeType *CT =
+ dyn_cast<CompositeType>(CurTy.getPointer())) {
+ CurTy.setPointer(CT->getTypeAtIndex(getOperand()));
} else {
- CurTy = nullptr;
+ CurTy.setPointer(nullptr);
}
++OpIt;
return *this;
@@ -83,15 +101,23 @@ namespace llvm {
typedef generic_gep_type_iterator<> gep_type_iterator;
inline gep_type_iterator gep_type_begin(const User *GEP) {
- return gep_type_iterator::begin
- (GEP->getOperand(0)->getType()->getScalarType(), GEP->op_begin()+1);
+ auto *GEPOp = cast<GEPOperator>(GEP);
+ return gep_type_iterator::begin(
+ GEPOp->getSourceElementType(),
+ cast<PointerType>(GEPOp->getPointerOperandType()->getScalarType())
+ ->getAddressSpace(),
+ GEP->op_begin() + 1);
}
inline gep_type_iterator gep_type_end(const User *GEP) {
return gep_type_iterator::end(GEP->op_end());
}
inline gep_type_iterator gep_type_begin(const User &GEP) {
- return gep_type_iterator::begin
- (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1);
+ auto &GEPOp = cast<GEPOperator>(GEP);
+ return gep_type_iterator::begin(
+ GEPOp.getSourceElementType(),
+ cast<PointerType>(GEPOp.getPointerOperandType()->getScalarType())
+ ->getAddressSpace(),
+ GEP.op_begin() + 1);
}
inline gep_type_iterator gep_type_end(const User &GEP) {
return gep_type_iterator::end(GEP.op_end());
diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h
index 075b5703bccf..ce73b7af8ca1 100644
--- a/include/llvm/IR/GlobalAlias.h
+++ b/include/llvm/IR/GlobalAlias.h
@@ -28,13 +28,13 @@ template<typename ValueSubClass, typename ItemParentClass>
class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> {
friend class SymbolTableListTraits<GlobalAlias, Module>;
- void operator=(const GlobalAlias &) LLVM_DELETED_FUNCTION;
- GlobalAlias(const GlobalAlias &) LLVM_DELETED_FUNCTION;
+ void operator=(const GlobalAlias &) = delete;
+ GlobalAlias(const GlobalAlias &) = delete;
void setParent(Module *parent);
- GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage,
- const Twine &Name, Constant *Aliasee, Module *Parent);
+ GlobalAlias(PointerType *Ty, LinkageTypes Linkage, const Twine &Name,
+ Constant *Aliasee, Module *Parent);
public:
// allocate space for exactly one operand
@@ -44,19 +44,17 @@ public:
/// If a parent module is specified, the alias is automatically inserted into
/// the end of the specified module's alias list.
- static GlobalAlias *create(Type *Ty, unsigned AddressSpace,
- LinkageTypes Linkage, const Twine &Name,
- Constant *Aliasee, Module *Parent);
+ static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage,
+ const Twine &Name, Constant *Aliasee,
+ Module *Parent);
// Without the Aliasee.
- static GlobalAlias *create(Type *Ty, unsigned AddressSpace,
- LinkageTypes Linkage, const Twine &Name,
- Module *Parent);
+ static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage,
+ const Twine &Name, Module *Parent);
// The module is taken from the Aliasee.
- static GlobalAlias *create(Type *Ty, unsigned AddressSpace,
- LinkageTypes Linkage, const Twine &Name,
- GlobalValue *Aliasee);
+ static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage,
+ const Twine &Name, GlobalValue *Aliasee);
// Type, Parent and AddressSpace taken from the Aliasee.
static GlobalAlias *create(LinkageTypes Linkage, const Twine &Name,
diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h
index 546fea2dfa9b..f0552410b61d 100644
--- a/include/llvm/IR/GlobalObject.h
+++ b/include/llvm/IR/GlobalObject.h
@@ -24,10 +24,10 @@ class Comdat;
class Module;
class GlobalObject : public GlobalValue {
- GlobalObject(const GlobalObject &) LLVM_DELETED_FUNCTION;
+ GlobalObject(const GlobalObject &) = delete;
protected:
- GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
+ GlobalObject(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
LinkageTypes Linkage, const Twine &Name)
: GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name), ObjComdat(nullptr) {
setGlobalValueSubClassData(0);
diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h
index d0f7e9a11790..1dfe0c28b02c 100644
--- a/include/llvm/IR/GlobalValue.h
+++ b/include/llvm/IR/GlobalValue.h
@@ -28,8 +28,12 @@ class Comdat;
class PointerType;
class Module;
+namespace Intrinsic {
+ enum ID : unsigned;
+}
+
class GlobalValue : public Constant {
- GlobalValue(const GlobalValue &) LLVM_DELETED_FUNCTION;
+ GlobalValue(const GlobalValue &) = delete;
public:
/// @brief An enumeration for the kinds of linkage for global values.
enum LinkageTypes {
@@ -61,12 +65,12 @@ public:
};
protected:
- GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
+ GlobalValue(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
LinkageTypes Linkage, const Twine &Name)
: Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage),
Visibility(DefaultVisibility), UnnamedAddr(0),
DllStorageClass(DefaultStorageClass),
- ThreadLocal(NotThreadLocal), Parent(nullptr) {
+ ThreadLocal(NotThreadLocal), IntID((Intrinsic::ID)0U), Parent(nullptr) {
setName(Name);
}
@@ -84,7 +88,16 @@ private:
// Give subclasses access to what otherwise would be wasted padding.
// (19 + 3 + 2 + 1 + 2 + 5) == 32.
unsigned SubClassData : 19;
+
protected:
+ /// \brief The intrinsic ID for this subclass (which must be a Function).
+ ///
+ /// This member is defined by this class, but not used for anything.
+ /// Subclasses can use it to store their intrinsic ID, if they have one.
+ ///
+ /// This is stored here to save space in Function on 64-bit hosts.
+ Intrinsic::ID IntID;
+
static const unsigned GlobalValueSubClassDataBits = 19;
unsigned getGlobalValueSubClassData() const {
return SubClassData;
@@ -104,7 +117,7 @@ public:
LocalExecTLSModel
};
- ~GlobalValue() {
+ ~GlobalValue() override {
removeDeadConstantUsers(); // remove any dead constants using this.
}
@@ -165,9 +178,9 @@ public:
const char *getSection() const;
/// Global values are always pointers.
- inline PointerType *getType() const {
- return cast<PointerType>(User::getType());
- }
+ PointerType *getType() const { return cast<PointerType>(User::getType()); }
+
+ Type *getValueType() const { return getType()->getElementType(); }
static LinkageTypes getLinkOnceLinkage(bool ODR) {
return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage;
@@ -317,7 +330,7 @@ public:
/// 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
/// lazily. If !isDematerializable(), this method is a noop.
- void Dematerialize();
+ void dematerialize();
/// @}
@@ -343,13 +356,11 @@ public:
virtual void eraseFromParent() = 0;
/// Get the module that this global value is contained inside of...
- inline Module *getParent() { return Parent; }
- inline const Module *getParent() const { return Parent; }
-
- const DataLayout *getDataLayout() const;
+ Module *getParent() { return Parent; }
+ const Module *getParent() const { return Parent; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Value *V) {
+ static bool classof(const Value *V) {
return V->getValueID() == Value::FunctionVal ||
V->getValueID() == Value::GlobalVariableVal ||
V->getValueID() == Value::GlobalAliasVal;
diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h
index 4189ccb90a54..9f57705dae72 100644
--- a/include/llvm/IR/GlobalVariable.h
+++ b/include/llvm/IR/GlobalVariable.h
@@ -34,9 +34,9 @@ template<typename ValueSubClass, typename ItemParentClass>
class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
friend class SymbolTableListTraits<GlobalVariable, Module>;
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION;
- GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ void operator=(const GlobalVariable &) = delete;
+ GlobalVariable(const GlobalVariable &) = delete;
void setParent(Module *parent);
@@ -66,7 +66,7 @@ public:
ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0,
bool isExternallyInitialized = false);
- ~GlobalVariable() {
+ ~GlobalVariable() override {
NumOperands = 1; // FIXME: needed by operator delete
}
diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index e5f62fb9625e..adf692469ad3 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -21,6 +21,8 @@
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/ConstantFolder.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Operator.h"
@@ -115,17 +117,15 @@ public:
}
/// \brief Set location information used by debugging information.
- void SetCurrentDebugLocation(const DebugLoc &L) {
- CurDbgLocation = L;
- }
+ void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); }
/// \brief Get location information used by debugging information.
- DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; }
+ const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; }
/// \brief If this builder has a current debug location, set it on the
/// specified instruction.
void SetInstDebugLocation(Instruction *I) const {
- if (!CurDbgLocation.isUnknown())
+ if (CurDbgLocation)
I->setDebugLoc(CurDbgLocation);
}
@@ -200,8 +200,8 @@ public:
BasicBlock::iterator Point;
DebugLoc DbgLoc;
- InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION;
- InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION;
+ InsertPointGuard(const InsertPointGuard &) = delete;
+ InsertPointGuard &operator=(const InsertPointGuard &) = delete;
public:
InsertPointGuard(IRBuilderBase &B)
@@ -221,9 +221,9 @@ public:
FastMathFlags FMF;
MDNode *FPMathTag;
- FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION;
+ FastMathFlagGuard(const FastMathFlagGuard &) = delete;
FastMathFlagGuard &operator=(
- const FastMathFlagGuard &) LLVM_DELETED_FUNCTION;
+ const FastMathFlagGuard &) = delete;
public:
FastMathFlagGuard(IRBuilderBase &B)
@@ -245,7 +245,7 @@ public:
/// filled in with the null terminated string value specified. The new global
/// variable will be marked mergable with any others of the same contents. If
/// Name is specified, it is the name of the global variable created.
- Value *CreateGlobalString(StringRef Str, const Twine &Name = "");
+ GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = "");
/// \brief Get a constant value representing either true or false.
ConstantInt *getInt1(bool V) {
@@ -322,6 +322,11 @@ public:
return Type::getInt64Ty(Context);
}
+ /// \brief Fetch the type representing a 128-bit integer.
+ IntegerType *getInt128Ty() {
+ return Type::getInt128Ty(Context);
+ }
+
/// \brief Fetch the type representing an N-bit integer.
IntegerType *getIntNTy(unsigned N) {
return Type::getIntNTy(Context, N);
@@ -353,8 +358,8 @@ public:
}
/// \brief Fetch the type representing a pointer to an integer value.
- IntegerType* getIntPtrTy(const DataLayout *DL, unsigned AddrSpace = 0) {
- return DL->getIntPtrType(Context, AddrSpace);
+ IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) {
+ return DL.getIntPtrType(Context, AddrSpace);
}
//===--------------------------------------------------------------------===//
@@ -443,11 +448,40 @@ public:
/// \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 = "");
+ CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
+ Value *ActualCallee,
+ ArrayRef<Value *> CallArgs,
+ ArrayRef<Value *> DeoptArgs,
+ ArrayRef<Value *> GCArgs,
+ const Twine &Name = "");
+
+ // \brief Conveninence function for the common case when CallArgs are filled
+ // in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be
+ // .get()'ed to get the Value pointer.
+ CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
+ Value *ActualCallee, ArrayRef<Use> CallArgs,
+ ArrayRef<Value *> DeoptArgs,
+ ArrayRef<Value *> GCArgs,
+ const Twine &Name = "");
+
+ /// brief Create an invoke to the experimental.gc.statepoint intrinsic to
+ /// start a new statepoint sequence.
+ InvokeInst *
+ CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes,
+ Value *ActualInvokee, BasicBlock *NormalDest,
+ BasicBlock *UnwindDest, ArrayRef<Value *> InvokeArgs,
+ ArrayRef<Value *> DeoptArgs,
+ ArrayRef<Value *> GCArgs, const Twine &Name = "");
+
+ // Conveninence function for the common case when CallArgs are filled in using
+ // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to
+ // get the Value *.
+ InvokeInst *
+ CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes,
+ Value *ActualInvokee, BasicBlock *NormalDest,
+ BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs,
+ 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.
@@ -466,7 +500,7 @@ public:
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,
+ CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops,
Type *DataTy, const Twine &Name = "");
Value *getCastedInt8PtrValue(Value *Ptr);
@@ -959,6 +993,9 @@ public:
LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") {
return Insert(new LoadInst(Ptr), Name);
}
+ LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") {
+ return Insert(new LoadInst(Ty, Ptr), Name);
+ }
LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") {
return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name);
}
@@ -1011,6 +1048,10 @@ public:
}
Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
+ return CreateGEP(nullptr, Ptr, IdxList, Name);
+ }
+ Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
+ const Twine &Name = "") {
if (Constant *PC = dyn_cast<Constant>(Ptr)) {
// Every index must be constant.
size_t i, e;
@@ -1018,12 +1059,16 @@ public:
if (!isa<Constant>(IdxList[i]))
break;
if (i == e)
- return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name);
+ return Insert(Folder.CreateGetElementPtr(Ty, PC, IdxList), Name);
}
- return Insert(GetElementPtrInst::Create(Ptr, IdxList), Name);
+ return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name);
}
Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
+ return CreateInBoundsGEP(nullptr, Ptr, IdxList, Name);
+ }
+ Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
+ const Twine &Name = "") {
if (Constant *PC = dyn_cast<Constant>(Ptr)) {
// Every index must be constant.
size_t i, e;
@@ -1031,79 +1076,88 @@ public:
if (!isa<Constant>(IdxList[i]))
break;
if (i == e)
- return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name);
+ return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IdxList),
+ Name);
}
- return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxList), Name);
+ return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name);
}
Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") {
+ return CreateGEP(nullptr, Ptr, Idx, Name);
+ }
+ Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") {
if (Constant *PC = dyn_cast<Constant>(Ptr))
if (Constant *IC = dyn_cast<Constant>(Idx))
- return Insert(Folder.CreateGetElementPtr(PC, IC), Name);
- return Insert(GetElementPtrInst::Create(Ptr, Idx), Name);
+ return Insert(Folder.CreateGetElementPtr(Ty, PC, IC), Name);
+ return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name);
}
- Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") {
+ Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx,
+ const Twine &Name = "") {
if (Constant *PC = dyn_cast<Constant>(Ptr))
if (Constant *IC = dyn_cast<Constant>(Idx))
- return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name);
- return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name);
+ return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IC), Name);
+ return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name);
}
Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") {
+ return CreateConstGEP1_32(nullptr, Ptr, Idx0, Name);
+ }
+ Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,
+ const Twine &Name = "") {
Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0);
if (Constant *PC = dyn_cast<Constant>(Ptr))
- return Insert(Folder.CreateGetElementPtr(PC, Idx), Name);
+ return Insert(Folder.CreateGetElementPtr(Ty, PC, Idx), Name);
- return Insert(GetElementPtrInst::Create(Ptr, Idx), Name);
+ return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name);
}
- Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0,
+ Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,
const Twine &Name = "") {
Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0);
if (Constant *PC = dyn_cast<Constant>(Ptr))
- return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name);
+ return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idx), Name);
- return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name);
+ return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name);
}
- Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1,
- const Twine &Name = "") {
+ Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1,
+ const Twine &Name = "") {
Value *Idxs[] = {
ConstantInt::get(Type::getInt32Ty(Context), Idx0),
ConstantInt::get(Type::getInt32Ty(Context), Idx1)
};
if (Constant *PC = dyn_cast<Constant>(Ptr))
- return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name);
+ return Insert(Folder.CreateGetElementPtr(Ty, PC, Idxs), Name);
- return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name);
+ return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name);
}
- Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1,
- const Twine &Name = "") {
+ Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0,
+ unsigned Idx1, const Twine &Name = "") {
Value *Idxs[] = {
ConstantInt::get(Type::getInt32Ty(Context), Idx0),
ConstantInt::get(Type::getInt32Ty(Context), Idx1)
};
if (Constant *PC = dyn_cast<Constant>(Ptr))
- return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name);
+ return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idxs), Name);
- return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name);
+ return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name);
}
Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") {
Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0);
if (Constant *PC = dyn_cast<Constant>(Ptr))
- return Insert(Folder.CreateGetElementPtr(PC, Idx), Name);
+ return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idx), Name);
- return Insert(GetElementPtrInst::Create(Ptr, Idx), Name);
+ return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name);
}
Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0,
const Twine &Name = "") {
Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0);
if (Constant *PC = dyn_cast<Constant>(Ptr))
- return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name);
+ return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idx), Name);
- return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name);
+ return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name);
}
Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1,
const Twine &Name = "") {
@@ -1113,9 +1167,9 @@ public:
};
if (Constant *PC = dyn_cast<Constant>(Ptr))
- return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name);
+ return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idxs), Name);
- return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name);
+ return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name);
}
Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1,
const Twine &Name = "") {
@@ -1125,21 +1179,23 @@ public:
};
if (Constant *PC = dyn_cast<Constant>(Ptr))
- return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name);
+ return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idxs),
+ Name);
- return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name);
+ return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name);
}
- Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") {
- return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name);
+ Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx,
+ const Twine &Name = "") {
+ return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name);
}
/// \brief Same as CreateGlobalString, but return a pointer with "i8*" type
/// instead of a pointer to array of i8.
Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") {
- Value *gv = CreateGlobalString(Str, Name);
+ GlobalVariable *gv = CreateGlobalString(Str, Name);
Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0);
Value *Args[] = { zero, zero };
- return CreateInBoundsGEP(gv, Args, Name);
+ return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name);
}
//===--------------------------------------------------------------------===//
@@ -1297,7 +1353,7 @@ private:
// \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
// compile time error, instead of converting the string to bool for the
// isSigned parameter.
- Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION;
+ Value *CreateIntCast(Value *, Type *, const char *) = delete;
public:
Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") {
if (V->getType() == DestTy)
@@ -1409,36 +1465,19 @@ public:
return Insert(PHINode::Create(Ty, NumReservedValues), Name);
}
- CallInst *CreateCall(Value *Callee, const Twine &Name = "") {
- return Insert(CallInst::Create(Callee), Name);
- }
- CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") {
- return Insert(CallInst::Create(Callee, Arg), Name);
- }
- CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2,
- const Twine &Name = "") {
- Value *Args[] = { Arg1, Arg2 };
- return Insert(CallInst::Create(Callee, Args), Name);
- }
- CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3,
- const Twine &Name = "") {
- Value *Args[] = { Arg1, Arg2, Arg3 };
- return Insert(CallInst::Create(Callee, Args), Name);
- }
- CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3,
- Value *Arg4, const Twine &Name = "") {
- Value *Args[] = { Arg1, Arg2, Arg3, Arg4 };
+ CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args,
+ const Twine &Name = "") {
return Insert(CallInst::Create(Callee, Args), Name);
}
- CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3,
- Value *Arg4, Value *Arg5, const Twine &Name = "") {
- Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 };
- return Insert(CallInst::Create(Callee, Args), Name);
+
+ CallInst *CreateCall(llvm::FunctionType *FTy, Value *Callee,
+ ArrayRef<Value *> Args, const Twine &Name = "") {
+ return Insert(CallInst::Create(FTy, Callee, Args), Name);
}
- CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args,
+ CallInst *CreateCall(Function *Callee, ArrayRef<Value *> Args,
const Twine &Name = "") {
- return Insert(CallInst::Create(Callee, Args), Name);
+ return CreateCall(Callee->getFunctionType(), Callee, Args, Name);
}
Value *CreateSelect(Value *C, Value *True, Value *False,
@@ -1462,6 +1501,11 @@ public:
return Insert(ExtractElementInst::Create(Vec, Idx), Name);
}
+ Value *CreateExtractElement(Value *Vec, uint64_t Idx,
+ const Twine &Name = "") {
+ return CreateExtractElement(Vec, getInt64(Idx), Name);
+ }
+
Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx,
const Twine &Name = "") {
if (Constant *VC = dyn_cast<Constant>(Vec))
@@ -1471,6 +1515,11 @@ public:
return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name);
}
+ Value *CreateInsertElement(Value *Vec, Value *NewElt, uint64_t Idx,
+ const Twine &Name = "") {
+ return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name);
+ }
+
Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask,
const Twine &Name = "") {
if (Constant *V1C = dyn_cast<Constant>(V1))
@@ -1480,6 +1529,16 @@ public:
return Insert(new ShuffleVectorInst(V1, V2, Mask), Name);
}
+ Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<int> IntMask,
+ const Twine &Name = "") {
+ size_t MaskSize = IntMask.size();
+ SmallVector<Constant*, 8> MaskVec(MaskSize);
+ for (size_t i = 0; i != MaskSize; ++i)
+ MaskVec[i] = getInt32(IntMask[i]);
+ Value *Mask = ConstantVector::get(MaskVec);
+ return CreateShuffleVector(V1, V2, Mask, Name);
+ }
+
Value *CreateExtractValue(Value *Agg,
ArrayRef<unsigned> Idxs,
const Twine &Name = "") {
@@ -1589,7 +1648,7 @@ public:
"trying to create an alignment assumption on a non-pointer?");
PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
- Type *IntPtrTy = getIntPtrTy(&DL, PtrTy->getAddressSpace());
+ Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint");
Value *Mask = ConstantInt::get(IntPtrTy,
diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h
index 7f2027b6e297..5f1d56f7e831 100644
--- a/include/llvm/IR/IRPrintingPasses.h
+++ b/include/llvm/IR/IRPrintingPasses.h
@@ -34,7 +34,8 @@ class raw_ostream;
/// \brief Create and return a pass that writes the module to the specified
/// \c raw_ostream.
ModulePass *createPrintModulePass(raw_ostream &OS,
- const std::string &Banner = "");
+ const std::string &Banner = "",
+ bool ShouldPreserveUseListOrder = false);
/// \brief Create and return a pass that prints functions to the specified
/// \c raw_ostream as they are processed.
@@ -53,10 +54,12 @@ BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS,
class PrintModulePass {
raw_ostream &OS;
std::string Banner;
+ bool ShouldPreserveUseListOrder;
public:
PrintModulePass();
- PrintModulePass(raw_ostream &OS, const std::string &Banner = "");
+ PrintModulePass(raw_ostream &OS, const std::string &Banner = "",
+ bool ShouldPreserveUseListOrder = false);
PreservedAnalyses run(Module &M);
diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h
index b2d79d0f0bfc..15942f16e67e 100644
--- a/include/llvm/IR/InlineAsm.h
+++ b/include/llvm/IR/InlineAsm.h
@@ -40,8 +40,8 @@ private:
friend struct InlineAsmKeyType;
friend class ConstantUniqueMap<InlineAsm>;
- InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION;
- void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION;
+ InlineAsm(const InlineAsm &) = delete;
+ void operator=(const InlineAsm&) = delete;
std::string AsmString, Constraints;
bool HasSideEffects;
@@ -51,7 +51,7 @@ private:
InlineAsm(PointerType *Ty, const std::string &AsmString,
const std::string &Constraints, bool hasSideEffects,
bool isAlignStack, AsmDialect asmDialect);
- virtual ~InlineAsm();
+ ~InlineAsm() override;
/// When the ConstantUniqueMap merges two types and makes two InlineAsms
/// identical, it destroys one of them with this method.
@@ -189,6 +189,20 @@ public:
// These are helper methods for dealing with flags in the INLINEASM SDNode
// in the backend.
+ //
+ // The encoding of the flag word is currently:
+ // Bits 2-0 - A Kind_* value indicating the kind of the operand.
+ // Bits 15-3 - The number of SDNode operands associated with this inline
+ // assembly operand.
+ // If bit 31 is set:
+ // Bit 30-16 - The operand number that this operand must match.
+ // When bits 2-0 are Kind_Mem, the Constraint_* value must be
+ // obtained from the flags for this operand number.
+ // Else if bits 2-0 are Kind_Mem:
+ // Bit 30-16 - A Constraint_* value indicating the original constraint
+ // code.
+ // Else:
+ // Bit 30-16 - The register class ID to use for the operand.
enum : uint32_t {
// Fixed operands on an INLINEASM SDNode.
@@ -220,6 +234,27 @@ public:
Kind_Imm = 5, // Immediate.
Kind_Mem = 6, // Memory operand, "m".
+ // Memory constraint codes.
+ // These could be tablegenerated but there's little need to do that since
+ // there's plenty of space in the encoding to support the union of all
+ // constraint codes for all targets.
+ Constraint_Unknown = 0,
+ Constraint_es,
+ Constraint_i,
+ Constraint_m,
+ Constraint_o,
+ Constraint_v,
+ Constraint_Q,
+ Constraint_R,
+ Constraint_S,
+ Constraint_T,
+ Constraint_X,
+ Constraint_Z,
+ Constraint_ZC,
+ Constraint_Zy,
+ Constraints_Max = Constraint_Zy,
+ Constraints_ShiftAmount = 16,
+
Flag_MatchingOperand = 0x80000000
};
@@ -252,6 +287,20 @@ public:
return InputFlag | (RC << 16);
}
+ /// Augment an existing flag word returned by getFlagWord with the constraint
+ /// code for a memory constraint.
+ static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) {
+ assert(Constraint <= 0x7fff && "Too large a memory constraint ID");
+ assert(Constraint <= Constraints_Max && "Unknown constraint ID");
+ assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
+ return InputFlag | (Constraint << Constraints_ShiftAmount);
+ }
+
+ static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) {
+ assert(isMemKind(InputFlag));
+ return InputFlag & ~(0x7fff << Constraints_ShiftAmount);
+ }
+
static unsigned getKind(unsigned Flags) {
return Flags & 7;
}
@@ -266,6 +315,11 @@ public:
return getKind(Flag) == Kind_Clobber;
}
+ static unsigned getMemoryConstraintID(unsigned Flag) {
+ assert(isMemKind(Flag));
+ return (Flag >> Constraints_ShiftAmount) & 0x7fff;
+ }
+
/// getNumOperandRegisters - Extract the number of registers field from the
/// inline asm operand flag.
static unsigned getNumOperandRegisters(unsigned Flag) {
diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h
index 75e93bd2ff8c..f3ce6490fb66 100644
--- a/include/llvm/IR/InstIterator.h
+++ b/include/llvm/IR/InstIterator.h
@@ -27,15 +27,14 @@ namespace llvm {
// This class implements inst_begin() & inst_end() for
// inst_iterator and const_inst_iterator's.
//
-template <class _BB_t, class _BB_i_t, class _BI_t, class _II_t>
-class InstIterator {
- typedef _BB_t BBty;
- typedef _BB_i_t BBIty;
- typedef _BI_t BIty;
- typedef _II_t IIty;
- _BB_t *BBs; // BasicBlocksType
- _BB_i_t BB; // BasicBlocksType::iterator
- _BI_t BI; // BasicBlock::iterator
+template <class BB_t, class BB_i_t, class BI_t, class II_t> class InstIterator {
+ typedef BB_t BBty;
+ typedef BB_i_t BBIty;
+ typedef BI_t BIty;
+ typedef II_t IIty;
+ BB_t *BBs; // BasicBlocksType
+ BB_i_t BB; // BasicBlocksType::iterator
+ BI_t BI; // BasicBlock::iterator
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef IIty value_type;
@@ -127,20 +126,32 @@ typedef InstIterator<const iplist<BasicBlock>,
inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); }
inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); }
+inline iterator_range<inst_iterator> inst_range(Function *F) {
+ return iterator_range<inst_iterator>(inst_begin(F), inst_end(F));
+}
inline const_inst_iterator inst_begin(const Function *F) {
return const_inst_iterator(*F);
}
inline const_inst_iterator inst_end(const Function *F) {
return const_inst_iterator(*F, true);
}
+inline iterator_range<const_inst_iterator> inst_range(const Function *F) {
+ return iterator_range<const_inst_iterator>(inst_begin(F), inst_end(F));
+}
inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); }
inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); }
+inline iterator_range<inst_iterator> inst_range(Function &F) {
+ return iterator_range<inst_iterator>(inst_begin(F), inst_end(F));
+}
inline const_inst_iterator inst_begin(const Function &F) {
return const_inst_iterator(F);
}
inline const_inst_iterator inst_end(const Function &F) {
return const_inst_iterator(F, true);
}
+inline iterator_range<const_inst_iterator> inst_range(const Function &F) {
+ return iterator_range<const_inst_iterator>(inst_begin(F), inst_end(F));
+}
} // End llvm namespace
diff --git a/include/llvm/IR/InstVisitor.h b/include/llvm/IR/InstVisitor.h
index 1cdcd55448c9..581e860b8382 100644
--- a/include/llvm/IR/InstVisitor.h
+++ b/include/llvm/IR/InstVisitor.h
@@ -259,7 +259,7 @@ private:
// Special helper function to delegate to CallInst subclass visitors.
RetTy delegateCallInst(CallInst &I) {
if (const Function *F = I.getCalledFunction()) {
- switch ((Intrinsic::ID)F->getIntrinsicID()) {
+ switch (F->getIntrinsicID()) {
default: DELEGATE(IntrinsicInst);
case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst);
case Intrinsic::dbg_value: DELEGATE(DbgValueInst);
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index 030f5d690a0c..108b9eb36b7e 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -44,7 +44,7 @@ protected:
: Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {}
// Out of line virtual method, so the vtable, etc has a home.
- ~TerminatorInst();
+ ~TerminatorInst() override;
/// Virtual methods - Terminators should overload these and provide inline
/// overrides of non-V methods.
@@ -83,7 +83,7 @@ public:
//===----------------------------------------------------------------------===//
class UnaryInstruction : public Instruction {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
protected:
UnaryInstruction(Type *Ty, unsigned iType, Value *V,
@@ -102,7 +102,7 @@ public:
}
// Out of line virtual method, so the vtable, etc has a home.
- ~UnaryInstruction();
+ ~UnaryInstruction() override;
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -132,7 +132,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value)
//===----------------------------------------------------------------------===//
class BinaryOperator : public Instruction {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
protected:
void init(BinaryOps iType);
BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty,
@@ -570,10 +570,9 @@ public:
/// 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.
- );
+ Type *SrcTy, ///< The Type from which the value should be cast.
+ Type *DestTy, ///< The Type to which the value should be cast.
+ const DataLayout &DL);
/// Returns the opcode necessary to cast Val into Ty using usual casting
/// rules.
@@ -621,9 +620,9 @@ public:
) const;
/// @brief Determine if this cast is a no-op cast.
- bool isNoopCast(
- const DataLayout *DL ///< DataLayout to get the Int Ptr type from.
- ) const;
+ ///
+ /// \param DL is the DataLayout to get the Int Ptr type from.
+ bool isNoopCast(const DataLayout &DL) const;
/// Determine how a pair of casts can be eliminated, if they can be at all.
/// This is a helper function for both CastInst and ConstantExpr.
@@ -674,8 +673,8 @@ public:
/// This class is the base class for the comparison instructions.
/// @brief Abstract base class of comparison instructions.
class CmpInst : public Instruction {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- CmpInst() LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ CmpInst() = delete;
protected:
CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred,
Value *LHS, Value *RHS, const Twine &Name = "",
diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h
index ba7791c99b6a..752c3f09bded 100644
--- a/include/llvm/IR/Instruction.h
+++ b/include/llvm/IR/Instruction.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/SymbolTableListTraits.h"
#include "llvm/IR/User.h"
namespace llvm {
@@ -25,14 +26,31 @@ namespace llvm {
class FastMathFlags;
class LLVMContext;
class MDNode;
+class BasicBlock;
struct AAMDNodes;
-template<typename ValueSubClass, typename ItemParentClass>
- class SymbolTableListTraits;
+template <>
+struct ilist_traits<Instruction>
+ : public SymbolTableListTraits<Instruction, BasicBlock> {
+
+ /// \brief Return a node that marks the end of a list.
+ ///
+ /// The sentinel is relative to this instance, so we use a non-static
+ /// method.
+ Instruction *createSentinel() const;
+ static void destroySentinel(Instruction *) {}
+
+ Instruction *provideInitialHead() const { return createSentinel(); }
+ Instruction *ensureHead(Instruction *) const { return createSentinel(); }
+ static void noteHead(Instruction *, Instruction *) {}
+
+private:
+ mutable ilist_half_node<Instruction> Sentinel;
+};
class Instruction : public User, public ilist_node<Instruction> {
- void operator=(const Instruction &) LLVM_DELETED_FUNCTION;
- Instruction(const Instruction &) LLVM_DELETED_FUNCTION;
+ void operator=(const Instruction &) = delete;
+ Instruction(const Instruction &) = delete;
BasicBlock *Parent;
DebugLoc DbgLoc; // 'dbg' Metadata cache.
@@ -44,7 +62,7 @@ class Instruction : public User, public ilist_node<Instruction> {
};
public:
// Out of line virtual method, so the vtable, etc has a home.
- ~Instruction();
+ ~Instruction() override;
/// user_back - Specialize the methods defined in Value, as we know that an
/// instruction can only be used by other instructions.
@@ -54,7 +72,13 @@ public:
inline const BasicBlock *getParent() const { return Parent; }
inline BasicBlock *getParent() { return Parent; }
- const DataLayout *getDataLayout() const;
+ /// \brief Return the module owning the function this instruction belongs to
+ /// or nullptr it the function does not have a module.
+ ///
+ /// Note: this is undefined behavior if the instruction does not have a
+ /// parent, or the parent basic block does not have a parent function.
+ const Module *getModule() const;
+ Module *getModule();
/// removeFromParent - This method unlinks 'this' from the containing basic
/// block, but does not delete it.
@@ -64,14 +88,15 @@ public:
/// eraseFromParent - This method unlinks 'this' from the containing basic
/// block and deletes it.
///
- void eraseFromParent();
+ /// \returns an iterator pointing to the element after the erased one
+ iplist<Instruction>::iterator eraseFromParent();
- /// insertBefore - Insert an unlinked instructions into a basic block
- /// immediately before the specified instruction.
+ /// Insert an unlinked instruction into a basic block immediately before
+ /// the specified instruction.
void insertBefore(Instruction *InsertPos);
- /// insertAfter - Insert an unlinked instructions into a basic block
- /// immediately after the specified instruction.
+ /// Insert an unlinked instruction into a basic block immediately after the
+ /// specified instruction.
void insertAfter(Instruction *InsertPos);
/// moveBefore - Unlink this instruction from its current basic block and
@@ -129,9 +154,7 @@ public:
/// hasMetadata() - Return true if this instruction has any metadata attached
/// to it.
- bool hasMetadata() const {
- return !DbgLoc.isUnknown() || hasMetadataHashEntry();
- }
+ bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); }
/// hasMetadataOtherThanDebugLoc - Return true if this instruction has
/// metadata attached to it other than a debug location.
@@ -201,7 +224,7 @@ public:
void setAAMetadata(const AAMDNodes &N);
/// setDebugLoc - Set the debug location information for this instruction.
- void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; }
+ void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); }
/// getDebugLoc - Return the debug location for this node as a DebugLoc.
const DebugLoc &getDebugLoc() const { return DbgLoc; }
@@ -490,6 +513,17 @@ protected:
};
+inline Instruction *ilist_traits<Instruction>::createSentinel() const {
+ // Since i(p)lists always publicly derive from their corresponding traits,
+ // placing a data member in this class will augment the i(p)list. But since
+ // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>,
+ // there is a legal viable downcast from it to NodeTy. We use this trick to
+ // superimpose an 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<Instruction *>(&Sentinel);
+}
+
// Instruction* is only 4-byte aligned.
template<>
class PointerLikeTypeTraits<Instruction*> {
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index 045e51eb1baa..9f5e244f0021 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -73,6 +73,8 @@ return (Ord == Release ||
/// AllocaInst - an instruction to allocate memory on the stack
///
class AllocaInst : public UnaryInstruction {
+ Type *AllocatedType;
+
protected:
AllocaInst *clone_impl() const override;
public:
@@ -91,7 +93,7 @@ public:
const Twine &Name, BasicBlock *InsertAtEnd);
// Out of line virtual method, so the vtable, etc. has a home.
- virtual ~AllocaInst();
+ ~AllocaInst() override;
/// isArrayAllocation - Return true if there is an allocation size parameter
/// to the allocation instruction that is not 1.
@@ -113,7 +115,10 @@ public:
/// getAllocatedType - Return the type that is being allocated by the
/// instruction.
///
- Type *getAllocatedType() const;
+ Type *getAllocatedType() const { return AllocatedType; }
+ /// \brief for use only in special circumstances that need to generically
+ /// transform a whole instruction (eg: IR linking and vectorization).
+ void setAllocatedType(Type *Ty) { AllocatedType = Ty; }
/// getAlignment - Return the alignment of the memory that is being allocated
/// by the instruction.
@@ -172,15 +177,28 @@ protected:
public:
LoadInst(Value *Ptr, const Twine &NameStr, Instruction *InsertBefore);
LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd);
- LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false,
+ LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile = false,
Instruction *InsertBefore = nullptr);
+ LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false,
+ Instruction *InsertBefore = nullptr)
+ : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr,
+ NameStr, isVolatile, InsertBefore) {}
LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
BasicBlock *InsertAtEnd);
- LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
+ LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align,
+ Instruction *InsertBefore = nullptr)
+ : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr,
+ NameStr, isVolatile, Align, InsertBefore) {}
+ LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile,
unsigned Align, Instruction *InsertBefore = nullptr);
LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
unsigned Align, BasicBlock *InsertAtEnd);
- LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
+ LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align,
+ AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread,
+ Instruction *InsertBefore = nullptr)
+ : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr,
+ NameStr, isVolatile, Align, Order, SynchScope, InsertBefore) {}
+ LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile,
unsigned Align, AtomicOrdering Order,
SynchronizationScope SynchScope = CrossThread,
Instruction *InsertBefore = nullptr);
@@ -191,9 +209,13 @@ public:
LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore);
LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd);
+ LoadInst(Type *Ty, Value *Ptr, const char *NameStr = nullptr,
+ bool isVolatile = false, Instruction *InsertBefore = nullptr);
explicit LoadInst(Value *Ptr, const char *NameStr = nullptr,
bool isVolatile = false,
- Instruction *InsertBefore = nullptr);
+ Instruction *InsertBefore = nullptr)
+ : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr,
+ NameStr, isVolatile, InsertBefore) {}
LoadInst(Value *Ptr, const char *NameStr, bool isVolatile,
BasicBlock *InsertAtEnd);
@@ -285,7 +307,7 @@ private:
/// StoreInst - an instruction for storing to memory
///
class StoreInst : public Instruction {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
void AssertOK();
protected:
StoreInst *clone_impl() const override;
@@ -411,7 +433,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value)
/// FenceInst - an instruction for ordering other memory operations
///
class FenceInst : public Instruction {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope);
protected:
FenceInst *clone_impl() const override;
@@ -478,7 +500,7 @@ private:
/// there. Returns the value that was loaded.
///
class AtomicCmpXchgInst : public Instruction {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
void Init(Value *Ptr, Value *Cmp, Value *NewVal,
AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
@@ -634,7 +656,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value)
/// the old value.
///
class AtomicRMWInst : public Instruction {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
protected:
AtomicRMWInst *clone_impl() const override;
public:
@@ -787,6 +809,8 @@ inline Type *checkGEPType(Type *Ty) {
/// access elements of arrays and structs
///
class GetElementPtrInst : public Instruction {
+ Type *SourceElementType;
+
GetElementPtrInst(const GetElementPtrInst &GEPI);
void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr);
@@ -794,28 +818,45 @@ class GetElementPtrInst : public Instruction {
/// list of indices. The first ctor can optionally insert before an existing
/// instruction, the second appends the new instruction to the specified
/// BasicBlock.
- inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList,
- unsigned Values, const Twine &NameStr,
- Instruction *InsertBefore);
- inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList,
- unsigned Values, const Twine &NameStr,
- BasicBlock *InsertAtEnd);
+ inline GetElementPtrInst(Type *PointeeType, Value *Ptr,
+ ArrayRef<Value *> IdxList, unsigned Values,
+ const Twine &NameStr, Instruction *InsertBefore);
+ inline GetElementPtrInst(Type *PointeeType, Value *Ptr,
+ ArrayRef<Value *> IdxList, unsigned Values,
+ const Twine &NameStr, BasicBlock *InsertAtEnd);
+
protected:
GetElementPtrInst *clone_impl() const override;
public:
- static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList,
+ static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr,
+ ArrayRef<Value *> IdxList,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
unsigned Values = 1 + unsigned(IdxList.size());
- return new(Values)
- GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertBefore);
- }
- static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList,
+ if (!PointeeType)
+ PointeeType =
+ cast<PointerType>(Ptr->getType()->getScalarType())->getElementType();
+ else
+ assert(
+ PointeeType ==
+ cast<PointerType>(Ptr->getType()->getScalarType())->getElementType());
+ return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values,
+ NameStr, InsertBefore);
+ }
+ static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr,
+ ArrayRef<Value *> IdxList,
const Twine &NameStr,
BasicBlock *InsertAtEnd) {
unsigned Values = 1 + unsigned(IdxList.size());
- return new(Values)
- GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertAtEnd);
+ if (!PointeeType)
+ PointeeType =
+ cast<PointerType>(Ptr->getType()->getScalarType())->getElementType();
+ else
+ assert(
+ PointeeType ==
+ cast<PointerType>(Ptr->getType()->getScalarType())->getElementType());
+ return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values,
+ NameStr, InsertAtEnd);
}
/// Create an "inbounds" getelementptr. See the documentation for the
@@ -824,7 +865,14 @@ public:
ArrayRef<Value *> IdxList,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr){
- GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertBefore);
+ return CreateInBounds(nullptr, Ptr, IdxList, NameStr, InsertBefore);
+ }
+ static GetElementPtrInst *
+ CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef<Value *> IdxList,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
+ GetElementPtrInst *GEP =
+ Create(PointeeType, Ptr, IdxList, NameStr, InsertBefore);
GEP->setIsInBounds(true);
return GEP;
}
@@ -832,7 +880,14 @@ public:
ArrayRef<Value *> IdxList,
const Twine &NameStr,
BasicBlock *InsertAtEnd) {
- GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertAtEnd);
+ return CreateInBounds(nullptr, Ptr, IdxList, NameStr, InsertAtEnd);
+ }
+ static GetElementPtrInst *CreateInBounds(Type *PointeeType, Value *Ptr,
+ ArrayRef<Value *> IdxList,
+ const Twine &NameStr,
+ BasicBlock *InsertAtEnd) {
+ GetElementPtrInst *GEP =
+ Create(PointeeType, Ptr, IdxList, NameStr, InsertAtEnd);
GEP->setIsInBounds(true);
return GEP;
}
@@ -845,6 +900,14 @@ public:
return cast<SequentialType>(Instruction::getType());
}
+ Type *getSourceElementType() const { return SourceElementType; }
+
+ void setSourceElementType(Type *Ty) { SourceElementType = Ty; }
+
+ Type *getResultElementType() const {
+ return cast<PointerType>(getType()->getScalarType())->getElementType();
+ }
+
/// \brief Returns the address space of this instruction's pointer type.
unsigned getAddressSpace() const {
// Note that this is always the same as the pointer operand's address space
@@ -858,9 +921,9 @@ public:
/// Null is returned if the indices are invalid for the specified
/// pointer type.
///
- static Type *getIndexedType(Type *Ptr, ArrayRef<Value *> IdxList);
- static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList);
- static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList);
+ static Type *getIndexedType(Type *Ty, ArrayRef<Value *> IdxList);
+ static Type *getIndexedType(Type *Ty, ArrayRef<Constant *> IdxList);
+ static Type *getIndexedType(Type *Ty, ArrayRef<uint64_t> IdxList);
inline op_iterator idx_begin() { return op_begin()+1; }
inline const_op_iterator idx_begin() const { return op_begin()+1; }
@@ -891,8 +954,13 @@ public:
/// GetGEPReturnType - Returns the pointer type returned by the GEP
/// instruction, which may be a vector of pointers.
static Type *getGEPReturnType(Value *Ptr, ArrayRef<Value *> IdxList) {
- Type *PtrTy = PointerType::get(checkGEPType(
- getIndexedType(Ptr->getType(), IdxList)),
+ return getGEPReturnType(
+ cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(),
+ Ptr, IdxList);
+ }
+ static Type *getGEPReturnType(Type *ElTy, Value *Ptr,
+ ArrayRef<Value *> IdxList) {
+ Type *PtrTy = PointerType::get(checkGEPType(getIndexedType(ElTy, IdxList)),
Ptr->getType()->getPointerAddressSpace());
// Vector GEP
if (Ptr->getType()->isVectorTy()) {
@@ -953,26 +1021,24 @@ struct OperandTraits<GetElementPtrInst> :
public VariadicOperandTraits<GetElementPtrInst, 1> {
};
-GetElementPtrInst::GetElementPtrInst(Value *Ptr,
- ArrayRef<Value *> IdxList,
- unsigned Values,
+GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,
+ ArrayRef<Value *> IdxList, unsigned Values,
const Twine &NameStr,
Instruction *InsertBefore)
- : Instruction(getGEPReturnType(Ptr, IdxList),
- GetElementPtr,
- OperandTraits<GetElementPtrInst>::op_end(this) - Values,
- Values, InsertBefore) {
+ : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr,
+ OperandTraits<GetElementPtrInst>::op_end(this) - Values,
+ Values, InsertBefore),
+ SourceElementType(PointeeType) {
init(Ptr, IdxList, NameStr);
}
-GetElementPtrInst::GetElementPtrInst(Value *Ptr,
- ArrayRef<Value *> IdxList,
- unsigned Values,
+GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,
+ ArrayRef<Value *> IdxList, unsigned Values,
const Twine &NameStr,
BasicBlock *InsertAtEnd)
- : Instruction(getGEPReturnType(Ptr, IdxList),
- GetElementPtr,
- OperandTraits<GetElementPtrInst>::op_end(this) - Values,
- Values, InsertAtEnd) {
+ : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr,
+ OperandTraits<GetElementPtrInst>::op_end(this) - Values,
+ Values, InsertAtEnd),
+ SourceElementType(PointeeType) {
init(Ptr, IdxList, NameStr);
}
@@ -1194,11 +1260,15 @@ public:
/// @returns true if the predicate of this instruction is EQ or NE.
/// \brief Determine if this is an equality predicate.
- bool isEquality() const {
- return getPredicate() == FCMP_OEQ || getPredicate() == FCMP_ONE ||
- getPredicate() == FCMP_UEQ || getPredicate() == FCMP_UNE;
+ static bool isEquality(Predicate Pred) {
+ return Pred == FCMP_OEQ || Pred == FCMP_ONE || Pred == FCMP_UEQ ||
+ Pred == FCMP_UNE;
}
+ /// @returns true if the predicate of this instruction is EQ or NE.
+ /// \brief Determine if this is an equality predicate.
+ bool isEquality() const { return isEquality(getPredicate()); }
+
/// @returns true if the predicate of this instruction is commutative.
/// \brief Determine if this is a commutative predicate.
bool isCommutative() const {
@@ -1240,14 +1310,26 @@ public:
///
class CallInst : public Instruction {
AttributeSet AttributeList; ///< parameter attributes for call
+ FunctionType *FTy;
CallInst(const CallInst &CI);
- void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr);
+ void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) {
+ init(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, NameStr);
+ }
+ void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
+ const Twine &NameStr);
void init(Value *Func, const Twine &NameStr);
/// Construct a CallInst given a range of arguments.
/// \brief Construct a CallInst from a range of arguments
- inline CallInst(Value *Func, ArrayRef<Value *> Args,
+ inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
const Twine &NameStr, Instruction *InsertBefore);
+ inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : CallInst(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, NameStr, InsertBefore) {}
/// Construct a CallInst given a range of arguments.
/// \brief Construct a CallInst from a range of arguments
@@ -1264,8 +1346,15 @@ public:
ArrayRef<Value *> Args,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
- return new(unsigned(Args.size() + 1))
- CallInst(Func, Args, NameStr, InsertBefore);
+ return Create(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, Args, NameStr, InsertBefore);
+ }
+ static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
+ return new (unsigned(Args.size() + 1))
+ CallInst(Ty, Func, Args, NameStr, InsertBefore);
}
static CallInst *Create(Value *Func,
ArrayRef<Value *> Args,
@@ -1301,7 +1390,14 @@ public:
static Instruction* CreateFree(Value* Source, Instruction *InsertBefore);
static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd);
- ~CallInst();
+ ~CallInst() override;
+
+ FunctionType *getFunctionType() const { return FTy; }
+
+ void mutateFunctionType(FunctionType *FTy) {
+ mutateType(FTy->getReturnType());
+ this->FTy = FTy;
+ }
// Note that 'musttail' implies 'tail'.
enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 };
@@ -1375,6 +1471,13 @@ public:
/// removeAttribute - removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute attr);
+ /// \brief adds the dereferenceable attribute to the list of attributes.
+ void addDereferenceableAttr(unsigned i, uint64_t Bytes);
+
+ /// \brief adds the dereferenceable_or_null attribute to the list of
+ /// attributes.
+ void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
+
/// \brief Determine whether this call has the given attribute.
bool hasFnAttr(Attribute::AttrKind A) const {
assert(A != Attribute::NoBuiltin &&
@@ -1396,6 +1499,12 @@ public:
return AttributeList.getDereferenceableBytes(i);
}
+ /// \brief Extract the number of dereferenceable_or_null bytes for a call or
+ /// parameter (0=unknown).
+ uint64_t getDereferenceableOrNullBytes(unsigned i) const {
+ return AttributeList.getDereferenceableOrNullBytes(i);
+ }
+
/// \brief Return true if the call should not be treated as a call to a
/// builtin.
bool isNoBuiltin() const {
@@ -1477,6 +1586,14 @@ public:
/// setCalledFunction - Set the function called.
void setCalledFunction(Value* Fn) {
+ setCalledFunction(
+ cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()),
+ Fn);
+ }
+ void setCalledFunction(FunctionType *FTy, Value *Fn) {
+ this->FTy = FTy;
+ assert(FTy == cast<FunctionType>(
+ cast<PointerType>(Fn->getType())->getElementType()));
Op<-1>() = Fn;
}
@@ -1517,14 +1634,12 @@ CallInst::CallInst(Value *Func, ArrayRef<Value *> Args,
init(Func, Args, NameStr);
}
-CallInst::CallInst(Value *Func, ArrayRef<Value *> Args,
+CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
const Twine &NameStr, Instruction *InsertBefore)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - (Args.size() + 1),
- unsigned(Args.size() + 1), InsertBefore) {
- init(Func, Args, NameStr);
+ : Instruction(Ty->getReturnType(), Instruction::Call,
+ OperandTraits<CallInst>::op_end(this) - (Args.size() + 1),
+ unsigned(Args.size() + 1), InsertBefore) {
+ init(Ty, Func, Args, NameStr);
}
@@ -1898,6 +2013,9 @@ public:
typedef const unsigned* idx_iterator;
inline idx_iterator idx_begin() const { return Indices.begin(); }
inline idx_iterator idx_end() const { return Indices.end(); }
+ inline iterator_range<idx_iterator> indices() const {
+ return iterator_range<idx_iterator>(idx_begin(), idx_end());
+ }
Value *getAggregateOperand() {
return getOperand(0);
@@ -1958,7 +2076,7 @@ ExtractValueInst::ExtractValueInst(Value *Agg,
class InsertValueInst : public Instruction {
SmallVector<unsigned, 4> Indices;
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
InsertValueInst(const InsertValueInst &IVI);
void init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
const Twine &NameStr);
@@ -2009,6 +2127,9 @@ public:
typedef const unsigned* idx_iterator;
inline idx_iterator idx_begin() const { return Indices.begin(); }
inline idx_iterator idx_end() const { return Indices.end(); }
+ inline iterator_range<idx_iterator> indices() const {
+ return iterator_range<idx_iterator>(idx_begin(), idx_end());
+ }
Value *getAggregateOperand() {
return getOperand(0);
@@ -2088,7 +2209,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value)
// scientist's overactive imagination.
//
class PHINode : public Instruction {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
/// ReservedSpace - The number of operands actually allocated. NumOperands is
/// the number actually in use.
unsigned ReservedSpace;
@@ -2132,7 +2253,7 @@ public:
const Twine &NameStr, BasicBlock *InsertAtEnd) {
return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd);
}
- ~PHINode();
+ ~PHINode() override;
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -2163,6 +2284,10 @@ public:
return block_begin() + getNumOperands();
}
+ op_range incoming_values() { return operands(); }
+
+ const_op_range incoming_values() const { return operands(); }
+
/// getNumIncomingValues - Return the number of incoming edges
///
unsigned getNumIncomingValues() const { return getNumOperands(); }
@@ -2295,7 +2420,7 @@ class LandingPadInst : public Instruction {
public:
enum ClauseType { Catch, Filter };
private:
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
// Allocate space for exactly zero operands.
void *operator new(size_t s) {
return User::operator new(s, 0);
@@ -2321,7 +2446,7 @@ public:
static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn,
unsigned NumReservedClauses,
const Twine &NameStr, BasicBlock *InsertAtEnd);
- ~LandingPadInst();
+ ~LandingPadInst() override;
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -2423,7 +2548,7 @@ public:
static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) {
return new(0) ReturnInst(C, InsertAtEnd);
}
- virtual ~ReturnInst();
+ ~ReturnInst() override;
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -2562,7 +2687,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value)
/// SwitchInst - Multiway switch
///
class SwitchInst : public TerminatorInst {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
unsigned ReservedSpace;
// Operand[0] = Value to switch on
// Operand[1] = Default basic block destination
@@ -2720,7 +2845,7 @@ public:
return new SwitchInst(Value, Default, NumCases, InsertAtEnd);
}
- ~SwitchInst();
+ ~SwitchInst() override;
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -2871,7 +2996,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value)
/// IndirectBrInst - Indirect Branch Instruction.
///
class IndirectBrInst : public TerminatorInst {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
unsigned ReservedSpace;
// Operand[0] = Value to switch on
// Operand[1] = Default basic block destination
@@ -2906,7 +3031,7 @@ public:
BasicBlock *InsertAtEnd) {
return new IndirectBrInst(Address, NumDests, InsertAtEnd);
}
- ~IndirectBrInst();
+ ~IndirectBrInst() override;
/// Provide fast operand accessors.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -2970,17 +3095,33 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value)
///
class InvokeInst : public TerminatorInst {
AttributeSet AttributeList;
+ FunctionType *FTy;
InvokeInst(const InvokeInst &BI);
void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, const Twine &NameStr);
+ ArrayRef<Value *> Args, const Twine &NameStr) {
+ init(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, IfNormal, IfException, Args, NameStr);
+ }
+ void init(FunctionType *FTy, Value *Func, BasicBlock *IfNormal,
+ BasicBlock *IfException, ArrayRef<Value *> Args,
+ const Twine &NameStr);
/// Construct an InvokeInst given a range of arguments.
///
/// \brief Construct an InvokeInst from a range of arguments
inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
ArrayRef<Value *> Args, unsigned Values,
- const Twine &NameStr, Instruction *InsertBefore);
-
+ const Twine &NameStr, Instruction *InsertBefore)
+ : InvokeInst(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, IfNormal, IfException, Args, Values, NameStr,
+ InsertBefore) {}
+
+ inline InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal,
+ BasicBlock *IfException, ArrayRef<Value *> Args,
+ unsigned Values, const Twine &NameStr,
+ Instruction *InsertBefore);
/// Construct an InvokeInst given a range of arguments.
///
/// \brief Construct an InvokeInst from a range of arguments
@@ -2994,9 +3135,17 @@ public:
BasicBlock *IfNormal, BasicBlock *IfException,
ArrayRef<Value *> Args, const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
+ return Create(cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType()),
+ Func, IfNormal, IfException, Args, NameStr, InsertBefore);
+ }
+ static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal,
+ BasicBlock *IfException, ArrayRef<Value *> Args,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
unsigned Values = unsigned(Args.size()) + 3;
- return new(Values) InvokeInst(Func, IfNormal, IfException, Args,
- Values, NameStr, InsertBefore);
+ return new (Values) InvokeInst(Ty, Func, IfNormal, IfException, Args,
+ Values, NameStr, InsertBefore);
}
static InvokeInst *Create(Value *Func,
BasicBlock *IfNormal, BasicBlock *IfException,
@@ -3010,6 +3159,13 @@ public:
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+ FunctionType *getFunctionType() const { return FTy; }
+
+ void mutateFunctionType(FunctionType *FTy) {
+ mutateType(FTy->getReturnType());
+ this->FTy = FTy;
+ }
+
/// getNumArgOperands - Return the number of invoke arguments.
///
unsigned getNumArgOperands() const { return getNumOperands() - 3; }
@@ -3056,6 +3212,13 @@ public:
/// removeAttribute - removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute attr);
+ /// \brief adds the dereferenceable attribute to the list of attributes.
+ void addDereferenceableAttr(unsigned i, uint64_t Bytes);
+
+ /// \brief adds the dereferenceable_or_null attribute to the list of
+ /// attributes.
+ void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
+
/// \brief Determine whether this call has the given attribute.
bool hasFnAttr(Attribute::AttrKind A) const {
assert(A != Attribute::NoBuiltin &&
@@ -3076,6 +3239,12 @@ public:
uint64_t getDereferenceableBytes(unsigned i) const {
return AttributeList.getDereferenceableBytes(i);
}
+
+ /// \brief Extract the number of dereferenceable_or_null bytes for a call or
+ /// parameter (0=unknown).
+ uint64_t getDereferenceableOrNullBytes(unsigned i) const {
+ return AttributeList.getDereferenceableOrNullBytes(i);
+ }
/// \brief Return true if the call should not be treated as a call to a
/// builtin.
@@ -3152,6 +3321,14 @@ public:
/// setCalledFunction - Set the function called.
void setCalledFunction(Value* Fn) {
+ setCalledFunction(
+ cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()),
+ Fn);
+ }
+ void setCalledFunction(FunctionType *FTy, Value *Fn) {
+ this->FTy = FTy;
+ assert(FTy == cast<FunctionType>(
+ cast<PointerType>(Fn->getType())->getElementType()));
Op<-3>() = Fn;
}
@@ -3211,16 +3388,14 @@ template <>
struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> {
};
-InvokeInst::InvokeInst(Value *Func,
- BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, unsigned Values,
- const Twine &NameStr, Instruction *InsertBefore)
- : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Invoke,
- OperandTraits<InvokeInst>::op_end(this) - Values,
- Values, InsertBefore) {
- init(Func, IfNormal, IfException, Args, NameStr);
+InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal,
+ BasicBlock *IfException, ArrayRef<Value *> Args,
+ unsigned Values, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : TerminatorInst(Ty->getReturnType(), Instruction::Invoke,
+ OperandTraits<InvokeInst>::op_end(this) - Values, Values,
+ InsertBefore) {
+ init(Ty, Func, IfNormal, IfException, Args, NameStr);
}
InvokeInst::InvokeInst(Value *Func,
BasicBlock *IfNormal, BasicBlock *IfException,
@@ -3296,7 +3471,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value)
/// end of the block cannot be reached.
///
class UnreachableInst : public TerminatorInst {
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
protected:
UnreachableInst *clone_impl() const override;
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index c227ea080167..2c8b6eb6f39a 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -35,14 +35,14 @@ namespace llvm {
/// functions. This allows the standard isa/dyncast/cast functionality to
/// work with calls to intrinsic functions.
class IntrinsicInst : public CallInst {
- IntrinsicInst() LLVM_DELETED_FUNCTION;
- IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION;
- void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION;
+ IntrinsicInst() = delete;
+ IntrinsicInst(const IntrinsicInst&) = delete;
+ void operator=(const IntrinsicInst&) = delete;
public:
/// getIntrinsicID - Return the intrinsic ID of this intrinsic.
///
Intrinsic::ID getIntrinsicID() const {
- return (Intrinsic::ID)getCalledFunction()->getIntrinsicID();
+ return getCalledFunction()->getIntrinsicID();
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -82,13 +82,18 @@ namespace llvm {
class DbgDeclareInst : public DbgInfoIntrinsic {
public:
Value *getAddress() const;
- MDNode *getVariable() const {
- return cast<MDNode>(
- cast<MetadataAsValue>(getArgOperand(1))->getMetadata());
+ DILocalVariable *getVariable() const {
+ return cast<DILocalVariable>(getRawVariable());
}
- MDNode *getExpression() const {
- return cast<MDNode>(
- cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ DIExpression *getExpression() const {
+ return cast<DIExpression>(getRawExpression());
+ }
+
+ Metadata *getRawVariable() const {
+ return cast<MetadataAsValue>(getArgOperand(1))->getMetadata();
+ }
+ Metadata *getRawExpression() const {
+ return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -110,13 +115,18 @@ namespace llvm {
return cast<ConstantInt>(
const_cast<Value*>(getArgOperand(1)))->getZExtValue();
}
- MDNode *getVariable() const {
- return cast<MDNode>(
- cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ DILocalVariable *getVariable() const {
+ return cast<DILocalVariable>(getRawVariable());
+ }
+ DIExpression *getExpression() const {
+ return cast<DIExpression>(getRawExpression());
+ }
+
+ Metadata *getRawVariable() const {
+ return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
}
- MDNode *getExpression() const {
- return cast<MDNode>(
- cast<MetadataAsValue>(getArgOperand(3))->getMetadata());
+ Metadata *getRawExpression() const {
+ return cast<MetadataAsValue>(getArgOperand(3))->getMetadata();
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h
index 56d1e4af26aa..e12ccace25ca 100644
--- a/include/llvm/IR/Intrinsics.h
+++ b/include/llvm/IR/Intrinsics.h
@@ -32,7 +32,7 @@ class AttributeSet;
/// function known by LLVM. The enum values are returned by
/// Function::getIntrinsicID().
namespace Intrinsic {
- enum ID {
+ enum ID : unsigned {
not_intrinsic = 0, // Must be zero
// Get the intrinsic enums generated from Intrinsics.td
@@ -41,7 +41,7 @@ namespace Intrinsic {
#undef GET_INTRINSIC_ENUM_VALUES
, num_intrinsics
};
-
+
/// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
std::string getName(ID id, ArrayRef<Type*> Tys = None);
@@ -69,7 +69,7 @@ namespace Intrinsic {
/// Map a MS builtin name to an intrinsic ID.
ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName);
-
+
/// This is a type descriptor which explains the type requirements of an
/// intrinsic. This is returned by getIntrinsicInfoTableEntries.
struct IITDescriptor {
@@ -77,9 +77,9 @@ namespace Intrinsic {
Void, VarArg, MMX, Metadata, Half, Float, Double,
Integer, Vector, Pointer, Struct,
Argument, ExtendArgument, TruncArgument, HalfVecArgument,
- SameVecWidthArgument, PtrToArgument
+ SameVecWidthArgument, PtrToArgument, VecOfPtrsToElt
} Kind;
-
+
union {
unsigned Integer_Width;
unsigned Float_Width;
@@ -88,8 +88,9 @@ namespace Intrinsic {
unsigned Struct_NumElements;
unsigned Argument_Info;
};
-
+
enum ArgKind {
+ AK_Any,
AK_AnyInteger,
AK_AnyFloat,
AK_AnyVector,
@@ -98,26 +99,28 @@ namespace Intrinsic {
unsigned getArgumentNumber() const {
assert(Kind == Argument || Kind == ExtendArgument ||
Kind == TruncArgument || Kind == HalfVecArgument ||
- Kind == SameVecWidthArgument || Kind == PtrToArgument);
- return Argument_Info >> 2;
+ Kind == SameVecWidthArgument || Kind == PtrToArgument ||
+ Kind == VecOfPtrsToElt);
+ return Argument_Info >> 3;
}
ArgKind getArgumentKind() const {
assert(Kind == Argument || Kind == ExtendArgument ||
Kind == TruncArgument || Kind == HalfVecArgument ||
- Kind == SameVecWidthArgument || Kind == PtrToArgument);
- return (ArgKind)(Argument_Info & 3);
+ Kind == SameVecWidthArgument || Kind == PtrToArgument ||
+ Kind == VecOfPtrsToElt);
+ return (ArgKind)(Argument_Info & 7);
}
-
+
static IITDescriptor get(IITDescriptorKind K, unsigned Field) {
IITDescriptor Result = { K, { Field } };
return Result;
}
};
-
+
/// Return the IIT table descriptor for the specified intrinsic into an array
/// of IITDescriptors.
void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
-
+
} // End Intrinsic namespace
} // End llvm namespace
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index a1188bccdc25..8f6cdebb0491 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -73,6 +73,11 @@ def IntrNoReturn : IntrinsicProperty;
// Parallels the noduplicate attribute on LLVM IR functions.
def IntrNoDuplicate : IntrinsicProperty;
+// IntrConvergent - Calls to this intrinsic are convergent and may only be
+// moved to control equivalent blocks.
+// Parallels the convergent attribute on LLVM IR functions.
+def IntrConvergent : IntrinsicProperty;
+
//===----------------------------------------------------------------------===//
// Types used by intrinsics.
//===----------------------------------------------------------------------===//
@@ -117,12 +122,14 @@ class LLVMVectorSameWidth<int num, LLVMType elty>
ValueType ElTy = elty.VT;
}
class LLVMPointerTo<int num> : LLVMMatchType<num>;
+class LLVMVectorOfPointersToElt<int num> : LLVMMatchType<num>;
// Match the type of another intrinsic parameter that is expected to be a
// vector type, but change the element count to be half as many
class LLVMHalfElementsVectorType<int num> : LLVMMatchType<num>;
def llvm_void_ty : LLVMType<isVoid>;
+def llvm_any_ty : LLVMType<Any>;
def llvm_anyint_ty : LLVMType<iAny>;
def llvm_anyfloat_ty : LLVMType<fAny>;
def llvm_anyvector_ty : LLVMType<vAny>;
@@ -179,6 +186,8 @@ def llvm_v4i64_ty : LLVMType<v4i64>; // 4 x i64
def llvm_v8i64_ty : LLVMType<v8i64>; // 8 x i64
def llvm_v16i64_ty : LLVMType<v16i64>; // 16 x i64
+def llvm_v1i128_ty : LLVMType<v1i128>; // 1 x i128
+
def llvm_v2f16_ty : LLVMType<v2f16>; // 2 x half (__fp16)
def llvm_v4f16_ty : LLVMType<v4f16>; // 4 x half (__fp16)
def llvm_v8f16_ty : LLVMType<v8f16>; // 8 x half (__fp16)
@@ -259,12 +268,12 @@ 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_frameescape : Intrinsic<[], [llvm_vararg_ty]>;
def int_framerecover : Intrinsic<[llvm_ptr_ty],
- [llvm_ptr_ty, llvm_ptr_ty],
- [IntrNoMem]>;
+ [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty],
+ [IntrNoMem]>;
def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty],
- [IntrNoMem], "llvm.read_register">;
+ [IntrReadMem], "llvm.read_register">;
def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty],
[], "llvm.write_register">;
@@ -409,6 +418,19 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>;
def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>;
def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>;
+// eh.begincatch takes a pointer returned by a landingpad instruction and
+// copies the exception object into the memory pointed to by the second
+// parameter. If the second parameter is null, no copy occurs.
+def int_eh_begincatch : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
+ [NoCapture<0>, NoCapture<1>]>;
+def int_eh_endcatch : Intrinsic<[], []>;
+
+// Represents the list of actions to take when an exception is thrown.
+def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
+
+def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], []>;
+def int_eh_exceptioninfo : Intrinsic<[llvm_ptr_ty], []>;
+
// __builtin_unwind_init is an undocumented GCC intrinsic that causes all
// callee-saved registers to be saved and restored (regardless of whether they
// are used) in the calling function. It is used by libgcc_eh.
@@ -513,17 +535,20 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty],
// These are documented in docs/Statepoint.rst
def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty],
- [llvm_anyptr_ty, llvm_i32_ty,
+ [llvm_i64_ty, llvm_i32_ty,
+ llvm_anyptr_ty, llvm_i32_ty,
llvm_i32_ty, llvm_vararg_ty]>;
+def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>;
+def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>;
+
+// Deprecated: will be removed in a couple of weeks
def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>;
-def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty],
+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 --------------------------===//
//
def int_flt_rounds : Intrinsic<[llvm_i32_ty]>,
@@ -581,6 +606,23 @@ def int_masked_load : Intrinsic<[llvm_anyvector_ty],
[LLVMPointerTo<0>, llvm_i32_ty,
LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>],
[IntrReadArgMem]>;
+
+def int_masked_gather: Intrinsic<[llvm_anyvector_ty],
+ [LLVMVectorOfPointersToElt<0>, llvm_i32_ty,
+ LLVMVectorSameWidth<0, llvm_i1_ty>,
+ LLVMMatchType<0>],
+ [IntrReadArgMem]>;
+
+def int_masked_scatter: Intrinsic<[],
+ [llvm_anyvector_ty,
+ LLVMVectorOfPointersToElt<0>, llvm_i32_ty,
+ LLVMVectorSameWidth<0, llvm_i1_ty>],
+ [IntrReadWriteArgMem]>;
+
+// Intrinsics to support bit sets.
+def int_bitset_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty],
+ [IntrNoMem]>;
+
//===----------------------------------------------------------------------===//
// Target-specific intrinsics
//===----------------------------------------------------------------------===//
@@ -594,3 +636,5 @@ include "llvm/IR/IntrinsicsHexagon.td"
include "llvm/IR/IntrinsicsNVVM.td"
include "llvm/IR/IntrinsicsMips.td"
include "llvm/IR/IntrinsicsR600.td"
+include "llvm/IR/IntrinsicsBPF.td"
+include "llvm/IR/IntrinsicsSystemZ.td"
diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td
new file mode 100644
index 000000000000..94eca8e40332
--- /dev/null
+++ b/include/llvm/IR/IntrinsicsBPF.td
@@ -0,0 +1,24 @@
+//===- IntrinsicsBPF.td - Defines BPF intrinsics -----------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines all of the BPF-specific intrinsics.
+//
+//===----------------------------------------------------------------------===//
+
+// Specialized loads from packet
+let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf."
+ def int_bpf_load_byte : GCCBuiltin<"__builtin_bpf_load_byte">,
+ Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>;
+ def int_bpf_load_half : GCCBuiltin<"__builtin_bpf_load_half">,
+ Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>;
+ def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">,
+ Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>;
+ def int_bpf_pseudo : GCCBuiltin<"__builtin_bpf_pseudo">,
+ Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty]>;
+}
diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td
index 8a8872931f36..78ee651d20f9 100644
--- a/include/llvm/IR/IntrinsicsHexagon.td
+++ b/include/llvm/IR/IntrinsicsHexagon.td
@@ -254,7 +254,7 @@ class Hexagon_qi_qiqi_Intrinsic<string GCCIntSuffix>
//
class Hexagon_qi_qiqiqi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [llvm_i1_ty], [llvm_i1_ty, llvm_i1_ty, llvm_i1_ty],
[IntrNoMem]>;
//
// DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) ->
@@ -422,19 +422,49 @@ class Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix>
llvm_i32_ty, llvm_i32_ty],
[IntrNoMem]>;
+class Hexagon_mem_memmemsi_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty,
+ llvm_i32_ty],
+ [IntrReadWriteArgMem]>;
+
+class Hexagon_mem_memsisi_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty,
+ llvm_i32_ty],
+ [IntrReadWriteArgMem]>;
+
+class Hexagon_mem_memdisi_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty,
+ llvm_i32_ty],
+ [IntrReadWriteArgMem]>;
+
class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty,
llvm_i32_ty, llvm_i32_ty],
[IntrReadWriteArgMem]>;
+class Hexagon_mem_memsisisi_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty,
+ llvm_i32_ty, llvm_i32_ty],
+ [IntrReadWriteArgMem]>;
+
+class Hexagon_mem_memdisisi_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty,
+ llvm_i32_ty, llvm_i32_ty],
+ [IntrReadWriteArgMem]>;
+
//
// Hexagon_sf_df_Intrinsic<string GCCIntSuffix>
//
class Hexagon_sf_si_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_float_ty], [llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_sf_df_Intrinsic<string GCCIntSuffix>
//
@@ -490,21 +520,21 @@ class Hexagon_si_df_Intrinsic<string GCCIntSuffix>
class Hexagon_sf_sfsf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_float_ty], [llvm_float_ty, llvm_float_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
-// Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix>
+// Hexagon_si_sfsf_Intrinsic<string GCCIntSuffix>
//
-class Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix>
+class Hexagon_si_sfsf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_float_ty, llvm_float_ty],
- [IntrNoMem]>;
+ [llvm_i32_ty], [llvm_float_ty, llvm_float_ty],
+ [IntrNoMem, Throws]>;
//
-// Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix>
+// Hexagon_si_sfsi_Intrinsic<string GCCIntSuffix>
//
-class Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix>
+class Hexagon_si_sfsi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_float_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ [llvm_i32_ty], [llvm_float_ty, llvm_i32_ty],
+ [IntrNoMem, Throws]>;
//
// Hexagon_qi_sfqi_Intrinsic<string GCCIntSuffix>
//
@@ -519,7 +549,7 @@ class Hexagon_sf_sfsfsf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_float_ty], [llvm_float_ty, llvm_float_ty,
llvm_float_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix>
//
@@ -528,7 +558,7 @@ class Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix>
[llvm_float_ty], [llvm_float_ty, llvm_float_ty,
llvm_float_ty,
llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_di_dididi_Intrinsic<string GCCIntSuffix>
//
@@ -543,7 +573,7 @@ class Hexagon_di_dididisi_Intrinsic<string GCCIntSuffix>
class Hexagon_df_si_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_double_ty], [llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_df_di_Intrinsic<string GCCIntSuffix>
//
@@ -571,21 +601,21 @@ class Hexagon_df_df_Intrinsic<string GCCIntSuffix>
class Hexagon_df_dfdf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_double_ty], [llvm_double_ty, llvm_double_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
-// Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix>
+// Hexagon_si_dfdf_Intrinsic<string GCCIntSuffix>
//
-class Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix>
+class Hexagon_si_dfdf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_double_ty, llvm_double_ty],
- [IntrNoMem]>;
+ [llvm_i32_ty], [llvm_double_ty, llvm_double_ty],
+ [IntrNoMem, Throws]>;
//
-// Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix>
+// Hexagon_si_dfsi_Intrinsic<string GCCIntSuffix>
//
-class Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix>
+class Hexagon_si_dfsi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_double_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ [llvm_i32_ty], [llvm_double_ty, llvm_i32_ty],
+ [IntrNoMem, Throws]>;
//
//
// Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix>
@@ -594,7 +624,7 @@ class Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_double_ty], [llvm_double_ty, llvm_double_ty,
llvm_double_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix>
//
@@ -603,53 +633,159 @@ class Hexagon_df_dfdfdfqi_Intrinsic<string GCCIntSuffix>
[llvm_double_ty], [llvm_double_ty, llvm_double_ty,
llvm_double_ty,
llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
-// This one below will not be generated from iset.py.
-// So make sure, you don't overwrite this one.
+// This one below will not be auto-generated,
+// so make sure, you don't overwrite this one.
//
// BUILTIN_INFO(SI_to_SXTHI_asrh,SI_ftype_SI,1)
//
def int_hexagon_SI_to_SXTHI_asrh :
Hexagon_si_si_Intrinsic<"SI_to_SXTHI_asrh">;
//
+// BUILTIN_INFO_NONCONST(brev_ldd,PTR_ftype_PTRPTRSI,3)
+//
+def int_hexagon_brev_ldd :
+Hexagon_mem_memmemsi_Intrinsic<"brev_ldd">;
+//
+// BUILTIN_INFO_NONCONST(brev_ldw,PTR_ftype_PTRPTRSI,3)
+//
+def int_hexagon_brev_ldw :
+Hexagon_mem_memmemsi_Intrinsic<"brev_ldw">;
+//
+// BUILTIN_INFO_NONCONST(brev_ldh,PTR_ftype_PTRPTRSI,3)
+//
+def int_hexagon_brev_ldh :
+Hexagon_mem_memmemsi_Intrinsic<"brev_ldh">;
+//
+// BUILTIN_INFO_NONCONST(brev_lduh,PTR_ftype_PTRPTRSI,3)
+//
+def int_hexagon_brev_lduh :
+Hexagon_mem_memmemsi_Intrinsic<"brev_lduh">;
+//
+// BUILTIN_INFO_NONCONST(brev_ldb,PTR_ftype_PTRPTRSI,3)
+//
+def int_hexagon_brev_ldb :
+Hexagon_mem_memmemsi_Intrinsic<"brev_ldb">;
+//
+// BUILTIN_INFO_NONCONST(brev_ldub,PTR_ftype_PTRPTRSI,3)
+//
+def int_hexagon_brev_ldub :
+Hexagon_mem_memmemsi_Intrinsic<"brev_ldub">;
+//
// BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4)
//
def int_hexagon_circ_ldd :
Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">;
-// This one above will not be generated from iset.py.
-// So make sure, you don't overwrite this one.
+//
+// BUILTIN_INFO_NONCONST(circ_ldw,PTR_ftype_PTRPTRSISI,4)
+//
+def int_hexagon_circ_ldw :
+Hexagon_mem_memmemsisi_Intrinsic<"circ_ldw">;
+//
+// BUILTIN_INFO_NONCONST(circ_ldh,PTR_ftype_PTRPTRSISI,4)
+//
+def int_hexagon_circ_ldh :
+Hexagon_mem_memmemsisi_Intrinsic<"circ_ldh">;
+//
+// BUILTIN_INFO_NONCONST(circ_lduh,PTR_ftype_PTRPTRSISI,4)
+//
+def int_hexagon_circ_lduh :
+Hexagon_mem_memmemsisi_Intrinsic<"circ_lduh">;
+//
+// BUILTIN_INFO_NONCONST(circ_ldb,PTR_ftype_PTRPTRSISI,4)
+//
+def int_hexagon_circ_ldb :
+Hexagon_mem_memmemsisi_Intrinsic<"circ_ldb">;
+//
+// BUILTIN_INFO_NONCONST(circ_ldub,PTR_ftype_PTRPTRSISI,4)
+//
+def int_hexagon_circ_ldub :
+Hexagon_mem_memmemsisi_Intrinsic<"circ_ldub">;
+
+//
+// BUILTIN_INFO_NONCONST(brev_stb,PTR_ftype_PTRSISI,3)
+//
+def int_hexagon_brev_stb :
+Hexagon_mem_memsisi_Intrinsic<"brev_stb">;
+//
+// BUILTIN_INFO_NONCONST(brev_sthhi,PTR_ftype_PTRSISI,3)
+//
+def int_hexagon_brev_sthhi :
+Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">;
+//
+// BUILTIN_INFO_NONCONST(brev_sth,PTR_ftype_PTRSISI,3)
+//
+def int_hexagon_brev_sth :
+Hexagon_mem_memsisi_Intrinsic<"brev_sth">;
+//
+// BUILTIN_INFO_NONCONST(brev_stw,PTR_ftype_PTRSISI,3)
+//
+def int_hexagon_brev_stw :
+Hexagon_mem_memsisi_Intrinsic<"brev_stw">;
+//
+// BUILTIN_INFO_NONCONST(brev_std,PTR_ftype_PTRSISI,3)
+//
+def int_hexagon_brev_std :
+Hexagon_mem_memdisi_Intrinsic<"brev_std">;
+//
+// BUILTIN_INFO_NONCONST(circ_std,PTR_ftype_PTRDISISI,4)
+//
+def int_hexagon_circ_std :
+Hexagon_mem_memdisisi_Intrinsic<"circ_std">;
+//
+// BUILTIN_INFO_NONCONST(circ_stw,PTR_ftype_PTRSISISI,4)
+//
+def int_hexagon_circ_stw :
+Hexagon_mem_memsisisi_Intrinsic<"circ_stw">;
+//
+// BUILTIN_INFO_NONCONST(circ_sth,PTR_ftype_PTRSISISI,4)
+//
+def int_hexagon_circ_sth :
+Hexagon_mem_memsisisi_Intrinsic<"circ_sth">;
+//
+// BUILTIN_INFO_NONCONST(circ_sthhi,PTR_ftype_PTRSISISI,4)
+//
+def int_hexagon_circ_sthhi :
+Hexagon_mem_memsisisi_Intrinsic<"circ_sthhi">;
+//
+// BUILTIN_INFO_NONCONST(circ_stb,PTR_ftype_PTRSISISI,4)
+//
+def int_hexagon_circ_stb :
+Hexagon_mem_memsisisi_Intrinsic<"circ_stb">;
+
+
//
// BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpeq :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeq">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeq">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpgt,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpgt :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgt">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgt">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpgtu,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpgtu :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpeqp,QI_ftype_DIDI,2)
//
def int_hexagon_C2_cmpeqp :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpeqp">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpeqp">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpgtp,QI_ftype_DIDI,2)
//
def int_hexagon_C2_cmpgtp :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtp">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtp">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpgtup,QI_ftype_DIDI,2)
//
def int_hexagon_C2_cmpgtup :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtup">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtup">;
//
// BUILTIN_INFO(HEXAGON.A4_rcmpeqi,SI_ftype_SISI,2)
//
@@ -674,182 +810,182 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpneq">;
// BUILTIN_INFO(HEXAGON.C2_bitsset,QI_ftype_SISI,2)
//
def int_hexagon_C2_bitsset :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsset">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsset">;
//
// BUILTIN_INFO(HEXAGON.C2_bitsclr,QI_ftype_SISI,2)
//
def int_hexagon_C2_bitsclr :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclr">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclr">;
//
// BUILTIN_INFO(HEXAGON.C4_nbitsset,QI_ftype_SISI,2)
//
def int_hexagon_C4_nbitsset :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsset">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsset">;
//
// BUILTIN_INFO(HEXAGON.C4_nbitsclr,QI_ftype_SISI,2)
//
def int_hexagon_C4_nbitsclr :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpeqi,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpeqi :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpgti,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpgti :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgti">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgti">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpgtui,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpgtui :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpgei,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpgei :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgei">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgei">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpgeui,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpgeui :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">;
//
// BUILTIN_INFO(HEXAGON.C2_cmplt,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmplt :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmplt">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmplt">;
//
// BUILTIN_INFO(HEXAGON.C2_cmpltu,QI_ftype_SISI,2)
//
def int_hexagon_C2_cmpltu :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpltu">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpltu">;
//
// BUILTIN_INFO(HEXAGON.C2_bitsclri,QI_ftype_SISI,2)
//
def int_hexagon_C2_bitsclri :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclri">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclri">;
//
// BUILTIN_INFO(HEXAGON.C4_nbitsclri,QI_ftype_SISI,2)
//
def int_hexagon_C4_nbitsclri :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">;
//
// BUILTIN_INFO(HEXAGON.C4_cmpneqi,QI_ftype_SISI,2)
//
def int_hexagon_C4_cmpneqi :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">;
//
// BUILTIN_INFO(HEXAGON.C4_cmpltei,QI_ftype_SISI,2)
//
def int_hexagon_C4_cmpltei :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpltei">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpltei">;
//
// BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2)
//
def int_hexagon_C4_cmplteui :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteui">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteui">;
//
// BUILTIN_INFO(HEXAGON.C4_cmpneq,QI_ftype_SISI,2)
//
def int_hexagon_C4_cmpneq :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneq">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneq">;
//
// BUILTIN_INFO(HEXAGON.C4_cmplte,QI_ftype_SISI,2)
//
def int_hexagon_C4_cmplte :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplte">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplte">;
//
// BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2)
//
def int_hexagon_C4_cmplteu :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteu">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteu">;
//
// BUILTIN_INFO(HEXAGON.C2_and,QI_ftype_QIQI,2)
//
def int_hexagon_C2_and :
-Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_and">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_and">;
//
// BUILTIN_INFO(HEXAGON.C2_or,QI_ftype_QIQI,2)
//
def int_hexagon_C2_or :
-Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_or">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_or">;
//
// BUILTIN_INFO(HEXAGON.C2_xor,QI_ftype_QIQI,2)
//
def int_hexagon_C2_xor :
-Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_xor">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_xor">;
//
// BUILTIN_INFO(HEXAGON.C2_andn,QI_ftype_QIQI,2)
//
def int_hexagon_C2_andn :
-Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_andn">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_andn">;
//
// BUILTIN_INFO(HEXAGON.C2_not,QI_ftype_QI,1)
//
def int_hexagon_C2_not :
-Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_not">;
+Hexagon_si_si_Intrinsic<"HEXAGON_C2_not">;
//
// BUILTIN_INFO(HEXAGON.C2_orn,QI_ftype_QIQI,2)
//
def int_hexagon_C2_orn :
-Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_orn">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_orn">;
//
// BUILTIN_INFO(HEXAGON.C4_and_and,QI_ftype_QIQIQI,3)
//
def int_hexagon_C4_and_and :
-Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_and">;
+Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_and">;
//
// BUILTIN_INFO(HEXAGON.C4_and_or,QI_ftype_QIQIQI,3)
//
def int_hexagon_C4_and_or :
-Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_or">;
+Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_or">;
//
// BUILTIN_INFO(HEXAGON.C4_or_and,QI_ftype_QIQIQI,3)
//
def int_hexagon_C4_or_and :
-Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_and">;
+Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_and">;
//
// BUILTIN_INFO(HEXAGON.C4_or_or,QI_ftype_QIQIQI,3)
//
def int_hexagon_C4_or_or :
-Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_or">;
+Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_or">;
//
// BUILTIN_INFO(HEXAGON.C4_and_andn,QI_ftype_QIQIQI,3)
//
def int_hexagon_C4_and_andn :
-Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_andn">;
+Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_andn">;
//
// BUILTIN_INFO(HEXAGON.C4_and_orn,QI_ftype_QIQIQI,3)
//
def int_hexagon_C4_and_orn :
-Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_orn">;
+Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_orn">;
//
// BUILTIN_INFO(HEXAGON.C4_or_andn,QI_ftype_QIQIQI,3)
//
def int_hexagon_C4_or_andn :
-Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_andn">;
+Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_andn">;
//
// BUILTIN_INFO(HEXAGON.C4_or_orn,QI_ftype_QIQIQI,3)
//
def int_hexagon_C4_or_orn :
-Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_orn">;
+Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_orn">;
//
// BUILTIN_INFO(HEXAGON.C2_pxfer_map,QI_ftype_QI,1)
//
def int_hexagon_C2_pxfer_map :
-Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_pxfer_map">;
+Hexagon_si_qi_Intrinsic<"HEXAGON_C2_pxfer_map">;
//
// BUILTIN_INFO(HEXAGON.C2_any8,QI_ftype_QI,1)
//
def int_hexagon_C2_any8 :
-Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_any8">;
+Hexagon_si_qi_Intrinsic<"HEXAGON_C2_any8">;
//
// BUILTIN_INFO(HEXAGON.C2_all8,QI_ftype_QI,1)
//
def int_hexagon_C2_all8 :
-Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_all8">;
+Hexagon_si_qi_Intrinsic<"HEXAGON_C2_all8">;
//
// BUILTIN_INFO(HEXAGON.C2_vitpack,SI_ftype_QIQI,2)
//
@@ -889,167 +1025,167 @@ Hexagon_di_qi_Intrinsic<"HEXAGON_C2_mask">;
// BUILTIN_INFO(HEXAGON.A2_vcmpbeq,QI_ftype_DIDI,2)
//
def int_hexagon_A2_vcmpbeq :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpbeqi,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmpbeqi :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpbeq_any,QI_ftype_DIDI,2)
//
def int_hexagon_A4_vcmpbeq_any :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">;
//
// BUILTIN_INFO(HEXAGON.A2_vcmpbgtu,QI_ftype_DIDI,2)
//
def int_hexagon_A2_vcmpbgtu :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpbgtui,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmpbgtui :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpbgt,QI_ftype_DIDI,2)
//
def int_hexagon_A4_vcmpbgt :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpbgti,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmpbgti :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">;
//
// BUILTIN_INFO(HEXAGON.A4_cmpbeq,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmpbeq :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">;
//
// BUILTIN_INFO(HEXAGON.A4_cmpbeqi,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmpbeqi :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">;
//
// BUILTIN_INFO(HEXAGON.A4_cmpbgtu,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmpbgtu :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">;
//
// BUILTIN_INFO(HEXAGON.A4_cmpbgtui,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmpbgtui :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">;
//
// BUILTIN_INFO(HEXAGON.A4_cmpbgt,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmpbgt :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">;
//
// BUILTIN_INFO(HEXAGON.A4_cmpbgti,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmpbgti :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">;
//
// BUILTIN_INFO(HEXAGON.A2_vcmpheq,QI_ftype_DIDI,2)
//
def int_hexagon_A2_vcmpheq :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpheq">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpheq">;
//
// BUILTIN_INFO(HEXAGON.A2_vcmphgt,QI_ftype_DIDI,2)
//
def int_hexagon_A2_vcmphgt :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgt">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgt">;
//
// BUILTIN_INFO(HEXAGON.A2_vcmphgtu,QI_ftype_DIDI,2)
//
def int_hexagon_A2_vcmphgtu :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpheqi,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmpheqi :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmphgti,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmphgti :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgti">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgti">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmphgtui,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmphgtui :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">;
//
// BUILTIN_INFO(HEXAGON.A4_cmpheq,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmpheq :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheq">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheq">;
//
// BUILTIN_INFO(HEXAGON.A4_cmphgt,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmphgt :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgt">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgt">;
//
// BUILTIN_INFO(HEXAGON.A4_cmphgtu,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmphgtu :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">;
//
// BUILTIN_INFO(HEXAGON.A4_cmpheqi,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmpheqi :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">;
//
// BUILTIN_INFO(HEXAGON.A4_cmphgti,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmphgti :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgti">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgti">;
//
// BUILTIN_INFO(HEXAGON.A4_cmphgtui,QI_ftype_SISI,2)
//
def int_hexagon_A4_cmphgtui :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">;
//
// BUILTIN_INFO(HEXAGON.A2_vcmpweq,QI_ftype_DIDI,2)
//
def int_hexagon_A2_vcmpweq :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpweq">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpweq">;
//
// BUILTIN_INFO(HEXAGON.A2_vcmpwgt,QI_ftype_DIDI,2)
//
def int_hexagon_A2_vcmpwgt :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">;
//
// BUILTIN_INFO(HEXAGON.A2_vcmpwgtu,QI_ftype_DIDI,2)
//
def int_hexagon_A2_vcmpwgtu :
-Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">;
+Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpweqi,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmpweqi :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpwgti,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmpwgti :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">;
//
// BUILTIN_INFO(HEXAGON.A4_vcmpwgtui,QI_ftype_DISI,2)
//
def int_hexagon_A4_vcmpwgtui :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">;
//
// BUILTIN_INFO(HEXAGON.A4_boundscheck,QI_ftype_SIDI,2)
//
def int_hexagon_A4_boundscheck :
-Hexagon_qi_sidi_Intrinsic<"HEXAGON_A4_boundscheck">;
+Hexagon_si_sidi_Intrinsic<"HEXAGON_A4_boundscheck">;
//
// BUILTIN_INFO(HEXAGON.A4_tlbmatch,QI_ftype_DISI,2)
//
def int_hexagon_A4_tlbmatch :
-Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_tlbmatch">;
+Hexagon_si_disi_Intrinsic<"HEXAGON_A4_tlbmatch">;
//
// BUILTIN_INFO(HEXAGON.C2_tfrpr,SI_ftype_QI,1)
//
@@ -1059,17 +1195,17 @@ Hexagon_si_qi_Intrinsic<"HEXAGON_C2_tfrpr">;
// BUILTIN_INFO(HEXAGON.C2_tfrrp,QI_ftype_SI,1)
//
def int_hexagon_C2_tfrrp :
-Hexagon_qi_si_Intrinsic<"HEXAGON_C2_tfrrp">;
+Hexagon_si_si_Intrinsic<"HEXAGON_C2_tfrrp">;
//
// BUILTIN_INFO(HEXAGON.C4_fastcorner9,QI_ftype_QIQI,2)
//
def int_hexagon_C4_fastcorner9 :
-Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">;
+Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">;
//
// BUILTIN_INFO(HEXAGON.C4_fastcorner9_not,QI_ftype_QIQI,2)
//
def int_hexagon_C4_fastcorner9_not :
-Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">;
+Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">;
//
// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s0,SI_ftype_SISISI,3)
//
@@ -2849,7 +2985,7 @@ Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrp">;
// BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1)
//
def int_hexagon_A2_tfrpi :
-Hexagon_di_si_Intrinsic<"HEXAGON_A2_tfrpi">;
+Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrpi">;
//
// BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1)
//
@@ -3609,22 +3745,22 @@ Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffms_lib">;
// BUILTIN_INFO(HEXAGON.F2_sfcmpeq,QI_ftype_SFSF,2)
//
def int_hexagon_F2_sfcmpeq :
-Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">;
+Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">;
//
// BUILTIN_INFO(HEXAGON.F2_sfcmpgt,QI_ftype_SFSF,2)
//
def int_hexagon_F2_sfcmpgt :
-Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">;
+Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">;
//
// BUILTIN_INFO(HEXAGON.F2_sfcmpge,QI_ftype_SFSF,2)
//
def int_hexagon_F2_sfcmpge :
-Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">;
+Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">;
//
// BUILTIN_INFO(HEXAGON.F2_sfcmpuo,QI_ftype_SFSF,2)
//
def int_hexagon_F2_sfcmpuo :
-Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">;
+Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">;
//
// BUILTIN_INFO(HEXAGON.F2_sfmax,SF_ftype_SFSF,2)
//
@@ -3639,7 +3775,7 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmin">;
// BUILTIN_INFO(HEXAGON.F2_sfclass,QI_ftype_SFSI,2)
//
def int_hexagon_F2_sfclass :
-Hexagon_qi_sfsi_Intrinsic<"HEXAGON_F2_sfclass">;
+Hexagon_si_sfsi_Intrinsic<"HEXAGON_F2_sfclass">;
//
// BUILTIN_INFO(HEXAGON.F2_sfimm_p,SF_ftype_SI,1)
//
@@ -3666,80 +3802,30 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sffixupd">;
def int_hexagon_F2_sffixupr :
Hexagon_sf_sf_Intrinsic<"HEXAGON_F2_sffixupr">;
//
-// BUILTIN_INFO(HEXAGON.F2_dfadd,DF_ftype_DFDF,2)
-//
-def int_hexagon_F2_dfadd :
-Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfadd">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dfsub,DF_ftype_DFDF,2)
-//
-def int_hexagon_F2_dfsub :
-Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfsub">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dfmpy,DF_ftype_DFDF,2)
-//
-def int_hexagon_F2_dfmpy :
-Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmpy">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dffma,DF_ftype_DFDFDF,3)
-//
-def int_hexagon_F2_dffma :
-Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dffms,DF_ftype_DFDFDF,3)
-//
-def int_hexagon_F2_dffms :
-Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dffma_lib,DF_ftype_DFDFDF,3)
-//
-def int_hexagon_F2_dffma_lib :
-Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma_lib">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dffms_lib,DF_ftype_DFDFDF,3)
-//
-def int_hexagon_F2_dffms_lib :
-Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms_lib">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dffma_sc,DF_ftype_DFDFDFQI,4)
-//
-def int_hexagon_F2_dffma_sc :
-Hexagon_df_dfdfdfqi_Intrinsic<"HEXAGON_F2_dffma_sc">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dfmax,DF_ftype_DFDF,2)
-//
-def int_hexagon_F2_dfmax :
-Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmax">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dfmin,DF_ftype_DFDF,2)
-//
-def int_hexagon_F2_dfmin :
-Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmin">;
-//
// BUILTIN_INFO(HEXAGON.F2_dfcmpeq,QI_ftype_DFDF,2)
//
def int_hexagon_F2_dfcmpeq :
-Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">;
+Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">;
//
// BUILTIN_INFO(HEXAGON.F2_dfcmpgt,QI_ftype_DFDF,2)
//
def int_hexagon_F2_dfcmpgt :
-Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">;
+Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">;
//
// BUILTIN_INFO(HEXAGON.F2_dfcmpge,QI_ftype_DFDF,2)
//
def int_hexagon_F2_dfcmpge :
-Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">;
+Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">;
//
// BUILTIN_INFO(HEXAGON.F2_dfcmpuo,QI_ftype_DFDF,2)
//
def int_hexagon_F2_dfcmpuo :
-Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">;
+Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">;
//
// BUILTIN_INFO(HEXAGON.F2_dfclass,QI_ftype_DFSI,2)
//
def int_hexagon_F2_dfclass :
-Hexagon_qi_dfsi_Intrinsic<"HEXAGON_F2_dfclass">;
+Hexagon_si_dfsi_Intrinsic<"HEXAGON_F2_dfclass">;
//
// BUILTIN_INFO(HEXAGON.F2_dfimm_p,DF_ftype_SI,1)
//
@@ -3751,21 +3837,6 @@ Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_p">;
def int_hexagon_F2_dfimm_n :
Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_n">;
//
-// BUILTIN_INFO(HEXAGON.F2_dffixupn,DF_ftype_DFDF,2)
-//
-def int_hexagon_F2_dffixupn :
-Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupn">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dffixupd,DF_ftype_DFDF,2)
-//
-def int_hexagon_F2_dffixupd :
-Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupd">;
-//
-// BUILTIN_INFO(HEXAGON.F2_dffixupr,DF_ftype_DF,1)
-//
-def int_hexagon_F2_dffixupr :
-Hexagon_df_df_Intrinsic<"HEXAGON_F2_dffixupr">;
-//
// BUILTIN_INFO(HEXAGON.F2_conv_sf2df,DF_ftype_SF,1)
//
def int_hexagon_F2_conv_sf2df :
@@ -4494,12 +4565,12 @@ Hexagon_di_didi_Intrinsic<"HEXAGON_S2_extractup_rp">;
// BUILTIN_INFO(HEXAGON.S2_tstbit_i,QI_ftype_SISI,2)
//
def int_hexagon_S2_tstbit_i :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">;
//
// BUILTIN_INFO(HEXAGON.S4_ntstbit_i,QI_ftype_SISI,2)
//
def int_hexagon_S4_ntstbit_i :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">;
//
// BUILTIN_INFO(HEXAGON.S2_setbit_i,SI_ftype_SISI,2)
//
@@ -4519,12 +4590,12 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_clrbit_i">;
// BUILTIN_INFO(HEXAGON.S2_tstbit_r,QI_ftype_SISI,2)
//
def int_hexagon_S2_tstbit_r :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">;
//
// BUILTIN_INFO(HEXAGON.S4_ntstbit_r,QI_ftype_SISI,2)
//
def int_hexagon_S4_ntstbit_r :
-Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">;
+Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">;
//
// BUILTIN_INFO(HEXAGON.S2_setbit_r,SI_ftype_SISI,2)
//
@@ -4875,3 +4946,21 @@ Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">;
//
def int_hexagon_S2_deinterleave :
Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">;
+
+def llvm_ptr32_ty : LLVMPointerType<llvm_i32_ty>;
+def llvm_ptr64_ty : LLVMPointerType<llvm_i64_ty>;
+
+// Mark locked loads as read/write to prevent any accidental reordering.
+def int_hexagon_L2_loadw_locked :
+Hexagon_Intrinsic<"HEXAGON_L2_loadw_locked", [llvm_i32_ty], [llvm_ptr32_ty],
+ [IntrReadWriteArgMem, NoCapture<0>]>;
+def int_hexagon_L4_loadd_locked :
+Hexagon_Intrinsic<"HEXAGON_L4_loadd_locked", [llvm_i64_ty], [llvm_ptr64_ty],
+ [IntrReadWriteArgMem, NoCapture<0>]>;
+
+def int_hexagon_S2_storew_locked :
+Hexagon_Intrinsic<"HEXAGON_S2_storew_locked", [llvm_i32_ty],
+ [llvm_ptr32_ty, llvm_i32_ty], [IntrReadWriteArgMem, NoCapture<0>]>;
+def int_hexagon_S4_stored_locked :
+Hexagon_Intrinsic<"HEXAGON_S4_stored_locked", [llvm_i32_ty],
+ [llvm_ptr64_ty, llvm_i64_ty], [IntrReadWriteArgMem, NoCapture<0>]>;
diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td
index 5cdabdeadaea..79654695837d 100644
--- a/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/include/llvm/IR/IntrinsicsPowerPC.td
@@ -24,7 +24,8 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>;
def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty],
[IntrReadWriteArgMem, NoCapture<0>]>;
- def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], []>;
+ def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty],
+ [IntrReadWriteArgMem, NoCapture<0>]>;
def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>;
def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>;
@@ -37,6 +38,25 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
// generated by the PowerPC backend!
def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>;
def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [], []>;
+
+ // Intrinsics for [double]word extended forms of divide instructions
+ def int_ppc_divwe : GCCBuiltin<"__builtin_divwe">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_ppc_divweu : GCCBuiltin<"__builtin_divweu">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_ppc_divde : GCCBuiltin<"__builtin_divde">,
+ Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+ def int_ppc_divdeu : GCCBuiltin<"__builtin_divdeu">,
+ Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+
+ // Bit permute doubleword
+ def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">,
+ Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
+ [IntrNoMem]>;
}
@@ -73,7 +93,7 @@ class PowerPC_Vec_FFF_Intrinsic<string GCCIntSuffix>
[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty],
[IntrNoMem]>;
-/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16f8
+/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16i8
/// vectors and returns one. These intrinsics have no side effects.
class PowerPC_Vec_BBB_Intrinsic<string GCCIntSuffix>
: PowerPC_Vec_Intrinsic<GCCIntSuffix,
@@ -94,6 +114,19 @@ class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix>
[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
[IntrNoMem]>;
+/// PowerPC_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2i64
+/// vectors and returns one. These intrinsics have no side effects.
+class PowerPC_Vec_DDD_Intrinsic<string GCCIntSuffix>
+ : PowerPC_Vec_Intrinsic<GCCIntSuffix,
+ [llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
+ [IntrNoMem]>;
+
+/// PowerPC_Vec_QQQ_Intrinsic - A PowerPC intrinsic that takes two v1i128
+/// vectors and returns one. These intrinsics have no side effects.
+class PowerPC_Vec_QQQ_Intrinsic<string GCCIntSuffix>
+ : PowerPC_Vec_Intrinsic<GCCIntSuffix,
+ [llvm_v1i128_ty], [llvm_v1i128_ty, llvm_v1i128_ty],
+ [IntrNoMem]>;
//===----------------------------------------------------------------------===//
// PowerPC VSX Intrinsic Class Definitions.
@@ -120,7 +153,6 @@ class PowerPC_VSX_Sca_DDD_Intrinsic<string GCCIntSuffix>
[llvm_double_ty], [llvm_double_ty, llvm_double_ty],
[IntrNoMem]>;
-
//===----------------------------------------------------------------------===//
// PowerPC Altivec Intrinsic Definitions.
@@ -198,7 +230,17 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty],
[IntrNoMem]>;
-
+
+ def int_ppc_altivec_vcmpequd : GCCBuiltin<"__builtin_altivec_vcmpequd">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
+ [IntrNoMem]>;
+ def int_ppc_altivec_vcmpgtsd : GCCBuiltin<"__builtin_altivec_vcmpgtsd">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
+ [IntrNoMem]>;
+ def int_ppc_altivec_vcmpgtud : GCCBuiltin<"__builtin_altivec_vcmpgtud">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
+ [IntrNoMem]>;
+
def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
[IntrNoMem]>;
@@ -242,7 +284,17 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">,
Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty],
[IntrNoMem]>;
-
+
+ def int_ppc_altivec_vcmpequd_p : GCCBuiltin<"__builtin_altivec_vcmpequd_p">,
+ Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty],
+ [IntrNoMem]>;
+ def int_ppc_altivec_vcmpgtsd_p : GCCBuiltin<"__builtin_altivec_vcmpgtsd_p">,
+ Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty],
+ [IntrNoMem]>;
+ def int_ppc_altivec_vcmpgtud_p : GCCBuiltin<"__builtin_altivec_vcmpgtud_p">,
+ Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty],
+ [IntrNoMem]>;
+
def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">,
Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty],
[IntrNoMem]>;
@@ -287,18 +339,22 @@ def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">;
def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">;
def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">;
def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">;
+def int_ppc_altivec_vmaxsd : PowerPC_Vec_DDD_Intrinsic<"vmaxsd">;
def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">;
def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">;
def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">;
+def int_ppc_altivec_vmaxud : PowerPC_Vec_DDD_Intrinsic<"vmaxud">;
// Vector minimum.
def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">;
def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">;
def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">;
def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">;
+def int_ppc_altivec_vminsd : PowerPC_Vec_DDD_Intrinsic<"vminsd">;
def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">;
def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">;
def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">;
+def int_ppc_altivec_vminud : PowerPC_Vec_DDD_Intrinsic<"vminud">;
// Saturating adds.
def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">;
@@ -308,6 +364,7 @@ def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">;
def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">;
def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">;
def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">;
+def int_ppc_altivec_vaddcuq : PowerPC_Vec_QQQ_Intrinsic<"vaddcuq">;
// Saturating subs.
def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">;
@@ -317,6 +374,7 @@ def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">;
def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">;
def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">;
def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">;
+def int_ppc_altivec_vsubcuq : PowerPC_Vec_QQQ_Intrinsic<"vsubcuq">;
let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
// Saturating multiply-adds.
@@ -361,12 +419,18 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">,
Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty],
[IntrNoMem]>;
+ def int_ppc_altivec_vmulesw : GCCBuiltin<"__builtin_altivec_vmulesw">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
+ [IntrNoMem]>;
def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">,
Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty],
[IntrNoMem]>;
def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">,
Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty],
[IntrNoMem]>;
+ def int_ppc_altivec_vmuleuw : GCCBuiltin<"__builtin_altivec_vmuleuw">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
+ [IntrNoMem]>;
def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">,
Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty],
@@ -374,12 +438,18 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">,
Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty],
[IntrNoMem]>;
+ def int_ppc_altivec_vmulosw : GCCBuiltin<"__builtin_altivec_vmulosw">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
+ [IntrNoMem]>;
def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">,
Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty],
[IntrNoMem]>;
def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">,
Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty],
[IntrNoMem]>;
+ def int_ppc_altivec_vmulouw : GCCBuiltin<"__builtin_altivec_vmulouw">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
+ [IntrNoMem]>;
// Vector Sum Intructions.
def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">,
@@ -419,6 +489,12 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">,
Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
[IntrNoMem]>;
+ def int_ppc_altivec_vpksdss : GCCBuiltin<"__builtin_altivec_vpksdss">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
+ [IntrNoMem]>;
+ def int_ppc_altivec_vpksdus : GCCBuiltin<"__builtin_altivec_vpksdus">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
+ [IntrNoMem]>;
// vpkuhum is lowered to a shuffle.
def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">,
Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty],
@@ -427,6 +503,10 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">,
Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
[IntrNoMem]>;
+ // vpkudum is lowered to a shuffle.
+ def int_ppc_altivec_vpkudus : GCCBuiltin<"__builtin_altivec_vpkudus">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
+ [IntrNoMem]>;
// Unpacks.
def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">,
@@ -435,12 +515,16 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>;
def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">,
Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>;
+ def int_ppc_altivec_vupkhsw : GCCBuiltin<"__builtin_altivec_vupkhsw">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>;
def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">,
Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>;
def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">,
Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>;
def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">,
Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>;
+ def int_ppc_altivec_vupklsw : GCCBuiltin<"__builtin_altivec_vupklsw">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>;
// FP <-> integer conversion.
@@ -465,6 +549,26 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>;
def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>;
+
+ // Add Extended Quadword
+ def int_ppc_altivec_vaddeuqm : GCCBuiltin<"__builtin_altivec_vaddeuqm">,
+ Intrinsic<[llvm_v1i128_ty],
+ [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty],
+ [IntrNoMem]>;
+ def int_ppc_altivec_vaddecuq : GCCBuiltin<"__builtin_altivec_vaddecuq">,
+ Intrinsic<[llvm_v1i128_ty],
+ [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty],
+ [IntrNoMem]>;
+
+ // Sub Extended Quadword
+ def int_ppc_altivec_vsubeuqm : GCCBuiltin<"__builtin_altivec_vsubeuqm">,
+ Intrinsic<[llvm_v1i128_ty],
+ [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty],
+ [IntrNoMem]>;
+ def int_ppc_altivec_vsubecuq : GCCBuiltin<"__builtin_altivec_vsubecuq">,
+ Intrinsic<[llvm_v1i128_ty],
+ [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty],
+ [IntrNoMem]>;
}
def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">;
@@ -489,6 +593,7 @@ def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">;
def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">;
def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">;
def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">;
+def int_ppc_altivec_vrld : PowerPC_Vec_DDD_Intrinsic<"vrld">;
let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
// Miscellaneous.
@@ -510,6 +615,42 @@ 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">;
+// Power8 Intrinsics
+// Crypto
+let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
+ def int_ppc_altivec_crypto_vsbox :
+ GCCBuiltin<"__builtin_altivec_crypto_vsbox">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>;
+ def int_ppc_altivec_crypto_vpermxor :
+ GCCBuiltin<"__builtin_altivec_crypto_vpermxor">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>;
+
+def int_ppc_altivec_crypto_vshasigmad :
+ GCCBuiltin<"__builtin_altivec_crypto_vshasigmad">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
+ llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
+def int_ppc_altivec_crypto_vshasigmaw :
+ GCCBuiltin<"__builtin_altivec_crypto_vshasigmaw">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
+ llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
+}
+def int_ppc_altivec_crypto_vcipher :
+ PowerPC_Vec_DDD_Intrinsic<"crypto_vcipher">;
+def int_ppc_altivec_crypto_vcipherlast :
+ PowerPC_Vec_DDD_Intrinsic<"crypto_vcipherlast">;
+def int_ppc_altivec_crypto_vncipher :
+ PowerPC_Vec_DDD_Intrinsic<"crypto_vncipher">;
+def int_ppc_altivec_crypto_vncipherlast :
+ PowerPC_Vec_DDD_Intrinsic<"crypto_vncipherlast">;
+def int_ppc_altivec_crypto_vpmsumb :
+ PowerPC_Vec_BBB_Intrinsic<"crypto_vpmsumb">;
+def int_ppc_altivec_crypto_vpmsumh :
+ PowerPC_Vec_HHH_Intrinsic<"crypto_vpmsumh">;
+def int_ppc_altivec_crypto_vpmsumw :
+ PowerPC_Vec_WWW_Intrinsic<"crypto_vpmsumw">;
+def int_ppc_altivec_crypto_vpmsumd :
+ PowerPC_Vec_DDD_Intrinsic<"crypto_vpmsumd">;
//===----------------------------------------------------------------------===//
// PowerPC VSX Intrinsic Definitions.
@@ -542,3 +683,239 @@ def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">;
def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">;
def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">;
}
+
+//===----------------------------------------------------------------------===//
+// PowerPC QPX Intrinsics.
+//
+
+let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
+ /// PowerPC_QPX_Intrinsic - Base class for all QPX intrinsics.
+ class PowerPC_QPX_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types,
+ list<LLVMType> param_types,
+ list<IntrinsicProperty> properties>
+ : GCCBuiltin<!strconcat("__builtin_qpx_", GCCIntSuffix)>,
+ Intrinsic<ret_types, param_types, properties>;
+}
+
+//===----------------------------------------------------------------------===//
+// PowerPC QPX Intrinsic Class Definitions.
+//
+
+/// PowerPC_QPX_FF_Intrinsic - A PowerPC intrinsic that takes one v4f64
+/// vector and returns one. These intrinsics have no side effects.
+class PowerPC_QPX_FF_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>;
+
+/// PowerPC_QPX_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f64
+/// vectors and returns one. These intrinsics have no side effects.
+class PowerPC_QPX_FFF_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty],
+ [IntrNoMem]>;
+
+/// PowerPC_QPX_FFFF_Intrinsic - A PowerPC intrinsic that takes three v4f64
+/// vectors and returns one. These intrinsics have no side effects.
+class PowerPC_QPX_FFFF_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
+ [IntrNoMem]>;
+
+/// PowerPC_QPX_Load_Intrinsic - A PowerPC intrinsic that takes a pointer
+/// and returns a v4f64.
+class PowerPC_QPX_Load_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+
+/// PowerPC_QPX_LoadPerm_Intrinsic - A PowerPC intrinsic that takes a pointer
+/// and returns a v4f64 permutation.
+class PowerPC_QPX_LoadPerm_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty], [llvm_ptr_ty], [IntrNoMem]>;
+
+/// PowerPC_QPX_Store_Intrinsic - A PowerPC intrinsic that takes a pointer
+/// and stores a v4f64.
+class PowerPC_QPX_Store_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [], [llvm_v4f64_ty, llvm_ptr_ty],
+ [IntrReadWriteArgMem]>;
+
+//===----------------------------------------------------------------------===//
+// PowerPC QPX Intrinsic Definitions.
+
+let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
+ // Add Instructions
+ def int_ppc_qpx_qvfadd : PowerPC_QPX_FFF_Intrinsic<"qvfadd">;
+ def int_ppc_qpx_qvfadds : PowerPC_QPX_FFF_Intrinsic<"qvfadds">;
+ def int_ppc_qpx_qvfsub : PowerPC_QPX_FFF_Intrinsic<"qvfsub">;
+ def int_ppc_qpx_qvfsubs : PowerPC_QPX_FFF_Intrinsic<"qvfsubs">;
+
+ // Estimate Instructions
+ def int_ppc_qpx_qvfre : PowerPC_QPX_FF_Intrinsic<"qvfre">;
+ def int_ppc_qpx_qvfres : PowerPC_QPX_FF_Intrinsic<"qvfres">;
+ def int_ppc_qpx_qvfrsqrte : PowerPC_QPX_FF_Intrinsic<"qvfrsqrte">;
+ def int_ppc_qpx_qvfrsqrtes : PowerPC_QPX_FF_Intrinsic<"qvfrsqrtes">;
+
+ // Multiply Instructions
+ def int_ppc_qpx_qvfmul : PowerPC_QPX_FFF_Intrinsic<"qvfmul">;
+ def int_ppc_qpx_qvfmuls : PowerPC_QPX_FFF_Intrinsic<"qvfmuls">;
+ def int_ppc_qpx_qvfxmul : PowerPC_QPX_FFF_Intrinsic<"qvfxmul">;
+ def int_ppc_qpx_qvfxmuls : PowerPC_QPX_FFF_Intrinsic<"qvfxmuls">;
+
+ // Multiply-add instructions
+ def int_ppc_qpx_qvfmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfmadd">;
+ def int_ppc_qpx_qvfmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfmadds">;
+ def int_ppc_qpx_qvfnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadd">;
+ def int_ppc_qpx_qvfnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadds">;
+ def int_ppc_qpx_qvfmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfmsub">;
+ def int_ppc_qpx_qvfmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfmsubs">;
+ def int_ppc_qpx_qvfnmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsub">;
+ def int_ppc_qpx_qvfnmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsubs">;
+ def int_ppc_qpx_qvfxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadd">;
+ def int_ppc_qpx_qvfxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadds">;
+ def int_ppc_qpx_qvfxxnpmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadd">;
+ def int_ppc_qpx_qvfxxnpmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadds">;
+ def int_ppc_qpx_qvfxxcpnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadd">;
+ def int_ppc_qpx_qvfxxcpnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadds">;
+ def int_ppc_qpx_qvfxxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadd">;
+ def int_ppc_qpx_qvfxxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadds">;
+
+ // Select Instruction
+ def int_ppc_qpx_qvfsel : PowerPC_QPX_FFFF_Intrinsic<"qvfsel">;
+
+ // Permute Instruction
+ def int_ppc_qpx_qvfperm : PowerPC_QPX_FFFF_Intrinsic<"qvfperm">;
+
+ // Convert and Round Instructions
+ def int_ppc_qpx_qvfctid : PowerPC_QPX_FF_Intrinsic<"qvfctid">;
+ def int_ppc_qpx_qvfctidu : PowerPC_QPX_FF_Intrinsic<"qvfctidu">;
+ def int_ppc_qpx_qvfctidz : PowerPC_QPX_FF_Intrinsic<"qvfctidz">;
+ def int_ppc_qpx_qvfctiduz : PowerPC_QPX_FF_Intrinsic<"qvfctiduz">;
+ def int_ppc_qpx_qvfctiw : PowerPC_QPX_FF_Intrinsic<"qvfctiw">;
+ def int_ppc_qpx_qvfctiwu : PowerPC_QPX_FF_Intrinsic<"qvfctiwu">;
+ def int_ppc_qpx_qvfctiwz : PowerPC_QPX_FF_Intrinsic<"qvfctiwz">;
+ def int_ppc_qpx_qvfctiwuz : PowerPC_QPX_FF_Intrinsic<"qvfctiwuz">;
+ def int_ppc_qpx_qvfcfid : PowerPC_QPX_FF_Intrinsic<"qvfcfid">;
+ def int_ppc_qpx_qvfcfidu : PowerPC_QPX_FF_Intrinsic<"qvfcfidu">;
+ def int_ppc_qpx_qvfcfids : PowerPC_QPX_FF_Intrinsic<"qvfcfids">;
+ def int_ppc_qpx_qvfcfidus : PowerPC_QPX_FF_Intrinsic<"qvfcfidus">;
+ def int_ppc_qpx_qvfrsp : PowerPC_QPX_FF_Intrinsic<"qvfrsp">;
+ def int_ppc_qpx_qvfriz : PowerPC_QPX_FF_Intrinsic<"qvfriz">;
+ def int_ppc_qpx_qvfrin : PowerPC_QPX_FF_Intrinsic<"qvfrin">;
+ def int_ppc_qpx_qvfrip : PowerPC_QPX_FF_Intrinsic<"qvfrip">;
+ def int_ppc_qpx_qvfrim : PowerPC_QPX_FF_Intrinsic<"qvfrim">;
+
+ // Move Instructions
+ def int_ppc_qpx_qvfneg : PowerPC_QPX_FF_Intrinsic<"qvfneg">;
+ def int_ppc_qpx_qvfabs : PowerPC_QPX_FF_Intrinsic<"qvfabs">;
+ def int_ppc_qpx_qvfnabs : PowerPC_QPX_FF_Intrinsic<"qvfnabs">;
+ def int_ppc_qpx_qvfcpsgn : PowerPC_QPX_FFF_Intrinsic<"qvfcpsgn">;
+
+ // Compare Instructions
+ def int_ppc_qpx_qvftstnan : PowerPC_QPX_FFF_Intrinsic<"qvftstnan">;
+ def int_ppc_qpx_qvfcmplt : PowerPC_QPX_FFF_Intrinsic<"qvfcmplt">;
+ def int_ppc_qpx_qvfcmpgt : PowerPC_QPX_FFF_Intrinsic<"qvfcmpgt">;
+ def int_ppc_qpx_qvfcmpeq : PowerPC_QPX_FFF_Intrinsic<"qvfcmpeq">;
+
+ // Load instructions
+ def int_ppc_qpx_qvlfd : PowerPC_QPX_Load_Intrinsic<"qvlfd">;
+ def int_ppc_qpx_qvlfda : PowerPC_QPX_Load_Intrinsic<"qvlfda">;
+ def int_ppc_qpx_qvlfs : PowerPC_QPX_Load_Intrinsic<"qvlfs">;
+ def int_ppc_qpx_qvlfsa : PowerPC_QPX_Load_Intrinsic<"qvlfsa">;
+
+ def int_ppc_qpx_qvlfcda : PowerPC_QPX_Load_Intrinsic<"qvlfcda">;
+ def int_ppc_qpx_qvlfcd : PowerPC_QPX_Load_Intrinsic<"qvlfcd">;
+ def int_ppc_qpx_qvlfcsa : PowerPC_QPX_Load_Intrinsic<"qvlfcsa">;
+ def int_ppc_qpx_qvlfcs : PowerPC_QPX_Load_Intrinsic<"qvlfcs">;
+ def int_ppc_qpx_qvlfiwaa : PowerPC_QPX_Load_Intrinsic<"qvlfiwaa">;
+ def int_ppc_qpx_qvlfiwa : PowerPC_QPX_Load_Intrinsic<"qvlfiwa">;
+ def int_ppc_qpx_qvlfiwza : PowerPC_QPX_Load_Intrinsic<"qvlfiwza">;
+ def int_ppc_qpx_qvlfiwz : PowerPC_QPX_Load_Intrinsic<"qvlfiwz">;
+
+ def int_ppc_qpx_qvlpcld : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcld">;
+ def int_ppc_qpx_qvlpcls : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcls">;
+ def int_ppc_qpx_qvlpcrd : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrd">;
+ def int_ppc_qpx_qvlpcrs : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrs">;
+
+ // Store instructions
+ def int_ppc_qpx_qvstfd : PowerPC_QPX_Store_Intrinsic<"qvstfd">;
+ def int_ppc_qpx_qvstfda : PowerPC_QPX_Store_Intrinsic<"qvstfda">;
+ def int_ppc_qpx_qvstfs : PowerPC_QPX_Store_Intrinsic<"qvstfs">;
+ def int_ppc_qpx_qvstfsa : PowerPC_QPX_Store_Intrinsic<"qvstfsa">;
+
+ def int_ppc_qpx_qvstfcda : PowerPC_QPX_Store_Intrinsic<"qvstfcda">;
+ def int_ppc_qpx_qvstfcd : PowerPC_QPX_Store_Intrinsic<"qvstfcd">;
+ def int_ppc_qpx_qvstfcsa : PowerPC_QPX_Store_Intrinsic<"qvstfcsa">;
+ def int_ppc_qpx_qvstfcs : PowerPC_QPX_Store_Intrinsic<"qvstfcs">;
+ def int_ppc_qpx_qvstfiwa : PowerPC_QPX_Store_Intrinsic<"qvstfiwa">;
+ def int_ppc_qpx_qvstfiw : PowerPC_QPX_Store_Intrinsic<"qvstfiw">;
+
+ // Logical and permutation formation
+ def int_ppc_qpx_qvflogical : PowerPC_QPX_Intrinsic<"qvflogical",
+ [llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_ppc_qpx_qvgpci : PowerPC_QPX_Intrinsic<"qvgpci",
+ [llvm_v4f64_ty], [llvm_i32_ty], [IntrNoMem]>;
+}
+
+//===----------------------------------------------------------------------===//
+// PowerPC HTM Intrinsic Definitions.
+
+let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
+
+def int_ppc_tbegin : GCCBuiltin<"__builtin_tbegin">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
+def int_ppc_tend : GCCBuiltin<"__builtin_tend">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
+
+def int_ppc_tabort : GCCBuiltin<"__builtin_tabort">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
+def int_ppc_tabortwc : GCCBuiltin<"__builtin_tabortwc">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
+def int_ppc_tabortwci : GCCBuiltin<"__builtin_tabortwci">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
+def int_ppc_tabortdc : GCCBuiltin<"__builtin_tabortdc">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
+def int_ppc_tabortdci : GCCBuiltin<"__builtin_tabortdci">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
+
+def int_ppc_tcheck : GCCBuiltin<"__builtin_tcheck">,
+ Intrinsic<[llvm_i32_ty], [], []>;
+def int_ppc_treclaim : GCCBuiltin<"__builtin_treclaim">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
+def int_ppc_trechkpt : GCCBuiltin<"__builtin_trechkpt">,
+ Intrinsic<[llvm_i32_ty], [], []>;
+def int_ppc_tsr : GCCBuiltin<"__builtin_tsr">,
+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
+
+def int_ppc_get_texasr : GCCBuiltin<"__builtin_get_texasr">,
+ Intrinsic<[llvm_i64_ty], [], []>;
+def int_ppc_get_texasru : GCCBuiltin<"__builtin_get_texasru">,
+ Intrinsic<[llvm_i64_ty], [], []>;
+def int_ppc_get_tfhar : GCCBuiltin<"__builtin_get_tfhar">,
+ Intrinsic<[llvm_i64_ty], [], []>;
+def int_ppc_get_tfiar : GCCBuiltin<"__builtin_get_tfiar">,
+ Intrinsic<[llvm_i64_ty], [], []>;
+
+def int_ppc_set_texasr : GCCBuiltin<"__builtin_set_texasr">,
+ Intrinsic<[], [llvm_i64_ty], []>;
+def int_ppc_set_texasru : GCCBuiltin<"__builtin_set_texasru">,
+ Intrinsic<[], [llvm_i64_ty], []>;
+def int_ppc_set_tfhar : GCCBuiltin<"__builtin_set_tfhar">,
+ Intrinsic<[], [llvm_i64_ty], []>;
+def int_ppc_set_tfiar : GCCBuiltin<"__builtin_set_tfiar">,
+ Intrinsic<[], [llvm_i64_ty], []>;
+
+// Extended mnemonics
+def int_ppc_tendall : GCCBuiltin<"__builtin_tendall">,
+ Intrinsic<[llvm_i32_ty], [], []>;
+def int_ppc_tresume : GCCBuiltin<"__builtin_tresume">,
+ Intrinsic<[llvm_i32_ty], [], []>;
+def int_ppc_tsuspend : GCCBuiltin<"__builtin_tsuspend">,
+ Intrinsic<[llvm_i32_ty], [], []>;
+
+def int_ppc_ttest : GCCBuiltin<"__builtin_ttest">,
+ Intrinsic<[llvm_i64_ty], [], []>;
+}
diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td
new file mode 100644
index 000000000000..96e7ca525696
--- /dev/null
+++ b/include/llvm/IR/IntrinsicsSystemZ.td
@@ -0,0 +1,376 @@
+//===- IntrinsicsSystemZ.td - Defines SystemZ intrinsics ---*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines all of the SystemZ-specific intrinsics.
+//
+//===----------------------------------------------------------------------===//
+
+class SystemZUnaryConv<string name, LLVMType result, LLVMType arg>
+ : GCCBuiltin<"__builtin_s390_" ## name>,
+ Intrinsic<[result], [arg], [IntrNoMem]>;
+
+class SystemZUnary<string name, LLVMType type>
+ : SystemZUnaryConv<name, type, type>;
+
+class SystemZUnaryConvCC<LLVMType result, LLVMType arg>
+ : Intrinsic<[result, llvm_i32_ty], [arg], [IntrNoMem]>;
+
+class SystemZUnaryCC<LLVMType type>
+ : SystemZUnaryConvCC<type, type>;
+
+class SystemZBinaryConv<string name, LLVMType result, LLVMType arg>
+ : GCCBuiltin<"__builtin_s390_" ## name>,
+ Intrinsic<[result], [arg, arg], [IntrNoMem]>;
+
+class SystemZBinary<string name, LLVMType type>
+ : SystemZBinaryConv<name, type, type>;
+
+class SystemZBinaryInt<string name, LLVMType type>
+ : GCCBuiltin<"__builtin_s390_" ## name>,
+ Intrinsic<[type], [type, llvm_i32_ty], [IntrNoMem]>;
+
+class SystemZBinaryConvCC<LLVMType result, LLVMType arg>
+ : Intrinsic<[result, llvm_i32_ty], [arg, arg], [IntrNoMem]>;
+
+class SystemZBinaryConvIntCC<LLVMType result, LLVMType arg>
+ : Intrinsic<[result, llvm_i32_ty], [arg, llvm_i32_ty], [IntrNoMem]>;
+
+class SystemZBinaryCC<LLVMType type>
+ : SystemZBinaryConvCC<type, type>;
+
+class SystemZTernaryConv<string name, LLVMType result, LLVMType arg>
+ : GCCBuiltin<"__builtin_s390_" ## name>,
+ Intrinsic<[result], [arg, arg, result], [IntrNoMem]>;
+
+class SystemZTernary<string name, LLVMType type>
+ : SystemZTernaryConv<name, type, type>;
+
+class SystemZTernaryInt<string name, LLVMType type>
+ : GCCBuiltin<"__builtin_s390_" ## name>,
+ Intrinsic<[type], [type, type, llvm_i32_ty], [IntrNoMem]>;
+
+class SystemZTernaryIntCC<LLVMType type>
+ : Intrinsic<[type, llvm_i32_ty], [type, type, llvm_i32_ty], [IntrNoMem]>;
+
+class SystemZQuaternaryInt<string name, LLVMType type>
+ : GCCBuiltin<"__builtin_s390_" ## name>,
+ Intrinsic<[type], [type, type, type, llvm_i32_ty], [IntrNoMem]>;
+
+class SystemZQuaternaryIntCC<LLVMType type>
+ : Intrinsic<[type, llvm_i32_ty], [type, type, type, llvm_i32_ty],
+ [IntrNoMem]>;
+
+multiclass SystemZUnaryExtBHF<string name> {
+ def b : SystemZUnaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>;
+ def h : SystemZUnaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>;
+ def f : SystemZUnaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>;
+}
+
+multiclass SystemZUnaryExtBHWF<string name> {
+ def b : SystemZUnaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>;
+ def hw : SystemZUnaryConv<name##"hw", llvm_v4i32_ty, llvm_v8i16_ty>;
+ def f : SystemZUnaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>;
+}
+
+multiclass SystemZUnaryBHF<string name> {
+ def b : SystemZUnary<name##"b", llvm_v16i8_ty>;
+ def h : SystemZUnary<name##"h", llvm_v8i16_ty>;
+ def f : SystemZUnary<name##"f", llvm_v4i32_ty>;
+}
+
+multiclass SystemZUnaryBHFG<string name> : SystemZUnaryBHF<name> {
+ def g : SystemZUnary<name##"g", llvm_v2i64_ty>;
+}
+
+multiclass SystemZUnaryCCBHF {
+ def bs : SystemZUnaryCC<llvm_v16i8_ty>;
+ def hs : SystemZUnaryCC<llvm_v8i16_ty>;
+ def fs : SystemZUnaryCC<llvm_v4i32_ty>;
+}
+
+multiclass SystemZBinaryTruncHFG<string name> {
+ def h : SystemZBinaryConv<name##"h", llvm_v16i8_ty, llvm_v8i16_ty>;
+ def f : SystemZBinaryConv<name##"f", llvm_v8i16_ty, llvm_v4i32_ty>;
+ def g : SystemZBinaryConv<name##"g", llvm_v4i32_ty, llvm_v2i64_ty>;
+}
+
+multiclass SystemZBinaryTruncCCHFG {
+ def hs : SystemZBinaryConvCC<llvm_v16i8_ty, llvm_v8i16_ty>;
+ def fs : SystemZBinaryConvCC<llvm_v8i16_ty, llvm_v4i32_ty>;
+ def gs : SystemZBinaryConvCC<llvm_v4i32_ty, llvm_v2i64_ty>;
+}
+
+multiclass SystemZBinaryExtBHF<string name> {
+ def b : SystemZBinaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>;
+ def h : SystemZBinaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>;
+ def f : SystemZBinaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>;
+}
+
+multiclass SystemZBinaryExtBHFG<string name> : SystemZBinaryExtBHF<name> {
+ def g : SystemZBinaryConv<name##"g", llvm_v16i8_ty, llvm_v2i64_ty>;
+}
+
+multiclass SystemZBinaryBHF<string name> {
+ def b : SystemZBinary<name##"b", llvm_v16i8_ty>;
+ def h : SystemZBinary<name##"h", llvm_v8i16_ty>;
+ def f : SystemZBinary<name##"f", llvm_v4i32_ty>;
+}
+
+multiclass SystemZBinaryBHFG<string name> : SystemZBinaryBHF<name> {
+ def g : SystemZBinary<name##"g", llvm_v2i64_ty>;
+}
+
+multiclass SystemZBinaryIntBHFG<string name> {
+ def b : SystemZBinaryInt<name##"b", llvm_v16i8_ty>;
+ def h : SystemZBinaryInt<name##"h", llvm_v8i16_ty>;
+ def f : SystemZBinaryInt<name##"f", llvm_v4i32_ty>;
+ def g : SystemZBinaryInt<name##"g", llvm_v2i64_ty>;
+}
+
+multiclass SystemZBinaryCCBHF {
+ def bs : SystemZBinaryCC<llvm_v16i8_ty>;
+ def hs : SystemZBinaryCC<llvm_v8i16_ty>;
+ def fs : SystemZBinaryCC<llvm_v4i32_ty>;
+}
+
+multiclass SystemZCompareBHFG<string name> {
+ def bs : SystemZBinaryCC<llvm_v16i8_ty>;
+ def hs : SystemZBinaryCC<llvm_v8i16_ty>;
+ def fs : SystemZBinaryCC<llvm_v4i32_ty>;
+ def gs : SystemZBinaryCC<llvm_v2i64_ty>;
+}
+
+multiclass SystemZTernaryExtBHF<string name> {
+ def b : SystemZTernaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>;
+ def h : SystemZTernaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>;
+ def f : SystemZTernaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>;
+}
+
+multiclass SystemZTernaryExtBHFG<string name> : SystemZTernaryExtBHF<name> {
+ def g : SystemZTernaryConv<name##"g", llvm_v16i8_ty, llvm_v2i64_ty>;
+}
+
+multiclass SystemZTernaryBHF<string name> {
+ def b : SystemZTernary<name##"b", llvm_v16i8_ty>;
+ def h : SystemZTernary<name##"h", llvm_v8i16_ty>;
+ def f : SystemZTernary<name##"f", llvm_v4i32_ty>;
+}
+
+multiclass SystemZTernaryIntBHF<string name> {
+ def b : SystemZTernaryInt<name##"b", llvm_v16i8_ty>;
+ def h : SystemZTernaryInt<name##"h", llvm_v8i16_ty>;
+ def f : SystemZTernaryInt<name##"f", llvm_v4i32_ty>;
+}
+
+multiclass SystemZTernaryIntCCBHF {
+ def bs : SystemZTernaryIntCC<llvm_v16i8_ty>;
+ def hs : SystemZTernaryIntCC<llvm_v8i16_ty>;
+ def fs : SystemZTernaryIntCC<llvm_v4i32_ty>;
+}
+
+multiclass SystemZQuaternaryIntBHF<string name> {
+ def b : SystemZQuaternaryInt<name##"b", llvm_v16i8_ty>;
+ def h : SystemZQuaternaryInt<name##"h", llvm_v8i16_ty>;
+ def f : SystemZQuaternaryInt<name##"f", llvm_v4i32_ty>;
+}
+
+multiclass SystemZQuaternaryIntBHFG<string name> : SystemZQuaternaryIntBHF<name> {
+ def g : SystemZQuaternaryInt<name##"g", llvm_v2i64_ty>;
+}
+
+multiclass SystemZQuaternaryIntCCBHF {
+ def bs : SystemZQuaternaryIntCC<llvm_v16i8_ty>;
+ def hs : SystemZQuaternaryIntCC<llvm_v8i16_ty>;
+ def fs : SystemZQuaternaryIntCC<llvm_v4i32_ty>;
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Transactional-execution intrinsics
+//
+//===----------------------------------------------------------------------===//
+
+let TargetPrefix = "s390" in {
+ def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty],
+ [IntrNoDuplicate]>;
+
+ def int_s390_tbegin_nofloat : Intrinsic<[llvm_i32_ty],
+ [llvm_ptr_ty, llvm_i32_ty],
+ [IntrNoDuplicate]>;
+
+ def int_s390_tbeginc : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty],
+ [IntrNoDuplicate]>;
+
+ def int_s390_tabort : Intrinsic<[], [llvm_i64_ty],
+ [IntrNoReturn, Throws]>;
+
+ def int_s390_tend : GCCBuiltin<"__builtin_tend">,
+ Intrinsic<[llvm_i32_ty], []>;
+
+ def int_s390_etnd : GCCBuiltin<"__builtin_tx_nesting_depth">,
+ Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
+
+ def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty],
+ [IntrReadWriteArgMem]>;
+
+ def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">,
+ Intrinsic<[], [llvm_i32_ty]>;
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Vector intrinsics
+//
+//===----------------------------------------------------------------------===//
+
+let TargetPrefix = "s390" in {
+ def int_s390_lcbb : GCCBuiltin<"__builtin_s390_lcbb">,
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+
+ def int_s390_vlbb : GCCBuiltin<"__builtin_s390_vlbb">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty],
+ [IntrReadArgMem]>;
+
+ def int_s390_vll : GCCBuiltin<"__builtin_s390_vll">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty],
+ [IntrReadArgMem]>;
+
+ def int_s390_vpdi : GCCBuiltin<"__builtin_s390_vpdi">,
+ Intrinsic<[llvm_v2i64_ty],
+ [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+
+ def int_s390_vperm : GCCBuiltin<"__builtin_s390_vperm">,
+ Intrinsic<[llvm_v16i8_ty],
+ [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty],
+ [IntrNoMem]>;
+
+ defm int_s390_vpks : SystemZBinaryTruncHFG<"vpks">;
+ defm int_s390_vpks : SystemZBinaryTruncCCHFG;
+
+ defm int_s390_vpkls : SystemZBinaryTruncHFG<"vpkls">;
+ defm int_s390_vpkls : SystemZBinaryTruncCCHFG;
+
+ def int_s390_vstl : GCCBuiltin<"__builtin_s390_vstl">,
+ Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty],
+ // In fact write-only but there's no property
+ // for that.
+ [IntrReadWriteArgMem]>;
+
+ defm int_s390_vupl : SystemZUnaryExtBHWF<"vupl">;
+ defm int_s390_vupll : SystemZUnaryExtBHF<"vupll">;
+
+ defm int_s390_vuph : SystemZUnaryExtBHF<"vuph">;
+ defm int_s390_vuplh : SystemZUnaryExtBHF<"vuplh">;
+
+ defm int_s390_vacc : SystemZBinaryBHFG<"vacc">;
+
+ def int_s390_vaq : SystemZBinary<"vaq", llvm_v16i8_ty>;
+ def int_s390_vacq : SystemZTernary<"vacq", llvm_v16i8_ty>;
+ def int_s390_vaccq : SystemZBinary<"vaccq", llvm_v16i8_ty>;
+ def int_s390_vacccq : SystemZTernary<"vacccq", llvm_v16i8_ty>;
+
+ defm int_s390_vavg : SystemZBinaryBHFG<"vavg">;
+ defm int_s390_vavgl : SystemZBinaryBHFG<"vavgl">;
+
+ def int_s390_vcksm : SystemZBinary<"vcksm", llvm_v4i32_ty>;
+
+ defm int_s390_vgfm : SystemZBinaryExtBHFG<"vgfm">;
+ defm int_s390_vgfma : SystemZTernaryExtBHFG<"vgfma">;
+
+ defm int_s390_vmah : SystemZTernaryBHF<"vmah">;
+ defm int_s390_vmalh : SystemZTernaryBHF<"vmalh">;
+ defm int_s390_vmae : SystemZTernaryExtBHF<"vmae">;
+ defm int_s390_vmale : SystemZTernaryExtBHF<"vmale">;
+ defm int_s390_vmao : SystemZTernaryExtBHF<"vmao">;
+ defm int_s390_vmalo : SystemZTernaryExtBHF<"vmalo">;
+
+ defm int_s390_vmh : SystemZBinaryBHF<"vmh">;
+ defm int_s390_vmlh : SystemZBinaryBHF<"vmlh">;
+ defm int_s390_vme : SystemZBinaryExtBHF<"vme">;
+ defm int_s390_vmle : SystemZBinaryExtBHF<"vmle">;
+ defm int_s390_vmo : SystemZBinaryExtBHF<"vmo">;
+ defm int_s390_vmlo : SystemZBinaryExtBHF<"vmlo">;
+
+ defm int_s390_verllv : SystemZBinaryBHFG<"verllv">;
+ defm int_s390_verll : SystemZBinaryIntBHFG<"verll">;
+ defm int_s390_verim : SystemZQuaternaryIntBHFG<"verim">;
+
+ def int_s390_vsl : SystemZBinary<"vsl", llvm_v16i8_ty>;
+ def int_s390_vslb : SystemZBinary<"vslb", llvm_v16i8_ty>;
+ def int_s390_vsra : SystemZBinary<"vsra", llvm_v16i8_ty>;
+ def int_s390_vsrab : SystemZBinary<"vsrab", llvm_v16i8_ty>;
+ def int_s390_vsrl : SystemZBinary<"vsrl", llvm_v16i8_ty>;
+ def int_s390_vsrlb : SystemZBinary<"vsrlb", llvm_v16i8_ty>;
+
+ def int_s390_vsldb : GCCBuiltin<"__builtin_s390_vsldb">,
+ Intrinsic<[llvm_v16i8_ty],
+ [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+
+ defm int_s390_vscbi : SystemZBinaryBHFG<"vscbi">;
+
+ def int_s390_vsq : SystemZBinary<"vsq", llvm_v16i8_ty>;
+ def int_s390_vsbiq : SystemZTernary<"vsbiq", llvm_v16i8_ty>;
+ def int_s390_vscbiq : SystemZBinary<"vscbiq", llvm_v16i8_ty>;
+ def int_s390_vsbcbiq : SystemZTernary<"vsbcbiq", llvm_v16i8_ty>;
+
+ def int_s390_vsumb : SystemZBinaryConv<"vsumb", llvm_v4i32_ty, llvm_v16i8_ty>;
+ def int_s390_vsumh : SystemZBinaryConv<"vsumh", llvm_v4i32_ty, llvm_v8i16_ty>;
+
+ def int_s390_vsumgh : SystemZBinaryConv<"vsumgh", llvm_v2i64_ty,
+ llvm_v8i16_ty>;
+ def int_s390_vsumgf : SystemZBinaryConv<"vsumgf", llvm_v2i64_ty,
+ llvm_v4i32_ty>;
+
+ def int_s390_vsumqf : SystemZBinaryConv<"vsumqf", llvm_v16i8_ty,
+ llvm_v4i32_ty>;
+ def int_s390_vsumqg : SystemZBinaryConv<"vsumqg", llvm_v16i8_ty,
+ llvm_v2i64_ty>;
+
+ def int_s390_vtm : SystemZBinaryConv<"vtm", llvm_i32_ty, llvm_v16i8_ty>;
+
+ defm int_s390_vceq : SystemZCompareBHFG<"vceq">;
+ defm int_s390_vch : SystemZCompareBHFG<"vch">;
+ defm int_s390_vchl : SystemZCompareBHFG<"vchl">;
+
+ defm int_s390_vfae : SystemZTernaryIntBHF<"vfae">;
+ defm int_s390_vfae : SystemZTernaryIntCCBHF;
+ defm int_s390_vfaez : SystemZTernaryIntBHF<"vfaez">;
+ defm int_s390_vfaez : SystemZTernaryIntCCBHF;
+
+ defm int_s390_vfee : SystemZBinaryBHF<"vfee">;
+ defm int_s390_vfee : SystemZBinaryCCBHF;
+ defm int_s390_vfeez : SystemZBinaryBHF<"vfeez">;
+ defm int_s390_vfeez : SystemZBinaryCCBHF;
+
+ defm int_s390_vfene : SystemZBinaryBHF<"vfene">;
+ defm int_s390_vfene : SystemZBinaryCCBHF;
+ defm int_s390_vfenez : SystemZBinaryBHF<"vfenez">;
+ defm int_s390_vfenez : SystemZBinaryCCBHF;
+
+ defm int_s390_vistr : SystemZUnaryBHF<"vistr">;
+ defm int_s390_vistr : SystemZUnaryCCBHF;
+
+ defm int_s390_vstrc : SystemZQuaternaryIntBHF<"vstrc">;
+ defm int_s390_vstrc : SystemZQuaternaryIntCCBHF;
+ defm int_s390_vstrcz : SystemZQuaternaryIntBHF<"vstrcz">;
+ defm int_s390_vstrcz : SystemZQuaternaryIntCCBHF;
+
+ def int_s390_vfcedbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>;
+ def int_s390_vfchdbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>;
+ def int_s390_vfchedbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>;
+
+ def int_s390_vftcidb : SystemZBinaryConvIntCC<llvm_v2i64_ty, llvm_v2f64_ty>;
+
+ def int_s390_vfidb : Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+}
diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td
index 81c729065505..3a8a4a643a43 100644
--- a/include/llvm/IR/IntrinsicsX86.td
+++ b/include/llvm/IR/IntrinsicsX86.td
@@ -18,6 +18,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
}
//===----------------------------------------------------------------------===//
+// SEH LSDA for Windows
+let TargetPrefix = "x86" in {
+ def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>;
+}
+
+//===----------------------------------------------------------------------===//
// Read Time Stamp Counter.
let TargetPrefix = "x86" in {
def int_x86_rdtsc : GCCBuiltin<"__builtin_ia32_rdtsc">,
@@ -453,19 +459,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
}
// Conversion ops
@@ -895,15 +888,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">,
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_i8_ty],
- [IntrNoMem]>;
- def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">,
- 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_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],
[IntrNoMem]>;
@@ -1169,12 +1153,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector blend
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_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_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]>;
@@ -1200,32 +1178,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
}
-// Vector extract and insert
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx_vextractf128_pd_256 :
- GCCBuiltin<"__builtin_ia32_vextractf128_pd256">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx_vextractf128_ps_256 :
- GCCBuiltin<"__builtin_ia32_vextractf128_ps256">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx_vextractf128_si_256 :
- GCCBuiltin<"__builtin_ia32_vextractf128_si256">,
- Intrinsic<[llvm_v4i32_ty], [llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
-
- def int_x86_avx_vinsertf128_pd_256 :
- GCCBuiltin<"__builtin_ia32_vinsertf128_pd256">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
- llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx_vinsertf128_ps_256 :
- GCCBuiltin<"__builtin_ia32_vinsertf128_ps256">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
- llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx_vinsertf128_si_256 :
- GCCBuiltin<"__builtin_ia32_vinsertf128_si256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
- llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
-}
-
// Vector convert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_cvtdq2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtdq2pd256">,
@@ -1363,6 +1315,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_mask_loadu_pd_512 : GCCBuiltin<"__builtin_ia32_loadupd512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrReadArgMem]>;
+ def int_x86_avx512_mask_load_ps_512 : GCCBuiltin<"__builtin_ia32_loadaps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty],
+ [IntrReadArgMem]>;
+ def int_x86_avx512_mask_load_pd_512 : GCCBuiltin<"__builtin_ia32_loadapd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty],
+ [IntrReadArgMem]>;
}
// Conditional store ops
@@ -1389,6 +1347,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
GCCBuiltin<"__builtin_ia32_storeupd512_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_store_ps_512 :
+ GCCBuiltin<"__builtin_ia32_storeaps512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty],
+ [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_store_pd_512 :
+ GCCBuiltin<"__builtin_ia32_storeapd512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty],
+ [IntrReadWriteArgMem]>;
def int_x86_avx512_mask_store_ss :
GCCBuiltin<"__builtin_ia32_storess_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty],
@@ -1448,12 +1414,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty,
llvm_v32i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Vector min, max
@@ -1572,19 +1532,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi256_byteshift">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">,
- Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
-
def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
@@ -1746,15 +1693,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb256">,
Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_v32i8_ty], [IntrNoMem]>;
- def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
- 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_i8_ty], [IntrNoMem]>;
- def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_i8_ty], [IntrNoMem]>;
}
// Vector load with broadcast
@@ -1768,8 +1706,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_vbroadcast_ss_ps_256 :
GCCBuiltin<"__builtin_ia32_vbroadcastss_ps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty], [IntrNoMem]>;
- def int_x86_avx2_vbroadcasti128 :
- Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
def int_x86_avx2_pbroadcastb_128 :
GCCBuiltin<"__builtin_ia32_pbroadcastb128">,
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>;
@@ -1823,13 +1759,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector extract and insert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx2_vextracti128 : GCCBuiltin<"__builtin_ia32_extract128i256">,
- Intrinsic<[llvm_v2i64_ty], [llvm_v4i64_ty,
- llvm_i8_ty], [IntrNoMem]>;
- 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,
@@ -3068,6 +2997,46 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_i64_ty], [IntrNoMem]>;
}
+// Pack ops.
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_avx512_mask_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packsswb_256 : GCCBuiltin<"__builtin_ia32_packsswb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packssdw_256 : GCCBuiltin<"__builtin_ia32_packssdw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packssdw_512 : GCCBuiltin<"__builtin_ia32_packssdw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packuswb_256 : GCCBuiltin<"__builtin_ia32_packuswb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packusdw_128 : GCCBuiltin<"__builtin_ia32_packusdw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packusdw_256 : GCCBuiltin<"__builtin_ia32_packusdw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_packusdw_512 : GCCBuiltin<"__builtin_ia32_packusdw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+}
+
// Vector convert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_mask_cvttps2dq_512: GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">,
@@ -3164,28 +3133,238 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty],
[IntrNoMem]>;
}
-
+//Bitwise Ops
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_avx512_mask_pand_d_128 : GCCBuiltin<"__builtin_ia32_pandd128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pand_d_256 : GCCBuiltin<"__builtin_ia32_pandd256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v8i32_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], [IntrNoMem]>;
+ def int_x86_avx512_mask_pand_q_128 : GCCBuiltin<"__builtin_ia32_pandq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pand_q_256 : GCCBuiltin<"__builtin_ia32_pandq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pandn_d_128 : GCCBuiltin<"__builtin_ia32_pandnd128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pandn_d_256 : GCCBuiltin<"__builtin_ia32_pandnd256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pandn_d_512 : GCCBuiltin<"__builtin_ia32_pandnd512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pandn_q_128 : GCCBuiltin<"__builtin_ia32_pandnq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pandn_q_256 : GCCBuiltin<"__builtin_ia32_pandnq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pandn_q_512 : GCCBuiltin<"__builtin_ia32_pandnq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_por_d_128 : GCCBuiltin<"__builtin_ia32_pord128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_por_d_256 : GCCBuiltin<"__builtin_ia32_pord256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_por_d_512 : GCCBuiltin<"__builtin_ia32_pord512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_por_q_128 : GCCBuiltin<"__builtin_ia32_porq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_por_q_256 : GCCBuiltin<"__builtin_ia32_porq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_por_q_512 : GCCBuiltin<"__builtin_ia32_porq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pxor_d_128 : GCCBuiltin<"__builtin_ia32_pxord128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pxor_d_256 : GCCBuiltin<"__builtin_ia32_pxord256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pxor_d_512 : GCCBuiltin<"__builtin_ia32_pxord512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pxor_q_128 : GCCBuiltin<"__builtin_ia32_pxorq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pxor_q_256 : GCCBuiltin<"__builtin_ia32_pxorq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pxor_q_512 : GCCBuiltin<"__builtin_ia32_pxorq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+}
// Arithmetic ops
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+
+ def int_x86_avx512_mask_add_ps_128 : GCCBuiltin<"__builtin_ia32_addps128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_add_ps_256 : GCCBuiltin<"__builtin_ia32_addps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_add_pd_128 : GCCBuiltin<"__builtin_ia32_addpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_add_pd_256 : GCCBuiltin<"__builtin_ia32_addpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_sub_ps_128 : GCCBuiltin<"__builtin_ia32_subps128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_sub_ps_256 : GCCBuiltin<"__builtin_ia32_subps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_sub_pd_128 : GCCBuiltin<"__builtin_ia32_subpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_sub_pd_256 : GCCBuiltin<"__builtin_ia32_subpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_mul_ps_128 : GCCBuiltin<"__builtin_ia32_mulps_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_mul_ps_256 : GCCBuiltin<"__builtin_ia32_mulps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_mul_pd_128 : GCCBuiltin<"__builtin_ia32_mulpd_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_mul_pd_256 : GCCBuiltin<"__builtin_ia32_mulpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_div_ps_128 : GCCBuiltin<"__builtin_ia32_divps_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_div_ps_256 : GCCBuiltin<"__builtin_ia32_divps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_div_pd_128 : GCCBuiltin<"__builtin_ia32_divpd_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_div_pd_256 : GCCBuiltin<"__builtin_ia32_divpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_max_ps_128 : GCCBuiltin<"__builtin_ia32_maxps_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_max_ps_256 : GCCBuiltin<"__builtin_ia32_maxps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_max_pd_128 : GCCBuiltin<"__builtin_ia32_maxpd_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_max_pd_256 : GCCBuiltin<"__builtin_ia32_maxpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_min_ps_128 : GCCBuiltin<"__builtin_ia32_minps_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_min_ps_256 : GCCBuiltin<"__builtin_ia32_minps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_min_pd_128 : GCCBuiltin<"__builtin_ia32_minpd_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_min_pd_256 : GCCBuiltin<"__builtin_ia32_minpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_div_ss_round : GCCBuiltin<"__builtin_ia32_divss_round">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_mul_ss_round : GCCBuiltin<"__builtin_ia32_mulss_round">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_sub_ss_round : GCCBuiltin<"__builtin_ia32_subss_round">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_max_ss_round : GCCBuiltin<"__builtin_ia32_maxss_round">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_min_ss_round : GCCBuiltin<"__builtin_ia32_minss_round">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_add_sd_round : GCCBuiltin<"__builtin_ia32_addsd_round">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_div_sd_round : GCCBuiltin<"__builtin_ia32_divsd_round">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_mul_sd_round : GCCBuiltin<"__builtin_ia32_mulsd_round">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_sub_sd_round : GCCBuiltin<"__builtin_ia32_subsd_round">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_max_sd_round : GCCBuiltin<"__builtin_ia32_maxsd_round">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_min_sd_round : GCCBuiltin<"__builtin_ia32_minsd_round">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem]>;
def int_x86_avx512_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty],
[IntrNoMem]>;
@@ -3265,21 +3444,273 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty],
[IntrNoMem]>;
}
-
-// Integer shift ops.
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi512_byteshift">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi512_byteshift">,
- Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
- llvm_i32_ty], [IntrNoMem]>;
+// FP logical ops
+let TargetPrefix = "x86" in {
+ def int_x86_avx512_mask_and_pd_128 : GCCBuiltin<"__builtin_ia32_andpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_and_pd_256 : GCCBuiltin<"__builtin_ia32_andpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_and_pd_512 : GCCBuiltin<"__builtin_ia32_andpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_and_ps_128 : GCCBuiltin<"__builtin_ia32_andps128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_and_ps_256 : GCCBuiltin<"__builtin_ia32_andps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_and_ps_512 : GCCBuiltin<"__builtin_ia32_andps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_andn_pd_128 : GCCBuiltin<"__builtin_ia32_andnpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_andn_pd_256 : GCCBuiltin<"__builtin_ia32_andnpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_andn_pd_512 : GCCBuiltin<"__builtin_ia32_andnpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_andn_ps_128 : GCCBuiltin<"__builtin_ia32_andnps128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_andn_ps_256 : GCCBuiltin<"__builtin_ia32_andnps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_andn_ps_512 : GCCBuiltin<"__builtin_ia32_andnps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_or_pd_128 : GCCBuiltin<"__builtin_ia32_orpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_or_pd_256 : GCCBuiltin<"__builtin_ia32_orpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_or_pd_512 : GCCBuiltin<"__builtin_ia32_orpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_or_ps_128 : GCCBuiltin<"__builtin_ia32_orps128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_or_ps_256 : GCCBuiltin<"__builtin_ia32_orps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_or_ps_512 : GCCBuiltin<"__builtin_ia32_orps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_xor_pd_128 : GCCBuiltin<"__builtin_ia32_xorpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_xor_pd_256 : GCCBuiltin<"__builtin_ia32_xorpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_xor_pd_512 : GCCBuiltin<"__builtin_ia32_xorpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_xor_ps_128 : GCCBuiltin<"__builtin_ia32_xorps128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_xor_ps_256 : GCCBuiltin<"__builtin_ia32_xorps256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_xor_ps_512 : GCCBuiltin<"__builtin_ia32_xorps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>;
+}
+// Integer arithmetic ops
+let TargetPrefix = "x86" in {
+ def int_x86_avx512_mask_padd_b_128 : GCCBuiltin<"__builtin_ia32_paddb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_b_256 : GCCBuiltin<"__builtin_ia32_paddb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_b_512 : GCCBuiltin<"__builtin_ia32_paddb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_w_128 : GCCBuiltin<"__builtin_ia32_paddw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_w_256 : GCCBuiltin<"__builtin_ia32_paddw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_w_512 : GCCBuiltin<"__builtin_ia32_paddw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padds_b_128 : GCCBuiltin<"__builtin_ia32_paddsb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padds_b_256 : GCCBuiltin<"__builtin_ia32_paddsb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padds_b_512 : GCCBuiltin<"__builtin_ia32_paddsb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padds_w_128 : GCCBuiltin<"__builtin_ia32_paddsw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padds_w_256 : GCCBuiltin<"__builtin_ia32_paddsw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padds_w_512 : GCCBuiltin<"__builtin_ia32_paddsw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_paddus_b_128 : GCCBuiltin<"__builtin_ia32_paddusb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_paddus_b_256 : GCCBuiltin<"__builtin_ia32_paddusb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_paddus_b_512 : GCCBuiltin<"__builtin_ia32_paddusb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_paddus_w_128 : GCCBuiltin<"__builtin_ia32_paddusw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_paddus_w_256 : GCCBuiltin<"__builtin_ia32_paddusw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_paddus_w_512 : GCCBuiltin<"__builtin_ia32_paddusw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_d_128 : GCCBuiltin<"__builtin_ia32_paddd128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_d_256 : GCCBuiltin<"__builtin_ia32_paddd256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_d_512 : GCCBuiltin<"__builtin_ia32_paddd512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_q_128 : GCCBuiltin<"__builtin_ia32_paddq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_q_256 : GCCBuiltin<"__builtin_ia32_paddq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_padd_q_512 : GCCBuiltin<"__builtin_ia32_paddq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_b_128 : GCCBuiltin<"__builtin_ia32_psubb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_b_256 : GCCBuiltin<"__builtin_ia32_psubb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_b_512 : GCCBuiltin<"__builtin_ia32_psubb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_w_128 : GCCBuiltin<"__builtin_ia32_psubw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_w_256 : GCCBuiltin<"__builtin_ia32_psubw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_w_512 : GCCBuiltin<"__builtin_ia32_psubw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubs_b_128 : GCCBuiltin<"__builtin_ia32_psubsb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubs_b_256 : GCCBuiltin<"__builtin_ia32_psubsb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubs_b_512 : GCCBuiltin<"__builtin_ia32_psubsb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubs_w_128 : GCCBuiltin<"__builtin_ia32_psubsw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubs_w_256 : GCCBuiltin<"__builtin_ia32_psubsw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubs_w_512 : GCCBuiltin<"__builtin_ia32_psubsw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubus_b_128 : GCCBuiltin<"__builtin_ia32_psubusb128_mask">,
+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
+ llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubus_b_256 : GCCBuiltin<"__builtin_ia32_psubusb256_mask">,
+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
+ llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubus_b_512 : GCCBuiltin<"__builtin_ia32_psubusb512_mask">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty,
+ llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubus_w_128 : GCCBuiltin<"__builtin_ia32_psubusw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubus_w_256 : GCCBuiltin<"__builtin_ia32_psubusw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psubus_w_512 : GCCBuiltin<"__builtin_ia32_psubusw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_d_128 : GCCBuiltin<"__builtin_ia32_psubd128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_d_256 : GCCBuiltin<"__builtin_ia32_psubd256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_d_512 : GCCBuiltin<"__builtin_ia32_psubd512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_q_128 : GCCBuiltin<"__builtin_ia32_psubq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_q_256 : GCCBuiltin<"__builtin_ia32_psubq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psub_q_512 : GCCBuiltin<"__builtin_ia32_psubq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmulu_dq_128 : GCCBuiltin<"__builtin_ia32_pmuludq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmul_dq_128 : GCCBuiltin<"__builtin_ia32_pmuldq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmulu_dq_256 : GCCBuiltin<"__builtin_ia32_pmuludq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmul_dq_256 : GCCBuiltin<"__builtin_ia32_pmuldq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_w_128 : GCCBuiltin<"__builtin_ia32_pmullw128_mask">,
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
+ llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_w_256 : GCCBuiltin<"__builtin_ia32_pmullw256_mask">,
+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
+ llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_w_512 : GCCBuiltin<"__builtin_ia32_pmullw512_mask">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty,
+ llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_d_128 : GCCBuiltin<"__builtin_ia32_pmulld128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_d_256 : GCCBuiltin<"__builtin_ia32_pmulld256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_d_512 : GCCBuiltin<"__builtin_ia32_pmulld512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_q_128 : GCCBuiltin<"__builtin_ia32_pmullq128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_q_256 : GCCBuiltin<"__builtin_ia32_pmullq256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pmull_q_512 : GCCBuiltin<"__builtin_ia32_pmullq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Gather and Scatter ops
@@ -3390,22 +3821,22 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_vpconflictsi_512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
llvm_v16i32_ty, llvm_i16_ty],
- []>;
+ [IntrNoMem]>;
def int_x86_avx512_mask_conflict_q_512 :
GCCBuiltin<"__builtin_ia32_vpconflictdi_512_mask">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
llvm_v8i64_ty, llvm_i8_ty],
- []>;
+ [IntrNoMem]>;
def int_x86_avx512_mask_lzcnt_d_512 :
GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
llvm_v16i32_ty, llvm_i16_ty],
- []>;
+ [IntrNoMem]>;
def int_x86_avx512_mask_lzcnt_q_512 :
GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">,
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
llvm_v8i64_ty, llvm_i8_ty],
- []>;
+ [IntrNoMem]>;
}
// Vector blend
@@ -3867,21 +4298,33 @@ let TargetPrefix = "x86" in {
}
// Misc.
let TargetPrefix = "x86" in {
- def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty,
- llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty,
- llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">,
- Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">,
- 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">,
+ def int_x86_avx512_mask_cmp_ps_512 :
+ GCCBuiltin<"__builtin_ia32_cmpps512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_pd_512 :
+ GCCBuiltin<"__builtin_ia32_cmppd512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_ps_256 :
+ GCCBuiltin<"__builtin_ia32_cmpps256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_pd_256 :
+ GCCBuiltin<"__builtin_ia32_cmppd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_ps_128 :
+ GCCBuiltin<"__builtin_ia32_cmpps128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_pd_128 :
+ GCCBuiltin<"__builtin_ia32_cmppd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>;
+
+ 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 2f18782a0730..e6c22090ab6d 100644
--- a/include/llvm/IR/LLVMContext.h
+++ b/include/llvm/IR/LLVMContext.h
@@ -58,7 +58,9 @@ public:
MD_noalias = 8, // "noalias",
MD_nontemporal = 9, // "nontemporal"
MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access"
- MD_nonnull = 11 // "nonnull"
+ MD_nonnull = 11, // "nonnull"
+ MD_dereferenceable = 12, // "dereferenceable"
+ MD_dereferenceable_or_null = 13 // "dereferenceable_or_null"
};
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
@@ -176,8 +178,8 @@ public:
}
private:
- LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
- void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
+ LLVMContext(LLVMContext&) = delete;
+ void operator=(LLVMContext&) = delete;
/// addModule - Register a module as being instantiated in this context. If
/// the context is deleted, the module will be deleted as well.
diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h
index 6c04e9dc3d3f..5257a0eed488 100644
--- a/include/llvm/IR/LegacyPassManager.h
+++ b/include/llvm/IR/LegacyPassManager.h
@@ -50,7 +50,7 @@ class PassManager : public PassManagerBase {
public:
PassManager();
- ~PassManager();
+ ~PassManager() override;
void add(Pass *P) override;
@@ -70,7 +70,7 @@ public:
/// FunctionPassManager ctor - This initializes the pass manager. It needs,
/// but does not take ownership of, the specified Module.
explicit FunctionPassManager(Module *M);
- ~FunctionPassManager();
+ ~FunctionPassManager() override;
void add(Pass *P) override;
diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h
index e2e4912ef64e..39ae80d797c7 100644
--- a/include/llvm/IR/LegacyPassNameParser.h
+++ b/include/llvm/IR/LegacyPassNameParser.h
@@ -41,14 +41,12 @@ namespace llvm {
//
class PassNameParser : public PassRegistrationListener,
public cl::parser<const PassInfo*> {
- cl::Option *Opt;
public:
- PassNameParser();
- virtual ~PassNameParser();
+ PassNameParser(cl::Option &O);
+ ~PassNameParser() override;
- void initialize(cl::Option &O) {
- Opt = &O;
- cl::parser<const PassInfo*>::initialize(O);
+ void initialize() {
+ cl::parser<const PassInfo*>::initialize();
// Add all of the passes to the map that got initialized before 'this' did.
enumeratePasses();
@@ -69,7 +67,7 @@ public:
// Implement the PassRegistrationListener callbacks used to populate our map
//
void passRegistered(const PassInfo *P) override {
- if (ignorablePass(P) || !Opt) return;
+ if (ignorablePass(P)) return;
if (findOption(P->getPassArgument()) != getNumOptions()) {
errs() << "Two passes with the same argument (-"
<< P->getPassArgument() << ") attempted to be registered!\n";
diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h
index 91a6685f6125..ba14457f7185 100644
--- a/include/llvm/IR/MDBuilder.h
+++ b/include/llvm/IR/MDBuilder.h
@@ -60,6 +60,9 @@ public:
/// \brief Return metadata containing a number of branch weights.
MDNode *createBranchWeights(ArrayRef<uint32_t> Weights);
+ /// Return metadata containing the entry count for a function.
+ MDNode *createFunctionEntryCount(uint64_t Count);
+
//===------------------------------------------------------------------===//
// Range metadata.
//===------------------------------------------------------------------===//
@@ -67,6 +70,9 @@ public:
/// \brief Return metadata describing the range [Lo, Hi).
MDNode *createRange(const APInt &Lo, const APInt &Hi);
+ /// \brief Return metadata describing the range [Lo, Hi).
+ MDNode *createRange(Constant *Lo, Constant *Hi);
+
//===------------------------------------------------------------------===//
// AA metadata.
//===------------------------------------------------------------------===//
diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def
index 2098bb57eb56..f2abff4752f7 100644
--- a/include/llvm/IR/Metadata.def
+++ b/include/llvm/IR/Metadata.def
@@ -1,4 +1,4 @@
-//===- llvm/Metadata.def - Metadata definitions -----------------*- C++ -*-===//
+//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \
- defined HANDLE_METADATA_BRANCH || defined HANDLE_UNIQUABLE_LEAF || \
- defined HANDLE_UNIQUABLE_BRANCH)
+ defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \
+ defined HANDLE_MDNODE_BRANCH || \
+ defined HANDLE_SPECIALIZED_MDNODE_LEAF || \
+ defined HANDLE_SPECIALIZED_MDNODE_BRANCH)
#error "Missing macro definition of HANDLE_METADATA*"
#endif
@@ -32,28 +34,67 @@
#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)
+// Handler for leaf nodes under MDNode.
+#ifndef HANDLE_MDNODE_LEAF
+#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS)
#endif
-// Handler for non-leaf nodes under UniquableMDNode.
-#ifndef HANDLE_UNIQUABLE_BRANCH
-#define HANDLE_UNIQUABLE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS)
+// Handler for non-leaf nodes under MDNode.
+#ifndef HANDLE_MDNODE_BRANCH
+#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS)
+#endif
+
+// Handler for specialized leaf nodes under MDNode.
+#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF
+#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS)
+#endif
+
+// Handler for specialized non-leaf nodes under MDNode.
+#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH
+#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS)
#endif
HANDLE_METADATA_LEAF(MDString)
HANDLE_METADATA_BRANCH(ValueAsMetadata)
HANDLE_METADATA_LEAF(ConstantAsMetadata)
HANDLE_METADATA_LEAF(LocalAsMetadata)
-HANDLE_METADATA_BRANCH(MDNode)
-HANDLE_METADATA_LEAF(MDNodeFwdDecl)
-HANDLE_UNIQUABLE_BRANCH(UniquableMDNode)
-HANDLE_UNIQUABLE_LEAF(MDTuple)
-HANDLE_UNIQUABLE_LEAF(MDLocation)
+HANDLE_MDNODE_BRANCH(MDNode)
+HANDLE_MDNODE_LEAF(MDTuple)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DILocation)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DIExpression)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode)
+HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDINode)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DISubrange)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DIEnumerator)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DIScope)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DIType)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DIBasicType)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DIDerivedTypeBase)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DIDerivedType)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DICompositeTypeBase)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DICompositeType)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DISubroutineType)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DIFile)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DISubprogram)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlock)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlockFile)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DINamespace)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DITemplateParameter)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateTypeParameter)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateValueParameter)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DIGlobalVariable)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DILocalVariable)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DIObjCProperty)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DIImportedEntity)
#undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF
#undef HANDLE_METADATA_BRANCH
-#undef HANDLE_UNIQUABLE_LEAF
-#undef HANDLE_UNIQUABLE_BRANCH
+#undef HANDLE_MDNODE_LEAF
+#undef HANDLE_MDNODE_BRANCH
+#undef HANDLE_SPECIALIZED_MDNODE_LEAF
+#undef HANDLE_SPECIALIZED_MDNODE_BRANCH
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index 27a5d6f80041..60718f531bd7 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -1,4 +1,4 @@
-//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===//
+//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -32,9 +32,8 @@ class Module;
template<typename ValueSubClass, typename ItemParentClass>
class SymbolTableListTraits;
-
enum LLVMConstants : uint32_t {
- DEBUG_METADATA_VERSION = 2 // Current debug info version number.
+ DEBUG_METADATA_VERSION = 3 // Current debug info version number.
};
/// \brief Root of the metadata hierarchy.
@@ -47,8 +46,11 @@ class Metadata {
const unsigned char SubclassID;
protected:
+ /// \brief Active type of storage.
+ enum StorageType { Uniqued, Distinct, Temporary };
+
/// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
- bool IsDistinctInContext : 1;
+ unsigned Storage : 2;
// TODO: expose remaining bits to subclasses.
unsigned short SubclassData16;
@@ -57,21 +59,37 @@ protected:
public:
enum MetadataKind {
MDTupleKind,
- MDLocationKind,
- MDNodeFwdDeclKind,
+ DILocationKind,
+ GenericDINodeKind,
+ DISubrangeKind,
+ DIEnumeratorKind,
+ DIBasicTypeKind,
+ DIDerivedTypeKind,
+ DICompositeTypeKind,
+ DISubroutineTypeKind,
+ DIFileKind,
+ DICompileUnitKind,
+ DISubprogramKind,
+ DILexicalBlockKind,
+ DILexicalBlockFileKind,
+ DINamespaceKind,
+ DITemplateTypeParameterKind,
+ DITemplateValueParameterKind,
+ DIGlobalVariableKind,
+ DILocalVariableKind,
+ DIExpressionKind,
+ DIObjCPropertyKind,
+ DIImportedEntityKind,
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; }
+ Metadata(unsigned ID, StorageType Storage)
+ : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) {
+ }
+ ~Metadata() = default;
/// \brief Default handling of a changed operand, which asserts.
///
@@ -85,15 +103,48 @@ public:
unsigned getMetadataID() const { return SubclassID; }
/// \brief User-friendly dump.
+ ///
+ /// If \c M is provided, metadata nodes will be numbered canonically;
+ /// otherwise, pointer addresses are substituted.
+ ///
+ /// Note: this uses an explicit overload instead of default arguments so that
+ /// the nullptr version is easy to call from a debugger.
+ ///
+ /// @{
void dump() const;
- void print(raw_ostream &OS) const;
- void printAsOperand(raw_ostream &OS, bool PrintType = true,
- const Module *M = nullptr) const;
+ void dump(const Module *M) const;
+ /// @}
+
+ /// \brief Print.
+ ///
+ /// Prints definition of \c this.
+ ///
+ /// If \c M is provided, metadata nodes will be numbered canonically;
+ /// otherwise, pointer addresses are substituted.
+ void print(raw_ostream &OS, const Module *M = nullptr) const;
+
+ /// \brief Print as operand.
+ ///
+ /// Prints reference of \c this.
+ ///
+ /// If \c M is provided, metadata nodes will be numbered canonically;
+ /// otherwise, pointer addresses are substituted.
+ void printAsOperand(raw_ostream &OS, const Module *M = nullptr) const;
};
#define HANDLE_METADATA(CLASS) class CLASS;
#include "llvm/IR/Metadata.def"
+// Provide specializations of isa so that we don't need definitions of
+// subclasses to see if the metadata is a subclass.
+#define HANDLE_METADATA_LEAF(CLASS) \
+ template <> struct isa_impl<CLASS, Metadata> { \
+ static inline bool doit(const Metadata &MD) { \
+ return MD.getMetadataID() == Metadata::CLASS##Kind; \
+ } \
+ };
+#include "llvm/IR/Metadata.def"
+
inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) {
MD.print(OS);
return OS;
@@ -113,7 +164,7 @@ class MetadataAsValue : public Value {
Metadata *MD;
MetadataAsValue(Type *Ty, Metadata *MD);
- ~MetadataAsValue();
+ ~MetadataAsValue() override;
/// \brief Drop use of metadata (during teardown).
void dropUse() { MD = nullptr; }
@@ -145,15 +196,19 @@ public:
typedef MetadataTracking::OwnerTy OwnerTy;
private:
+ LLVMContext &Context;
uint64_t NextIndex;
SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
public:
- ReplaceableMetadataImpl() : NextIndex(0) {}
+ ReplaceableMetadataImpl(LLVMContext &Context)
+ : Context(Context), NextIndex(0) {}
~ReplaceableMetadataImpl() {
assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
}
+ LLVMContext &getContext() const { return Context; }
+
/// \brief Replace all uses of this with MD.
///
/// Replace all uses of this with \c MD, which is allowed to be null.
@@ -162,8 +217,8 @@ public:
/// \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.
+ /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand
+ /// is resolved.
void resolveAllUses(bool ResolveUsers = true);
private:
@@ -195,10 +250,10 @@ class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl {
protected:
ValueAsMetadata(unsigned ID, Value *V)
- : Metadata(ID), V(V) {
+ : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) {
assert(V && "Expected valid value");
}
- ~ValueAsMetadata() {}
+ ~ValueAsMetadata() = default;
public:
static ValueAsMetadata *get(Value *V);
@@ -441,13 +496,13 @@ dyn_extract_or_null(Y &&MD) {
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;
+ MDString(const MDString &) = delete;
+ MDString &operator=(MDString &&) = delete;
+ MDString &operator=(const MDString &) = delete;
StringMapEntry<MDString> *Entry;
- MDString() : Metadata(MDStringKind), Entry(nullptr) {}
- MDString(MDString &&) : Metadata(MDStringKind) {}
+ MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {}
+ MDString(MDString &&) : Metadata(MDStringKind, Uniqued) {}
public:
static MDString *get(LLVMContext &Context, StringRef Str);
@@ -489,7 +544,7 @@ struct AAMDNodes {
bool operator!=(const AAMDNodes &A) const { return !(*this == A); }
- LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; }
+ explicit operator bool() const { return TBAA || Scope || NoAlias; }
/// \brief The tag for type-based alias analysis.
MDNode *TBAA;
@@ -528,10 +583,10 @@ struct DenseMapInfo<AAMDNodes> {
///
/// 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;
+ MDOperand(MDOperand &&) = delete;
+ MDOperand(const MDOperand &) = delete;
+ MDOperand &operator=(MDOperand &&) = delete;
+ MDOperand &operator=(const MDOperand &) = delete;
Metadata *MD;
@@ -580,18 +635,109 @@ template <> struct simplify_type<const MDOperand> {
static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); }
};
-//===----------------------------------------------------------------------===//
-/// \brief Tuple of metadata.
+/// \brief Pointer to the context, with optional RAUW support.
+///
+/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer
+/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext).
+class ContextAndReplaceableUses {
+ PointerUnion<LLVMContext *, ReplaceableMetadataImpl *> Ptr;
+
+ ContextAndReplaceableUses() = delete;
+ ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete;
+ ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete;
+ ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete;
+ ContextAndReplaceableUses &
+ operator=(const ContextAndReplaceableUses &) = delete;
+
+public:
+ ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {}
+ ContextAndReplaceableUses(
+ std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses)
+ : Ptr(ReplaceableUses.release()) {
+ assert(getReplaceableUses() && "Expected non-null replaceable uses");
+ }
+ ~ContextAndReplaceableUses() { delete getReplaceableUses(); }
+
+ operator LLVMContext &() { return getContext(); }
+
+ /// \brief Whether this contains RAUW support.
+ bool hasReplaceableUses() const {
+ return Ptr.is<ReplaceableMetadataImpl *>();
+ }
+ LLVMContext &getContext() const {
+ if (hasReplaceableUses())
+ return getReplaceableUses()->getContext();
+ return *Ptr.get<LLVMContext *>();
+ }
+ ReplaceableMetadataImpl *getReplaceableUses() const {
+ if (hasReplaceableUses())
+ return Ptr.get<ReplaceableMetadataImpl *>();
+ return nullptr;
+ }
+
+ /// \brief Assign RAUW support to this.
+ ///
+ /// Make this replaceable, taking ownership of \c ReplaceableUses (which must
+ /// not be null).
+ void
+ makeReplaceable(std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) {
+ assert(ReplaceableUses && "Expected non-null replaceable uses");
+ assert(&ReplaceableUses->getContext() == &getContext() &&
+ "Expected same context");
+ delete getReplaceableUses();
+ Ptr = ReplaceableUses.release();
+ }
+
+ /// \brief Drop RAUW support.
+ ///
+ /// Cede ownership of RAUW support, returning it.
+ std::unique_ptr<ReplaceableMetadataImpl> takeReplaceableUses() {
+ assert(hasReplaceableUses() && "Expected to own replaceable uses");
+ std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses(
+ getReplaceableUses());
+ Ptr = &ReplaceableUses->getContext();
+ return ReplaceableUses;
+ }
+};
+
+struct TempMDNodeDeleter {
+ inline void operator()(MDNode *Node) const;
+};
+
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ typedef std::unique_ptr<CLASS, TempMDNodeDeleter> Temp##CLASS;
+#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS)
+#include "llvm/IR/Metadata.def"
+
+/// \brief Metadata node.
+///
+/// Metadata nodes can be uniqued, like constants, or distinct. Temporary
+/// metadata nodes (with full support for RAUW) can be used to delay uniquing
+/// until forward references are known. The basic metadata node is an \a
+/// MDTuple.
+///
+/// There is limited support for RAUW at construction time. At construction
+/// time, if any operand is a temporary node (or an unresolved uniqued node,
+/// which indicates a transitive temporary operand), the node itself will be
+/// unresolved. As soon as all operands become resolved, it will drop RAUW
+/// support permanently.
+///
+/// If an unresolved node is part of a cycle, \a resolveCycles() needs
+/// to be called on some member of the cycle once all temporary nodes have been
+/// replaced.
class MDNode : public Metadata {
- MDNode(const MDNode &) LLVM_DELETED_FUNCTION;
- void operator=(const MDNode &) LLVM_DELETED_FUNCTION;
- void *operator new(size_t) LLVM_DELETED_FUNCTION;
+ friend class ReplaceableMetadataImpl;
+ friend class LLVMContextImpl;
+
+ MDNode(const MDNode &) = delete;
+ void operator=(const MDNode &) = delete;
+ void *operator new(size_t) = delete;
- LLVMContext &Context;
unsigned NumOperands;
+ unsigned NumUnresolved;
protected:
- unsigned MDNodeSubclassData;
+ ContextAndReplaceableUses Context;
void *operator new(size_t Size, unsigned NumOps);
void operator delete(void *Mem);
@@ -606,56 +752,163 @@ protected:
llvm_unreachable("Constructor throws?");
}
- MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs);
- ~MDNode() {}
+ MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
+ ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None);
+ ~MDNode() = default;
void dropAllReferences();
MDOperand *mutable_begin() { return mutable_end() - NumOperands; }
MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); }
-public:
- 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);
+ typedef iterator_range<MDOperand *> mutable_op_range;
+ mutable_op_range mutable_operands() {
+ return mutable_op_range(mutable_begin(), mutable_end());
+ }
- /// \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,
+public:
+ static inline MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs);
+ static inline MDTuple *getIfExists(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+ static inline MDTuple *getDistinct(LLVMContext &Context,
ArrayRef<Metadata *> MDs);
+ static inline TempMDTuple getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+
+ /// \brief Create a (temporary) clone of this.
+ TempMDNode clone() const;
/// \brief Deallocate a node created by getTemporary.
///
- /// The node must not have any users.
+ /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining
+ /// references will be reset.
static void deleteTemporary(MDNode *N);
- LLVMContext &getContext() const { return Context; }
+ LLVMContext &getContext() const { return Context.getContext(); }
/// \brief Replace a specific operand.
void replaceOperandWith(unsigned I, Metadata *New);
/// \brief Check if node is fully resolved.
- bool isResolved() const;
+ ///
+ /// If \a isTemporary(), this always returns \c false; if \a isDistinct(),
+ /// this always returns \c true.
+ ///
+ /// If \a isUniqued(), returns \c true if this has already dropped RAUW
+ /// support (because all operands are resolved).
+ ///
+ /// As forward declarations are resolved, their containers should get
+ /// resolved automatically. However, if this (or one of its operands) is
+ /// involved in a cycle, \a resolveCycles() needs to be called explicitly.
+ bool isResolved() const { return !Context.hasReplaceableUses(); }
+
+ bool isUniqued() const { return Storage == Uniqued; }
+ bool isDistinct() const { return Storage == Distinct; }
+ bool isTemporary() const { return Storage == Temporary; }
- /// \brief Check if node is distinct.
+ /// \brief RAUW a temporary.
///
- /// Distinct nodes are not uniqued, and will not be returned by \a
- /// MDNode::get().
- bool isDistinct() const {
- return isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this);
+ /// \pre \a isTemporary() must be \c true.
+ void replaceAllUsesWith(Metadata *MD) {
+ assert(isTemporary() && "Expected temporary node");
+ assert(!isResolved() && "Expected RAUW support");
+ Context.getReplaceableUses()->replaceAllUsesWith(MD);
}
+ /// \brief Resolve cycles.
+ ///
+ /// Once all forward declarations have been resolved, force cycles to be
+ /// resolved.
+ ///
+ /// \pre No operands (or operands' operands, etc.) have \a isTemporary().
+ void resolveCycles();
+
+ /// \brief Replace a temporary node with a permanent one.
+ ///
+ /// Try to create a uniqued version of \c N -- in place, if possible -- and
+ /// return it. If \c N cannot be uniqued, return a distinct node instead.
+ template <class T>
+ static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+ replaceWithPermanent(std::unique_ptr<T, TempMDNodeDeleter> N) {
+ return cast<T>(N.release()->replaceWithPermanentImpl());
+ }
+
+ /// \brief Replace a temporary node with a uniqued one.
+ ///
+ /// Create a uniqued version of \c N -- in place, if possible -- and return
+ /// it. Takes ownership of the temporary node.
+ ///
+ /// \pre N does not self-reference.
+ template <class T>
+ static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+ replaceWithUniqued(std::unique_ptr<T, TempMDNodeDeleter> N) {
+ return cast<T>(N.release()->replaceWithUniquedImpl());
+ }
+
+ /// \brief Replace a temporary node with a distinct one.
+ ///
+ /// Create a distinct version of \c N -- in place, if possible -- and return
+ /// it. Takes ownership of the temporary node.
+ template <class T>
+ static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+ replaceWithDistinct(std::unique_ptr<T, TempMDNodeDeleter> N) {
+ return cast<T>(N.release()->replaceWithDistinctImpl());
+ }
+
+private:
+ MDNode *replaceWithPermanentImpl();
+ MDNode *replaceWithUniquedImpl();
+ MDNode *replaceWithDistinctImpl();
+
protected:
/// \brief Set an operand.
///
/// Sets the operand directly, without worrying about uniquing.
void setOperand(unsigned I, Metadata *New);
+ void storeDistinctInContext();
+ template <class T, class StoreT>
+ static T *storeImpl(T *N, StorageType Storage, StoreT &Store);
+
+private:
+ void handleChangedOperand(void *Ref, Metadata *New);
+
+ void resolve();
+ void resolveAfterOperandChange(Metadata *Old, Metadata *New);
+ void decrementUnresolvedOperandCount();
+ unsigned countUnresolvedOperands();
+
+ /// \brief Mutate this to be "uniqued".
+ ///
+ /// Mutate this so that \a isUniqued().
+ /// \pre \a isTemporary().
+ /// \pre already added to uniquing set.
+ void makeUniqued();
+
+ /// \brief Mutate this to be "distinct".
+ ///
+ /// Mutate this so that \a isDistinct().
+ /// \pre \a isTemporary().
+ void makeDistinct();
+
+ void deleteAsSubclass();
+ MDNode *uniquify();
+ void eraseFromStore();
+
+ template <class NodeTy> struct HasCachedHash;
+ template <class NodeTy>
+ static void dispatchRecalculateHash(NodeTy *N, std::true_type) {
+ N->recalculateHash();
+ }
+ template <class NodeTy>
+ static void dispatchRecalculateHash(NodeTy *N, std::false_type) {}
+ template <class NodeTy>
+ static void dispatchResetHash(NodeTy *N, std::true_type) {
+ N->setHash(0);
+ }
+ template <class NodeTy>
+ static void dispatchResetHash(NodeTy *N, std::false_type) {}
+
public:
typedef const MDOperand *op_iterator;
typedef iterator_range<op_iterator> op_range;
@@ -678,9 +931,14 @@ public:
/// \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;
+ switch (MD->getMetadataID()) {
+ default:
+ return false;
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ return true;
+#include "llvm/IR/Metadata.def"
+ }
}
/// \brief Check whether MDNode is a vtable access.
@@ -690,225 +948,163 @@ public:
static MDNode *concatenate(MDNode *A, MDNode *B);
static MDNode *intersect(MDNode *A, MDNode *B);
static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B);
- static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B);
static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B);
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
static MDNode *getMostGenericAliasScope(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 {
+class MDTuple : public MDNode {
friend class LLVMContextImpl;
- friend class UniquableMDNode;
+ friend class MDNode;
- MDTuple(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW)
- : UniquableMDNode(C, MDTupleKind, Vals, AllowRAUW) {}
+ MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash,
+ ArrayRef<Metadata *> Vals)
+ : MDNode(C, MDTupleKind, Storage, Vals) {
+ setHash(Hash);
+ }
~MDTuple() { dropAllReferences(); }
- void setHash(unsigned Hash) { MDNodeSubclassData = Hash; }
+ void setHash(unsigned Hash) { SubclassData32 = Hash; }
void recalculateHash();
static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
- bool ShouldCreate);
+ StorageType Storage, bool ShouldCreate = true);
+
+ TempMDTuple cloneImpl() const {
+ return getTemporary(getContext(),
+ SmallVector<Metadata *, 4>(op_begin(), op_end()));
+ }
public:
/// \brief Get the hash, if any.
- unsigned getHash() const { return MDNodeSubclassData; }
+ unsigned getHash() const { return SubclassData32; }
static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
- return getImpl(Context, MDs, /* ShouldCreate */ true);
+ return getImpl(Context, MDs, Uniqued);
}
static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
- return getImpl(Context, MDs, /* ShouldCreate */ false);
+ return getImpl(Context, MDs, Uniqued, /* 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 MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return getImpl(Context, MDs, Distinct);
+ }
+
+ /// \brief Return a temporary node.
+ ///
+ /// For use in constructing cyclic MDNode structures. A temporary MDNode is
+ /// not uniqued, may be RAUW'd, and must be manually deleted with
+ /// deleteTemporary.
+ static TempMDTuple getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs) {
+ return TempMDTuple(getImpl(Context, MDs, Temporary));
+ }
+
+ /// \brief Return a (temporary) clone of this.
+ TempMDTuple clone() const { return cloneImpl(); }
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDTupleKind;
}
-
-private:
- MDTuple *uniquifyImpl();
- void eraseFromStoreImpl();
};
-MDNode *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+MDTuple *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
return MDTuple::get(Context, MDs);
}
-MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
return MDTuple::getIfExists(Context, MDs);
}
-MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
return MDTuple::getDistinct(Context, MDs);
}
+TempMDTuple MDNode::getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs) {
+ return MDTuple::getTemporary(Context, MDs);
+}
-/// \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);
+void TempMDNodeDeleter::operator()(MDNode *Node) const {
+ MDNode::deleteTemporary(Node);
+}
- // Disallow replacing operands.
- void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION;
+/// \brief Typed iterator through MDNode operands.
+///
+/// An iterator that transforms an \a MDNode::iterator into an iterator over a
+/// particular Metadata subclass.
+template <class T>
+class TypedMDOperandIterator
+ : std::iterator<std::input_iterator_tag, T *, std::ptrdiff_t, void, T *> {
+ MDNode::op_iterator I = nullptr;
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;
+ TypedMDOperandIterator() = default;
+ explicit TypedMDOperandIterator(MDNode::op_iterator I) : I(I) {}
+ T *operator*() const { return cast_or_null<T>(*I); }
+ TypedMDOperandIterator &operator++() {
+ ++I;
+ return *this;
}
-
- static bool classof(const Metadata *MD) {
- return MD->getMetadataID() == MDLocationKind;
+ TypedMDOperandIterator operator++(int) {
+ TypedMDOperandIterator Temp(*this);
+ ++I;
+ return Temp;
}
-
-private:
- MDLocation *uniquifyImpl();
- void eraseFromStoreImpl();
+ bool operator==(const TypedMDOperandIterator &X) const { return I == X.I; }
+ bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; }
};
-/// \brief Forward declaration of metadata.
+/// \brief Typed, array-like tuple 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) {}
+/// This is a wrapper for \a MDTuple that makes it act like an array holding a
+/// particular type of metadata.
+template <class T> class MDTupleTypedArrayWrapper {
+ const MDTuple *N = nullptr;
public:
- ~MDNodeFwdDecl() { dropAllReferences(); }
-
- // MSVC doesn't see the alternative: "using MDNode::operator delete".
- void operator delete(void *Mem) { MDNode::operator delete(Mem); }
-
- static MDNodeFwdDecl *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
- return new (MDs.size()) MDNodeFwdDecl(Context, MDs);
- }
-
- static bool classof(const Metadata *MD) {
- return MD->getMetadataID() == MDNodeFwdDeclKind;
- }
-
- using ReplaceableMetadataImpl::replaceAllUsesWith;
+ MDTupleTypedArrayWrapper() = default;
+ MDTupleTypedArrayWrapper(const MDTuple *N) : N(N) {}
+
+ template <class U>
+ MDTupleTypedArrayWrapper(
+ const MDTupleTypedArrayWrapper<U> &Other,
+ typename std::enable_if<std::is_convertible<U *, T *>::value>::type * =
+ nullptr)
+ : N(Other.get()) {}
+
+ template <class U>
+ explicit MDTupleTypedArrayWrapper(
+ const MDTupleTypedArrayWrapper<U> &Other,
+ typename std::enable_if<!std::is_convertible<U *, T *>::value>::type * =
+ nullptr)
+ : N(Other.get()) {}
+
+ explicit operator bool() const { return get(); }
+ explicit operator MDTuple *() const { return get(); }
+
+ MDTuple *get() const { return const_cast<MDTuple *>(N); }
+ MDTuple *operator->() const { return get(); }
+ MDTuple &operator*() const { return *get(); }
+
+ // FIXME: Fix callers and remove condition on N.
+ unsigned size() const { return N ? N->getNumOperands() : 0u; }
+ T *operator[](unsigned I) const { return cast_or_null<T>(N->getOperand(I)); }
+
+ // FIXME: Fix callers and remove condition on N.
+ typedef TypedMDOperandIterator<T> iterator;
+ iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); }
+ iterator end() const { return N ? iterator(N->op_end()) : iterator(); }
};
+#define HANDLE_METADATA(CLASS) \
+ typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array;
+#include "llvm/IR/Metadata.def"
+
//===----------------------------------------------------------------------===//
/// \brief A tuple of MDNodes.
///
@@ -921,7 +1117,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> {
friend struct ilist_traits<NamedMDNode>;
friend class LLVMContextImpl;
friend class Module;
- NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION;
+ NamedMDNode(const NamedMDNode &) = delete;
std::string Name;
Module *Parent;
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index b24023b05e4f..d8636dfb123e 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -219,14 +219,7 @@ private:
std::string TargetTriple; ///< Platform target triple Module compiled on
///< Format: (arch)(sub)-(vendor)-(sys0-(abi)
void *NamedMDSymTab; ///< NamedMDNode names.
-
- // We need to keep the string because the C API expects us to own the string
- // representation.
- // Since we have it, we also use an empty string to represent a module without
- // a DataLayout. If it has a DataLayout, these variables are in sync and the
- // string is just a cache of getDataLayout()->getStringRepresentation().
- std::string DataLayoutStr;
- DataLayout DL;
+ DataLayout DL; ///< DataLayout associated with the module
friend class Constant;
@@ -256,10 +249,12 @@ public:
/// Get the data layout string for the module's target platform. This is
/// equivalent to getDataLayout()->getStringRepresentation().
- const std::string &getDataLayoutStr() const { return DataLayoutStr; }
+ const std::string getDataLayoutStr() const {
+ return DL.getStringRepresentation();
+ }
/// Get the data layout for the module's target platform.
- const DataLayout *getDataLayout() const;
+ const DataLayout &getDataLayout() const;
/// Get the target triple which is a string describing the target host.
/// @returns a string containing the target triple.
@@ -293,12 +288,13 @@ public:
/// Set the data layout
void setDataLayout(StringRef Desc);
- void setDataLayout(const DataLayout *Other);
+ void setDataLayout(const DataLayout &Other);
/// Set the target triple.
void setTargetTriple(StringRef T) { TargetTriple = T; }
/// Set the module-scope inline assembly blocks.
+ /// A trailing newline is added if the input doesn't have one.
void setModuleInlineAsm(StringRef Asm) {
GlobalScopeAsm = Asm;
if (!GlobalScopeAsm.empty() &&
@@ -306,8 +302,8 @@ public:
GlobalScopeAsm += '\n';
}
- /// Append to the module-scope inline assembly blocks, automatically inserting
- /// a separating newline if necessary.
+ /// Append to the module-scope inline assembly blocks.
+ /// A trailing newline is added if the input doesn't have one.
void appendModuleInlineAsm(StringRef Asm) {
GlobalScopeAsm += Asm;
if (!GlobalScopeAsm.empty() &&
@@ -496,7 +492,7 @@ public:
/// 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 no-op.
- void Dematerialize(GlobalValue *GV);
+ void dematerialize(GlobalValue *GV);
/// Make sure all GlobalValues in this Module are fully read.
std::error_code materializeAll();
@@ -506,6 +502,8 @@ public:
/// Materializer.
std::error_code materializeAllPermanently();
+ std::error_code materializeMetadata();
+
/// @}
/// @name Direct access to the globals list, functions list, and symbol table
/// @{
@@ -630,13 +628,25 @@ public:
named_metadata_end());
}
+ /// Destroy ConstantArrays in LLVMContext if they are not used.
+ /// ConstantArrays constructed during linking can cause quadratic memory
+ /// explosion. Releasing all unused constants can cause a 20% LTO compile-time
+ /// slowdown for a large application.
+ ///
+ /// NOTE: Constants are currently owned by LLVMContext. This can then only
+ /// be called where all uses of the LLVMContext are understood.
+ void dropTriviallyDeadConstantArrays();
+
/// @}
/// @name Utility functions for printing and dumping Module objects
/// @{
/// Print the module to an output stream with an optional
- /// AssemblyAnnotationWriter.
- void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const;
+ /// AssemblyAnnotationWriter. If \c ShouldPreserveUseListOrder, then include
+ /// uselistorder directives so that use-lists can be recreated when reading
+ /// the assembly.
+ void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW,
+ bool ShouldPreserveUseListOrder = false) const;
/// Dump the module to stderr (for debugging).
void dump() const;
diff --git a/include/llvm/IR/NoFolder.h b/include/llvm/IR/NoFolder.h
index a9cdfc36fb4a..61f4817a9b62 100644
--- a/include/llvm/IR/NoFolder.h
+++ b/include/llvm/IR/NoFolder.h
@@ -177,34 +177,35 @@ public:
// Memory Instructions
//===--------------------------------------------------------------------===//
- Constant *CreateGetElementPtr(Constant *C,
+ Constant *CreateGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) const {
- return ConstantExpr::getGetElementPtr(C, IdxList);
+ return ConstantExpr::getGetElementPtr(Ty, C, IdxList);
}
- Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const {
+ Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
- return ConstantExpr::getGetElementPtr(C, Idx);
+ return ConstantExpr::getGetElementPtr(Ty, C, Idx);
}
- Instruction *CreateGetElementPtr(Constant *C,
+ Instruction *CreateGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) const {
- return GetElementPtrInst::Create(C, IdxList);
+ return GetElementPtrInst::Create(Ty, C, IdxList);
}
- Constant *CreateInBoundsGetElementPtr(Constant *C,
+ Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) const {
- return ConstantExpr::getInBoundsGetElementPtr(C, IdxList);
+ return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList);
}
- Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const {
+ Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
+ Constant *Idx) const {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
- return ConstantExpr::getInBoundsGetElementPtr(C, Idx);
+ return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx);
}
- Instruction *CreateInBoundsGetElementPtr(Constant *C,
+ Instruction *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) const {
- return GetElementPtrInst::CreateInBounds(C, IdxList);
+ return GetElementPtrInst::CreateInBounds(Ty, C, IdxList);
}
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h
index 0933f2170236..1b9102ecc7e4 100644
--- a/include/llvm/IR/Operator.h
+++ b/include/llvm/IR/Operator.h
@@ -18,7 +18,6 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
-#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Type.h"
@@ -34,15 +33,15 @@ class Operator : public User {
private:
// The Operator class is intended to be used as a utility, and is never itself
// instantiated.
- void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
- void *operator new(size_t s) LLVM_DELETED_FUNCTION;
- Operator() LLVM_DELETED_FUNCTION;
+ void *operator new(size_t, unsigned) = delete;
+ void *operator new(size_t s) = delete;
+ Operator() = delete;
protected:
- // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete
+ // NOTE: Cannot use = delete because it's not legal to delete
// an overridden method that's not deleted in the base class. Cannot leave
// this unimplemented because that leads to an ODR-violation.
- ~Operator();
+ ~Operator() override;
public:
/// Return the opcode for this Instruction or ConstantExpr.
@@ -181,17 +180,17 @@ public:
{ }
/// Whether any flag is set
- bool any() { return Flags != 0; }
+ bool any() const { return Flags != 0; }
/// Set all the flags to false
void clear() { Flags = 0; }
/// Flag queries
- bool noNaNs() { return 0 != (Flags & NoNaNs); }
- bool noInfs() { return 0 != (Flags & NoInfs); }
- bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); }
- bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); }
- bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); }
+ bool noNaNs() const { return 0 != (Flags & NoNaNs); }
+ bool noInfs() const { return 0 != (Flags & NoInfs); }
+ bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); }
+ bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); }
+ bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); }
/// Flag setters
void setNoNaNs() { Flags |= NoNaNs; }
@@ -400,6 +399,8 @@ public:
return getPointerOperand()->getType();
}
+ Type *getSourceElementType() const;
+
/// Method to return the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return getPointerOperandType()->getPointerAddressSpace();
@@ -445,36 +446,7 @@ public:
/// undefined (it is *not* preserved!). The APInt passed into this routine
/// must be at exactly as wide as the IntPtr type for the address space of the
/// base GEP pointer.
- bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const {
- assert(Offset.getBitWidth() ==
- DL.getPointerSizeInBits(getPointerAddressSpace()) &&
- "The offset must have exactly as many bits as our pointer.");
-
- for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
- GTI != GTE; ++GTI) {
- ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
- if (!OpC)
- return false;
- if (OpC->isZero())
- continue;
-
- // Handle a struct index, which adds its field offset to the pointer.
- if (StructType *STy = dyn_cast<StructType>(*GTI)) {
- unsigned ElementIdx = OpC->getZExtValue();
- const StructLayout *SL = DL.getStructLayout(STy);
- Offset += APInt(Offset.getBitWidth(),
- SL->getElementOffset(ElementIdx));
- continue;
- }
-
- // For array or vector indices, scale the index by the size of the type.
- APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth());
- Offset += Index * APInt(Offset.getBitWidth(),
- DL.getTypeAllocSize(GTI.getIndexedType()));
- }
- return true;
- }
-
+ bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const;
};
class PtrToIntOperator
@@ -504,6 +476,20 @@ public:
}
};
+class BitCastOperator
+ : public ConcreteOperator<Operator, Instruction::BitCast> {
+ friend class BitCastInst;
+ friend class ConstantExpr;
+
+public:
+ Type *getSrcTy() const {
+ return getOperand(0)->getType();
+ }
+
+ Type *getDestTy() const {
+ return getType();
+ }
+};
} // End llvm namespace
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index 262576849264..4166babd63e5 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -46,6 +46,7 @@
#include "llvm/IR/PassManagerInternal.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/type_traits.h"
#include <list>
#include <memory>
@@ -241,8 +242,8 @@ public:
private:
typedef detail::PassConcept<IRUnitT> PassConceptT;
- PassManager(const PassManager &) LLVM_DELETED_FUNCTION;
- PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION;
+ PassManager(const PassManager &) = delete;
+ PassManager &operator=(const PassManager &) = delete;
std::vector<std::unique_ptr<PassConceptT>> Passes;
@@ -281,9 +282,9 @@ template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase {
return static_cast<const DerivedT *>(this);
}
- AnalysisManagerBase(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION;
+ AnalysisManagerBase(const AnalysisManagerBase &) = delete;
AnalysisManagerBase &
- operator=(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION;
+ operator=(const AnalysisManagerBase &) = delete;
protected:
typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT;
@@ -453,8 +454,8 @@ public:
}
private:
- AnalysisManager(const AnalysisManager &) LLVM_DELETED_FUNCTION;
- AnalysisManager &operator=(const AnalysisManager &) LLVM_DELETED_FUNCTION;
+ AnalysisManager(const AnalysisManager &) = delete;
+ AnalysisManager &operator=(const AnalysisManager &) = delete;
/// \brief Get an analysis result, running the pass if necessary.
ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) {
@@ -471,6 +472,12 @@ private:
dbgs() << "Running analysis: " << P.name() << "\n";
AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
ResultList.emplace_back(PassID, P.run(IR, this));
+
+ // P.run may have inserted elements into AnalysisResults and invalidated
+ // RI.
+ RI = AnalysisResults.find(std::make_pair(PassID, &IR));
+ assert(RI != AnalysisResults.end() && "we just inserted it!");
+
RI->second = std::prev(ResultList.end());
}
@@ -502,7 +509,7 @@ private:
PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) {
// Short circuit for a common case of all analyses being preserved.
if (PA.areAllPreserved())
- return std::move(PA);
+ return PA;
if (DebugLogging)
dbgs() << "Invalidating all non-preserved analyses for: "
@@ -542,7 +549,7 @@ private:
if (ResultsList.empty())
AnalysisResultLists.erase(&IR);
- return std::move(PA);
+ return PA;
}
/// \brief List of function analysis pass IDs and associated concept pointers.
@@ -782,8 +789,11 @@ public:
FAM = &AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
PreservedAnalyses PA = PreservedAnalyses::all();
- for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
- PreservedAnalyses PassPA = Pass.run(*I, FAM);
+ for (Function &F : M) {
+ if (F.isDeclaration())
+ continue;
+
+ PreservedAnalyses PassPA = Pass.run(F, FAM);
// We know that the function pass couldn't have invalidated any other
// function's analyses (that's the contract of a function pass), so
@@ -791,7 +801,7 @@ public:
// update our preserved set to reflect that these have already been
// handled.
if (FAM)
- PassPA = FAM->invalidate(*I, std::move(PassPA));
+ PassPA = FAM->invalidate(F, std::move(PassPA));
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@@ -817,7 +827,7 @@ private:
template <typename FunctionPassT>
ModuleToFunctionPassAdaptor<FunctionPassT>
createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
- return std::move(ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
+ return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
}
/// \brief A template utility pass to force an analysis result to be available.
diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h
index 297f5f4e07f4..92de10bcd75b 100644
--- a/include/llvm/IR/PassManagerInternal.h
+++ b/include/llvm/IR/PassManagerInternal.h
@@ -19,6 +19,7 @@
#define LLVM_IR_PASSMANAGERINTERNAL_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/STLExtras.h"
namespace llvm {
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index f94e10576893..41154e6441a9 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -295,6 +295,9 @@ template <typename Class> struct bind_ty {
/// \brief Match a value, capturing it if we match.
inline bind_ty<Value> m_Value(Value *&V) { return V; }
+/// \brief Match an instruction, capturing it if we match.
+inline bind_ty<Instruction> m_Instruction(Instruction *&I) { return I; }
+
/// \brief Match a binary operator, capturing it if we match.
inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; }
@@ -1103,6 +1106,52 @@ m_UnordFMax(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R);
}
+//===----------------------------------------------------------------------===//
+// Matchers for overflow check patterns: e.g. (a + b) u< a
+//
+
+template <typename LHS_t, typename RHS_t, typename Sum_t>
+struct UAddWithOverflow_match {
+ LHS_t L;
+ RHS_t R;
+ Sum_t S;
+
+ UAddWithOverflow_match(const LHS_t &L, const RHS_t &R, const Sum_t &S)
+ : L(L), R(R), S(S) {}
+
+ template <typename OpTy> bool match(OpTy *V) {
+ Value *ICmpLHS, *ICmpRHS;
+ ICmpInst::Predicate Pred;
+ if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V))
+ return false;
+
+ Value *AddLHS, *AddRHS;
+ auto AddExpr = m_Add(m_Value(AddLHS), m_Value(AddRHS));
+
+ // (a + b) u< a, (a + b) u< b
+ if (Pred == ICmpInst::ICMP_ULT)
+ if (AddExpr.match(ICmpLHS) && (ICmpRHS == AddLHS || ICmpRHS == AddRHS))
+ return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpLHS);
+
+ // a >u (a + b), b >u (a + b)
+ if (Pred == ICmpInst::ICMP_UGT)
+ if (AddExpr.match(ICmpRHS) && (ICmpLHS == AddLHS || ICmpLHS == AddRHS))
+ return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS);
+
+ return false;
+ }
+};
+
+/// \brief Match an icmp instruction checking for unsigned overflow on addition.
+///
+/// S is matched to the addition whose result is being checked for overflow, and
+/// L and R are matched to the LHS and RHS of S.
+template <typename LHS_t, typename RHS_t, typename Sum_t>
+UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>
+m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) {
+ return UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>(L, R, S);
+}
+
/// \brief Match an 'unordered' floating point minimum function.
/// Floating point has one special value 'NaN'. Therefore, there is no total
/// order. However, if we can ignore the 'NaN' value (for example, because of a
diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h
index 5e1be37805ff..118310aed1d0 100644
--- a/include/llvm/IR/PredIteratorCache.h
+++ b/include/llvm/IR/PredIteratorCache.h
@@ -14,6 +14,7 @@
#ifndef LLVM_IR_PREDITERATORCACHE_H
#define LLVM_IR_PREDITERATORCACHE_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/CFG.h"
@@ -21,50 +22,58 @@
namespace llvm {
- /// PredIteratorCache - This class is an extremely trivial cache for
- /// predecessor iterator queries. This is useful for code that repeatedly
- /// wants the predecessor list for the same blocks.
- class PredIteratorCache {
- /// BlockToPredsMap - Pointer to null-terminated list.
- DenseMap<BasicBlock*, BasicBlock**> BlockToPredsMap;
- DenseMap<BasicBlock*, unsigned> BlockToPredCountMap;
+/// PredIteratorCache - This class is an extremely trivial cache for
+/// predecessor iterator queries. This is useful for code that repeatedly
+/// wants the predecessor list for the same blocks.
+class PredIteratorCache {
+ /// BlockToPredsMap - Pointer to null-terminated list.
+ DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap;
+ DenseMap<BasicBlock *, unsigned> BlockToPredCountMap;
- /// Memory - This is the space that holds cached preds.
- BumpPtrAllocator Memory;
- public:
+ /// Memory - This is the space that holds cached preds.
+ BumpPtrAllocator Memory;
- /// GetPreds - Get a cached list for the null-terminated predecessor list of
- /// the specified block. This can be used in a loop like this:
- /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI)
- /// use(*PI);
- /// instead of:
- /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
- BasicBlock **GetPreds(BasicBlock *BB) {
- BasicBlock **&Entry = BlockToPredsMap[BB];
- if (Entry) return Entry;
+private:
+ /// GetPreds - Get a cached list for the null-terminated predecessor list of
+ /// the specified block. This can be used in a loop like this:
+ /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI)
+ /// use(*PI);
+ /// instead of:
+ /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
+ BasicBlock **GetPreds(BasicBlock *BB) {
+ BasicBlock **&Entry = BlockToPredsMap[BB];
+ if (Entry)
+ return Entry;
- SmallVector<BasicBlock*, 32> PredCache(pred_begin(BB), pred_end(BB));
- PredCache.push_back(nullptr); // null terminator.
-
- BlockToPredCountMap[BB] = PredCache.size()-1;
+ SmallVector<BasicBlock *, 32> PredCache(pred_begin(BB), pred_end(BB));
+ PredCache.push_back(nullptr); // null terminator.
- Entry = Memory.Allocate<BasicBlock*>(PredCache.size());
- std::copy(PredCache.begin(), PredCache.end(), Entry);
- return Entry;
- }
-
- unsigned GetNumPreds(BasicBlock *BB) {
- GetPreds(BB);
- return BlockToPredCountMap[BB];
- }
+ BlockToPredCountMap[BB] = PredCache.size() - 1;
+
+ Entry = Memory.Allocate<BasicBlock *>(PredCache.size());
+ std::copy(PredCache.begin(), PredCache.end(), Entry);
+ return Entry;
+ }
+
+ unsigned GetNumPreds(BasicBlock *BB) {
+ GetPreds(BB);
+ return BlockToPredCountMap[BB];
+ }
+
+public:
+ size_t size(BasicBlock *BB) { return GetNumPreds(BB); }
+ ArrayRef<BasicBlock *> get(BasicBlock *BB) {
+ return makeArrayRef(GetPreds(BB), GetNumPreds(BB));
+ }
+
+ /// clear - Remove all information.
+ void clear() {
+ BlockToPredsMap.clear();
+ BlockToPredCountMap.clear();
+ Memory.Reset();
+ }
+};
- /// clear - Remove all information.
- void clear() {
- BlockToPredsMap.clear();
- BlockToPredCountMap.clear();
- Memory.Reset();
- }
- };
} // end namespace llvm
#endif
diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h
index e3c4243e9d81..cd09618e3eee 100644
--- a/include/llvm/IR/Statepoint.h
+++ b/include/llvm/IR/Statepoint.h
@@ -17,21 +17,35 @@
#define __LLVM_IR_STATEPOINT_H
#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
+/// The statepoint intrinsic accepts a set of flags as its third argument.
+/// Valid values come out of this set.
+enum class StatepointFlags {
+ None = 0,
+ GCTransition = 1, ///< Indicates that this statepoint is a transition from
+ ///< GC-aware code to code that is not GC-aware.
+
+ MaskAll = GCTransition ///< A bitmask that includes all valid flags.
+};
+
+class GCRelocateOperands;
+class ImmutableStatepoint;
bool isStatepoint(const ImmutableCallSite &CS);
-bool isStatepoint(const Instruction *inst);
-bool isStatepoint(const Instruction &inst);
+bool isStatepoint(const Value *inst);
+bool isStatepoint(const Value &inst);
-bool isGCRelocate(const Instruction *inst);
+bool isGCRelocate(const Value *inst);
bool isGCRelocate(const ImmutableCallSite &CS);
-bool isGCResult(const Instruction *inst);
+bool isGCResult(const Value *inst);
bool isGCResult(const ImmutableCallSite &CS);
/// Analogous to CallSiteBase, this provides most of the actual
@@ -45,10 +59,10 @@ bool isGCResult(const ImmutableCallSite &CS);
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;
+ void *operator new(size_t, unsigned) = delete;
+ void *operator new(size_t s) = delete;
- protected:
+protected:
explicit StatepointBase(InstructionTy *I) : StatepointCS(I) {
assert(isStatepoint(I));
}
@@ -56,38 +70,68 @@ class StatepointBase {
assert(isStatepoint(CS));
}
- public:
+public:
typedef typename CallSiteTy::arg_iterator arg_iterator;
+ enum {
+ IDPos = 0,
+ NumPatchBytesPos = 1,
+ ActualCalleePos = 2,
+ NumCallArgsPos = 3,
+ FlagsPos = 4,
+ CallArgsBeginPos = 5,
+ };
+
/// Return the underlying CallSite.
- CallSiteTy getCallSite() {
- return StatepointCS;
+ CallSiteTy getCallSite() { return StatepointCS; }
+
+ uint64_t getFlags() const {
+ return cast<ConstantInt>(StatepointCS.getArgument(FlagsPos))
+ ->getZExtValue();
+ }
+
+ /// Return the ID associated with this statepoint.
+ uint64_t getID() {
+ const Value *IDVal = StatepointCS.getArgument(IDPos);
+ return cast<ConstantInt>(IDVal)->getZExtValue();
+ }
+
+ /// Return the number of patchable bytes associated with this statepoint.
+ uint32_t getNumPatchBytes() {
+ const Value *NumPatchBytesVal = StatepointCS.getArgument(NumPatchBytesPos);
+ uint64_t NumPatchBytes =
+ cast<ConstantInt>(NumPatchBytesVal)->getZExtValue();
+ assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!");
+ return NumPatchBytes;
}
/// Return the value actually being called or invoked.
- ValueTy *actualCallee() {
- return StatepointCS.getArgument(0);
+ ValueTy *getActualCallee() {
+ return StatepointCS.getArgument(ActualCalleePos);
}
- /// Number of arguments to be passed to the actual callee.
- int numCallArgs() {
- return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
+
+ /// Return the type of the value returned by the call underlying the
+ /// statepoint.
+ Type *getActualReturnType() {
+ auto *FTy = cast<FunctionType>(
+ cast<PointerType>(getActualCallee()->getType())->getElementType());
+ return FTy->getReturnType();
}
- /// Number of additional arguments excluding those intended
- /// for garbage collection.
- int numTotalVMSArgs() {
- return cast<ConstantInt>(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue();
+
+ /// Number of arguments to be passed to the actual callee.
+ int getNumCallArgs() {
+ const Value *NumCallArgsVal = StatepointCS.getArgument(NumCallArgsPos);
+ return cast<ConstantInt>(NumCallArgsVal)->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;
+ assert(CallArgsBeginPos <= (int)StatepointCS.arg_size());
+ return StatepointCS.arg_begin() + CallArgsBeginPos;
}
typename CallSiteTy::arg_iterator call_args_end() {
- int Offset = 3 + numCallArgs();
- assert(Offset <= (int)StatepointCS.arg_size());
- return StatepointCS.arg_begin() + Offset;
+ auto I = call_args_begin() + getNumCallArgs();
+ assert((StatepointCS.arg_end() - I) >= 0);
+ return I;
}
/// range adapter for call arguments
@@ -95,13 +139,44 @@ class StatepointBase {
return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
}
+ /// Number of GC transition args.
+ int getNumTotalGCTransitionArgs() {
+ const Value *NumGCTransitionArgs = *call_args_end();
+ return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
+ }
+ typename CallSiteTy::arg_iterator gc_transition_args_begin() {
+ auto I = call_args_end() + 1;
+ assert((StatepointCS.arg_end() - I) >= 0);
+ return I;
+ }
+ typename CallSiteTy::arg_iterator gc_transition_args_end() {
+ auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs();
+ assert((StatepointCS.arg_end() - I) >= 0);
+ return I;
+ }
+
+ /// range adapter for GC transition arguments
+ iterator_range<arg_iterator> gc_transition_args() {
+ return iterator_range<arg_iterator>(gc_transition_args_begin(),
+ gc_transition_args_end());
+ }
+
+ /// Number of additional arguments excluding those intended
+ /// for garbage collection.
+ int getNumTotalVMSArgs() {
+ const Value *NumVMSArgs = *gc_transition_args_end();
+ return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
+ }
+
typename CallSiteTy::arg_iterator vm_state_begin() {
- return call_args_end();
+ auto I = gc_transition_args_end() + 1;
+ assert((StatepointCS.arg_end() - I) >= 0);
+ return I;
}
typename CallSiteTy::arg_iterator vm_state_end() {
- int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs();
- assert(Offset <= (int)StatepointCS.arg_size());
- return StatepointCS.arg_begin() + Offset;
+ auto I = vm_state_begin() + getNumTotalVMSArgs();
+ assert((StatepointCS.arg_end() - I) >= 0);
+ return I;
}
/// range adapter for vm state arguments
@@ -109,15 +184,7 @@ class StatepointBase {
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_begin() { return vm_state_end(); }
typename CallSiteTy::arg_iterator gc_args_end() {
return StatepointCS.arg_end();
}
@@ -127,18 +194,25 @@ class StatepointBase {
return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
}
+ /// Get list of all gc reloactes linked to this statepoint
+ /// May contain several relocations for the same base/derived pair.
+ /// For example this could happen due to relocations on unwinding
+ /// path of invoke.
+ std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS);
#ifndef NDEBUG
/// Asserts if this statepoint is malformed. Common cases for failure
/// include incorrect length prefixes for variable length sections or
/// illegal values for parameters.
void verify() {
- assert(numCallArgs() >= 0 &&
+ assert(getNumCallArgs() >= 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)gc_transition_args_begin();
+ (void)gc_transition_args_end();
(void)vm_state_begin();
(void)vm_state_end();
(void)gc_args_begin();
@@ -150,8 +224,7 @@ class StatepointBase {
/// A specialization of it's base class for read only access
/// to a gc.statepoint.
class ImmutableStatepoint
- : public StatepointBase<const Instruction, const Value,
- ImmutableCallSite> {
+ : public StatepointBase<const Instruction, const Value, ImmutableCallSite> {
typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
Base;
@@ -176,40 +249,106 @@ public:
class GCRelocateOperands {
ImmutableCallSite RelocateCS;
- public:
- GCRelocateOperands(const User* U) : RelocateCS(U) {
- assert(isGCRelocate(U));
- }
+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));
+ GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); }
+
+ /// Return true if this relocate is tied to the invoke statepoint.
+ /// This includes relocates which are on the unwinding path.
+ bool isTiedToInvoke() const {
+ const Value *Token = RelocateCS.getArgument(0);
+
+ return isa<ExtractValueInst>(Token) || isa<InvokeInst>(Token);
}
+ /// Get enclosed relocate intrinsic
+ ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; }
+
/// The statepoint with which this gc.relocate is associated.
- const Instruction *statepoint() {
- return cast<Instruction>(RelocateCS.getArgument(0));
+ const Instruction *getStatepoint() {
+ const Value *Token = RelocateCS.getArgument(0);
+
+ // This takes care both of relocates for call statepoints and relocates
+ // on normal path of invoke statepoint.
+ if (!isa<ExtractValueInst>(Token)) {
+ return cast<Instruction>(Token);
+ }
+
+ // This relocate is on exceptional path of an invoke statepoint
+ const BasicBlock *InvokeBB =
+ cast<Instruction>(Token)->getParent()->getUniquePredecessor();
+
+ assert(InvokeBB && "safepoints should have unique landingpads");
+ assert(InvokeBB->getTerminator() &&
+ "safepoint block should be well formed");
+ assert(isStatepoint(InvokeBB->getTerminator()));
+
+ return InvokeBB->getTerminator();
}
+
/// The index into the associate statepoint's argument list
/// which contains the base pointer of the pointer whose
/// relocation this gc.relocate describes.
- int basePtrIndex() {
+ unsigned getBasePtrIndex() {
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() {
+ unsigned getDerivedPtrIndex() {
return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
}
- Value *basePtr() {
- ImmutableCallSite CS(statepoint());
- return *(CS.arg_begin() + basePtrIndex());
+
+ Value *getBasePtr() {
+ ImmutableCallSite CS(getStatepoint());
+ return *(CS.arg_begin() + getBasePtrIndex());
}
- Value *derivedPtr() {
- ImmutableCallSite CS(statepoint());
- return *(CS.arg_begin() + derivedPtrIndex());
+
+ Value *getDerivedPtr() {
+ ImmutableCallSite CS(getStatepoint());
+ return *(CS.arg_begin() + getDerivedPtrIndex());
}
};
+
+template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
+std::vector<GCRelocateOperands>
+StatepointBase<InstructionTy, ValueTy, CallSiteTy>::getRelocates(
+ ImmutableStatepoint &IS) {
+
+ std::vector<GCRelocateOperands> Result;
+
+ ImmutableCallSite StatepointCS = IS.getCallSite();
+
+ // Search for relocated pointers. Note that working backwards from the
+ // gc_relocates ensures that we only get pairs which are actually relocated
+ // and used after the statepoint.
+ for (const User *U : StatepointCS.getInstruction()->users())
+ if (isGCRelocate(U))
+ Result.push_back(GCRelocateOperands(U));
+
+ if (!StatepointCS.isInvoke())
+ return Result;
+
+ // We need to scan thorough exceptional relocations if it is invoke statepoint
+ LandingPadInst *LandingPad =
+ cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
+
+ // Search for extract value from landingpad instruction to which
+ // gc relocates will be attached
+ for (const User *LandingPadUser : LandingPad->users()) {
+ if (!isa<ExtractValueInst>(LandingPadUser))
+ continue;
+
+ // gc relocates should be attached to this extract value
+ for (const User *U : LandingPadUser->users())
+ if (isGCRelocate(U))
+ Result.push_back(GCRelocateOperands(U));
+ }
+ return Result;
+}
}
+
#endif
diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h
index c2073c7750b2..6ab0bd0631a0 100644
--- a/include/llvm/IR/Type.h
+++ b/include/llvm/IR/Type.h
@@ -91,8 +91,8 @@ protected:
NumContainedTys(0), ContainedTys(nullptr) {
setTypeID(tid);
}
- ~Type() {}
-
+ ~Type() = default;
+
void setTypeID(TypeID ID) {
IDAndSubclassData = (ID & 0xFF) | (IDAndSubclassData & 0xFFFFFF00);
assert(getTypeID() == ID && "TypeID data too large for field");
@@ -395,7 +395,8 @@ public:
static IntegerType *getInt16Ty(LLVMContext &C);
static IntegerType *getInt32Ty(LLVMContext &C);
static IntegerType *getInt64Ty(LLVMContext &C);
-
+ static IntegerType *getInt128Ty(LLVMContext &C);
+
//===--------------------------------------------------------------------===//
// Convenience methods for getting pointer types with one of the above builtin
// types as pointee.
diff --git a/include/llvm/IR/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h
index 5a29e1e10855..d2c6f00079da 100644
--- a/include/llvm/IR/TypeBuilder.h
+++ b/include/llvm/IR/TypeBuilder.h
@@ -34,6 +34,8 @@ namespace llvm {
/// you'll need to specialize it. For example, say you want to call a
/// function defined externally as:
///
+/// \code{.cpp}
+///
/// struct MyType {
/// int32 a;
/// int32 *b;
@@ -41,12 +43,16 @@ namespace llvm {
/// };
/// int8 AFunction(struct MyType *value);
///
+/// \endcode
+///
/// You'll want to use
/// Function::Create(TypeBuilder<types::i<8>(MyType*), true>::get(), ...)
/// to declare the function, but when you first try this, your compiler will
/// complain that TypeBuilder<MyType, true>::get() doesn't exist. To fix this,
/// write:
///
+/// \code{.cpp}
+///
/// namespace llvm {
/// template<bool xcompile> class TypeBuilder<MyType, xcompile> {
/// public:
@@ -57,7 +63,7 @@ namespace llvm {
/// TypeBuilder<types::i<32>, xcompile>::get(Context),
/// TypeBuilder<types::i<32>*, xcompile>::get(Context),
/// TypeBuilder<types::i<8>*[], xcompile>::get(Context),
-/// NULL);
+/// nullptr);
/// }
///
/// // You may find this a convenient place to put some constants
@@ -71,6 +77,8 @@ namespace llvm {
/// }
/// } // namespace llvm
///
+/// \endcode
+///
/// TypeBuilder cannot handle recursive types or types you only know at runtime.
/// If you try to give it a recursive type, it will deadlock, infinitely
/// recurse, or do something similarly undesirable.
diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h
index 033cd3e2f5da..160d71b03e7f 100644
--- a/include/llvm/IR/Use.h
+++ b/include/llvm/IR/Use.h
@@ -77,7 +77,7 @@ public:
typedef PointerIntPair<User *, 1, unsigned> UserRef;
private:
- Use(const Use &U) LLVM_DELETED_FUNCTION;
+ Use(const Use &U) = delete;
/// Destructor - Only for zap()
~Use() {
diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h
index 5df459b1bd30..b7c2418d348d 100644
--- a/include/llvm/IR/UseListOrder.h
+++ b/include/llvm/IR/UseListOrder.h
@@ -45,18 +45,12 @@ struct UseListOrder {
}
private:
- UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION;
- UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION;
+ UseListOrder(const UseListOrder &X) = delete;
+ UseListOrder &operator=(const UseListOrder &X) = delete;
};
typedef std::vector<UseListOrder> UseListOrderStack;
-/// \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 f578227d6cae..455900566afd 100644
--- a/include/llvm/IR/User.h
+++ b/include/llvm/IR/User.h
@@ -33,8 +33,8 @@ template <class>
struct OperandTraits;
class User : public Value {
- User(const User &) LLVM_DELETED_FUNCTION;
- void *operator new(size_t) LLVM_DELETED_FUNCTION;
+ User(const User &) = delete;
+ void *operator new(size_t) = delete;
template <unsigned>
friend struct HungoffOperandTraits;
virtual void anchor();
@@ -60,9 +60,7 @@ protected:
NumOperands = 0;
}
public:
- ~User() {
- Use::zap(OperandList, OperandList + NumOperands);
- }
+ ~User() override { Use::zap(OperandList, OperandList + NumOperands); }
/// \brief Free memory allocated for User and Use objects.
void operator delete(void *Usr);
/// \brief Placement delete - required by std, but never called.
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index 705fc0f52d58..3bf2943a8980 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -106,17 +106,12 @@ protected:
private:
template <typename UseT> // UseT == 'Use' or 'const Use'
class use_iterator_impl
- : public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> {
- typedef std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> super;
-
+ : public std::iterator<std::forward_iterator_tag, UseT *> {
UseT *U;
explicit use_iterator_impl(UseT *u) : U(u) {}
friend class Value;
public:
- typedef typename super::reference reference;
- typedef typename super::pointer pointer;
-
use_iterator_impl() : U() {}
bool operator==(const use_iterator_impl &x) const { return U == x.U; }
@@ -147,17 +142,12 @@ private:
template <typename UserTy> // UserTy == 'User' or 'const User'
class user_iterator_impl
- : public std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> {
- typedef std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> super;
-
+ : public std::iterator<std::forward_iterator_tag, UserTy *> {
use_iterator_impl<Use> UI;
explicit user_iterator_impl(Use *U) : UI(U) {}
friend class Value;
public:
- typedef typename super::reference reference;
- typedef typename super::pointer pointer;
-
user_iterator_impl() {}
bool operator==(const user_iterator_impl &x) const { return UI == x.UI; }
@@ -188,15 +178,10 @@ private:
}
Use &getUse() const { return *UI; }
-
- /// \brief Return the operand # of this use in its User.
- ///
- /// FIXME: Replace all callers with a direct call to Use::getOperandNo.
- unsigned getOperandNo() const { return UI->getOperandNo(); }
};
- void operator=(const Value &) LLVM_DELETED_FUNCTION;
- Value(const Value &) LLVM_DELETED_FUNCTION;
+ void operator=(const Value &) = delete;
+ Value(const Value &) = delete;
protected:
Value(Type *Ty, unsigned scid);
@@ -231,6 +216,7 @@ public:
private:
void destroyValueName();
+ void setNameImpl(const Twine &Name);
public:
/// \brief Return a constant reference to the value's name.
@@ -461,12 +447,6 @@ public:
return const_cast<Value*>(this)->stripInBoundsOffsets();
}
- /// \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;
-
/// \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
@@ -484,7 +464,8 @@ public:
///
/// This is the greatest alignment value supported by load, store, and alloca
/// instructions, and global values.
- static const unsigned MaximumAlignment = 1u << 29;
+ static const unsigned MaxAlignmentExponent = 29;
+ static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent;
/// \brief Mutate the type of this Value to be of the specified type.
///
diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h
index 8fc7fdb03950..355748e05977 100644
--- a/include/llvm/IR/ValueHandle.h
+++ b/include/llvm/IR/ValueHandle.h
@@ -58,7 +58,7 @@ private:
Value* V;
- ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION;
+ ValueHandleBase(const ValueHandleBase&) = delete;
public:
explicit ValueHandleBase(HandleBaseKind Kind)
: PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {}
diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h
index f2ea405f1428..4d00b637609c 100644
--- a/include/llvm/IR/ValueMap.h
+++ b/include/llvm/IR/ValueMap.h
@@ -86,8 +86,8 @@ class ValueMap {
MapT Map;
std::unique_ptr<MDMapT> MDMap;
ExtraData Data;
- ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION;
- ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION;
+ ValueMap(const ValueMap&) = delete;
+ ValueMap& operator=(const ValueMap&) = delete;
public:
typedef KeyT key_type;
typedef ValueT mapped_type;
@@ -99,8 +99,6 @@ public:
explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64)
: Map(NumInitBuckets), Data(Data) {}
- ~ValueMap() {}
-
bool hasMD() const { return MDMap; }
MDMapT &MD() {
if (!MDMap)
@@ -149,9 +147,14 @@ public:
// If the key is already in the map, it returns false and doesn't update the
// value.
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
- std::pair<typename MapT::iterator, bool> map_result=
- Map.insert(std::make_pair(Wrap(KV.first), KV.second));
- return std::make_pair(iterator(map_result.first), map_result.second);
+ auto MapResult = Map.insert(std::make_pair(Wrap(KV.first), KV.second));
+ return std::make_pair(iterator(MapResult.first), MapResult.second);
+ }
+
+ std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
+ auto MapResult =
+ Map.insert(std::make_pair(Wrap(KV.first), std::move(KV.second)));
+ return std::make_pair(iterator(MapResult.first), MapResult.second);
}
/// insert - Range insertion of pairs.
@@ -258,9 +261,9 @@ public:
// I could == Copy.Map->Map.end() if the onRAUW callback already
// removed the old mapping.
if (I != Copy.Map->Map.end()) {
- ValueT Target(I->second);
+ ValueT Target(std::move(I->second));
Copy.Map->Map.erase(I); // Definitely destroys *this.
- Copy.Map->insert(std::make_pair(typed_new_key, Target));
+ Copy.Map->insert(std::make_pair(typed_new_key, std::move(Target)));
}
}
}
diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h
index 43bd123e7f44..89039d24195e 100644
--- a/include/llvm/IR/Verifier.h
+++ b/include/llvm/IR/Verifier.h
@@ -56,20 +56,9 @@ bool verifyModule(const Module &M, raw_ostream *OS = nullptr);
/// printed to stderr, and by default they are fatal. You can override that by
/// passing \c false to \p FatalErrors.
///
-/// Note that this creates a pass suitable for the legacy pass manager. It has nothing to do with \c VerifierPass.
-FunctionPass *createVerifierPass(bool FatalErrors = true);
-
-/// \brief Create a debug-info verifier pass.
-///
-/// Check a module for validity of debug info. This is essentially a pass
-/// wrapped around the debug-info parts of \a verifyModule(). When the pass
-/// detects a verification error it is always printed to stderr, and by default
-/// they are fatal. You can override that by passing \c false to \p
-/// FatalErrors.
-///
/// Note that this creates a pass suitable for the legacy pass manager. It has
/// nothing to do with \c VerifierPass.
-ModulePass *createDebugInfoVerifierPass(bool FatalErrors = true);
+FunctionPass *createVerifierPass(bool FatalErrors = true);
class VerifierPass {
bool FatalErrors;
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 30280033ee20..497ac55da4b4 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -40,7 +40,7 @@ void initializeObjCARCOpts(PassRegistry&);
void initializeVectorization(PassRegistry&);
/// initializeInstCombine - Initialize all passes linked into the
-/// ScalarOpts library.
+/// InstCombine library.
void initializeInstCombine(PassRegistry&);
/// initializeIPO - Initialize all passes linked into the IPO library.
@@ -65,6 +65,7 @@ void initializeTarget(PassRegistry&);
void initializeAAEvalPass(PassRegistry&);
void initializeAddDiscriminatorsPass(PassRegistry&);
void initializeADCEPass(PassRegistry&);
+void initializeBDCEPass(PassRegistry&);
void initializeAliasAnalysisAnalysisGroup(PassRegistry&);
void initializeAliasAnalysisCounterPass(PassRegistry&);
void initializeAliasDebuggerPass(PassRegistry&);
@@ -77,7 +78,6 @@ void initializeAlignmentFromAssumptionsPass(PassRegistry&);
void initializeBarrierNoopPass(PassRegistry&);
void initializeBasicAliasAnalysisPass(PassRegistry&);
void initializeCallGraphWrapperPassPass(PassRegistry &);
-void initializeBasicTTIPass(PassRegistry&);
void initializeBlockExtractorPassPass(PassRegistry&);
void initializeBlockFrequencyInfoPass(PassRegistry&);
void initializeBoundsCheckingPass(PassRegistry&);
@@ -106,11 +106,11 @@ void initializeDAEPass(PassRegistry&);
void initializeDAHPass(PassRegistry&);
void initializeDCEPass(PassRegistry&);
void initializeDSEPass(PassRegistry&);
-void initializeDebugInfoVerifierLegacyPassPass(PassRegistry &);
void initializeDeadInstEliminationPass(PassRegistry&);
void initializeDeadMachineInstructionElimPass(PassRegistry&);
void initializeDelinearizationPass(PassRegistry &);
void initializeDependenceAnalysisPass(PassRegistry&);
+void initializeDivergenceAnalysisPass(PassRegistry&);
void initializeDomOnlyPrinterPass(PassRegistry&);
void initializeDomOnlyViewerPass(PassRegistry&);
void initializeDomPrinterPass(PassRegistry&);
@@ -129,7 +129,7 @@ void initializeThreadSanitizerPass(PassRegistry&);
void initializeSanitizerCoverageModulePass(PassRegistry&);
void initializeDataFlowSanitizerPass(PassRegistry&);
void initializeScalarizerPass(PassRegistry&);
-void initializeEarlyCSEPass(PassRegistry&);
+void initializeEarlyCSELegacyPassPass(PassRegistry &);
void initializeExpandISelPseudosPass(PassRegistry&);
void initializeFunctionAttrsPass(PassRegistry&);
void initializeGCMachineCodeAnalysisPass(PassRegistry&);
@@ -142,15 +142,14 @@ void initializeIPCPPass(PassRegistry&);
void initializeIPSCCPPass(PassRegistry&);
void initializeIVUsersPass(PassRegistry&);
void initializeIfConverterPass(PassRegistry&);
+void initializeInductiveRangeCheckEliminationPass(PassRegistry&);
void initializeIndVarSimplifyPass(PassRegistry&);
void initializeInlineCostAnalysisPass(PassRegistry&);
-void initializeInstCombinerPass(PassRegistry&);
+void initializeInstructionCombiningPassPass(PassRegistry&);
void initializeInstCountPass(PassRegistry&);
void initializeInstNamerPass(PassRegistry&);
void initializeInternalizePassPass(PassRegistry&);
void initializeIntervalPartitionPass(PassRegistry&);
-void initializeJumpInstrTableInfoPass(PassRegistry&);
-void initializeJumpInstrTablesPass(PassRegistry&);
void initializeJumpThreadingPass(PassRegistry&);
void initializeLCSSAPass(PassRegistry&);
void initializeLICMPass(PassRegistry&);
@@ -166,7 +165,8 @@ void initializeLoaderPassPass(PassRegistry&);
void initializeLocalStackSlotPassPass(PassRegistry&);
void initializeLoopDeletionPass(PassRegistry&);
void initializeLoopExtractorPass(PassRegistry&);
-void initializeLoopInfoPass(PassRegistry&);
+void initializeLoopInfoWrapperPassPass(PassRegistry&);
+void initializeLoopInterchangePass(PassRegistry &);
void initializeLoopInstSimplifyPass(PassRegistry&);
void initializeLoopRotatePass(PassRegistry&);
void initializeLoopSimplifyPass(PassRegistry&);
@@ -177,6 +177,7 @@ void initializeLoopUnrollPass(PassRegistry&);
void initializeLoopUnswitchPass(PassRegistry&);
void initializeLoopIdiomRecognizePass(PassRegistry&);
void initializeLowerAtomicPass(PassRegistry&);
+void initializeLowerBitSetsPass(PassRegistry&);
void initializeLowerExpectIntrinsicPass(PassRegistry&);
void initializeLowerIntrinsicsPass(PassRegistry&);
void initializeLowerInvokePass(PassRegistry&);
@@ -199,11 +200,13 @@ void initializeMachineTraceMetricsPass(PassRegistry&);
void initializeMachineVerifierPassPass(PassRegistry&);
void initializeMemCpyOptPass(PassRegistry&);
void initializeMemDepPrinterPass(PassRegistry&);
+void initializeMemDerefPrinterPass(PassRegistry&);
void initializeMemoryDependenceAnalysisPass(PassRegistry&);
void initializeMergedLoadStoreMotionPass(PassRegistry &);
void initializeMetaRenamerPass(PassRegistry&);
void initializeMergeFunctionsPass(PassRegistry&);
void initializeModuleDebugInfoPrinterPass(PassRegistry&);
+void initializeNaryReassociatePass(PassRegistry&);
void initializeNoAAPass(PassRegistry&);
void initializeObjCARCAliasAnalysisPass(PassRegistry&);
void initializeObjCARCAPElimPass(PassRegistry&);
@@ -237,22 +240,27 @@ void initializeRegionOnlyPrinterPass(PassRegistry&);
void initializeRegionOnlyViewerPass(PassRegistry&);
void initializeRegionPrinterPass(PassRegistry&);
void initializeRegionViewerPass(PassRegistry&);
+void initializeRewriteStatepointsForGCPass(PassRegistry&);
void initializeSCCPPass(PassRegistry&);
void initializeSROAPass(PassRegistry&);
void initializeSROA_DTPass(PassRegistry&);
void initializeSROA_SSAUpPass(PassRegistry&);
void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&);
void initializeScalarEvolutionPass(PassRegistry&);
+void initializeShrinkWrapPass(PassRegistry &);
void initializeSimpleInlinerPass(PassRegistry&);
+void initializeShadowStackGCLoweringPass(PassRegistry&);
void initializeRegisterCoalescerPass(PassRegistry&);
void initializeSingleLoopExtractorPass(PassRegistry&);
void initializeSinkingPass(PassRegistry&);
void initializeSeparateConstOffsetFromGEPPass(PassRegistry &);
void initializeSlotIndexesPass(PassRegistry&);
void initializeSpillPlacementPass(PassRegistry&);
+void initializeSpeculativeExecutionPass(PassRegistry&);
void initializeStackProtectorPass(PassRegistry&);
void initializeStackColoringPass(PassRegistry&);
void initializeStackSlotColoringPass(PassRegistry&);
+void initializeStraightLineStrengthReducePass(PassRegistry &);
void initializeStripDeadDebugInfoPass(PassRegistry&);
void initializeStripDeadPrototypesPassPass(PassRegistry&);
void initializeStripDebugDeclarePass(PassRegistry&);
@@ -261,11 +269,8 @@ void initializeStripSymbolsPass(PassRegistry&);
void initializeTailCallElimPass(PassRegistry&);
void initializeTailDuplicatePassPass(PassRegistry&);
void initializeTargetPassConfigPass(PassRegistry&);
-void initializeDataLayoutPassPass(PassRegistry &);
-void initializeTargetTransformInfoAnalysisGroup(PassRegistry&);
-void initializeFunctionTargetTransformInfoPass(PassRegistry &);
-void initializeNoTTIPass(PassRegistry&);
-void initializeTargetLibraryInfoPass(PassRegistry&);
+void initializeTargetTransformInfoWrapperPassPass(PassRegistry &);
+void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &);
void initializeAssumptionCacheTrackerPass(PassRegistry &);
void initializeTwoAddressInstructionPassPass(PassRegistry&);
void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
@@ -279,6 +284,7 @@ void initializeVirtRegRewriterPass(PassRegistry&);
void initializeInstSimplifierPass(PassRegistry&);
void initializeUnpackMachineBundlesPass(PassRegistry&);
void initializeFinalizeMachineBundlesPass(PassRegistry&);
+void initializeLoopAccessAnalysisPass(PassRegistry&);
void initializeLoopVectorizePass(PassRegistry&);
void initializeSLPVectorizerPass(PassRegistry&);
void initializeBBVectorizePass(PassRegistry&);
@@ -287,6 +293,12 @@ void initializeStackMapLivenessPass(PassRegistry&);
void initializeMachineCombinerPass(PassRegistry &);
void initializeLoadCombinePass(PassRegistry&);
void initializeRewriteSymbolsPass(PassRegistry&);
+void initializeWinEHPreparePass(PassRegistry&);
+void initializePlaceBackedgeSafepointsImplPass(PassRegistry&);
+void initializePlaceSafepointsPass(PassRegistry&);
+void initializeDwarfEHPreparePass(PassRegistry&);
+void initializeFloat2IntPass(PassRegistry&);
+void initializeLoopDistributePass(PassRegistry&);
}
#endif
diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h
index 0c9ce4a54f02..3b4be81b223c 100644
--- a/include/llvm/LTO/LTOCodeGenerator.h
+++ b/include/llvm/LTO/LTOCodeGenerator.h
@@ -53,6 +53,7 @@ namespace llvm {
class TargetLibraryInfo;
class TargetMachine;
class raw_ostream;
+ class raw_pwrite_stream;
//===----------------------------------------------------------------------===//
/// C++ class which implements the opaque lto_code_gen_t type.
@@ -67,12 +68,19 @@ struct LTOCodeGenerator {
// Merge given module, return true on success.
bool addModule(struct LTOModule *);
+ // Set the destination module.
+ void setModule(struct LTOModule *);
+
void setTargetOptions(TargetOptions options);
void setDebugInfo(lto_debug_model);
void setCodePICModel(lto_codegen_model);
void setCpu(const char *mCpu) { MCpu = mCpu; }
void setAttr(const char *mAttr) { MAttr = mAttr; }
+ void setOptLevel(unsigned optLevel) { OptLevel = optLevel; }
+
+ void setShouldInternalize(bool Value) { ShouldInternalize = Value; }
+ void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; }
void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; }
@@ -99,7 +107,6 @@ struct LTOCodeGenerator {
// Do not try to remove the object file in LTOCodeGenerator's destructor
// as we don't who (LTOCodeGenerator or the obj file) will last longer.
bool compile_to_file(const char **name,
- bool disableOpt,
bool disableInline,
bool disableGVNLoadPRE,
bool disableVectorization,
@@ -111,12 +118,22 @@ struct LTOCodeGenerator {
// caller. This function should delete intermediate object file once its content
// is brought to memory. Return NULL if the compilation was not successful.
const void *compile(size_t *length,
- bool disableOpt,
bool disableInline,
bool disableGVNLoadPRE,
bool disableVectorization,
std::string &errMsg);
+ // Optimizes the merged module. Returns true on success.
+ bool optimize(bool disableInline,
+ bool disableGVNLoadPRE,
+ bool disableVectorization,
+ std::string &errMsg);
+
+ // Compiles the merged optimized module into a single object file. It brings
+ // the object to a buffer, and returns the buffer to the caller. Return NULL
+ // if the compilation was not successful.
+ const void *compileOptimized(size_t *length, std::string &errMsg);
+
void setDiagnosticHandler(lto_diagnostic_handler_t, void *);
LLVMContext &getContext() { return Context; }
@@ -124,9 +141,8 @@ struct LTOCodeGenerator {
private:
void initializeLTOPasses();
- bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline,
- bool disableGVNLoadPRE, bool disableVectorization,
- std::string &errMsg);
+ bool compileOptimized(raw_pwrite_stream &out, std::string &errMsg);
+ bool compileOptimizedToFile(const char **name, std::string &errMsg);
void applyScopeRestrictions();
void applyRestriction(GlobalValue &GV, ArrayRef<StringRef> Libcalls,
std::vector<const char *> &MustPreserveList,
@@ -140,14 +156,14 @@ private:
typedef StringMap<uint8_t> StringSet;
- void initialize();
+ void destroyMergedModule();
std::unique_ptr<LLVMContext> OwnedContext;
LLVMContext &Context;
Linker IRLinker;
- TargetMachine *TargetMach;
- bool EmitDwarfDebugInfo;
- bool ScopeRestrictionsDone;
- lto_codegen_model CodeModel;
+ TargetMachine *TargetMach = nullptr;
+ bool EmitDwarfDebugInfo = false;
+ bool ScopeRestrictionsDone = false;
+ lto_codegen_model CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT;
StringSet MustPreserveSymbols;
StringSet AsmUndefinedRefs;
std::unique_ptr<MemoryBuffer> NativeObjectFile;
@@ -156,8 +172,12 @@ private:
std::string MAttr;
std::string NativeObjectPath;
TargetOptions Options;
- lto_diagnostic_handler_t DiagHandler;
- void *DiagContext;
+ unsigned OptLevel = 2;
+ lto_diagnostic_handler_t DiagHandler = nullptr;
+ void *DiagContext = nullptr;
+ LTOModule *OwnedModule = nullptr;
+ bool ShouldInternalize = true;
+ bool ShouldEmbedUselists = false;
};
}
#endif
diff --git a/include/llvm/LineEditor/LineEditor.h b/include/llvm/LineEditor/LineEditor.h
index 1a9a69106032..bb106f87ca48 100644
--- a/include/llvm/LineEditor/LineEditor.h
+++ b/include/llvm/LineEditor/LineEditor.h
@@ -119,7 +119,7 @@ private:
};
struct ListCompleterConcept : CompleterConcept {
- ~ListCompleterConcept();
+ ~ListCompleterConcept() override;
CompletionAction complete(StringRef Buffer, size_t Pos) const override;
static std::string getCommonPrefix(const std::vector<Completion> &Comps);
virtual std::vector<Completion> getCompletions(StringRef Buffer,
diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h
index 2e8feab6d29d..bf21678b71cb 100644
--- a/include/llvm/LinkAllPasses.h
+++ b/include/llvm/LinkAllPasses.h
@@ -15,6 +15,7 @@
#ifndef LLVM_LINKALLPASSES_H
#define LLVM_LINKALLPASSES_H
+#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/CallPrinter.h"
#include "llvm/Analysis/DomPrinter.h"
@@ -35,6 +36,7 @@
#include "llvm/Transforms/Utils/SymbolRewriter.h"
#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
#include "llvm/Transforms/Vectorize.h"
+#include "llvm/Support/Valgrind.h"
#include <cstdlib>
namespace {
@@ -49,6 +51,7 @@ namespace {
(void) llvm::createAAEvalPass();
(void) llvm::createAggressiveDCEPass();
+ (void) llvm::createBitTrackingDCEPass();
(void) llvm::createAliasAnalysisCounterPass();
(void) llvm::createAliasDebugger();
(void) llvm::createArgumentPromotionPass();
@@ -73,6 +76,7 @@ namespace {
(void) llvm::createDeadInstEliminationPass();
(void) llvm::createDeadStoreEliminationPass();
(void) llvm::createDependenceAnalysisPass();
+ (void) llvm::createDivergenceAnalysisPass();
(void) llvm::createDomOnlyPrinterPass();
(void) llvm::createDomPrinterPass();
(void) llvm::createDomOnlyViewerPass();
@@ -86,15 +90,15 @@ namespace {
(void) llvm::createGlobalsModRefPass();
(void) llvm::createIPConstantPropagationPass();
(void) llvm::createIPSCCPPass();
+ (void) llvm::createInductiveRangeCheckEliminationPass();
(void) llvm::createIndVarSimplifyPass();
(void) llvm::createInstructionCombiningPass();
(void) llvm::createInternalizePass();
- (void) llvm::createJumpInstrTableInfoPass();
- (void) llvm::createJumpInstrTablesPass();
(void) llvm::createLCSSAPass();
(void) llvm::createLICMPass();
(void) llvm::createLazyValueInfoPass();
(void) llvm::createLoopExtractorPass();
+ (void)llvm::createLoopInterchangePass();
(void) llvm::createLoopSimplifyPass();
(void) llvm::createLoopStrengthReducePass();
(void) llvm::createLoopRerollPass();
@@ -105,6 +109,7 @@ namespace {
(void) llvm::createLowerExpectIntrinsicPass();
(void) llvm::createLowerInvokePass();
(void) llvm::createLowerSwitchPass();
+ (void) llvm::createNaryReassociatePass();
(void) llvm::createNoAAPass();
(void) llvm::createObjCARCAliasAnalysisPass();
(void) llvm::createObjCARCAPElimPass();
@@ -165,7 +170,11 @@ namespace {
(void) llvm::createPartiallyInlineLibCallsPass();
(void) llvm::createScalarizerPass();
(void) llvm::createSeparateConstOffsetFromGEPPass();
+ (void) llvm::createSpeculativeExecutionPass();
(void) llvm::createRewriteSymbolsPass();
+ (void) llvm::createStraightLineStrengthReducePass();
+ (void) llvm::createMemDerefPrinter();
+ (void) llvm::createFloat2IntPass();
(void)new llvm::IntervalPartition();
(void)new llvm::ScalarEvolution();
@@ -174,6 +183,8 @@ namespace {
((llvm::RegionPass*)nullptr)->runOnRegion((llvm::Region*)nullptr, RGM);
llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)nullptr);
X.add(nullptr, 0, llvm::AAMDNodes()); // for -print-alias-sets
+ (void) llvm::AreStatisticsEnabled();
+ (void) llvm::sys::RunningOnValgrind();
}
} ForcePassLinking; // Force link by creating a global definition.
}
diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h
index 9c3ecea590bd..c43b90e9cd26 100644
--- a/include/llvm/Linker/Linker.h
+++ b/include/llvm/Linker/Linker.h
@@ -54,6 +54,7 @@ public:
NonOpaqueStructTypeSet NonOpaqueStructTypes;
void addNonOpaque(StructType *Ty);
+ void switchToNonOpaque(StructType *Ty);
void addOpaque(StructType *Ty);
StructType *findNonOpaque(ArrayRef<Type *> ETypes, bool IsPacked);
bool hasType(StructType *Ty);
@@ -67,8 +68,13 @@ public:
void deleteModule();
/// \brief Link \p Src into the composite. The source is destroyed.
+ /// Passing OverrideSymbols as true will have symbols from Src
+ /// shadow those in the Dest.
/// Returns true on error.
- bool linkInModule(Module *Src);
+ bool linkInModule(Module *Src, bool OverrideSymbols = false);
+
+ /// \brief Set the composite to the passed-in module.
+ void setModule(Module *Dst);
static bool LinkModules(Module *Dest, Module *Src,
DiagnosticHandlerFunction DiagnosticHandler);
diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h
index 1fc0332f63c2..9aa4663ba0fc 100644
--- a/include/llvm/MC/ConstantPools.h
+++ b/include/llvm/MC/ConstantPools.h
@@ -73,21 +73,18 @@ class AssemblerConstantPools {
// sections in a stable order to ensure that we have print the
// constant pools in a deterministic order when printing an assembly
// file.
- typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy;
+ typedef MapVector<MCSection *, ConstantPool> ConstantPoolMapTy;
ConstantPoolMapTy ConstantPools;
public:
- AssemblerConstantPools() {}
- ~AssemblerConstantPools() {}
-
void emitAll(MCStreamer &Streamer);
void emitForCurrentSection(MCStreamer &Streamer);
const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr,
unsigned Size);
private:
- ConstantPool *getConstantPool(const MCSection *Section);
- ConstantPool &getOrCreateConstantPool(const MCSection *Section);
+ ConstantPool *getConstantPool(MCSection *Section);
+ ConstantPool &getOrCreateConstantPool(MCSection *Section);
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h
index a6d41392724e..c0a95d48e370 100644
--- a/include/llvm/MC/MCAsmBackend.h
+++ b/include/llvm/MC/MCAsmBackend.h
@@ -30,10 +30,10 @@ class MCSection;
class MCValue;
class raw_ostream;
-/// MCAsmBackend - Generic interface to target specific assembler backends.
+/// Generic interface to target specific assembler backends.
class MCAsmBackend {
- MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION;
- void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION;
+ MCAsmBackend(const MCAsmBackend &) = delete;
+ void operator=(const MCAsmBackend &) = delete;
protected: // Can only create subclasses.
MCAsmBackend();
@@ -46,70 +46,62 @@ public:
/// lifetime management
virtual void reset() {}
- /// createObjectWriter - Create a new MCObjectWriter instance for use by the
- /// assembler backend to emit the final object file.
- virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0;
+ /// Create a new MCObjectWriter instance for use by the assembler backend to
+ /// emit the final object file.
+ virtual MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const = 0;
- /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable
- /// non-standard ELFObjectWriters.
+ /// Create a new ELFObjectTargetWriter to enable non-standard
+ /// ELFObjectWriters.
virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
llvm_unreachable("createELFObjectTargetWriter is not supported by asm "
"backend");
}
- /// hasDataInCodeSupport - Check whether this target implements data-in-code
- /// markers. If not, data region directives will be ignored.
+ /// Check whether this target implements data-in-code 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;
- }
-
- /// @name Target Fixup Interfaces
+ /// \name Target Fixup Interfaces
/// @{
- /// getNumFixupKinds - Get the number of target specific fixup kinds.
+ /// Get the number of target specific fixup kinds.
virtual unsigned getNumFixupKinds() const = 0;
- /// getFixupKindInfo - Get information on a fixup kind.
+ /// Get information on a fixup kind.
virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const;
- /// processFixupValue - Target hook to adjust the literal value of a fixup
- /// if necessary. IsResolved signals whether the caller believes a relocation
- /// is needed; the target can modify the value. The default does nothing.
+ /// Target hook to adjust the literal value of a fixup if necessary.
+ /// IsResolved signals whether the caller believes a relocation is needed; the
+ /// target can modify the value. The default does nothing.
virtual void processFixupValue(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFixup &Fixup, const MCFragment *DF,
const MCValue &Target, uint64_t &Value,
bool &IsResolved) {}
- /// applyFixup - Apply the \p Value for given \p Fixup into the provided
- /// data fragment, at the offset specified by the fixup and following the
- /// fixup kind as appropriate.
+ /// Apply the \p Value for given \p Fixup into the provided data fragment, at
+ /// the offset specified by the fixup and following the fixup kind as
+ /// appropriate.
virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
uint64_t Value, bool IsPCRel) const = 0;
/// @}
- /// @name Target Relaxation Interfaces
+ /// \name Target Relaxation Interfaces
/// @{
- /// mayNeedRelaxation - Check whether the given instruction may need
- /// relaxation.
+ /// Check whether the given instruction may need relaxation.
///
/// \param Inst - The instruction to test.
virtual bool mayNeedRelaxation(const MCInst &Inst) const = 0;
- /// fixupNeedsRelaxation - Target specific predicate for whether a given
- /// fixup requires the associated instruction to be relaxed.
+ /// Target specific predicate for whether a given fixup requires the
+ /// associated instruction to be relaxed.
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const = 0;
- /// RelaxInstruction - Relax the instruction in the given fragment to the next
- /// wider instruction.
+ /// Relax the instruction in the given fragment to the next wider instruction.
///
/// \param Inst The instruction to relax, which may be the same as the
/// output.
@@ -118,22 +110,19 @@ public:
/// @}
- /// getMinimumNopSize - Returns the minimum size of a nop in bytes on this
- /// target. The assembler will use this to emit excess padding in situations
- /// where the padding required for simple alignment would be less than the
- /// minimum nop size.
+ /// Returns the minimum size of a nop in bytes on this target. The assembler
+ /// will use this to emit excess padding in situations where the padding
+ /// required for simple alignment would be less than the minimum nop size.
///
virtual unsigned getMinimumNopSize() const { return 1; }
- /// writeNopData - Write an (optimal) nop sequence of Count bytes to the given
- /// output. If the target cannot generate such a sequence, it should return an
- /// error.
+ /// Write an (optimal) nop sequence of Count bytes to the given output. If the
+ /// target cannot generate such a sequence, it should return an error.
///
/// \return - True on success.
virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW) const = 0;
- /// handleAssemblerFlag - Handle any target-specific assembler flags.
- /// By default, do nothing.
+ /// Handle any target-specific assembler flags. By default, do nothing.
virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}
/// \brief Generate the compact unwind encoding for the CFI instructions.
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index a750a0fd5cef..0335f3188fc3 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -18,7 +18,6 @@
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MachineLocation.h"
#include <cassert>
#include <vector>
@@ -37,17 +36,17 @@ enum class EncodingType {
ARM, /// Windows NT (Windows on ARM)
CE, /// Windows CE ARM, PowerPC, SH3, SH4
Itanium, /// Windows x64, Windows Itanium (IA-64)
+ X86, /// Windows x86, uses no CFI, just EH tables
MIPS = Alpha,
};
}
enum class ExceptionHandling {
- None, /// No exception support
- DwarfCFI, /// DWARF-like instruction based exceptions
- SjLj, /// setjmp/longjmp based exceptions
- ARM, /// ARM EHABI
- ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata)
- MSVC, /// MSVC compatible exception handling
+ None, /// No exception support
+ DwarfCFI, /// DWARF-like instruction based exceptions
+ SjLj, /// setjmp/longjmp based exceptions
+ ARM, /// ARM EHABI
+ WinEH, /// Windows Exception Handling
};
namespace LCOMM {
@@ -119,6 +118,9 @@ protected:
// Print the EH begin symbol with an assignment. Defaults to false.
bool UseAssignmentForEHBegin;
+ // Do we need to create a local symbol for .size?
+ bool NeedsLocalForSize;
+
/// This prefix is used for globals like constant pool entries that are
/// completely private to the .s file and should not have names in the .o
/// file. Defaults to "L"
@@ -226,7 +228,7 @@ protected:
/// True if the expression
/// .long f - g
- /// uses an relocation but it can be supressed by writting
+ /// uses a relocation but it can be suppressed by writing
/// a = f - g
/// .long a
bool SetDirectiveSuppressesReloc;
@@ -254,6 +256,10 @@ protected:
/// argument and how it is interpreted. Defaults to NoAlignment.
LCOMM::LCOMMType LCOMMDirectiveAlignmentType;
+ // True if the target allows .align directives on functions. This is true for
+ // most targets, so defaults to true.
+ bool HasFunctionAlignment;
+
/// True if the target has .type and .size directives, this is true for most
/// ELF targets. Defaults to true.
bool HasDotTypeDotSizeDirective;
@@ -333,7 +339,7 @@ protected:
std::vector<MCCFIInstruction> InitialFrameState;
- //===--- Integrated Assembler State ----------------------------------===//
+ //===--- Integrated Assembler Information ----------------------------===//
/// Should we use the integrated assembler?
/// The integrated assembler should be enabled by default (by the
@@ -345,6 +351,10 @@ protected:
/// Compress DWARF debug sections. Defaults to false.
bool CompressDebugSections;
+ /// True if the integrated assembler should interpret 'a >> b' constant
+ /// expressions as logical rather than arithmetic.
+ bool UseLogicalShr;
+
public:
explicit MCAsmInfo();
virtual ~MCAsmInfo();
@@ -378,7 +388,7 @@ public:
/// Targets can implement this method to specify a section to switch to if the
/// translation unit doesn't have any trampolines that require an executable
/// stack.
- virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const {
+ virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const {
return nullptr;
}
@@ -428,6 +438,7 @@ public:
const char *getLabelSuffix() const { return LabelSuffix; }
bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; }
+ bool needsLocalForSize() const { return NeedsLocalForSize; }
const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; }
const char *getPrivateLabelPrefix() const { return PrivateLabelPrefix; }
bool hasLinkerPrivateGlobalPrefix() const {
@@ -464,6 +475,7 @@ public:
LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const {
return LCOMMDirectiveAlignmentType;
}
+ bool hasFunctionAlignment() const { return HasFunctionAlignment; }
bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; }
bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; }
bool hasIdentDirective() const { return HasIdentDirective; }
@@ -490,18 +502,17 @@ public:
ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; }
WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; }
- /// Return true if the exception handling type uses the language-specific data
- /// area (LSDA) format specified by the Itanium C++ ABI.
- bool usesItaniumLSDAForExceptions() const {
+ /// Returns true if the exception handling method for the platform uses call
+ /// frame information to unwind.
+ bool usesCFIForEH() const {
return (ExceptionsType == ExceptionHandling::DwarfCFI ||
- ExceptionsType == ExceptionHandling::ARM ||
- // This Windows EH type uses the Itanium LSDA encoding.
- ExceptionsType == ExceptionHandling::ItaniumWinEH);
+ ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI());
}
bool usesWindowsCFI() const {
- return ExceptionsType == ExceptionHandling::ItaniumWinEH ||
- ExceptionsType == ExceptionHandling::MSVC;
+ return ExceptionsType == ExceptionHandling::WinEH &&
+ (WinEHEncodingType != WinEH::EncodingType::Invalid &&
+ WinEHEncodingType != WinEH::EncodingType::X86);
}
bool doesDwarfUseRelocationsAcrossSections() const {
@@ -532,6 +543,8 @@ public:
void setCompressDebugSections(bool CompressDebugSections) {
this->CompressDebugSections = CompressDebugSections;
}
+
+ bool shouldUseLogicalShr() const { return UseLogicalShr; }
};
}
diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h
index 7bd246056eca..7125f5c7ad7a 100644
--- a/include/llvm/MC/MCAsmInfoELF.h
+++ b/include/llvm/MC/MCAsmInfoELF.h
@@ -15,8 +15,7 @@
namespace llvm {
class MCAsmInfoELF : public MCAsmInfo {
virtual void anchor();
- const MCSection *
- getNonexecutableStackSection(MCContext &Ctx) const override final;
+ MCSection *getNonexecutableStackSection(MCContext &Ctx) const final;
protected:
MCAsmInfoELF();
diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h
index f048e34671db..fb28420e0fa3 100644
--- a/include/llvm/MC/MCAsmLayout.h
+++ b/include/llvm/MC/MCAsmLayout.h
@@ -16,7 +16,7 @@
namespace llvm {
class MCAssembler;
class MCFragment;
-class MCSectionData;
+class MCSection;
class MCSymbol;
class MCSymbolData;
@@ -28,20 +28,15 @@ class MCSymbolData;
/// efficiently compute the exact address of any symbol in the assembly file,
/// even during the relaxation process.
class MCAsmLayout {
-public:
- typedef llvm::SmallVectorImpl<MCSectionData*>::const_iterator const_iterator;
- typedef llvm::SmallVectorImpl<MCSectionData*>::iterator iterator;
-
-private:
MCAssembler &Assembler;
/// List of sections in layout order.
- llvm::SmallVector<MCSectionData*, 16> SectionOrder;
+ llvm::SmallVector<MCSection *, 16> SectionOrder;
/// The last fragment which was laid out, or 0 if nothing has been laid
/// out. Fragments are always laid out in order, so all fragments with a
/// lower ordinal will be valid.
- mutable DenseMap<const MCSectionData*, MCFragment*> LastValidFragment;
+ mutable DenseMap<const MCSection *, MCFragment *> LastValidFragment;
/// \brief Make sure that the layout for the given fragment is valid, lazily
/// computing it if necessary.
@@ -50,13 +45,8 @@ private:
/// \brief Is the layout for this fragment valid?
bool isFragmentValid(const MCFragment *F) const;
- /// \brief Compute the amount of padding required before this fragment to
- /// obey bundling restrictions.
- uint64_t computeBundlePadding(const MCFragment *F,
- uint64_t FOffset, uint64_t FSize);
-
public:
- MCAsmLayout(MCAssembler &_Assembler);
+ MCAsmLayout(MCAssembler &Assembler);
/// Get the assembler object this is a layout for.
MCAssembler &getAssembler() const { return Assembler; }
@@ -71,43 +61,41 @@ public:
/// been initialized.
void layoutFragment(MCFragment *Fragment);
- /// @name Section Access (in layout order)
+ /// \name Section Access (in layout order)
/// @{
- llvm::SmallVectorImpl<MCSectionData*> &getSectionOrder() {
- return SectionOrder;
- }
- const llvm::SmallVectorImpl<MCSectionData*> &getSectionOrder() const {
+ llvm::SmallVectorImpl<MCSection *> &getSectionOrder() { return SectionOrder; }
+ const llvm::SmallVectorImpl<MCSection *> &getSectionOrder() const {
return SectionOrder;
}
/// @}
- /// @name Fragment Layout Data
+ /// \name Fragment Layout Data
/// @{
/// \brief Get the offset of the given fragment inside its containing section.
uint64_t getFragmentOffset(const MCFragment *F) const;
/// @}
- /// @name Utility Functions
+ /// \name Utility Functions
/// @{
/// \brief Get the address space size of the given section, as it effects
/// layout. This may differ from the size reported by \see getSectionSize() by
/// not including section tail padding.
- uint64_t getSectionAddressSize(const MCSectionData *SD) const;
+ uint64_t getSectionAddressSize(const MCSection *Sec) const;
/// \brief Get the data size of the given section, as emitted to the object
/// file. This may include additional padding, or be 0 for virtual sections.
- uint64_t getSectionFileSize(const MCSectionData *SD) const;
+ uint64_t getSectionFileSize(const MCSection *Sec) const;
/// \brief Get the offset of the given symbol, as computed in the current
/// layout.
- /// \result True on success.
- bool getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const;
+ /// \return True on success.
+ bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const;
/// \brief Variant that reports a fatal error if the offset is not computable.
- uint64_t getSymbolOffset(const MCSymbolData *SD) const;
+ uint64_t getSymbolOffset(const MCSymbol &S) const;
/// \brief If this symbol is equivalent to A + Constant, return A.
const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const;
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 681a31728799..593504ce0607 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -11,16 +11,20 @@
#define LLVM_MC_MCASSEMBLER_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCLinkerOptimizationHint.h"
+#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
#include <algorithm>
@@ -36,18 +40,15 @@ class MCExpr;
class MCFragment;
class MCObjectWriter;
class MCSection;
-class MCSectionData;
class MCSubtargetInfo;
-class MCSymbol;
-class MCSymbolData;
class MCValue;
class MCAsmBackend;
class MCFragment : public ilist_node<MCFragment> {
friend class MCAsmLayout;
- MCFragment(const MCFragment&) LLVM_DELETED_FUNCTION;
- void operator=(const MCFragment&) LLVM_DELETED_FUNCTION;
+ MCFragment(const MCFragment &) = delete;
+ void operator=(const MCFragment &) = delete;
public:
enum FragmentType {
@@ -65,14 +66,14 @@ public:
private:
FragmentType Kind;
- /// Parent - The data for the section this fragment is in.
- MCSectionData *Parent;
+ /// The data for the section this fragment is in.
+ MCSection *Parent;
/// Atom - The atom this fragment is in, as represented by it's defining
/// symbol.
- MCSymbolData *Atom;
+ const MCSymbol *Atom;
- /// @name Assembler Backend Data
+ /// \name Assembler Backend Data
/// @{
//
// FIXME: This could all be kept private to the assembler implementation.
@@ -87,7 +88,7 @@ private:
/// @}
protected:
- MCFragment(FragmentType _Kind, MCSectionData *_Parent = nullptr);
+ MCFragment(FragmentType Kind, MCSection *Parent = nullptr);
public:
// Only for sentinel.
@@ -96,11 +97,11 @@ public:
FragmentType getKind() const { return Kind; }
- MCSectionData *getParent() const { return Parent; }
- void setParent(MCSectionData *Value) { Parent = Value; }
+ MCSection *getParent() const { return Parent; }
+ void setParent(MCSection *Value) { Parent = Value; }
- MCSymbolData *getAtom() const { return Atom; }
- void setAtom(MCSymbolData *Value) { Atom = Value; }
+ const MCSymbol *getAtom() const { return Atom; }
+ void setAtom(const MCSymbol *Value) { Atom = Value; }
unsigned getLayoutOrder() const { return LayoutOrder; }
void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
@@ -111,21 +112,18 @@ public:
/// \brief Should this fragment be placed at the end of an aligned bundle?
virtual bool alignToBundleEnd() const { return false; }
- virtual void setAlignToBundleEnd(bool V) { }
+ virtual void setAlignToBundleEnd(bool V) {}
/// \brief Get the padding size that must be inserted before this fragment.
/// Used for bundling. By default, no padding is inserted.
/// Note that padding size is restricted to 8 bits. This is an optimization
/// to reduce the amount of space used for each fragment. In practice, larger
/// padding should never be required.
- virtual uint8_t getBundlePadding() const {
- return 0;
- }
+ virtual uint8_t getBundlePadding() const { return 0; }
/// \brief Set the padding size for this fragment. By default it's a no-op,
/// and only some fragments have a meaningful implementation.
- virtual void setBundlePadding(uint8_t N) {
- }
+ virtual void setBundlePadding(uint8_t N) {}
void dump();
};
@@ -137,33 +135,28 @@ class MCEncodedFragment : public MCFragment {
virtual void anchor();
uint8_t BundlePadding;
+
public:
- MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = nullptr)
- : MCFragment(FType, SD), BundlePadding(0)
- {
- }
- virtual ~MCEncodedFragment();
+ MCEncodedFragment(MCFragment::FragmentType FType, MCSection *Sec = nullptr)
+ : MCFragment(FType, Sec), BundlePadding(0) {}
+ ~MCEncodedFragment() override;
virtual SmallVectorImpl<char> &getContents() = 0;
virtual const SmallVectorImpl<char> &getContents() const = 0;
- uint8_t getBundlePadding() const override {
- return BundlePadding;
- }
+ uint8_t getBundlePadding() const override { return BundlePadding; }
- void setBundlePadding(uint8_t N) override {
- BundlePadding = N;
- }
+ void setBundlePadding(uint8_t N) override { BundlePadding = N; }
static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind();
switch (Kind) {
- default:
- return false;
- case MCFragment::FT_Relaxable:
- case MCFragment::FT_CompactEncodedInst:
- case MCFragment::FT_Data:
- return true;
+ default:
+ return false;
+ case MCFragment::FT_Relaxable:
+ case MCFragment::FT_CompactEncodedInst:
+ case MCFragment::FT_Data:
+ return true;
}
}
};
@@ -176,12 +169,10 @@ class MCEncodedFragmentWithFixups : public MCEncodedFragment {
public:
MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
- MCSectionData *SD = nullptr)
- : MCEncodedFragment(FType, SD)
- {
- }
+ MCSection *Sec = nullptr)
+ : MCEncodedFragment(FType, Sec) {}
- virtual ~MCEncodedFragmentWithFixups();
+ ~MCEncodedFragmentWithFixups() override;
typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator;
typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator;
@@ -190,7 +181,7 @@ public:
virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0;
virtual fixup_iterator fixup_begin() = 0;
- virtual const_fixup_iterator fixup_begin() const = 0;
+ virtual const_fixup_iterator fixup_begin() const = 0;
virtual fixup_iterator fixup_end() = 0;
virtual const_fixup_iterator fixup_end() const = 0;
@@ -215,25 +206,18 @@ class MCDataFragment : public MCEncodedFragmentWithFixups {
/// Fixups - The list of fixups in this fragment.
SmallVector<MCFixup, 4> Fixups;
+
public:
- MCDataFragment(MCSectionData *SD = nullptr)
- : MCEncodedFragmentWithFixups(FT_Data, SD),
- HasInstructions(false), AlignToBundleEnd(false)
- {
- }
+ MCDataFragment(MCSection *Sec = nullptr)
+ : MCEncodedFragmentWithFixups(FT_Data, Sec), HasInstructions(false),
+ AlignToBundleEnd(false) {}
SmallVectorImpl<char> &getContents() override { return Contents; }
- const SmallVectorImpl<char> &getContents() const override {
- return Contents;
- }
+ const SmallVectorImpl<char> &getContents() const override { return Contents; }
- SmallVectorImpl<MCFixup> &getFixups() override {
- return Fixups;
- }
+ SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; }
- const SmallVectorImpl<MCFixup> &getFixups() const override {
- return Fixups;
- }
+ const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; }
bool hasInstructions() const override { return HasInstructions; }
virtual void setHasInstructions(bool V) { HasInstructions = V; }
@@ -244,8 +228,8 @@ public:
fixup_iterator fixup_begin() override { return Fixups.begin(); }
const_fixup_iterator fixup_begin() const override { return Fixups.begin(); }
- fixup_iterator fixup_end() override {return Fixups.end();}
- const_fixup_iterator fixup_end() const override {return Fixups.end();}
+ fixup_iterator fixup_end() override { return Fixups.end(); }
+ const_fixup_iterator fixup_end() const override { return Fixups.end(); }
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Data;
@@ -264,15 +248,13 @@ class MCCompactEncodedInstFragment : public MCEncodedFragment {
bool AlignToBundleEnd;
SmallVector<char, 4> Contents;
+
public:
- MCCompactEncodedInstFragment(MCSectionData *SD = nullptr)
- : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false)
- {
+ MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
+ : MCEncodedFragment(FT_CompactEncodedInst, Sec), AlignToBundleEnd(false) {
}
- bool hasInstructions() const override {
- return true;
- }
+ bool hasInstructions() const override { return true; }
SmallVectorImpl<char> &getContents() override { return Contents; }
const SmallVectorImpl<char> &getContents() const override { return Contents; }
@@ -306,35 +288,29 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups {
SmallVector<MCFixup, 1> Fixups;
public:
- MCRelaxableFragment(const MCInst &_Inst,
- const MCSubtargetInfo &_STI,
- MCSectionData *SD = nullptr)
- : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst), STI(_STI) {
- }
+ MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCSection *Sec = nullptr)
+ : MCEncodedFragmentWithFixups(FT_Relaxable, Sec), Inst(Inst), STI(STI) {}
SmallVectorImpl<char> &getContents() override { return Contents; }
const SmallVectorImpl<char> &getContents() const override { return Contents; }
const MCInst &getInst() const { return Inst; }
- void setInst(const MCInst& Value) { Inst = Value; }
+ void setInst(const MCInst &Value) { Inst = Value; }
const MCSubtargetInfo &getSubtargetInfo() { return STI; }
- SmallVectorImpl<MCFixup> &getFixups() override {
- return Fixups;
- }
+ SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; }
- const SmallVectorImpl<MCFixup> &getFixups() const override {
- return Fixups;
- }
+ const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; }
bool hasInstructions() const override { return true; }
fixup_iterator fixup_begin() override { return Fixups.begin(); }
const_fixup_iterator fixup_begin() const override { return Fixups.begin(); }
- fixup_iterator fixup_end() override {return Fixups.end();}
- const_fixup_iterator fixup_end() const override {return Fixups.end();}
+ fixup_iterator fixup_end() override { return Fixups.end(); }
+ const_fixup_iterator fixup_end() const override { return Fixups.end(); }
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Relaxable;
@@ -363,13 +339,12 @@ class MCAlignFragment : public MCFragment {
bool EmitNops : 1;
public:
- MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
- unsigned _MaxBytesToEmit, MCSectionData *SD = nullptr)
- : MCFragment(FT_Align, SD), Alignment(_Alignment),
- Value(_Value),ValueSize(_ValueSize),
- MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {}
+ MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
+ unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
+ : MCFragment(FT_Align, Sec), Alignment(Alignment), Value(Value),
+ ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit), EmitNops(false) {}
- /// @name Accessors
+ /// \name Accessors
/// @{
unsigned getAlignment() const { return Alignment; }
@@ -404,15 +379,15 @@ class MCFillFragment : public MCFragment {
uint64_t Size;
public:
- MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Size,
- MCSectionData *SD = nullptr)
- : MCFragment(FT_Fill, SD),
- Value(_Value), ValueSize(_ValueSize), Size(_Size) {
+ MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size,
+ MCSection *Sec = nullptr)
+ : MCFragment(FT_Fill, Sec), Value(Value), ValueSize(ValueSize),
+ Size(Size) {
assert((!ValueSize || (Size % ValueSize) == 0) &&
"Fill size must be a multiple of the value size!");
}
- /// @name Accessors
+ /// \name Accessors
/// @{
int64_t getValue() const { return Value; }
@@ -438,12 +413,10 @@ class MCOrgFragment : public MCFragment {
int8_t Value;
public:
- MCOrgFragment(const MCExpr &_Offset, int8_t _Value,
- MCSectionData *SD = nullptr)
- : MCFragment(FT_Org, SD),
- Offset(&_Offset), Value(_Value) {}
+ MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSection *Sec = nullptr)
+ : MCFragment(FT_Org, Sec), Offset(&Offset), Value(Value) {}
- /// @name Accessors
+ /// \name Accessors
/// @{
const MCExpr &getOffset() const { return *Offset; }
@@ -467,13 +440,14 @@ class MCLEBFragment : public MCFragment {
bool IsSigned;
SmallString<8> Contents;
+
public:
- MCLEBFragment(const MCExpr &Value_, bool IsSigned_,
- MCSectionData *SD = nullptr)
- : MCFragment(FT_LEB, SD),
- Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); }
+ MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
+ : MCFragment(FT_LEB, Sec), Value(&Value_), IsSigned(IsSigned_) {
+ Contents.push_back(0);
+ }
- /// @name Accessors
+ /// \name Accessors
/// @{
const MCExpr &getValue() const { return *Value; }
@@ -504,12 +478,13 @@ class MCDwarfLineAddrFragment : public MCFragment {
SmallString<8> Contents;
public:
- MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta,
- MCSectionData *SD = nullptr)
- : MCFragment(FT_Dwarf, SD),
- LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); }
+ MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
+ MCSection *Sec = nullptr)
+ : MCFragment(FT_Dwarf, Sec), LineDelta(LineDelta), AddrDelta(&AddrDelta) {
+ Contents.push_back(0);
+ }
- /// @name Accessors
+ /// \name Accessors
/// @{
int64_t getLineDelta() const { return LineDelta; }
@@ -536,12 +511,12 @@ class MCDwarfCallFrameFragment : public MCFragment {
SmallString<8> Contents;
public:
- MCDwarfCallFrameFragment(const MCExpr &_AddrDelta,
- MCSectionData *SD = nullptr)
- : MCFragment(FT_DwarfFrame, SD),
- AddrDelta(&_AddrDelta) { Contents.push_back(0); }
+ MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
+ : MCFragment(FT_DwarfFrame, Sec), AddrDelta(&AddrDelta) {
+ Contents.push_back(0);
+ }
- /// @name Accessors
+ /// \name Accessors
/// @{
const MCExpr &getAddrDelta() const { return *AddrDelta; }
@@ -556,265 +531,10 @@ public:
}
};
-// FIXME: Should this be a separate class, or just merged into MCSection? Since
-// we anticipate the fast path being through an MCAssembler, the only reason to
-// keep it out is for API abstraction.
-class MCSectionData : public ilist_node<MCSectionData> {
- friend class MCAsmLayout;
-
- MCSectionData(const MCSectionData&) LLVM_DELETED_FUNCTION;
- void operator=(const MCSectionData&) LLVM_DELETED_FUNCTION;
-
-public:
- typedef iplist<MCFragment> FragmentListType;
-
- typedef FragmentListType::const_iterator const_iterator;
- typedef FragmentListType::iterator iterator;
-
- typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
- typedef FragmentListType::reverse_iterator reverse_iterator;
-
- /// \brief Express the state of bundle locked groups while emitting code.
- enum BundleLockStateType {
- NotBundleLocked,
- BundleLocked,
- BundleLockedAlignToEnd
- };
-private:
- FragmentListType Fragments;
- const MCSection *Section;
-
- /// Ordinal - The section index in the assemblers section list.
- unsigned Ordinal;
-
- /// LayoutOrder - The index of this section in the layout order.
- unsigned LayoutOrder;
-
- /// Alignment - The maximum alignment seen in this section.
- unsigned Alignment;
-
- /// \brief Keeping track of bundle-locked state.
- 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.
- bool BundleGroupBeforeFirstInst;
-
- /// @name Assembler Backend Data
- /// @{
- //
- // FIXME: This could all be kept private to the assembler implementation.
-
- /// HasInstructions - Whether this section has had instructions emitted into
- /// it.
- unsigned HasInstructions : 1;
-
- /// Mapping from subsection number to insertion point for subsection numbers
- /// below that number.
- SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
-
- /// @}
-
-public:
- // Only for use as sentinel.
- MCSectionData();
- MCSectionData(const MCSection &Section, MCAssembler *A = nullptr);
-
- const MCSection &getSection() const { return *Section; }
-
- unsigned getAlignment() const { return Alignment; }
- void setAlignment(unsigned Value) { Alignment = Value; }
-
- bool hasInstructions() const { return HasInstructions; }
- void setHasInstructions(bool Value) { HasInstructions = Value; }
-
- unsigned getOrdinal() const { return Ordinal; }
- void setOrdinal(unsigned Value) { Ordinal = Value; }
-
- unsigned getLayoutOrder() const { return LayoutOrder; }
- void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
-
- /// @name Fragment Access
- /// @{
-
- const FragmentListType &getFragmentList() const { return Fragments; }
- FragmentListType &getFragmentList() { return Fragments; }
-
- iterator begin() { return Fragments.begin(); }
- const_iterator begin() const { return Fragments.begin(); }
-
- iterator end() { return Fragments.end(); }
- const_iterator end() const { return Fragments.end(); }
-
- reverse_iterator rbegin() { return Fragments.rbegin(); }
- const_reverse_iterator rbegin() const { return Fragments.rbegin(); }
-
- reverse_iterator rend() { return Fragments.rend(); }
- const_reverse_iterator rend() const { return Fragments.rend(); }
-
- size_t size() const { return Fragments.size(); }
-
- bool empty() const { return Fragments.empty(); }
-
- iterator getSubsectionInsertionPoint(unsigned Subsection);
-
- bool isBundleLocked() const {
- return BundleLockState != NotBundleLocked;
- }
-
- BundleLockStateType getBundleLockState() const {
- return BundleLockState;
- }
-
- void setBundleLockState(BundleLockStateType NewState);
-
- bool isBundleGroupBeforeFirstInst() const {
- return BundleGroupBeforeFirstInst;
- }
-
- void setBundleGroupBeforeFirstInst(bool IsFirst) {
- BundleGroupBeforeFirstInst = IsFirst;
- }
-
- void dump();
-
- /// @}
-};
-
-// FIXME: Same concerns as with SectionData.
-class MCSymbolData : public ilist_node<MCSymbolData> {
- const MCSymbol *Symbol;
-
- /// 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;
-
- 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'.
- 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', or -1.
- //
- // FIXME: Pack this in with other fields?
- unsigned CommonAlign;
-
- /// Flags - The Flags field is used by object file implementations to store
- /// additional per symbol information which is not easily classified.
- uint32_t Flags;
-
- /// Index - Index field, for use by the object file implementation.
- uint64_t Index;
-
-public:
- // Only for use as sentinel.
- MCSymbolData();
- MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset,
- MCAssembler *A = nullptr);
-
- /// @name Accessors
- /// @{
-
- const MCSymbol &getSymbol() const { return *Symbol; }
-
- MCFragment *getFragment() const { return Fragment.getPointer(); }
- void setFragment(MCFragment *Value) { Fragment.setPointer(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 Fragment.getInt() & 1; }
- void setExternal(bool Value) {
- Fragment.setInt((Fragment.getInt() & ~1) | unsigned(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 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;
- }
-
- /// getCommonSize - Return the size of a 'common' symbol.
- uint64_t getCommonSize() const {
- assert(isCommon() && "Not a 'common' symbol!");
- return CommonSize;
- }
-
- void setSize(const MCExpr *SS) {
- SymbolSize = SS;
- }
-
- const MCExpr *getSize() const {
- return SymbolSize;
- }
-
-
- /// getCommonAlignment - Return the alignment of a 'common' symbol.
- unsigned getCommonAlignment() const {
- assert(isCommon() && "Not a 'common' symbol!");
- return CommonAlign;
- }
-
- /// getFlags - Get the (implementation defined) symbol flags.
- uint32_t getFlags() const { return Flags; }
-
- /// setFlags - Set the (implementation defined) symbol flags.
- void setFlags(uint32_t Value) { Flags = Value; }
-
- /// modifyFlags - Modify the flags via a mask
- void modifyFlags(uint32_t Value, uint32_t Mask) {
- Flags = (Flags & ~Mask) | Value;
- }
-
- /// getIndex - Get the (implementation defined) index.
- uint64_t getIndex() const { return Index; }
-
- /// setIndex - Set the (implementation defined) index.
- void setIndex(uint64_t Value) { Index = Value; }
-
- /// @}
-
- void dump() const;
-};
-
// FIXME: This really doesn't belong here. See comments below.
struct IndirectSymbolData {
MCSymbol *Symbol;
- MCSectionData *SectionData;
+ MCSection *Section;
};
// FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk
@@ -831,14 +551,15 @@ class MCAssembler {
friend class MCAsmLayout;
public:
- typedef iplist<MCSectionData> SectionDataListType;
- typedef iplist<MCSymbolData> SymbolDataListType;
+ typedef SetVector<MCSection *> SectionListType;
+ typedef std::vector<const MCSymbol *> SymbolDataListType;
- typedef SectionDataListType::const_iterator const_iterator;
- typedef SectionDataListType::iterator iterator;
+ typedef pointee_iterator<SectionListType::const_iterator> const_iterator;
+ typedef pointee_iterator<SectionListType::iterator> iterator;
- typedef SymbolDataListType::const_iterator const_symbol_iterator;
- typedef SymbolDataListType::iterator symbol_iterator;
+ typedef pointee_iterator<SymbolDataListType::const_iterator>
+ const_symbol_iterator;
+ typedef pointee_iterator<SymbolDataListType::iterator> symbol_iterator;
typedef iterator_range<symbol_iterator> symbol_range;
typedef iterator_range<const_symbol_iterator> const_symbol_range;
@@ -847,11 +568,11 @@ public:
typedef FileNameVectorType::const_iterator const_file_name_iterator;
typedef std::vector<IndirectSymbolData>::const_iterator
- const_indirect_symbol_iterator;
+ const_indirect_symbol_iterator;
typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
typedef std::vector<DataRegionData>::const_iterator
- const_data_region_iterator;
+ const_data_region_iterator;
typedef std::vector<DataRegionData>::iterator data_region_iterator;
/// MachO specific deployment target version info.
@@ -863,9 +584,10 @@ public:
unsigned Minor;
unsigned Update;
} VersionMinInfoType;
+
private:
- MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION;
- void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION;
+ MCAssembler(const MCAssembler &) = delete;
+ void operator=(const MCAssembler &) = delete;
MCContext &Context;
@@ -877,26 +599,18 @@ private:
raw_ostream &OS;
- iplist<MCSectionData> Sections;
+ SectionListType Sections;
- iplist<MCSymbolData> Symbols;
+ SymbolDataListType Symbols;
- /// The map of sections to their associated assembler backend data.
- //
- // FIXME: Avoid this indirection?
- DenseMap<const MCSection*, MCSectionData*> SectionMap;
-
- /// The map of symbols to their associated assembler backend data.
- //
- // FIXME: Avoid this indirection?
- DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap;
+ DenseSet<const MCSymbol *> LocalsUsedInReloc;
std::vector<IndirectSymbolData> IndirectSymbols;
std::vector<DataRegionData> DataRegions;
/// The list of linker options to propagate into the object file.
- std::vector<std::vector<std::string> > LinkerOptions;
+ std::vector<std::vector<std::string>> LinkerOptions;
/// List of declared file names
FileNameVectorType FileNames;
@@ -908,7 +622,7 @@ private:
// here. Maybe when the relocation stuff moves to target specific,
// this can go with it? The streamer would need some target specific
// refactoring too.
- mutable SmallPtrSet<const MCSymbol*, 64> ThumbFuncs;
+ mutable SmallPtrSet<const MCSymbol *, 64> ThumbFuncs;
/// \brief The bundle alignment size currently set in the assembler.
///
@@ -930,6 +644,7 @@ private:
MCLOHContainer LOHContainer;
VersionMinInfoType VersionMinInfo;
+
private:
/// Evaluate a fixup to a relocatable expression and the value which should be
/// placed into the fixup.
@@ -944,9 +659,9 @@ private:
/// \return Whether the fixup value was fully resolved. This is true if the
/// \p Value result is fixed, otherwise the value may change due to
/// relocation.
- bool evaluateFixup(const MCAsmLayout &Layout,
- const MCFixup &Fixup, const MCFragment *DF,
- MCValue &Target, uint64_t &Value) const;
+ bool evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup,
+ const MCFragment *DF, MCValue &Target,
+ uint64_t &Value) const;
/// Check whether a fixup can be satisfied, or whether it needs to be relaxed
/// (increased in size, in order to hold its value correctly).
@@ -963,7 +678,7 @@ private:
/// \brief Perform one layout iteration of the given section and return true
/// if any offsets were adjusted.
- bool layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD);
+ bool layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec);
bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF);
@@ -980,6 +695,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,
@@ -987,7 +705,7 @@ public:
/// Find the symbol which defines the atom containing the given symbol, or
/// null if there is no such symbol.
- const MCSymbolData *getAtom(const MCSymbolData *Symbol) const;
+ const MCSymbol *getAtom(const MCSymbol &S) const;
/// Check whether a particular symbol is visible to the linker and is required
/// in the symbol table, or whether it can be discarded by the assembler. This
@@ -996,7 +714,7 @@ public:
bool isSymbolLinkerVisible(const MCSymbol &SD) const;
/// Emit the section contents using the given object writer.
- void writeSectionData(const MCSectionData *Section,
+ void writeSectionData(const MCSection *Section,
const MCAsmLayout &Layout) const;
/// Check whether a given symbol has been flagged with .thumb_func.
@@ -1006,8 +724,8 @@ public:
void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); }
/// ELF e_header flags
- unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;}
- void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;}
+ unsigned getELFHeaderEFlags() const { return ELFHeaderEFlags; }
+ void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; }
/// MachO deployment target version information.
const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; }
@@ -1051,36 +769,25 @@ public:
void Finish();
// FIXME: This does not belong here.
- bool getSubsectionsViaSymbols() const {
- return SubsectionsViaSymbols;
- }
- void setSubsectionsViaSymbols(bool Value) {
- SubsectionsViaSymbols = Value;
- }
+ bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; }
+ void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; }
bool getRelaxAll() const { return RelaxAll; }
void setRelaxAll(bool Value) { RelaxAll = Value; }
- bool isBundlingEnabled() const {
- return BundleAlignSize != 0;
- }
+ bool isBundlingEnabled() const { return BundleAlignSize != 0; }
- unsigned getBundleAlignSize() const {
- return BundleAlignSize;
- }
+ unsigned getBundleAlignSize() const { return BundleAlignSize; }
void setBundleAlignSize(unsigned Size) {
- assert((Size == 0 || !(Size & (Size - 1))) &&
+ assert((Size == 0 || !(Size & (Size - 1))) &&
"Expect a power-of-two bundle align size");
BundleAlignSize = Size;
}
- /// @name Section List Access
+ /// \name Section List Access
/// @{
- const SectionDataListType &getSectionList() const { return Sections; }
- SectionDataListType &getSectionList() { return Sections; }
-
iterator begin() { return Sections.begin(); }
const_iterator begin() const { return Sections.begin(); }
@@ -1090,12 +797,8 @@ public:
size_t size() const { return Sections.size(); }
/// @}
- /// @name Symbol List Access
+ /// \name Symbol List Access
/// @{
-
- const SymbolDataListType &getSymbolList() const { return Symbols; }
- SymbolDataListType &getSymbolList() { return Symbols; }
-
symbol_iterator symbol_begin() { return Symbols.begin(); }
const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
@@ -1103,12 +806,14 @@ public:
const_symbol_iterator symbol_end() const { return Symbols.end(); }
symbol_range symbols() { return make_range(symbol_begin(), symbol_end()); }
- const_symbol_range symbols() const { return make_range(symbol_begin(), symbol_end()); }
+ const_symbol_range symbols() const {
+ return make_range(symbol_begin(), symbol_end());
+ }
size_t symbol_size() const { return Symbols.size(); }
/// @}
- /// @name Indirect Symbol List Access
+ /// \name Indirect Symbol List Access
/// @{
// FIXME: This is a total hack, this should not be here. Once things are
@@ -1135,34 +840,28 @@ public:
size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
/// @}
- /// @name Linker Option List Access
+ /// \name Linker Option List Access
/// @{
- std::vector<std::vector<std::string> > &getLinkerOptions() {
+ std::vector<std::vector<std::string>> &getLinkerOptions() {
return LinkerOptions;
}
/// @}
- /// @name Data Region List Access
+ /// \name Data Region List Access
/// @{
// FIXME: This is a total hack, this should not be here. Once things are
// factored so that the streamer has direct access to the .o writer, it can
// disappear.
- std::vector<DataRegionData> &getDataRegions() {
- return DataRegions;
- }
+ std::vector<DataRegionData> &getDataRegions() { return DataRegions; }
- data_region_iterator data_region_begin() {
- return DataRegions.begin();
- }
+ data_region_iterator data_region_begin() { return DataRegions.begin(); }
const_data_region_iterator data_region_begin() const {
return DataRegions.begin();
}
- data_region_iterator data_region_end() {
- return DataRegions.end();
- }
+ data_region_iterator data_region_end() { return DataRegions.end(); }
const_data_region_iterator data_region_end() const {
return DataRegions.end();
}
@@ -1170,42 +869,23 @@ public:
size_t data_region_size() const { return DataRegions.size(); }
/// @}
- /// @name Data Region List Access
+ /// \name Data Region List Access
/// @{
// FIXME: This is a total hack, this should not be here. Once things are
// factored so that the streamer has direct access to the .o writer, it can
// disappear.
- MCLOHContainer & getLOHContainer() {
- return LOHContainer;
- }
- const MCLOHContainer & getLOHContainer() const {
+ MCLOHContainer &getLOHContainer() { return LOHContainer; }
+ const MCLOHContainer &getLOHContainer() const {
return const_cast<MCAssembler *>(this)->getLOHContainer();
}
/// @}
- /// @name Backend Data Access
+ /// \name Backend Data Access
/// @{
- MCSectionData &getSectionData(const MCSection &Section) const {
- MCSectionData *Entry = SectionMap.lookup(&Section);
- assert(Entry && "Missing section data!");
- return *Entry;
- }
-
- MCSectionData &getOrCreateSectionData(const MCSection &Section,
- bool *Created = nullptr) {
- MCSectionData *&Entry = SectionMap[&Section];
+ bool registerSection(MCSection &Section) { return Sections.insert(&Section); }
- if (Created) *Created = !Entry;
- if (!Entry)
- Entry = new MCSectionData(Section, this);
-
- return *Entry;
- }
-
- bool hasSymbolData(const MCSymbol &Symbol) const {
- return SymbolMap.lookup(&Symbol) != nullptr;
- }
+ bool hasSymbolData(const MCSymbol &Symbol) const { return Symbol.hasData(); }
MCSymbolData &getSymbolData(const MCSymbol &Symbol) {
return const_cast<MCSymbolData &>(
@@ -1213,29 +893,25 @@ public:
}
const MCSymbolData &getSymbolData(const MCSymbol &Symbol) const {
- MCSymbolData *Entry = SymbolMap.lookup(&Symbol);
- assert(Entry && "Missing symbol data!");
- return *Entry;
+ return Symbol.getData();
}
MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol,
bool *Created = nullptr) {
- MCSymbolData *&Entry = SymbolMap[&Symbol];
-
- if (Created) *Created = !Entry;
- if (!Entry)
- Entry = new MCSymbolData(Symbol, nullptr, 0, this);
-
- return *Entry;
+ if (Created)
+ *Created = !hasSymbolData(Symbol);
+ if (!hasSymbolData(Symbol)) {
+ Symbol.initializeData();
+ Symbols.push_back(&Symbol);
+ }
+ return Symbol.getData();
}
const_file_name_iterator file_names_begin() const {
return FileNames.begin();
}
- const_file_name_iterator file_names_end() const {
- return FileNames.end();
- }
+ const_file_name_iterator file_names_end() const { return FileNames.end(); }
void addFileName(StringRef FileName) {
if (std::find(file_names_begin(), file_names_end(), FileName) ==
@@ -1243,11 +919,22 @@ public:
FileNames.push_back(FileName);
}
+ /// \brief Write the necessary bundle padding to the given object writer.
+ /// Expects a fragment \p F containing instructions and its size \p FSize.
+ void writeFragmentPadding(const MCFragment &F, uint64_t FSize,
+ MCObjectWriter *OW) const;
+
/// @}
void dump();
};
+/// \brief Compute the amount of padding required before the fragment \p F to
+/// obey bundling restrictions, where \p FOffset is the fragment's offset in
+/// its section and \p FSize is the fragment's size.
+uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F,
+ uint64_t FOffset, uint64_t FSize);
+
} // end namespace llvm
#endif
diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h
index d3b56177d50a..b6c19150c12a 100644
--- a/include/llvm/MC/MCCodeEmitter.h
+++ b/include/llvm/MC/MCCodeEmitter.h
@@ -22,8 +22,9 @@ template<typename T> class SmallVectorImpl;
/// MCCodeEmitter - Generic instruction encoding interface.
class MCCodeEmitter {
private:
- MCCodeEmitter(const MCCodeEmitter &) LLVM_DELETED_FUNCTION;
- void operator=(const MCCodeEmitter &) LLVM_DELETED_FUNCTION;
+ MCCodeEmitter(const MCCodeEmitter &) = delete;
+ void operator=(const MCCodeEmitter &) = delete;
+
protected: // Can only create subclasses.
MCCodeEmitter();
@@ -31,11 +32,11 @@ public:
virtual ~MCCodeEmitter();
/// Lifetime management
- virtual void reset() { }
+ virtual void reset() {}
/// EncodeInstruction - Encode the given \p Inst to bytes on the output
/// stream \p OS.
- virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS,
+ virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const = 0;
};
diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h
index 84ce934d822e..0a4744f1d0f7 100644
--- a/include/llvm/MC/MCCodeGenInfo.h
+++ b/include/llvm/MC/MCCodeGenInfo.h
@@ -19,33 +19,33 @@
namespace llvm {
- class MCCodeGenInfo {
- /// RelocationModel - Relocation model: static, pic, etc.
- ///
- Reloc::Model RelocationModel;
+class MCCodeGenInfo {
+ /// RelocationModel - Relocation model: static, pic, etc.
+ ///
+ Reloc::Model RelocationModel;
- /// CMModel - Code model.
- ///
- CodeModel::Model CMModel;
+ /// CMModel - Code model.
+ ///
+ CodeModel::Model CMModel;
- /// OptLevel - Optimization level.
- ///
- CodeGenOpt::Level OptLevel;
+ /// OptLevel - Optimization level.
+ ///
+ CodeGenOpt::Level OptLevel;
- public:
- void InitMCCodeGenInfo(Reloc::Model RM = Reloc::Default,
- CodeModel::Model CM = CodeModel::Default,
- CodeGenOpt::Level OL = CodeGenOpt::Default);
+public:
+ void initMCCodeGenInfo(Reloc::Model RM = Reloc::Default,
+ CodeModel::Model CM = CodeModel::Default,
+ CodeGenOpt::Level OL = CodeGenOpt::Default);
- Reloc::Model getRelocationModel() const { return RelocationModel; }
+ Reloc::Model getRelocationModel() const { return RelocationModel; }
- CodeModel::Model getCodeModel() const { return CMModel; }
+ CodeModel::Model getCodeModel() const { return CMModel; }
- CodeGenOpt::Level getOptLevel() const { return OptLevel; }
+ CodeGenOpt::Level getOptLevel() const { return OptLevel; }
- // Allow overriding OptLevel on a per-function basis.
- void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; }
- };
+ // Allow overriding OptLevel on a per-function basis.
+ void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; }
+};
} // namespace llvm
#endif
diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h
index e3163a7946a7..5b57b9d448e8 100644
--- a/include/llvm/MC/MCContext.h
+++ b/include/llvm/MC/MCContext.h
@@ -15,8 +15,8 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
@@ -37,20 +37,20 @@ namespace llvm {
class MCRegisterInfo;
class MCLineSection;
class SMLoc;
- class StringRef;
- class Twine;
class MCSectionMachO;
class MCSectionELF;
class MCSectionCOFF;
- /// MCContext - Context object for machine code objects. This class owns all
- /// of the sections that it creates.
+ /// Context object for machine code objects. This class owns all of the
+ /// sections that it creates.
///
class MCContext {
- MCContext(const MCContext&) LLVM_DELETED_FUNCTION;
- MCContext &operator=(const MCContext&) LLVM_DELETED_FUNCTION;
+ MCContext(const MCContext &) = delete;
+ MCContext &operator=(const MCContext &) = delete;
+
public:
- typedef StringMap<MCSymbol*, BumpPtrAllocator&> SymbolTable;
+ typedef StringMap<MCSymbol *, BumpPtrAllocator &> SymbolTable;
+
private:
/// The SourceMgr for this object, if any.
const SourceMgr *SrcMgr;
@@ -64,34 +64,34 @@ namespace llvm {
/// The MCObjectFileInfo for this target.
const MCObjectFileInfo *MOFI;
- /// Allocator - Allocator object used for creating machine code objects.
+ /// Allocator object used for creating machine code objects.
///
/// We use a bump pointer allocator to avoid the need to track all allocated
/// objects.
BumpPtrAllocator Allocator;
- /// Symbols - Bindings of names to 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;
+ DenseMap<const MCSectionELF *, MCSymbol *> SectionSymbols;
- /// A maping from a local label number and an instance count to a symbol.
+ /// A mapping from a local label number and an instance count to a symbol.
/// For example, in the assembly
/// 1:
/// 2:
/// 1:
/// We have three labels represented by the pairs (1, 0), (2, 0) and (1, 1)
- DenseMap<std::pair<unsigned, unsigned>, MCSymbol*> LocalSymbols;
+ DenseMap<std::pair<unsigned, unsigned>, MCSymbol *> LocalSymbols;
- /// UsedNames - Keeps tracks of names that were used both for used declared
- /// and artificial symbols.
- StringMap<bool, BumpPtrAllocator&> UsedNames;
+ /// Keeps tracks of names that were used both for used declared and
+ /// artificial symbols.
+ StringMap<bool, BumpPtrAllocator &> UsedNames;
- /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary
- /// symbol.
- unsigned NextUniqueID;
+ /// The next ID to dole out to an unnamed assembler temporary symbol with
+ /// a given prefix.
+ StringMap<unsigned> NextID;
/// Instances of directional local labels.
DenseMap<unsigned, MCLabel *> Instances;
@@ -136,10 +136,8 @@ namespace llvm {
/// assembly source files.
unsigned GenDwarfFileNumber;
- /// Symbols created for the start and end of each section, used for
- /// generating the .debug_ranges and .debug_aranges sections.
- MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> >
- SectionStartEndSyms;
+ /// Sections for generating the .debug_ranges and .debug_aranges sections.
+ SetVector<MCSection *> SectionsForRanges;
/// The information gathered from labels that will have dwarf label
/// entries when generating dwarf assembly source files.
@@ -160,21 +158,54 @@ namespace llvm {
/// differences between temporary and non-temporary labels (primarily on
/// Darwin).
bool AllowTemporaryLabels;
+ bool UseNamesOnTempLabels = true;
/// The Compile Unit ID that we are currently processing.
unsigned DwarfCompileUnitID;
- typedef std::pair<std::string, std::string> SectionGroupPair;
- typedef std::tuple<std::string, std::string, int> SectionGroupTriple;
-
- StringMap<const MCSectionMachO*> MachOUniquingMap;
- std::map<SectionGroupPair, const MCSectionELF *> ELFUniquingMap;
- std::map<SectionGroupTriple, const MCSectionCOFF *> COFFUniquingMap;
+ struct ELFSectionKey {
+ std::string SectionName;
+ StringRef GroupName;
+ unsigned UniqueID;
+ ELFSectionKey(StringRef SectionName, StringRef GroupName,
+ unsigned UniqueID)
+ : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) {
+ }
+ bool operator<(const ELFSectionKey &Other) const {
+ if (SectionName != Other.SectionName)
+ return SectionName < Other.SectionName;
+ if (GroupName != Other.GroupName)
+ return GroupName < Other.GroupName;
+ return UniqueID < Other.UniqueID;
+ }
+ };
+
+ struct COFFSectionKey {
+ std::string SectionName;
+ StringRef GroupName;
+ int SelectionKey;
+ COFFSectionKey(StringRef SectionName, StringRef GroupName,
+ int SelectionKey)
+ : SectionName(SectionName), GroupName(GroupName),
+ SelectionKey(SelectionKey) {}
+ bool operator<(const COFFSectionKey &Other) const {
+ if (SectionName != Other.SectionName)
+ return SectionName < Other.SectionName;
+ if (GroupName != Other.GroupName)
+ return GroupName < Other.GroupName;
+ return SelectionKey < Other.SelectionKey;
+ }
+ };
+
+ StringMap<MCSectionMachO *> MachOUniquingMap;
+ std::map<ELFSectionKey, MCSectionELF *> ELFUniquingMap;
+ std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap;
+ StringMap<bool> ELFRelSecNames;
/// Do automatic reset in destructor
bool AutoReset;
- MCSymbol *CreateSymbol(StringRef Name);
+ MCSymbol *CreateSymbol(StringRef Name, bool AlwaysAddSuffix);
MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal,
unsigned Instance);
@@ -194,8 +225,9 @@ namespace llvm {
const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; }
void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; }
+ void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; }
- /// @name Module Lifetime Management
+ /// \name Module Lifetime Management
/// @{
/// reset - return object to right after construction state to prepare
@@ -204,104 +236,144 @@ namespace llvm {
/// @}
- /// @name Symbol Management
+ /// \name Symbol Management
/// @{
- /// CreateLinkerPrivateTempSymbol - Create and return a new linker temporary
- /// symbol with a unique but unspecified name.
- MCSymbol *CreateLinkerPrivateTempSymbol();
+ /// Create and return a new linker temporary symbol with a unique but
+ /// unspecified name.
+ MCSymbol *createLinkerPrivateTempSymbol();
- /// CreateTempSymbol - Create and return a new assembler temporary symbol
- /// with a unique but unspecified name.
- MCSymbol *CreateTempSymbol();
+ /// Create and return a new assembler temporary symbol with a unique but
+ /// unspecified name.
+ MCSymbol *createTempSymbol();
- /// getUniqueSymbolID() - Return a unique identifier for use in constructing
- /// symbol names.
- unsigned getUniqueSymbolID() { return NextUniqueID++; }
+ MCSymbol *createTempSymbol(const Twine &Name, bool AlwaysAddSuffix);
/// Create the definition of a directional local symbol for numbered label
/// (used for "1:" definitions).
- MCSymbol *CreateDirectionalLocalSymbol(unsigned LocalLabelVal);
+ MCSymbol *createDirectionalLocalSymbol(unsigned LocalLabelVal);
/// Create and return a directional local symbol for numbered label (used
/// for "1b" or 1f" references).
- MCSymbol *GetDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before);
+ MCSymbol *getDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before);
- /// GetOrCreateSymbol - Lookup the symbol inside with the specified
- /// @p Name. If it exists, return it. If not, create a forward
- /// reference and return it.
+ /// Lookup the symbol inside with the specified \p Name. If it exists,
+ /// return it. If not, create a forward reference and return it.
///
- /// @param Name - The symbol name, which must be unique across all symbols.
- MCSymbol *GetOrCreateSymbol(StringRef Name);
- MCSymbol *GetOrCreateSymbol(const Twine &Name);
+ /// \param Name - The symbol name, which must be unique across all symbols.
+ MCSymbol *getOrCreateSymbol(const Twine &Name);
MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section);
- MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName);
+ /// Gets a symbol that will be defined to the final stack offset of a local
+ /// variable after codegen.
+ ///
+ /// \param Idx - The index of a local variable passed to @llvm.frameescape.
+ MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx);
+
+ MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName);
+
+ MCSymbol *getOrCreateLSDASymbol(StringRef FuncName);
- /// LookupSymbol - Get the symbol for \p Name, or null.
- MCSymbol *LookupSymbol(StringRef Name) const;
- MCSymbol *LookupSymbol(const Twine &Name) const;
+ /// Get the symbol for \p Name, or null.
+ MCSymbol *lookupSymbol(const Twine &Name) const;
/// getSymbols - Get a reference for the symbol table for clients that
/// want to, for example, iterate over all symbols. 'const' because we
/// still want any modifications to the table itself to use the MCContext
/// APIs.
- const SymbolTable &getSymbols() const {
- return Symbols;
- }
+ const SymbolTable &getSymbols() const { return Symbols; }
/// @}
- /// @name Section Management
+ /// \name Section Management
/// @{
- /// getMachOSection - Return the MCSection for the specified mach-o section.
- /// This requires the operands to be valid.
- const MCSectionMachO *getMachOSection(StringRef Segment,
- StringRef Section,
- unsigned TypeAndAttributes,
- unsigned Reserved2,
- SectionKind K);
- const MCSectionMachO *getMachOSection(StringRef Segment,
- StringRef Section,
- unsigned TypeAndAttributes,
- SectionKind K) {
- return getMachOSection(Segment, Section, TypeAndAttributes, 0, K);
+ /// Return the MCSection for the specified mach-o section. This requires
+ /// the operands to be valid.
+ MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section,
+ unsigned TypeAndAttributes,
+ unsigned Reserved2, SectionKind K,
+ const char *BeginSymName = nullptr);
+
+ MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section,
+ unsigned TypeAndAttributes, SectionKind K,
+ const char *BeginSymName = nullptr) {
+ return getMachOSection(Segment, Section, TypeAndAttributes, 0, K,
+ BeginSymName);
}
- const MCSectionELF *getELFSection(StringRef Section, unsigned Type,
- unsigned Flags, SectionKind Kind);
+ MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ unsigned Flags) {
+ return getELFSection(Section, Type, Flags, nullptr);
+ }
- const MCSectionELF *getELFSection(StringRef Section, unsigned Type,
- unsigned Flags, SectionKind Kind,
- unsigned EntrySize, StringRef Group);
+ MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ unsigned Flags, const char *BeginSymName) {
+ return getELFSection(Section, Type, Flags, 0, "", BeginSymName);
+ }
- void renameELFSection(const MCSectionELF *Section, StringRef Name);
+ MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ unsigned Flags, unsigned EntrySize,
+ StringRef Group) {
+ return getELFSection(Section, Type, Flags, EntrySize, Group, nullptr);
+ }
- const MCSectionELF *CreateELFGroupSection();
+ MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ unsigned Flags, unsigned EntrySize,
+ StringRef Group, const char *BeginSymName) {
+ return getELFSection(Section, Type, Flags, EntrySize, Group, ~0,
+ BeginSymName);
+ }
- const MCSectionCOFF *getCOFFSection(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind,
- StringRef COMDATSymName, int Selection);
+ MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ unsigned Flags, unsigned EntrySize,
+ StringRef Group, unsigned UniqueID) {
+ return getELFSection(Section, Type, Flags, EntrySize, Group, UniqueID,
+ nullptr);
+ }
- const MCSectionCOFF *getCOFFSection(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind);
+ MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ unsigned Flags, unsigned EntrySize,
+ StringRef Group, unsigned UniqueID,
+ const char *BeginSymName);
- const MCSectionCOFF *getCOFFSection(StringRef Section);
+ MCSectionELF *getELFSection(StringRef Section, unsigned Type,
+ unsigned Flags, unsigned EntrySize,
+ const MCSymbol *Group, unsigned UniqueID,
+ const char *BeginSymName,
+ const MCSectionELF *Associated);
+
+ MCSectionELF *createELFRelSection(StringRef Name, unsigned Type,
+ unsigned Flags, unsigned EntrySize,
+ const MCSymbol *Group,
+ const MCSectionELF *Associated);
+
+ void renameELFSection(MCSectionELF *Section, StringRef Name);
+
+ MCSectionELF *createELFGroupSection(const MCSymbol *Group);
+
+ MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
+ SectionKind Kind, StringRef COMDATSymName,
+ int Selection,
+ const char *BeginSymName = nullptr);
+
+ MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
+ SectionKind Kind,
+ const char *BeginSymName = nullptr);
+
+ 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);
+ MCSectionCOFF *getAssociativeCOFFSection(MCSectionCOFF *Sec,
+ const MCSymbol *KeySym);
/// @}
- /// @name Dwarf Management
+ /// \name Dwarf Management
/// @{
/// \brief Get the compilation directory for DW_AT_comp_dir
@@ -323,8 +395,8 @@ namespace llvm {
/// \brief Set the main file name and override the default.
void setMainFileName(StringRef S) { MainFileName = S; }
- /// GetDwarfFile - creates an entry in the dwarf file and directory tables.
- unsigned GetDwarfFile(StringRef Directory, StringRef FileName,
+ /// Creates an entry in the dwarf file and directory tables.
+ unsigned getDwarfFile(StringRef Directory, StringRef FileName,
unsigned FileNumber, unsigned CUID);
bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0);
@@ -356,9 +428,7 @@ namespace llvm {
return true;
return false;
}
- unsigned getDwarfCompileUnitID() {
- return DwarfCompileUnitID;
- }
+ unsigned getDwarfCompileUnitID() { return DwarfCompileUnitID; }
void setDwarfCompileUnitID(unsigned CUIndex) {
DwarfCompileUnitID = CUIndex;
}
@@ -366,10 +436,10 @@ namespace llvm {
getMCDwarfLineTable(CUID).setCompilationDir(CompilationDir);
}
- /// setCurrentDwarfLoc - saves the information from the currently parsed
- /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction
- /// is assembled an entry in the line number table with this information and
- /// the address of the instruction will be created.
+ /// Saves the information from the currently parsed dwarf .loc directive
+ /// and sets DwarfLocSeen. When the next instruction is assembled an entry
+ /// in the line number table with this information and the address of the
+ /// instruction will be created.
void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column,
unsigned Flags, unsigned Isa,
unsigned Discriminator) {
@@ -381,7 +451,7 @@ namespace llvm {
CurrentDwarfLoc.setDiscriminator(Discriminator);
DwarfLocSeen = true;
}
- void ClearDwarfLocSeen() { DwarfLocSeen = false; }
+ void clearDwarfLocSeen() { DwarfLocSeen = false; }
bool getDwarfLocSeen() { return DwarfLocSeen; }
const MCDwarfLoc &getCurrentDwarfLoc() { return CurrentDwarfLoc; }
@@ -392,17 +462,13 @@ namespace llvm {
void setGenDwarfFileNumber(unsigned FileNumber) {
GenDwarfFileNumber = FileNumber;
}
- MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > &
- getGenDwarfSectionSyms() {
- return SectionStartEndSyms;
+ const SetVector<MCSection *> &getGenDwarfSectionSyms() {
+ return SectionsForRanges;
}
- std::pair<MapVector<const MCSection *,
- std::pair<MCSymbol *, MCSymbol *> >::iterator,
- bool>
- addGenDwarfSection(const MCSection *Sec) {
- return SectionStartEndSyms.insert(
- std::make_pair(Sec, std::make_pair(nullptr, nullptr)));
+ bool addGenDwarfSection(MCSection *Sec) {
+ return SectionsForRanges.insert(Sec);
}
+
void finalizeDwarfSections(MCStreamer &MCOS);
const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const {
return MCGenDwarfLabelEntries;
@@ -425,56 +491,52 @@ namespace llvm {
char *getSecureLogFile() { return SecureLogFile; }
raw_ostream *getSecureLog() { return SecureLog; }
bool getSecureLogUsed() { return SecureLogUsed; }
- void setSecureLog(raw_ostream *Value) {
- SecureLog = Value;
- }
- void setSecureLogUsed(bool Value) {
- SecureLogUsed = Value;
- }
+ void setSecureLog(raw_ostream *Value) { SecureLog = Value; }
+ void setSecureLogUsed(bool Value) { SecureLogUsed = Value; }
- void *Allocate(unsigned Size, unsigned Align = 8) {
+ void *allocate(unsigned Size, unsigned Align = 8) {
return Allocator.Allocate(Size, Align);
}
- void Deallocate(void *Ptr) {
- }
+ void deallocate(void *Ptr) {}
// Unrecoverable error has occurred. Display the best diagnostic we can
// and bail via exit(1). For now, most MC backend errors are unrecoverable.
// FIXME: We should really do something about that.
- LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg) const;
+ LLVM_ATTRIBUTE_NORETURN void reportFatalError(SMLoc L,
+ const Twine &Msg) const;
};
} // end namespace llvm
// operator new and delete aren't allowed inside namespaces.
// The throw specifications are mandated by the standard.
-/// @brief Placement new for using the MCContext's allocator.
+/// \brief Placement new for using the MCContext's allocator.
///
/// This placement form of operator new uses the MCContext's allocator for
/// obtaining memory. It is a non-throwing new, which means that it returns
/// null on error. (If that is what the allocator does. The current does, so if
/// this ever changes, this operator will have to be changed, too.)
/// Usage looks like this (assuming there's an MCContext 'Context' in scope):
-/// @code
-/// // Default alignment (16)
+/// \code
+/// // Default alignment (8)
/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments);
/// // Specific alignment
-/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments);
-/// @endcode
+/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments);
+/// \endcode
/// Please note that you cannot use delete on the pointer; it must be
/// deallocated using an explicit destructor call followed by
-/// @c Context.Deallocate(Ptr).
+/// \c Context.Deallocate(Ptr).
///
-/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
-/// @param C The MCContext that provides the allocator.
-/// @param Alignment The alignment of the allocated memory (if the underlying
+/// \param Bytes The number of bytes to allocate. Calculated by the compiler.
+/// \param C The MCContext that provides the allocator.
+/// \param Alignment The alignment of the allocated memory (if the underlying
/// allocator supports it).
-/// @return The allocated memory. Could be NULL.
+/// \return The allocated memory. Could be NULL.
inline void *operator new(size_t Bytes, llvm::MCContext &C,
- size_t Alignment = 16) throw () {
- return C.Allocate(Bytes, Alignment);
+ size_t Alignment = 8) throw() {
+ return C.allocate(Bytes, Alignment);
}
-/// @brief Placement delete companion to the new above.
+/// \brief Placement delete companion to the new above.
///
/// This operator is just a companion to the new above. There is no way of
/// invoking it directly; see the new operator for more details. This operator
@@ -482,41 +544,41 @@ inline void *operator new(size_t Bytes, llvm::MCContext &C,
/// the MCContext throws in the object constructor.
inline void operator delete(void *Ptr, llvm::MCContext &C, size_t)
throw () {
- C.Deallocate(Ptr);
+ C.deallocate(Ptr);
}
/// This placement form of operator new[] uses the MCContext's allocator for
/// obtaining memory. It is a non-throwing new[], which means that it returns
/// null on error.
/// Usage looks like this (assuming there's an MCContext 'Context' in scope):
-/// @code
-/// // Default alignment (16)
+/// \code
+/// // Default alignment (8)
/// char *data = new (Context) char[10];
/// // Specific alignment
-/// char *data = new (Context, 8) char[10];
-/// @endcode
+/// char *data = new (Context, 4) char[10];
+/// \endcode
/// Please note that you cannot use delete on the pointer; it must be
/// deallocated using an explicit destructor call followed by
-/// @c Context.Deallocate(Ptr).
+/// \c Context.Deallocate(Ptr).
///
-/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
-/// @param C The MCContext that provides the allocator.
-/// @param Alignment The alignment of the allocated memory (if the underlying
+/// \param Bytes The number of bytes to allocate. Calculated by the compiler.
+/// \param C The MCContext that provides the allocator.
+/// \param Alignment The alignment of the allocated memory (if the underlying
/// allocator supports it).
-/// @return The allocated memory. Could be NULL.
+/// \return The allocated memory. Could be NULL.
inline void *operator new[](size_t Bytes, llvm::MCContext& C,
- size_t Alignment = 16) throw () {
- return C.Allocate(Bytes, Alignment);
+ size_t Alignment = 8) throw() {
+ return C.allocate(Bytes, Alignment);
}
-/// @brief Placement delete[] companion to the new[] above.
+/// \brief Placement delete[] companion to the new[] above.
///
/// This operator is just a companion to the new[] above. There is no way of
/// invoking it directly; see the new[] operator for more details. This operator
/// is called implicitly by the compiler if a placement new[] expression using
/// the MCContext throws in the object constructor.
inline void operator delete[](void *Ptr, llvm::MCContext &C) throw () {
- C.Deallocate(Ptr);
+ C.deallocate(Ptr);
}
#endif
diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h
index d6b0a305b1da..57c40d660f64 100644
--- a/include/llvm/MC/MCDisassembler.h
+++ b/include/llvm/MC/MCDisassembler.h
@@ -11,7 +11,6 @@
#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"
@@ -61,16 +60,16 @@ public:
/// 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 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.
- /// @return - MCDisassembler::Success if the instruction is valid,
+ /// \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.
diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h
index c266acf2f09c..c7bed8eccda9 100644
--- a/include/llvm/MC/MCDwarf.h
+++ b/include/llvm/MC/MCDwarf.h
@@ -37,34 +37,29 @@ class MCSymbol;
class SourceMgr;
class SMLoc;
-/// MCDwarfFile - Instances of this class represent the name of the dwarf
+/// \brief Instances of this class represent the name of the dwarf
/// .file directive and its associated dwarf file number in the MC file,
-/// and MCDwarfFile's are created and unique'd by the MCContext class where
+/// and MCDwarfFile's are created and uniqued by the MCContext class where
/// the file number for each is its index into the vector of DwarfFiles (note
/// index 0 is not used and not a valid dwarf file number).
struct MCDwarfFile {
- // Name - the base name of the file without its directory path.
+ // \brief The base name of the file without its directory path.
// The StringRef references memory allocated in the MCContext.
std::string Name;
- // DirIndex - the index into the list of directory names for this file name.
+ // \brief The index into the list of directory names for this file name.
unsigned DirIndex;
};
-/// MCDwarfLoc - Instances of this class represent the information from a
+/// \brief Instances of this class represent the information from a
/// dwarf .loc directive.
class MCDwarfLoc {
- // FileNum - the file number.
unsigned FileNum;
- // Line - the line number.
unsigned Line;
- // Column - the column position.
unsigned Column;
// Flags (see #define's below)
unsigned Flags;
- // Isa
unsigned Isa;
- // Discriminator
unsigned Discriminator;
// Flag that indicates the initial value of the is_stmt_start flag.
@@ -87,46 +82,46 @@ private: // MCContext manages these
// for an MCDwarfLoc object.
public:
- /// getFileNum - Get the FileNum of this MCDwarfLoc.
+ /// \brief Get the FileNum of this MCDwarfLoc.
unsigned getFileNum() const { return FileNum; }
- /// getLine - Get the Line of this MCDwarfLoc.
+ /// \brief Get the Line of this MCDwarfLoc.
unsigned getLine() const { return Line; }
- /// getColumn - Get the Column of this MCDwarfLoc.
+ /// \brief Get the Column of this MCDwarfLoc.
unsigned getColumn() const { return Column; }
- /// getFlags - Get the Flags of this MCDwarfLoc.
+ /// \brief Get the Flags of this MCDwarfLoc.
unsigned getFlags() const { return Flags; }
- /// getIsa - Get the Isa of this MCDwarfLoc.
+ /// \brief Get the Isa of this MCDwarfLoc.
unsigned getIsa() const { return Isa; }
- /// getDiscriminator - Get the Discriminator of this MCDwarfLoc.
+ /// \brief Get the Discriminator of this MCDwarfLoc.
unsigned getDiscriminator() const { return Discriminator; }
- /// setFileNum - Set the FileNum of this MCDwarfLoc.
+ /// \brief Set the FileNum of this MCDwarfLoc.
void setFileNum(unsigned fileNum) { FileNum = fileNum; }
- /// setLine - Set the Line of this MCDwarfLoc.
+ /// \brief Set the Line of this MCDwarfLoc.
void setLine(unsigned line) { Line = line; }
- /// setColumn - Set the Column of this MCDwarfLoc.
+ /// \brief Set the Column of this MCDwarfLoc.
void setColumn(unsigned column) { Column = column; }
- /// setFlags - Set the Flags of this MCDwarfLoc.
+ /// \brief Set the Flags of this MCDwarfLoc.
void setFlags(unsigned flags) { Flags = flags; }
- /// setIsa - Set the Isa of this MCDwarfLoc.
+ /// \brief Set the Isa of this MCDwarfLoc.
void setIsa(unsigned isa) { Isa = isa; }
- /// setDiscriminator - Set the Discriminator of this MCDwarfLoc.
+ /// \brief Set the Discriminator of this MCDwarfLoc.
void setDiscriminator(unsigned discriminator) {
Discriminator = discriminator;
}
};
-/// MCLineEntry - Instances of this class represent the line information for
+/// \brief Instances of this class represent the line information for
/// the dwarf line table entries. Which is created after a machine
/// instruction is assembled and uses an address from a temporary label
/// created at the current address in the current section and the info from
@@ -148,24 +143,24 @@ public:
// This is called when an instruction is assembled into the specified
// section and if there is information from the last .loc directive that
// has yet to have a line entry made for it is made.
- static void Make(MCObjectStreamer *MCOS, const MCSection *Section);
+ static void Make(MCObjectStreamer *MCOS, MCSection *Section);
};
-/// MCLineSection - Instances of this class represent the line information
-/// for a compile unit where machine instructions have been assembled after seeing
-/// .loc directives. This is the information used to build the dwarf line
+/// \brief Instances of this class represent the line information for a compile
+/// unit where machine instructions have been assembled after seeing .loc
+/// directives. This is the information used to build the dwarf line
/// table for a section.
class MCLineSection {
public:
- // addLineEntry - adds an entry to this MCLineSection's line entries
- void addLineEntry(const MCLineEntry &LineEntry, const MCSection *Sec) {
+ // \brief Add an entry to this MCLineSection's line entries.
+ void addLineEntry(const MCLineEntry &LineEntry, MCSection *Sec) {
MCLineDivisions[Sec].push_back(LineEntry);
}
typedef std::vector<MCLineEntry> MCLineEntryCollection;
typedef MCLineEntryCollection::iterator iterator;
typedef MCLineEntryCollection::const_iterator const_iterator;
- typedef MapVector<const MCSection *, MCLineEntryCollection> MCLineDivisionMap;
+ typedef MapVector<MCSection *, MCLineEntryCollection> MCLineDivisionMap;
private:
// A collection of MCLineEntry for each section.
diff --git a/include/llvm/MC/MCELF.h b/include/llvm/MC/MCELF.h
index 294a51bf7c76..f409988d5726 100644
--- a/include/llvm/MC/MCELF.h
+++ b/include/llvm/MC/MCELF.h
@@ -15,8 +15,6 @@
#ifndef LLVM_MC_MCELF_H
#define LLVM_MC_MCELF_H
-#include "llvm/MC/MCExpr.h"
-
namespace llvm {
class MCSymbolData;
diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h
index 421e7a0b2c19..cf73eca340d7 100644
--- a/include/llvm/MC/MCELFObjectWriter.h
+++ b/include/llvm/MC/MCELFObjectWriter.h
@@ -20,10 +20,21 @@ class MCAssembler;
class MCFixup;
class MCFragment;
class MCObjectWriter;
-class MCSectionData;
class MCSymbol;
class MCSymbolData;
class MCValue;
+class raw_pwrite_stream;
+
+struct ELFRelocationEntry {
+ uint64_t Offset; // Where is the relocation.
+ const MCSymbol *Symbol; // The symbol to relocate with.
+ unsigned Type; // The type of the relocation.
+ uint64_t Addend; // The addend to use.
+
+ ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type,
+ uint64_t Addend)
+ : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
+};
class MCELFObjectTargetWriter {
const uint8_t OSABI;
@@ -41,6 +52,9 @@ protected:
public:
static uint8_t getOSABI(Triple::OSType OSType) {
switch (OSType) {
+ case Triple::CloudABI:
+ return ELF::ELFOSABI_CLOUDABI;
+ case Triple::PS4:
case Triple::FreeBSD:
return ELF::ELFOSABI_FREEBSD;
case Triple::Linux:
@@ -58,7 +72,10 @@ public:
virtual bool needsRelocateWithSymbol(const MCSymbolData &SD,
unsigned Type) const;
- /// @name Accessors
+ virtual void sortRelocs(const MCAssembler &Asm,
+ std::vector<ELFRelocationEntry> &Relocs);
+
+ /// \name Accessors
/// @{
uint8_t getOSABI() const { return OSABI; }
uint16_t getEMachine() const { return EMachine; }
@@ -113,7 +130,8 @@ public:
/// \param OS - The stream to write to.
/// \returns The constructed object writer.
MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
- raw_ostream &OS, bool IsLittleEndian);
+ raw_pwrite_stream &OS,
+ bool IsLittleEndian);
} // End llvm namespace
#endif
diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h
index ab6c5e3d6124..97058f5e9981 100644
--- a/include/llvm/MC/MCELFStreamer.h
+++ b/include/llvm/MC/MCELFStreamer.h
@@ -29,32 +29,26 @@ class raw_ostream;
class MCELFStreamer : public MCObjectStreamer {
public:
- MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
+ MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS,
MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter),
- SeenIdent(false) {}
+ : MCObjectStreamer(Context, TAB, OS, Emitter), SeenIdent(false) {}
- MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
- MCCodeEmitter *Emitter, MCAssembler *Assembler)
- : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler),
- SeenIdent(false) {}
-
- virtual ~MCELFStreamer();
+ ~MCELFStreamer() override;
/// state management
void reset() override {
+ SeenIdent = false;
LocalCommons.clear();
BindingExplicitlySet.clear();
- SeenIdent = false;
+ BundleGroups.clear();
MCObjectStreamer::reset();
}
- /// @name MCStreamer Interface
+ /// \name MCStreamer Interface
/// @{
void InitSections(bool NoExecStack) override;
- void ChangeSection(const MCSection *Section,
- const MCExpr *Subsection) override;
+ void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
void EmitLabel(MCSymbol *Symbol) override;
void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
void EmitThumbFunc(MCSymbol *Func) override;
@@ -73,10 +67,10 @@ public:
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr,
+ void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
uint64_t Size = 0, unsigned ByteAlignment = 0) override;
- void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment = 0) override;
+ void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment = 0) override;
void EmitValueImpl(const MCExpr *Value, unsigned Size,
const SMLoc &Loc = SMLoc()) override;
@@ -95,15 +89,19 @@ public:
void EmitBundleUnlock() override;
private:
+ bool isBundleLocked() const;
void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override;
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
void fixSymbolsInTLSFixups(const MCExpr *expr);
+ /// \brief Merge the content of the fragment \p EF into the fragment \p DF.
+ void mergeFragment(MCDataFragment *, MCEncodedFragmentWithFixups *);
+
bool SeenIdent;
struct LocalCommon {
- MCSymbolData *SD;
+ const MCSymbol *Symbol;
uint64_t Size;
unsigned ByteAlignment;
};
@@ -111,11 +109,16 @@ private:
std::vector<LocalCommon> LocalCommons;
SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet;
+
+ /// BundleGroups - The stack of fragments holding the bundle-locked
+ /// instructions.
+ llvm::SmallVector<MCDataFragment *, 4> BundleGroups;
};
MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
- raw_ostream &OS, MCCodeEmitter *Emitter,
- bool RelaxAll, bool IsThumb);
+ raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter, bool RelaxAll,
+ bool IsThumb);
} // end namespace llvm
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index bd9b2bc4751a..b38ad7daee3e 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -21,15 +21,14 @@ class MCAssembler;
class MCContext;
class MCFixup;
class MCSection;
-class MCSectionData;
class MCStreamer;
class MCSymbol;
class MCValue;
class raw_ostream;
class StringRef;
-typedef DenseMap<const MCSectionData*, uint64_t> SectionAddrMap;
+typedef DenseMap<const MCSection *, uint64_t> SectionAddrMap;
-/// MCExpr - Base class for the full range of assembler expressions which are
+/// \brief Base class for the full range of assembler expressions which are
/// needed for parsing.
class MCExpr {
public:
@@ -44,8 +43,8 @@ public:
private:
ExprKind Kind;
- MCExpr(const MCExpr&) LLVM_DELETED_FUNCTION;
- void operator=(const MCExpr&) LLVM_DELETED_FUNCTION;
+ MCExpr(const MCExpr&) = delete;
+ void operator=(const MCExpr&) = delete;
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
@@ -56,53 +55,52 @@ private:
const SectionAddrMap *Addrs, bool InSet) const;
protected:
- explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {}
+ 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;
+ const SectionAddrMap *Addrs, bool InSet) const;
public:
- /// @name Accessors
+ /// \name Accessors
/// @{
ExprKind getKind() const { return Kind; }
/// @}
- /// @name Utility Methods
+ /// \name Utility Methods
/// @{
void print(raw_ostream &OS) const;
void dump() const;
/// @}
- /// @name Expression Evaluation
+ /// \name Expression Evaluation
/// @{
- /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value.
+ /// \brief Try to evaluate the expression to an absolute value.
///
- /// @param Res - The absolute value, if evaluation succeeds.
- /// @param Layout - The assembler layout object to use for evaluating symbol
+ /// \param Res - The absolute value, if evaluation succeeds.
+ /// \param Layout - The assembler layout object to use for evaluating symbol
/// values. If not given, then only non-symbolic expressions will be
/// evaluated.
- /// @result - True on success.
+ /// \return - True on success.
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout,
const SectionAddrMap &Addrs) const;
bool EvaluateAsAbsolute(int64_t &Res) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
- int64_t evaluateKnownAbsolute(const MCAsmLayout &Layout) const;
+ bool evaluateKnownAbsolute(int64_t &Res, 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).
+ /// \brief 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.
+ /// \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.
+ /// \return - True on success.
bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
const MCFixup *Fixup) const;
@@ -110,16 +108,14 @@ public:
/// neither a nor b are variables.
///
/// This is a more aggressive variant of EvaluateAsRelocatable. The intended
- /// use is for when relocations are not available, like the symbol value in
- /// the symbol table.
- bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout,
- const MCFixup *Fixup) const;
+ /// use is for when relocations are not available, like the .size directive.
+ bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const;
- /// FindAssociatedSection - Find the "associated section" for this expression,
- /// which is currently defined as the absolute section for constants, or
+ /// \brief Find the "associated section" for this expression, which is
+ /// currently defined as the absolute section for constants, or
/// otherwise the section associated with the first defined symbol in the
/// expression.
- const MCSection *FindAssociatedSection() const;
+ MCSection *FindAssociatedSection() const;
/// @}
};
@@ -129,21 +125,21 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) {
return OS;
}
-//// MCConstantExpr - Represent a constant integer expression.
+//// \brief Represent a constant integer expression.
class MCConstantExpr : public MCExpr {
int64_t Value;
- explicit MCConstantExpr(int64_t _Value)
- : MCExpr(MCExpr::Constant), Value(_Value) {}
+ explicit MCConstantExpr(int64_t Value)
+ : MCExpr(MCExpr::Constant), Value(Value) {}
public:
- /// @name Construction
+ /// \name Construction
/// @{
static const MCConstantExpr *Create(int64_t Value, MCContext &Ctx);
/// @}
- /// @name Accessors
+ /// \name Accessors
/// @{
int64_t getValue() const { return Value; }
@@ -155,15 +151,14 @@ public:
}
};
-/// MCSymbolRefExpr - Represent a reference to a symbol from inside an
-/// expression.
+/// \brief Represent a reference to a symbol from inside an expression.
///
/// A symbol reference in an expression may be a use of a label, a use of an
/// assembler variable (defined constant), or constitute an implicit definition
/// of the symbol as external.
class MCSymbolRefExpr : public MCExpr {
public:
- enum VariantKind {
+ enum VariantKind : uint16_t {
VK_None,
VK_Invalid,
@@ -188,6 +183,7 @@ public:
VK_GOTPAGE,
VK_GOTPAGEOFF,
VK_SECREL,
+ VK_SIZE, // symbol@SIZE
VK_WEAKREF, // The link between the symbols in .weakref foo, bar
VK_ARM_NONE,
@@ -280,12 +276,25 @@ public:
VK_Mips_PCREL_HI16,
VK_Mips_PCREL_LO16,
- VK_COFF_IMGREL32 // symbol@imgrel (image-relative)
+ VK_COFF_IMGREL32, // symbol@imgrel (image-relative)
+
+ VK_Hexagon_PCREL,
+ VK_Hexagon_LO16,
+ VK_Hexagon_HI16,
+ VK_Hexagon_GPREL,
+ VK_Hexagon_GD_GOT,
+ VK_Hexagon_LD_GOT,
+ VK_Hexagon_GD_PLT,
+ VK_Hexagon_LD_PLT,
+ VK_Hexagon_IE,
+ VK_Hexagon_IE_GOT,
+ VK_TPREL,
+ VK_DTPREL
};
private:
/// The symbol reference modifier.
- const unsigned Kind : 16;
+ const VariantKind Kind;
/// Specifies how the variant kind should be printed.
const unsigned UseParensForSymbolVariant : 1;
@@ -300,7 +309,7 @@ private:
const MCAsmInfo *MAI);
public:
- /// @name Construction
+ /// \name Construction
/// @{
static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx) {
@@ -313,19 +322,19 @@ public:
MCContext &Ctx);
/// @}
- /// @name Accessors
+ /// \name Accessors
/// @{
const MCSymbol &getSymbol() const { return *Symbol; }
- VariantKind getKind() const { return static_cast<VariantKind>(Kind); }
+ VariantKind getKind() const { return Kind; }
void printVariantKind(raw_ostream &OS) const;
bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; }
/// @}
- /// @name Static Utility Functions
+ /// \name Static Utility Functions
/// @{
static StringRef getVariantKindName(VariantKind Kind);
@@ -339,7 +348,7 @@ public:
}
};
-/// MCUnaryExpr - Unary assembler expressions.
+/// \brief Unary assembler expressions.
class MCUnaryExpr : public MCExpr {
public:
enum Opcode {
@@ -353,11 +362,11 @@ private:
Opcode Op;
const MCExpr *Expr;
- MCUnaryExpr(Opcode _Op, const MCExpr *_Expr)
- : MCExpr(MCExpr::Unary), Op(_Op), Expr(_Expr) {}
+ MCUnaryExpr(Opcode Op, const MCExpr *Expr)
+ : MCExpr(MCExpr::Unary), Op(Op), Expr(Expr) {}
public:
- /// @name Construction
+ /// \name Construction
/// @{
static const MCUnaryExpr *Create(Opcode Op, const MCExpr *Expr,
@@ -376,13 +385,13 @@ public:
}
/// @}
- /// @name Accessors
+ /// \name Accessors
/// @{
- /// getOpcode - Get the kind of this unary expression.
+ /// \brief Get the kind of this unary expression.
Opcode getOpcode() const { return Op; }
- /// getSubExpr - Get the child of this unary expression.
+ /// \brief Get the child of this unary expression.
const MCExpr *getSubExpr() const { return Expr; }
/// @}
@@ -392,7 +401,7 @@ public:
}
};
-/// MCBinaryExpr - Binary assembler expressions.
+/// \brief Binary assembler expressions.
class MCBinaryExpr : public MCExpr {
public:
enum Opcode {
@@ -415,7 +424,8 @@ public:
NE, ///< Inequality comparison.
Or, ///< Bitwise or.
Shl, ///< Shift left.
- Shr, ///< Shift right (arithmetic or logical, depending on target)
+ AShr, ///< Arithmetic shift right.
+ LShr, ///< Logical shift right.
Sub, ///< Subtraction.
Xor ///< Bitwise exclusive or.
};
@@ -424,11 +434,11 @@ private:
Opcode Op;
const MCExpr *LHS, *RHS;
- MCBinaryExpr(Opcode _Op, const MCExpr *_LHS, const MCExpr *_RHS)
- : MCExpr(MCExpr::Binary), Op(_Op), LHS(_LHS), RHS(_RHS) {}
+ MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS)
+ : MCExpr(MCExpr::Binary), Op(Op), LHS(LHS), RHS(RHS) {}
public:
- /// @name Construction
+ /// \name Construction
/// @{
static const MCBinaryExpr *Create(Opcode Op, const MCExpr *LHS,
@@ -493,9 +503,13 @@ public:
MCContext &Ctx) {
return Create(Shl, LHS, RHS, Ctx);
}
- static const MCBinaryExpr *CreateShr(const MCExpr *LHS, const MCExpr *RHS,
+ static const MCBinaryExpr *CreateAShr(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
- return Create(Shr, LHS, RHS, Ctx);
+ return Create(AShr, LHS, RHS, Ctx);
+ }
+ static const MCBinaryExpr *CreateLShr(const MCExpr *LHS, const MCExpr *RHS,
+ MCContext &Ctx) {
+ return Create(LShr, LHS, RHS, Ctx);
}
static const MCBinaryExpr *CreateSub(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
@@ -507,16 +521,16 @@ public:
}
/// @}
- /// @name Accessors
+ /// \name Accessors
/// @{
- /// getOpcode - Get the kind of this binary expression.
+ /// \brief Get the kind of this binary expression.
Opcode getOpcode() const { return Op; }
- /// getLHS - Get the left-hand side expression of the binary operator.
+ /// \brief Get the left-hand side expression of the binary operator.
const MCExpr *getLHS() const { return LHS; }
- /// getRHS - Get the right-hand side expression of the binary operator.
+ /// \brief Get the right-hand side expression of the binary operator.
const MCExpr *getRHS() const { return RHS; }
/// @}
@@ -526,8 +540,8 @@ public:
}
};
-/// MCTargetExpr - This is an extension point for target-specific MCExpr
-/// subclasses to implement.
+/// \brief This is an extension point for target-specific MCExpr subclasses to
+/// implement.
///
/// NOTE: All subclasses are required to have trivial destructors because
/// MCExprs are bump pointer allocated and not destructed.
@@ -543,7 +557,7 @@ public:
const MCAsmLayout *Layout,
const MCFixup *Fixup) const = 0;
virtual void visitUsedExpr(MCStreamer& Streamer) const = 0;
- virtual const MCSection *FindAssociatedSection() const = 0;
+ virtual MCSection *FindAssociatedSection() const = 0;
virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0;
diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h
index 98a1419a1934..8ab477c401a1 100644
--- a/include/llvm/MC/MCFixup.h
+++ b/include/llvm/MC/MCFixup.h
@@ -19,7 +19,7 @@
namespace llvm {
class MCExpr;
-/// MCFixupKind - Extensible enumeration to represent the type of a fixup.
+/// \brief Extensible enumeration to represent the type of a fixup.
enum MCFixupKind {
FK_Data_1 = 0, ///< A one-byte fixup.
FK_Data_2, ///< A two-byte fixup.
@@ -45,7 +45,7 @@ enum MCFixupKind {
MaxTargetFixupKind = (1 << 8)
};
-/// MCFixup - Encode information on a single operation to perform on a byte
+/// \brief Encode information on a single operation to perform on a byte
/// sequence (e.g., an encoded instruction) which requires assemble- or run-
/// time patching.
///
@@ -75,7 +75,7 @@ class MCFixup {
/// The source location which gave rise to the fixup, if any.
SMLoc Loc;
public:
- static MCFixup Create(uint32_t Offset, const MCExpr *Value,
+ static MCFixup create(uint32_t Offset, const MCExpr *Value,
MCFixupKind Kind, SMLoc Loc = SMLoc()) {
assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!");
MCFixup FI;
@@ -93,8 +93,8 @@ public:
const MCExpr *getValue() const { return Value; }
- /// getKindForSize - Return the generic fixup kind for a value with the given
- /// size. It is an error to pass an unsupported size.
+ /// \brief Return the generic fixup kind for a value with the given size. It
+ /// is an error to pass an unsupported size.
static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) {
switch (Size) {
default: llvm_unreachable("Invalid generic fixup size!");
diff --git a/include/llvm/MC/MCFixupKindInfo.h b/include/llvm/MC/MCFixupKindInfo.h
index 6979ad5807d0..58183bd778e6 100644
--- a/include/llvm/MC/MCFixupKindInfo.h
+++ b/include/llvm/MC/MCFixupKindInfo.h
@@ -12,7 +12,7 @@
namespace llvm {
-/// MCFixupKindInfo - Target independent information on a fixup kind.
+/// \brief Target independent information on a fixup kind.
struct MCFixupKindInfo {
enum FixupKindFlags {
/// Is this fixup kind PCrelative? This is used by the assembler backend to
diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h
index 25cd5ccb08fd..2fc509148403 100644
--- a/include/llvm/MC/MCInst.h
+++ b/include/llvm/MC/MCInst.h
@@ -28,7 +28,7 @@ class MCInstPrinter;
class MCExpr;
class MCInst;
-/// MCOperand - Instances of this class represent operands of the MCInst class.
+/// \brief Instances of this class represent operands of the MCInst class.
/// This is a simple discriminated union.
class MCOperand {
enum MachineOperandType : unsigned char {
@@ -59,13 +59,13 @@ public:
bool isExpr() const { return Kind == kExpr; }
bool isInst() const { return Kind == kInst; }
- /// getReg - Returns the register number.
+ /// \brief Returns the register number.
unsigned getReg() const {
assert(isReg() && "This is not a register operand!");
return RegVal;
}
- /// setReg - Set the register number.
+ /// \brief Set the register number.
void setReg(unsigned Reg) {
assert(isReg() && "This is not a register operand!");
RegVal = Reg;
@@ -108,44 +108,44 @@ public:
InstVal = Val;
}
- static MCOperand CreateReg(unsigned Reg) {
+ static MCOperand createReg(unsigned Reg) {
MCOperand Op;
Op.Kind = kRegister;
Op.RegVal = Reg;
return Op;
}
- static MCOperand CreateImm(int64_t Val) {
+ static MCOperand createImm(int64_t Val) {
MCOperand Op;
Op.Kind = kImmediate;
Op.ImmVal = Val;
return Op;
}
- static MCOperand CreateFPImm(double Val) {
+ static MCOperand createFPImm(double Val) {
MCOperand Op;
Op.Kind = kFPImmediate;
Op.FPImmVal = Val;
return Op;
}
- static MCOperand CreateExpr(const MCExpr *Val) {
+ static MCOperand createExpr(const MCExpr *Val) {
MCOperand Op;
Op.Kind = kExpr;
Op.ExprVal = Val;
return Op;
}
- static MCOperand CreateInst(const MCInst *Val) {
+ static MCOperand createInst(const MCInst *Val) {
MCOperand Op;
Op.Kind = kInst;
Op.InstVal = Val;
return Op;
}
- void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
+ void print(raw_ostream &OS) const;
void dump() const;
};
template <> struct isPodLike<MCOperand> { static const bool value = true; };
-/// MCInst - Instances of this class represent a single low-level machine
+/// \brief Instances of this class represent a single low-level machine
/// instruction.
class MCInst {
unsigned Opcode;
@@ -169,7 +169,7 @@ public:
}
void clear() { Operands.clear(); }
- size_t size() { return Operands.size(); }
+ size_t size() const { return Operands.size(); }
typedef SmallVectorImpl<MCOperand>::iterator iterator;
typedef SmallVectorImpl<MCOperand>::const_iterator const_iterator;
@@ -181,24 +181,23 @@ public:
return Operands.insert(I, Op);
}
- void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
+ void print(raw_ostream &OS) const;
void dump() const;
/// \brief Dump the MCInst as prettily as possible using the additional MC
/// structures, if given. Operators are separated by the \p Separator
/// string.
- void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = nullptr,
- const MCInstPrinter *Printer = nullptr,
+ void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr,
StringRef Separator = " ") const;
};
inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) {
- MO.print(OS, nullptr);
+ MO.print(OS);
return OS;
}
inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) {
- MI.print(OS, nullptr);
+ MI.print(OS);
return OS;
}
diff --git a/include/llvm/MC/MCInstBuilder.h b/include/llvm/MC/MCInstBuilder.h
index c5acb26eecac..30609bdb8b27 100644
--- a/include/llvm/MC/MCInstBuilder.h
+++ b/include/llvm/MC/MCInstBuilder.h
@@ -30,31 +30,37 @@ public:
/// \brief Add a new register operand.
MCInstBuilder &addReg(unsigned Reg) {
- Inst.addOperand(MCOperand::CreateReg(Reg));
+ Inst.addOperand(MCOperand::createReg(Reg));
return *this;
}
/// \brief Add a new integer immediate operand.
MCInstBuilder &addImm(int64_t Val) {
- Inst.addOperand(MCOperand::CreateImm(Val));
+ Inst.addOperand(MCOperand::createImm(Val));
return *this;
}
/// \brief Add a new floating point immediate operand.
MCInstBuilder &addFPImm(double Val) {
- Inst.addOperand(MCOperand::CreateFPImm(Val));
+ Inst.addOperand(MCOperand::createFPImm(Val));
return *this;
}
/// \brief Add a new MCExpr operand.
MCInstBuilder &addExpr(const MCExpr *Val) {
- Inst.addOperand(MCOperand::CreateExpr(Val));
+ Inst.addOperand(MCOperand::createExpr(Val));
return *this;
}
/// \brief Add a new MCInst operand.
MCInstBuilder &addInst(const MCInst *Val) {
- Inst.addOperand(MCOperand::CreateInst(Val));
+ Inst.addOperand(MCOperand::createInst(Val));
+ return *this;
+ }
+
+ /// \brief Add an operand.
+ MCInstBuilder &addOperand(const MCOperand &Op) {
+ Inst.addOperand(Op);
return *this;
}
diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h
index 95124c3021dd..7e8563a195d0 100644
--- a/include/llvm/MC/MCInstPrinter.h
+++ b/include/llvm/MC/MCInstPrinter.h
@@ -19,6 +19,7 @@ class raw_ostream;
class MCAsmInfo;
class MCInstrInfo;
class MCRegisterInfo;
+class MCSubtargetInfo;
class StringRef;
namespace HexStyle {
@@ -28,21 +29,18 @@ namespace HexStyle {
};
}
-/// MCInstPrinter - This is an instance of a target assembly language printer
-/// that converts an MCInst to valid target assembly syntax.
+/// \brief This is an instance of a target assembly language printer that
+/// converts an MCInst to valid target assembly syntax.
class MCInstPrinter {
protected:
- /// CommentStream - a stream that comments can be emitted to if desired.
- /// Each comment must end with a newline. This will be null if verbose
- /// assembly emission is disable.
+ /// \brief A stream that comments can be emitted to if desired. Each comment
+ /// must end with a newline. This will be null if verbose assembly emission
+ /// is disable.
raw_ostream *CommentStream;
const MCAsmInfo &MAI;
const MCInstrInfo &MII;
const MCRegisterInfo &MRI;
- /// The current set of available features.
- uint64_t AvailableFeatures;
-
/// True if we are printing marked up assembly.
bool UseMarkup;
@@ -58,29 +56,25 @@ public:
MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii,
const MCRegisterInfo &mri)
: CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri),
- AvailableFeatures(0), UseMarkup(0), PrintImmHex(0),
+ UseMarkup(0), PrintImmHex(0),
PrintHexStyle(HexStyle::C) {}
virtual ~MCInstPrinter();
- /// setCommentStream - Specify a stream to emit comments to.
+ /// \brief Specify a stream to emit comments to.
void setCommentStream(raw_ostream &OS) { CommentStream = &OS; }
- /// printInst - Print the specified MCInst to the specified raw_ostream.
- ///
+ /// \brief Print the specified MCInst to the specified raw_ostream.
virtual void printInst(const MCInst *MI, raw_ostream &OS,
- StringRef Annot) = 0;
+ StringRef Annot, const MCSubtargetInfo &STI) = 0;
- /// getOpcodeName - Return the name of the specified opcode enum (e.g.
- /// "MOV32ri") or empty if we can't resolve it.
+ /// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or
+ /// empty if we can't resolve it.
StringRef getOpcodeName(unsigned Opcode) const;
- /// printRegName - Print the assembler register name.
+ /// \brief Print the assembler register name.
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
- uint64_t getAvailableFeatures() const { return AvailableFeatures; }
- void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; }
-
bool getUseMarkup() const { return UseMarkup; }
void setUseMarkup(bool Value) { UseMarkup = Value; }
@@ -95,12 +89,14 @@ public:
void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; }
/// Utility function to print immediates in decimal or hex.
- format_object1<int64_t> formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); }
+ format_object<int64_t> formatImm(int64_t Value) const {
+ return PrintImmHex ? formatHex(Value) : formatDec(Value);
+ }
/// Utility functions to print decimal/hexadecimal values.
- format_object1<int64_t> formatDec(const int64_t Value) const;
- format_object1<int64_t> formatHex(const int64_t Value) const;
- format_object1<uint64_t> formatHex(const uint64_t Value) const;
+ format_object<int64_t> formatDec(int64_t Value) const;
+ format_object<int64_t> formatHex(int64_t Value) const;
+ format_object<uint64_t> formatHex(uint64_t Value) const;
};
} // namespace llvm
diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h
index e921f768ac45..8f5159e9e1c8 100644
--- a/include/llvm/MC/MCInstrAnalysis.h
+++ b/include/llvm/MC/MCInstrAnalysis.h
@@ -59,8 +59,8 @@ public:
return Info->get(Inst.getOpcode()).isTerminator();
}
- /// evaluateBranch - Given a branch instruction try to get the address the
- /// branch targets. Return true on success, and the address in Target.
+ /// \brief Given a branch instruction try to get the address the branch
+ /// targets. Return true on success, and the address in Target.
virtual bool
evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const;
diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h
index 360989305d3a..de3a1959e05c 100644
--- a/include/llvm/MC/MCInstrDesc.h
+++ b/include/llvm/MC/MCInstrDesc.h
@@ -15,142 +15,142 @@
#ifndef LLVM_MC_MCINSTRDESC_H
#define LLVM_MC_MCINSTRDESC_H
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/DataTypes.h"
+#include <string>
namespace llvm {
+ class MCInst;
+ class MCRegisterInfo;
+ class MCSubtargetInfo;
+ class FeatureBitset;
//===----------------------------------------------------------------------===//
// Machine Operand Flags and Description
//===----------------------------------------------------------------------===//
namespace MCOI {
- // Operand constraints
- enum OperandConstraint {
- TIED_TO = 0, // Must be allocated the same register as.
- EARLY_CLOBBER // Operand is an early clobber register operand
- };
-
- /// OperandFlags - These are flags set on operands, but should be considered
- /// private, all access should go through the MCOperandInfo accessors.
- /// See the accessors for a description of what these are.
- enum OperandFlags {
- LookupPtrRegClass = 0,
- Predicate,
- OptionalDef
- };
-
- /// Operand Type - Operands are tagged with one of the values of this enum.
- enum OperandType {
- OPERAND_UNKNOWN = 0,
- OPERAND_IMMEDIATE = 1,
- OPERAND_REGISTER = 2,
- OPERAND_MEMORY = 3,
- OPERAND_PCREL = 4,
- OPERAND_FIRST_TARGET = 5
- };
+// Operand constraints
+enum OperandConstraint {
+ TIED_TO = 0, // Must be allocated the same register as.
+ EARLY_CLOBBER // Operand is an early clobber register operand
+};
+
+/// \brief These are flags set on operands, but should be considered
+/// private, all access should go through the MCOperandInfo accessors.
+/// See the accessors for a description of what these are.
+enum OperandFlags { LookupPtrRegClass = 0, Predicate, OptionalDef };
+
+/// \brief Operands are tagged with one of the values of this enum.
+enum OperandType {
+ OPERAND_UNKNOWN = 0,
+ OPERAND_IMMEDIATE = 1,
+ OPERAND_REGISTER = 2,
+ OPERAND_MEMORY = 3,
+ OPERAND_PCREL = 4,
+ OPERAND_FIRST_TARGET = 5
+};
}
-/// MCOperandInfo - This holds information about one operand of a machine
-/// instruction, indicating the register class for register operands, etc.
-///
+/// \brief This holds information about one operand of a machine instruction,
+/// indicating the register class for register operands, etc.
class MCOperandInfo {
public:
- /// RegClass - This specifies the register class enumeration of the operand
+ /// \brief This specifies the register class enumeration of the operand
/// if the operand is a register. If isLookupPtrRegClass is set, then this is
/// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to
/// get a dynamic register class.
int16_t RegClass;
- /// Flags - These are flags from the MCOI::OperandFlags enum.
+ /// \brief These are flags from the MCOI::OperandFlags enum.
uint8_t Flags;
- /// OperandType - Information about the type of the operand.
+ /// \brief Information about the type of the operand.
uint8_t OperandType;
-
- /// Lower 16 bits are used to specify which constraints are set. The higher 16
- /// bits are used to specify the value of constraints (4 bits each).
+ /// \brief The lower 16 bits are used to specify which constraints are set.
+ /// The higher 16 bits are used to specify the value of constraints (4 bits
+ /// each).
uint32_t Constraints;
- /// Currently no other information.
- /// isLookupPtrRegClass - Set if this operand is a pointer value and it
- /// requires a callback to look up its register class.
- bool isLookupPtrRegClass() const {return Flags&(1 <<MCOI::LookupPtrRegClass);}
+ /// \brief Set if this operand is a pointer value and it requires a callback
+ /// to look up its register class.
+ bool isLookupPtrRegClass() const {
+ return Flags & (1 << MCOI::LookupPtrRegClass);
+ }
- /// isPredicate - Set if this is one of the operands that made up of
- /// the predicate operand that controls an isPredicable() instruction.
+ /// \brief Set if this is one of the operands that made up of the predicate
+ /// operand that controls an isPredicable() instruction.
bool isPredicate() const { return Flags & (1 << MCOI::Predicate); }
- /// isOptionalDef - Set if this operand is a optional def.
- ///
+ /// \brief Set if this operand is a optional def.
bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); }
};
-
//===----------------------------------------------------------------------===//
// Machine Instruction Flags and Description
//===----------------------------------------------------------------------===//
-/// MCInstrDesc flags - These should be considered private to the
-/// implementation of the MCInstrDesc class. Clients should use the predicate
-/// methods on MCInstrDesc, not use these directly. These all correspond to
-/// bitfields in the MCInstrDesc::Flags field.
namespace MCID {
- enum {
- Variadic = 0,
- HasOptionalDef,
- Pseudo,
- Return,
- Call,
- Barrier,
- Terminator,
- Branch,
- IndirectBranch,
- Compare,
- MoveImm,
- Bitcast,
- Select,
- DelaySlot,
- FoldableAsLoad,
- MayLoad,
- MayStore,
- Predicable,
- NotDuplicable,
- UnmodeledSideEffects,
- Commutable,
- ConvertibleTo3Addr,
- UsesCustomInserter,
- HasPostISelHook,
- Rematerializable,
- CheapAsAMove,
- ExtraSrcRegAllocReq,
- ExtraDefRegAllocReq,
- RegSequence,
- ExtractSubreg,
- InsertSubreg
- };
+/// \brief These should be considered private to the implementation of the
+/// MCInstrDesc class. Clients should use the predicate methods on MCInstrDesc,
+/// not use these directly. These all correspond to bitfields in the
+/// MCInstrDesc::Flags field.
+enum Flag {
+ Variadic = 0,
+ HasOptionalDef,
+ Pseudo,
+ Return,
+ Call,
+ Barrier,
+ Terminator,
+ Branch,
+ IndirectBranch,
+ Compare,
+ MoveImm,
+ Bitcast,
+ Select,
+ DelaySlot,
+ FoldableAsLoad,
+ MayLoad,
+ MayStore,
+ Predicable,
+ NotDuplicable,
+ UnmodeledSideEffects,
+ Commutable,
+ ConvertibleTo3Addr,
+ UsesCustomInserter,
+ HasPostISelHook,
+ Rematerializable,
+ CheapAsAMove,
+ ExtraSrcRegAllocReq,
+ ExtraDefRegAllocReq,
+ RegSequence,
+ ExtractSubreg,
+ InsertSubreg
+};
}
-/// MCInstrDesc - Describe properties that are true of each instruction in the
-/// target description file. This captures information about side effects,
-/// register use and many other things. There is one instance of this struct
-/// for each target instruction class, and the MachineInstr class points to
-/// this struct directly to describe itself.
+/// \brief Describe properties that are true of each instruction in the target
+/// description file. This captures information about side effects, register
+/// use and many other things. There is one instance of this struct for each
+/// target instruction class, and the MachineInstr class points to this struct
+/// directly to describe itself.
class MCInstrDesc {
public:
- unsigned short Opcode; // The opcode number
- unsigned short NumOperands; // Num of args (may be more if variable_ops)
- unsigned short NumDefs; // Num of args that are definitions
- unsigned short SchedClass; // enum identifying instr sched class
- unsigned short Size; // Number of bytes in encoding.
- unsigned Flags; // Flags identifying machine instr class
- uint64_t TSFlags; // Target Specific Flag values
- const uint16_t *ImplicitUses; // Registers implicitly read by this instr
- const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr
- const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands
- uint64_t DeprecatedFeatureMask;// Feature bits that this is deprecated on, if any
+ unsigned short Opcode; // The opcode number
+ unsigned short NumOperands; // Num of args (may be more if variable_ops)
+ unsigned short NumDefs; // Num of args that are definitions
+ unsigned short SchedClass; // enum identifying instr sched class
+ unsigned short Size; // Number of bytes in encoding.
+ unsigned Flags; // Flags identifying machine instr class
+ uint64_t TSFlags; // Target Specific Flag values
+ const uint16_t *ImplicitUses; // Registers implicitly read by this instr
+ const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr
+ const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands
+ // Subtarget feature that this is deprecated on, if any
+ // -1 implies this is not deprecated by any single feature. It may still be
+ // deprecated due to a "complex" reason, below.
+ int64_t DeprecatedFeature;
+
// A complex method to determine is a certain is deprecated or not, and return
// the reason for deprecation.
bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &);
@@ -170,38 +170,23 @@ public:
/// \brief Returns true if a certain instruction is deprecated and if so
/// returns the reason in \p Info.
bool getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI,
- std::string &Info) const {
- if (ComplexDeprecationInfo)
- return ComplexDeprecationInfo(MI, STI, Info);
- if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) {
- // FIXME: it would be nice to include the subtarget feature here.
- Info = "deprecated";
- return true;
- }
- return false;
- }
+ std::string &Info) const;
/// \brief Return the opcode number for this descriptor.
- unsigned getOpcode() const {
- return Opcode;
- }
+ unsigned getOpcode() const { return Opcode; }
/// \brief Return the number of declared MachineOperands for this
/// MachineInstruction. Note that variadic (isVariadic() returns true)
/// instructions may have additional operands at the end of the list, and note
/// that the machine instruction may include implicit register def/uses as
/// well.
- unsigned getNumOperands() const {
- return NumOperands;
- }
+ unsigned getNumOperands() const { return NumOperands; }
/// \brief Return the number of MachineOperands that are register
/// definitions. Register definitions always occur at the start of the
/// machine operand list. This is the number of "outs" in the .td file,
/// and does not include implicit defs.
- unsigned getNumDefs() const {
- return NumDefs;
- }
+ unsigned getNumDefs() const { return NumDefs; }
/// \brief Return flags of this instruction.
unsigned getFlags() const { return Flags; }
@@ -210,39 +195,26 @@ public:
/// operands. In this case, the variable operands will be after the normal
/// operands but before the implicit definitions and uses (if any are
/// present).
- bool isVariadic() const {
- return Flags & (1 << MCID::Variadic);
- }
+ bool isVariadic() const { return Flags & (1 << MCID::Variadic); }
/// \brief Set if this instruction has an optional definition, e.g.
/// ARM instructions which can set condition code if 's' bit is set.
- bool hasOptionalDef() const {
- return Flags & (1 << MCID::HasOptionalDef);
- }
+ bool hasOptionalDef() const { return Flags & (1 << MCID::HasOptionalDef); }
/// \brief Return true if this is a pseudo instruction that doesn't
/// correspond to a real machine instruction.
- ///
- bool isPseudo() const {
- return Flags & (1 << MCID::Pseudo);
- }
+ bool isPseudo() const { return Flags & (1 << MCID::Pseudo); }
/// \brief Return true if the instruction is a return.
- bool isReturn() const {
- return Flags & (1 << MCID::Return);
- }
+ bool isReturn() const { return Flags & (1 << MCID::Return); }
/// \brief Return true if the instruction is a call.
- bool isCall() const {
- return Flags & (1 << MCID::Call);
- }
+ bool isCall() const { return Flags & (1 << MCID::Call); }
/// \brief Returns true if the specified instruction stops control flow
/// from executing the instruction immediately following it. Examples include
/// unconditional branches and return instructions.
- bool isBarrier() const {
- return Flags & (1 << MCID::Barrier);
- }
+ bool isBarrier() const { return Flags & (1 << MCID::Barrier); }
/// \brief Returns true if this instruction part of the terminator for
/// a basic block. Typically this is things like return and branch
@@ -250,23 +222,17 @@ public:
///
/// Various passes use this to insert code into the bottom of a basic block,
/// but before control flow occurs.
- bool isTerminator() const {
- return Flags & (1 << MCID::Terminator);
- }
+ bool isTerminator() const { return Flags & (1 << MCID::Terminator); }
/// \brief Returns true if this is a conditional, unconditional, or
/// indirect branch. Predicates below can be used to discriminate between
/// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to
/// get more information.
- bool isBranch() const {
- return Flags & (1 << MCID::Branch);
- }
+ bool isBranch() const { return Flags & (1 << MCID::Branch); }
/// \brief Return true if this is an indirect branch, such as a
/// branch through a register.
- bool isIndirectBranch() const {
- return Flags & (1 << MCID::IndirectBranch);
- }
+ bool isIndirectBranch() const { return Flags & (1 << MCID::IndirectBranch); }
/// \brief Return true if this is a branch which may fall
/// through to the next instruction or may transfer control flow to some other
@@ -287,79 +253,44 @@ public:
/// \brief Return true if this is a branch or an instruction which directly
/// writes to the program counter. Considered 'may' affect rather than
/// 'does' affect as things like predication are not taken into account.
- bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const {
- if (isBranch() || isCall() || isReturn() || isIndirectBranch())
- return true;
- unsigned PC = RI.getProgramCounter();
- if (PC == 0)
- return false;
- if (hasDefOfPhysReg(MI, PC, RI))
- return true;
- // A variadic instruction may define PC in the variable operand list.
- // There's currently no indication of which entries in a variable
- // list are defs and which are uses. While that's the case, this function
- // needs to assume they're defs in order to be conservatively correct.
- for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) {
- if (MI.getOperand(i).isReg() &&
- RI.isSubRegisterEq(PC, MI.getOperand(i).getReg()))
- return true;
- }
- return false;
- }
+ bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const;
/// \brief Return true if this instruction has a predicate operand
/// that controls execution. It may be set to 'always', or may be set to other
/// values. There are various methods in TargetInstrInfo that can be used to
/// control and modify the predicate in this instruction.
- bool isPredicable() const {
- return Flags & (1 << MCID::Predicable);
- }
+ bool isPredicable() const { return Flags & (1 << MCID::Predicable); }
/// \brief Return true if this instruction is a comparison.
- bool isCompare() const {
- return Flags & (1 << MCID::Compare);
- }
+ bool isCompare() const { return Flags & (1 << MCID::Compare); }
/// \brief Return true if this instruction is a move immediate
/// (including conditional moves) instruction.
- bool isMoveImmediate() const {
- return Flags & (1 << MCID::MoveImm);
- }
+ bool isMoveImmediate() const { return Flags & (1 << MCID::MoveImm); }
/// \brief Return true if this instruction is a bitcast instruction.
- bool isBitcast() const {
- return Flags & (1 << MCID::Bitcast);
- }
+ bool isBitcast() const { return Flags & (1 << MCID::Bitcast); }
/// \brief Return true if this is a select instruction.
- bool isSelect() const {
- return Flags & (1 << MCID::Select);
- }
+ bool isSelect() const { return Flags & (1 << MCID::Select); }
/// \brief Return true if this instruction cannot be safely
/// duplicated. For example, if the instruction has a unique labels attached
/// to it, duplicating it would cause multiple definition errors.
- bool isNotDuplicable() const {
- return Flags & (1 << MCID::NotDuplicable);
- }
+ bool isNotDuplicable() const { return Flags & (1 << MCID::NotDuplicable); }
- /// hasDelaySlot - Returns true if the specified instruction has a delay slot
- /// which must be filled by the code generator.
- bool hasDelaySlot() const {
- return Flags & (1 << MCID::DelaySlot);
- }
+ /// \brief Returns true if the specified instruction has a delay slot which
+ /// must be filled by the code generator.
+ bool hasDelaySlot() const { return Flags & (1 << MCID::DelaySlot); }
- /// canFoldAsLoad - Return true for instructions that can be folded as
- /// memory operands in other instructions. The most common use for this
- /// is instructions that are simple loads from memory that don't modify
- /// the loaded value in any way, but it can also be used for instructions
- /// that can be expressed as constant-pool loads, such as V_SETALLONES
- /// on x86, to allow them to be folded when it is beneficial.
- /// This should only be set on instructions that return a value in their
- /// only virtual register definition.
- bool canFoldAsLoad() const {
- return Flags & (1 << MCID::FoldableAsLoad);
- }
+ /// \brief Return true for instructions that can be folded as memory operands
+ /// in other instructions. The most common use for this is instructions that
+ /// are simple loads from memory that don't modify the loaded value in any
+ /// way, but it can also be used for instructions that can be expressed as
+ /// constant-pool loads, such as V_SETALLONES on x86, to allow them to be
+ /// folded when it is beneficial. This should only be set on instructions
+ /// that return a value in their only virtual register definition.
+ bool canFoldAsLoad() const { return Flags & (1 << MCID::FoldableAsLoad); }
/// \brief Return true if this instruction behaves
/// the same way as the generic REG_SEQUENCE instructions.
@@ -398,9 +329,7 @@ public:
/// 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);
- }
+ bool isInsertSubregLike() const { return Flags & (1 << MCID::InsertSubreg); }
//===--------------------------------------------------------------------===//
// Side Effect Analysis
@@ -409,20 +338,15 @@ public:
/// \brief Return true if this instruction could possibly read memory.
/// Instructions with this flag set are not necessarily simple load
/// instructions, they may load a value and modify it, for example.
- bool mayLoad() const {
- return Flags & (1 << MCID::MayLoad);
- }
-
+ bool mayLoad() const { return Flags & (1 << MCID::MayLoad); }
/// \brief Return true if this instruction could possibly modify memory.
/// Instructions with this flag set are not necessarily simple store
/// instructions, they may store a modified value based on their operands, or
/// may not actually modify anything, for example.
- bool mayStore() const {
- return Flags & (1 << MCID::MayStore);
- }
+ bool mayStore() const { return Flags & (1 << MCID::MayStore); }
- /// hasUnmodeledSideEffects - Return true if this instruction has side
+ /// \brief Return true if this instruction has side
/// effects that are not modeled by other flags. This does not return true
/// for instructions whose effects are captured by:
///
@@ -434,7 +358,6 @@ public:
/// Examples of side effects would be modifying 'invisible' machine state like
/// a control register, flushing a cache, modifying a register invisible to
/// LLVM, etc.
- ///
bool hasUnmodeledSideEffects() const {
return Flags & (1 << MCID::UnmodeledSideEffects);
}
@@ -443,9 +366,9 @@ public:
// Flags that indicate whether an instruction can be modified by a method.
//===--------------------------------------------------------------------===//
- /// isCommutable - Return true if this may be a 2- or 3-address
- /// instruction (of the form "X = op Y, Z, ..."), which produces the same
- /// result if Y and Z are exchanged. If this flag is set, then the
+ /// \brief Return true if this may be a 2- or 3-address instruction (of the
+ /// form "X = op Y, Z, ..."), which produces the same result if Y and Z are
+ /// exchanged. If this flag is set, then the
/// TargetInstrInfo::commuteInstruction method may be used to hack on the
/// instruction.
///
@@ -453,18 +376,16 @@ public:
/// sometimes. In these cases, the call to commuteInstruction will fail.
/// Also note that some instructions require non-trivial modification to
/// commute them.
- bool isCommutable() const {
- return Flags & (1 << MCID::Commutable);
- }
-
- /// isConvertibleTo3Addr - Return true if this is a 2-address instruction
- /// which can be changed into a 3-address instruction if needed. Doing this
- /// transformation can be profitable in the register allocator, because it
- /// means that the instruction can use a 2-address form if possible, but
- /// degrade into a less efficient form if the source and dest register cannot
- /// be assigned to the same register. For example, this allows the x86
- /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which
- /// is the same speed as the shift but has bigger code size.
+ bool isCommutable() const { return Flags & (1 << MCID::Commutable); }
+
+ /// \brief Return true if this is a 2-address instruction which can be changed
+ /// into a 3-address instruction if needed. Doing this transformation can be
+ /// profitable in the register allocator, because it means that the
+ /// instruction can use a 2-address form if possible, but degrade into a less
+ /// efficient form if the source and dest register cannot be assigned to the
+ /// same register. For example, this allows the x86 backend to turn a "shl
+ /// reg, 3" instruction into an LEA instruction, which is the same speed as
+ /// the shift but has bigger code size.
///
/// If this returns true, then the target must implement the
/// TargetInstrInfo::convertToThreeAddress method for this instruction, which
@@ -475,11 +396,11 @@ public:
return Flags & (1 << MCID::ConvertibleTo3Addr);
}
- /// usesCustomInsertionHook - Return true if this instruction requires
- /// custom insertion support when the DAG scheduler is inserting it into a
- /// machine basic block. If this is true for the instruction, it basically
- /// means that it is a pseudo instruction used at SelectionDAG time that is
- /// expanded out into magic code by the target when MachineInstrs are formed.
+ /// \brief Return true if this instruction requires custom insertion support
+ /// when the DAG scheduler is inserting it into a machine basic block. If
+ /// this is true for the instruction, it basically means that it is a pseudo
+ /// instruction used at SelectionDAG time that is expanded out into magic code
+ /// by the target when MachineInstrs are formed.
///
/// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method
/// is used to insert this into the MachineBasicBlock.
@@ -487,17 +408,14 @@ public:
return Flags & (1 << MCID::UsesCustomInserter);
}
- /// hasPostISelHook - Return true if this instruction requires *adjustment*
- /// after instruction selection by calling a target hook. For example, this
- /// can be used to fill in ARM 's' optional operand depending on whether
- /// the conditional flag register is used.
- bool hasPostISelHook() const {
- return Flags & (1 << MCID::HasPostISelHook);
- }
+ /// \brief Return true if this instruction requires *adjustment* after
+ /// instruction selection by calling a target hook. For example, this can be
+ /// used to fill in ARM 's' optional operand depending on whether the
+ /// conditional flag register is used.
+ bool hasPostISelHook() const { return Flags & (1 << MCID::HasPostISelHook); }
- /// isRematerializable - Returns true if this instruction is a candidate for
- /// remat. This flag is only used in TargetInstrInfo method
- /// isTriviallyRematerializable.
+ /// \brief Returns true if this instruction is a candidate for remat. This
+ /// flag is only used in TargetInstrInfo method isTriviallyRematerializable.
///
/// If this flag is set, the isReallyTriviallyReMaterializable()
/// or isReallyTriviallyReMaterializableGeneric methods are called to verify
@@ -506,80 +424,76 @@ public:
return Flags & (1 << MCID::Rematerializable);
}
- /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or
- /// less) than a move instruction. This is useful during certain types of
- /// optimizations (e.g., remat during two-address conversion or machine licm)
- /// where we would like to remat or hoist the instruction, but not if it costs
- /// more than moving the instruction into the appropriate register. Note, we
- /// are not marking copies from and to the same register class with this flag.
+ /// \brief Returns true if this instruction has the same cost (or less) than a
+ /// move instruction. This is useful during certain types of optimizations
+ /// (e.g., remat during two-address conversion or machine licm) where we would
+ /// like to remat or hoist the instruction, but not if it costs more than
+ /// 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);
- }
-
- /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands
- /// have special register allocation requirements that are not captured by the
- /// operand register classes. e.g. ARM::STRD's two source registers must be an
- /// even / odd pair, ARM::STM registers have to be in ascending order.
- /// Post-register allocation passes should not attempt to change allocations
- /// for sources of instructions with this flag.
+ bool isAsCheapAsAMove() const { return Flags & (1 << MCID::CheapAsAMove); }
+
+ /// \brief Returns true if this instruction source operands have special
+ /// register allocation requirements that are not captured by the operand
+ /// register classes. e.g. ARM::STRD's two source registers must be an even /
+ /// odd pair, ARM::STM registers have to be in ascending order. Post-register
+ /// allocation passes should not attempt to change allocations for sources of
+ /// instructions with this flag.
bool hasExtraSrcRegAllocReq() const {
return Flags & (1 << MCID::ExtraSrcRegAllocReq);
}
- /// hasExtraDefRegAllocReq - Returns true if this instruction def operands
- /// have special register allocation requirements that are not captured by the
- /// operand register classes. e.g. ARM::LDRD's two def registers must be an
- /// even / odd pair, ARM::LDM registers have to be in ascending order.
- /// Post-register allocation passes should not attempt to change allocations
- /// for definitions of instructions with this flag.
+ /// \brief Returns true if this instruction def operands have special register
+ /// allocation requirements that are not captured by the operand register
+ /// classes. e.g. ARM::LDRD's two def registers must be an even / odd pair,
+ /// ARM::LDM registers have to be in ascending order. Post-register
+ /// allocation passes should not attempt to change allocations for definitions
+ /// of instructions with this flag.
bool hasExtraDefRegAllocReq() const {
return Flags & (1 << MCID::ExtraDefRegAllocReq);
}
-
- /// getImplicitUses - Return a list of registers that are potentially
- /// read by any instance of this machine instruction. For example, on X86,
- /// the "adc" instruction adds two register operands and adds the carry bit in
- /// from the flags register. In this case, the instruction is marked as
- /// implicitly reading the flags. Likewise, the variable shift instruction on
- /// X86 is marked as implicitly reading the 'CL' register, which it always
- /// does.
+ /// \brief Return a list of registers that are potentially read by any
+ /// instance of this machine instruction. For example, on X86, the "adc"
+ /// instruction adds two register operands and adds the carry bit in from the
+ /// flags register. In this case, the instruction is marked as implicitly
+ /// reading the flags. Likewise, the variable shift instruction on X86 is
+ /// marked as implicitly reading the 'CL' register, which it always does.
///
/// This method returns null if the instruction has no implicit uses.
- const uint16_t *getImplicitUses() const {
- return ImplicitUses;
- }
+ const uint16_t *getImplicitUses() const { return ImplicitUses; }
/// \brief Return the number of implicit uses this instruction has.
unsigned getNumImplicitUses() const {
- if (!ImplicitUses) return 0;
+ if (!ImplicitUses)
+ return 0;
unsigned i = 0;
- for (; ImplicitUses[i]; ++i) /*empty*/;
+ for (; ImplicitUses[i]; ++i) /*empty*/
+ ;
return i;
}
- /// getImplicitDefs - Return a list of registers that are potentially
- /// written by any instance of this machine instruction. For example, on X86,
- /// many instructions implicitly set the flags register. In this case, they
- /// are marked as setting the FLAGS. Likewise, many instructions always
- /// deposit their result in a physical register. For example, the X86 divide
+ /// \brief Return a list of registers that are potentially written by any
+ /// instance of this machine instruction. For example, on X86, many
+ /// instructions implicitly set the flags register. In this case, they are
+ /// marked as setting the FLAGS. Likewise, many instructions always deposit
+ /// their result in a physical register. For example, the X86 divide
/// instruction always deposits the quotient and remainder in the EAX/EDX
/// registers. For that instruction, this will return a list containing the
/// EAX/EDX/EFLAGS registers.
///
/// This method returns null if the instruction has no implicit defs.
- const uint16_t *getImplicitDefs() const {
- return ImplicitDefs;
- }
+ const uint16_t *getImplicitDefs() const { return ImplicitDefs; }
/// \brief Return the number of implicit defs this instruct has.
unsigned getNumImplicitDefs() const {
- if (!ImplicitDefs) return 0;
+ if (!ImplicitDefs)
+ return 0;
unsigned i = 0;
- for (; ImplicitDefs[i]; ++i) /*empty*/;
+ for (; ImplicitDefs[i]; ++i) /*empty*/
+ ;
return i;
}
@@ -588,45 +502,25 @@ public:
bool hasImplicitUseOfPhysReg(unsigned Reg) const {
if (const uint16_t *ImpUses = ImplicitUses)
for (; *ImpUses; ++ImpUses)
- if (*ImpUses == Reg) return true;
+ if (*ImpUses == Reg)
+ return true;
return false;
}
/// \brief Return true if this instruction implicitly
/// defines the specified physical register.
bool hasImplicitDefOfPhysReg(unsigned Reg,
- const MCRegisterInfo *MRI = nullptr) const {
- if (const uint16_t *ImpDefs = ImplicitDefs)
- for (; *ImpDefs; ++ImpDefs)
- if (*ImpDefs == Reg || (MRI && MRI->isSubRegister(Reg, *ImpDefs)))
- return true;
- return false;
- }
-
- /// \brief Return true if this instruction defines the specified physical
- /// register, either explicitly or implicitly.
- bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg,
- const MCRegisterInfo &RI) const {
- for (int i = 0, e = NumDefs; i != e; ++i)
- if (MI.getOperand(i).isReg() &&
- RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg()))
- return true;
- return hasImplicitDefOfPhysReg(Reg, &RI);
- }
+ const MCRegisterInfo *MRI = nullptr) const;
/// \brief Return the scheduling class for this instruction. The
/// scheduling class is an index into the InstrItineraryData table. This
/// returns zero if there is no known scheduling information for the
/// instruction.
- unsigned getSchedClass() const {
- return SchedClass;
- }
+ unsigned getSchedClass() const { return SchedClass; }
/// \brief Return the number of bytes in the encoding of this instruction,
/// or zero if the encoding size cannot be known from the opcode.
- unsigned getSize() const {
- return Size;
- }
+ unsigned getSize() const { return Size; }
/// \brief Find the index of the first operand in the
/// operand list that is used to represent the predicate. It returns -1 if
@@ -639,6 +533,13 @@ public:
}
return -1;
}
+
+private:
+
+ /// \brief Return true if this instruction defines the specified physical
+ /// register, either explicitly or implicitly.
+ bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg,
+ const MCRegisterInfo &RI) const;
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h
index 1d3a36ca7c73..70c86587b08c 100644
--- a/include/llvm/MC/MCInstrInfo.h
+++ b/include/llvm/MC/MCInstrInfo.h
@@ -20,9 +20,7 @@
namespace llvm {
//---------------------------------------------------------------------------
-///
-/// MCInstrInfo - Interface to description of machine instruction set
-///
+/// \brief Interface to description of machine instruction set.
class MCInstrInfo {
const MCInstrDesc *Desc; // Raw array to allow static init'n
const unsigned *InstrNameIndices; // Array for name indices in InstrNameData
@@ -30,8 +28,8 @@ class MCInstrInfo {
unsigned NumOpcodes; // Number of entries in the desc array
public:
- /// InitMCInstrInfo - Initialize MCInstrInfo, called by TableGen
- /// auto-generated routines. *DO NOT USE*.
+ /// \brief Initialize MCInstrInfo, called by TableGen auto-generated routines.
+ /// *DO NOT USE*.
void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND,
unsigned NO) {
Desc = D;
@@ -42,15 +40,14 @@ public:
unsigned getNumOpcodes() const { return NumOpcodes; }
- /// get - Return the machine instruction descriptor that corresponds to the
+ /// \brief Return the machine instruction descriptor that corresponds to the
/// specified instruction opcode.
- ///
const MCInstrDesc &get(unsigned Opcode) const {
assert(Opcode < NumOpcodes && "Invalid opcode!");
return Desc[Opcode];
}
- /// getName - Returns the name for the instructions with the given opcode.
+ /// \brief Returns the name for the instructions with the given opcode.
const char *getName(unsigned Opcode) const {
assert(Opcode < NumOpcodes && "Invalid opcode!");
return &InstrNameData[InstrNameIndices[Opcode]];
diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h
index 94d599f672af..161705de7c4e 100644
--- a/include/llvm/MC/MCInstrItineraries.h
+++ b/include/llvm/MC/MCInstrItineraries.h
@@ -67,12 +67,12 @@ struct InstrStage {
int NextCycles_; ///< Number of machine cycles to next stage
ReservationKinds Kind_; ///< Kind of the FU reservation
- /// Returns the number of cycles the stage is occupied.
+ /// \brief Returns the number of cycles the stage is occupied.
unsigned getCycles() const {
return Cycles_;
}
- /// Returns the choice of FUs.
+ /// \brief Returns the choice of FUs.
unsigned getUnits() const {
return Units_;
}
@@ -81,8 +81,8 @@ struct InstrStage {
return Kind_;
}
- /// Returns the number of cycles from the start of
- /// this stage to the start of the next stage in the itinerary
+ /// \brief 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_;
}
@@ -115,7 +115,6 @@ public:
const InstrItinerary *Itineraries; ///< Array of itineraries selected
/// Ctors.
- ///
InstrItineraryData() : SchedModel(MCSchedModel::GetDefaultSchedModel()),
Stages(nullptr), OperandCycles(nullptr),
Forwardings(nullptr), Itineraries(nullptr) {}
@@ -125,30 +124,30 @@ public:
: SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F),
Itineraries(SchedModel.InstrItineraries) {}
- /// Returns true if there are no itineraries.
+ /// \brief Returns true if there are no itineraries.
bool isEmpty() const { return Itineraries == nullptr; }
- /// Returns true if the index is for the end marker itinerary.
+ /// \brief Returns true if the index is for the end marker itinerary.
bool isEndMarker(unsigned ItinClassIndx) const {
return ((Itineraries[ItinClassIndx].FirstStage == ~0U) &&
(Itineraries[ItinClassIndx].LastStage == ~0U));
}
- /// Return the first stage of the itinerary.
+ /// \brief Return the first stage of the itinerary.
const InstrStage *beginStage(unsigned ItinClassIndx) const {
unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage;
return Stages + StageIdx;
}
- /// Return the last+1 stage of the itinerary.
+ /// \brief Return the last+1 stage of the itinerary.
const InstrStage *endStage(unsigned ItinClassIndx) const {
unsigned StageIdx = Itineraries[ItinClassIndx].LastStage;
return Stages + StageIdx;
}
- /// 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.
+ /// \brief 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
// non-zero default value for all instructions.
@@ -165,8 +164,8 @@ public:
return Latency;
}
- /// Return the cycle for the given class and operand.
- /// Return -1 if no cycle is specified for the operand.
+ /// \brief 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;
@@ -179,11 +178,11 @@ public:
return (int)OperandCycles[FirstIdx + OperandIdx];
}
- /// Return true if there is a pipeline forwarding
- /// between instructions of itinerary classes DefClass and UseClasses so that
- /// value produced by an instruction of itinerary class DefClass, operand
- /// index DefIdx can be bypassed when it's read by an instruction of
- /// itinerary class UseClass, operand index UseIdx.
+ /// \brief Return true if there is a pipeline forwarding between instructions
+ /// of itinerary classes DefClass and UseClasses so that value produced by an
+ /// instruction of itinerary class DefClass, operand index DefIdx can be
+ /// bypassed when it's read by an instruction of itinerary class UseClass,
+ /// operand index UseIdx.
bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx,
unsigned UseClass, unsigned UseIdx) const {
unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle;
@@ -202,9 +201,9 @@ public:
Forwardings[FirstUseIdx + UseIdx];
}
- /// 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.
+ /// \brief 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,
unsigned UseClass, unsigned UseIdx) const {
if (isEmpty())
@@ -226,7 +225,7 @@ public:
return UseCycle;
}
- /// Return the number of micro-ops that the given class decodes to.
+ /// \brief Return the number of micro-ops that the given class decodes to.
/// Return -1 for classes that require dynamic lookup via TargetInstrInfo.
int getNumMicroOps(unsigned ItinClassIndx) const {
if (isEmpty())
diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h
index f531de8b40d9..de2d0af1423a 100644
--- a/include/llvm/MC/MCLabel.h
+++ b/include/llvm/MC/MCLabel.h
@@ -20,11 +20,11 @@ namespace llvm {
class MCContext;
class raw_ostream;
- /// MCLabel - Instances of this class represent a label name in the MC file,
- /// and MCLabel are created and unique'd by the MCContext class. MCLabel
+ /// \brief Instances of this class represent a label name in the MC file,
+ /// and MCLabel are created and uniqued by the MCContext class. MCLabel
/// should only be constructed for valid instances in the object file.
class MCLabel {
- // Instance - the instance number of this Directional Local Label
+ // \brief The instance number of this Directional Local Label.
unsigned Instance;
private: // MCContext creates and uniques these.
@@ -32,20 +32,19 @@ namespace llvm {
MCLabel(unsigned instance)
: Instance(instance) {}
- MCLabel(const MCLabel&) LLVM_DELETED_FUNCTION;
- void operator=(const MCLabel&) LLVM_DELETED_FUNCTION;
+ MCLabel(const MCLabel&) = delete;
+ void operator=(const MCLabel&) = delete;
public:
- /// getInstance - Get the current instance of this Directional Local Label.
+ /// \brief Get the current instance of this Directional Local Label.
unsigned getInstance() const { return Instance; }
- /// incInstance - Increment the current instance of this Directional Local
- /// Label.
+ /// \brief Increment the current instance of this Directional Local Label.
unsigned incInstance() { return ++Instance; }
- /// print - Print the value to the stream \p OS.
+ /// \brief Print the value to the stream \p OS.
void print(raw_ostream &OS) const;
- /// dump - Print the value to stderr.
+ /// \brief Print the value to stderr.
void dump() const;
};
diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h
index 890d6385aacd..a186a14b8001 100644
--- a/include/llvm/MC/MCLinkerOptimizationHint.h
+++ b/include/llvm/MC/MCLinkerOptimizationHint.h
@@ -103,8 +103,8 @@ class MCLOHDirective {
/// Arguments of this directive. Order matters.
SmallVector<MCSymbol *, 3> Args;
- /// Emit this directive in @p OutStream using the information available
- /// in the given @p ObjWriter and @p Layout to get the address of the
+ /// Emit this directive in \p OutStream using the information available
+ /// in the given \p ObjWriter and \p Layout to get the address of the
/// arguments within the object file.
void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter,
const MCAsmLayout &Layout) const;
@@ -128,8 +128,8 @@ public:
Emit_impl(OutStream, ObjWriter, Layout);
}
- /// Get the size in bytes of this directive if emitted in @p ObjWriter with
- /// the given @p Layout.
+ /// Get the size in bytes of this directive if emitted in \p ObjWriter with
+ /// the given \p Layout.
uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
const MCAsmLayout &Layout) const {
class raw_counting_ostream : public raw_ostream {
@@ -141,7 +141,7 @@ public:
public:
raw_counting_ostream() : Count(0) {}
- ~raw_counting_ostream() { flush(); }
+ ~raw_counting_ostream() override { flush(); }
};
raw_counting_ostream OutStream;
@@ -167,8 +167,8 @@ public:
return Directives;
}
- /// Add the directive of the given kind @p Kind with the given arguments
- /// @p Args to the container.
+ /// Add the directive of the given kind \p Kind with the given arguments
+ /// \p Args to the container.
void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) {
Directives.push_back(MCLOHDirective(Kind, Args));
}
diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h
index 0c5aa8a18063..63c2a28a7c9c 100644
--- a/include/llvm/MC/MCMachObjectWriter.h
+++ b/include/llvm/MC/MCMachObjectWriter.h
@@ -21,7 +21,6 @@
namespace llvm {
-class MCSectionData;
class MachObjectWriter;
class MCMachObjectTargetWriter {
@@ -45,14 +44,14 @@ protected:
public:
virtual ~MCMachObjectTargetWriter();
- /// @name Lifetime Management
+ /// \name Lifetime Management
/// @{
virtual void reset() {};
/// @}
- /// @name Accessors
+ /// \name Accessors
/// @{
bool is64Bit() const { return Is64Bit; }
@@ -65,15 +64,13 @@ public:
/// @}
- /// @name API
+ /// \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;
/// @}
@@ -83,7 +80,7 @@ class MachObjectWriter : public MCObjectWriter {
/// MachSymbolData - Helper struct for containing some precomputed information
/// on symbols.
struct MachSymbolData {
- MCSymbolData *SymbolData;
+ const MCSymbol *Symbol;
uint64_t StringIndex;
uint8_t SectionIndex;
@@ -94,15 +91,21 @@ class MachObjectWriter : public MCObjectWriter {
/// The target specific Mach-O writer instance.
std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter;
- /// @name Relocation Data
+ /// \name Relocation Data
/// @{
- llvm::DenseMap<const MCSectionData*,
- std::vector<MachO::any_relocation_info> > Relocations;
- llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase;
+ struct RelAndSymbol {
+ const MCSymbol *Sym;
+ MachO::any_relocation_info MRE;
+ RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE)
+ : Sym(Sym), MRE(MRE) {}
+ };
+
+ llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
+ llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase;
/// @}
- /// @name Symbol Table Data
+ /// \name Symbol Table Data
/// @{
StringTableBuilder StringTable;
@@ -115,19 +118,20 @@ class MachObjectWriter : public MCObjectWriter {
MachSymbolData *findSymbolData(const MCSymbol &Sym);
public:
- MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
- bool _IsLittleEndian)
- : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) {
- }
+ MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
+ bool IsLittleEndian)
+ : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
+
+ const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;
- /// @name Lifetime management Methods
+ /// \name Lifetime management Methods
/// @{
void reset() override;
/// @}
- /// @name Utility Methods
+ /// \name Utility Methods
/// @{
bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
@@ -136,23 +140,21 @@ public:
SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
- uint64_t getSectionAddress(const MCSectionData* SD) const {
- return SectionAddress.lookup(SD);
+ uint64_t getSectionAddress(const MCSection *Sec) const {
+ return SectionAddress.lookup(Sec);
}
- uint64_t getSymbolAddress(const MCSymbolData* SD,
- const MCAsmLayout &Layout) const;
+ uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const;
uint64_t getFragmentAddress(const MCFragment *Fragment,
const MCAsmLayout &Layout) const;
- uint64_t getPaddingSize(const MCSectionData *SD,
- const MCAsmLayout &Layout) const;
+ uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const;
- bool doesSymbolRequireExternRelocation(const MCSymbolData *SD);
+ bool doesSymbolRequireExternRelocation(const MCSymbol &S);
/// @}
- /// @name Target Writer Proxy Accessors
+ /// \name Target Writer Proxy Accessors
/// @{
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
@@ -176,7 +178,7 @@ public:
uint64_t SectionDataSize);
void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCSectionData &SD, uint64_t FileOffset,
+ const MCSection &Sec, uint64_t FileOffset,
uint64_t RelocationsStart, unsigned NumRelocations);
void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
@@ -213,9 +215,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 MCSymbol *RelSymbol, const MCSection *Sec,
MachO::any_relocation_info &MRE) {
- Relocations[SD].push_back(MRE);
+ RelAndSymbol P(RelSymbol, MRE);
+ Relocations[Sec].push_back(P);
}
void RecordScatteredRelocation(const MCAssembler &Asm,
@@ -231,7 +239,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;
@@ -248,15 +256,12 @@ public:
void computeSectionAddresses(const MCAssembler &Asm,
const MCAsmLayout &Layout);
- void markAbsoluteVariableSymbols(MCAssembler &Asm,
- const MCAsmLayout &Layout);
void ExecutePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) override;
bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
- const MCSymbolData &DataA,
- const MCFragment &FB,
- bool InSet,
+ const MCSymbol &SymA,
+ const MCFragment &FB, bool InSet,
bool IsPCRel) const override;
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
@@ -271,7 +276,8 @@ public:
/// \param OS - The stream to write to.
/// \returns The constructed object writer.
MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
- raw_ostream &OS, bool IsLittleEndian);
+ raw_pwrite_stream &OS,
+ bool IsLittleEndian);
} // End llvm namespace
diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h
index 321043c522ee..f28b9c668cdc 100644
--- a/include/llvm/MC/MCObjectFileInfo.h
+++ b/include/llvm/MC/MCObjectFileInfo.h
@@ -53,144 +53,139 @@ protected:
/// should emit only an EH frame.
unsigned CompactUnwindDwarfEHFrameOnly;
- /// TextSection - Section directive for standard text.
+ /// Section directive for standard text.
///
- const MCSection *TextSection;
+ MCSection *TextSection;
- /// DataSection - Section directive for standard data.
+ /// Section directive for standard data.
///
- const MCSection *DataSection;
+ MCSection *DataSection;
- /// BSSSection - Section that is default initialized to zero.
- const MCSection *BSSSection;
+ /// Section that is default initialized to zero.
+ MCSection *BSSSection;
- /// ReadOnlySection - Section that is readonly and can contain arbitrary
- /// initialized data. Targets are not required to have a readonly section.
- /// If they don't, various bits of code will fall back to using the data
- /// section for constants.
- const MCSection *ReadOnlySection;
+ /// Section that is readonly and can contain arbitrary initialized data.
+ /// Targets are not required to have a readonly section. If they don't,
+ /// various bits of code will fall back to using the data section for
+ /// constants.
+ MCSection *ReadOnlySection;
- /// StaticCtorSection - This section contains the static constructor pointer
- /// list.
- const MCSection *StaticCtorSection;
+ /// This section contains the static constructor pointer list.
+ MCSection *StaticCtorSection;
- /// StaticDtorSection - This section contains the static destructor pointer
- /// list.
- const MCSection *StaticDtorSection;
+ /// This section contains the static destructor pointer list.
+ MCSection *StaticDtorSection;
- /// LSDASection - If exception handling is supported by the target, this is
- /// the section the Language Specific Data Area information is emitted to.
- const MCSection *LSDASection;
+ /// If exception handling is supported by the target, this is the section the
+ /// Language Specific Data Area information is emitted to.
+ MCSection *LSDASection;
- /// CompactUnwindSection - If exception handling is supported by the target
- /// and the target can support a compact representation of the CIE and FDE,
- /// this is the section to emit them into.
- const MCSection *CompactUnwindSection;
+ /// If exception handling is supported by the target and the target can
+ /// support a compact representation of the CIE and FDE, this is the section
+ /// to emit them into.
+ MCSection *CompactUnwindSection;
// Dwarf sections for debug info. If a target supports debug info, these must
// be set.
- const MCSection *DwarfAbbrevSection;
- const MCSection *DwarfInfoSection;
- const MCSection *DwarfLineSection;
- const MCSection *DwarfFrameSection;
- const MCSection *DwarfPubTypesSection;
+ MCSection *DwarfAbbrevSection;
+ MCSection *DwarfInfoSection;
+ MCSection *DwarfLineSection;
+ MCSection *DwarfFrameSection;
+ MCSection *DwarfPubTypesSection;
const MCSection *DwarfDebugInlineSection;
- const MCSection *DwarfStrSection;
- const MCSection *DwarfLocSection;
- const MCSection *DwarfARangesSection;
- const MCSection *DwarfRangesSection;
- const MCSection *DwarfMacroInfoSection;
+ MCSection *DwarfStrSection;
+ MCSection *DwarfLocSection;
+ MCSection *DwarfARangesSection;
+ MCSection *DwarfRangesSection;
// The pubnames section is no longer generated by default. The generation
// can be enabled by a compiler flag.
- const MCSection *DwarfPubNamesSection;
+ MCSection *DwarfPubNamesSection;
// DWARF5 Experimental Debug Info Sections
/// DwarfAccelNamesSection, DwarfAccelObjCSection,
/// DwarfAccelNamespaceSection, DwarfAccelTypesSection -
/// If we use the DWARF accelerated hash tables then we want to emit these
/// sections.
- const MCSection *DwarfAccelNamesSection;
- const MCSection *DwarfAccelObjCSection;
- const MCSection *DwarfAccelNamespaceSection;
- const MCSection *DwarfAccelTypesSection;
+ MCSection *DwarfAccelNamesSection;
+ MCSection *DwarfAccelObjCSection;
+ MCSection *DwarfAccelNamespaceSection;
+ MCSection *DwarfAccelTypesSection;
/// 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;
- const MCSection *DwarfLocDWOSection;
- const MCSection *DwarfStrOffDWOSection;
- const MCSection *DwarfAddrSection;
+ MCSection *DwarfInfoDWOSection;
+ MCSection *DwarfTypesDWOSection;
+ MCSection *DwarfAbbrevDWOSection;
+ MCSection *DwarfStrDWOSection;
+ MCSection *DwarfLineDWOSection;
+ MCSection *DwarfLocDWOSection;
+ MCSection *DwarfStrOffDWOSection;
+ MCSection *DwarfAddrSection;
/// Sections for newer gnu pubnames and pubtypes.
- const MCSection *DwarfGnuPubNamesSection;
- const MCSection *DwarfGnuPubTypesSection;
+ MCSection *DwarfGnuPubNamesSection;
+ MCSection *DwarfGnuPubTypesSection;
- const MCSection *COFFDebugSymbolsSection;
+ MCSection *COFFDebugSymbolsSection;
// Extra TLS Variable Data section. If the target needs to put additional
// information for a TLS variable, it'll go here.
- const MCSection *TLSExtraDataSection;
+ MCSection *TLSExtraDataSection;
- /// TLSDataSection - Section directive for Thread Local data.
- /// ELF, MachO and COFF.
- const MCSection *TLSDataSection; // Defaults to ".tdata".
+ /// Section directive for Thread Local data. ELF, MachO and COFF.
+ MCSection *TLSDataSection; // Defaults to ".tdata".
- /// TLSBSSSection - Section directive for Thread Local uninitialized data.
- /// Null if this target doesn't support a BSS section.
- /// ELF and MachO only.
- const MCSection *TLSBSSSection; // Defaults to ".tbss".
+ /// Section directive for Thread Local uninitialized data. Null if this target
+ /// doesn't support a BSS section. ELF and MachO only.
+ MCSection *TLSBSSSection; // Defaults to ".tbss".
/// StackMap section.
- const MCSection *StackMapSection;
+ MCSection *StackMapSection;
- /// EHFrameSection - EH frame section. It is initialized on demand so it
- /// can be overwritten (with uniquing).
- const MCSection *EHFrameSection;
+ /// EH frame section. It is initialized on demand so it can be overwritten
+ /// (with uniquing).
+ MCSection *EHFrameSection;
/// ELF specific sections.
///
- const MCSection *DataRelSection;
+ MCSection *DataRelSection;
const MCSection *DataRelLocalSection;
- const MCSection *DataRelROSection;
- const MCSection *DataRelROLocalSection;
- const MCSection *MergeableConst4Section;
- const MCSection *MergeableConst8Section;
- const MCSection *MergeableConst16Section;
+ MCSection *DataRelROSection;
+ MCSection *DataRelROLocalSection;
+ MCSection *MergeableConst4Section;
+ MCSection *MergeableConst8Section;
+ MCSection *MergeableConst16Section;
/// MachO specific sections.
///
- /// TLSTLVSection - Section for thread local structure information.
- /// Contains the source code name of the variable, visibility and a pointer
- /// to the initial value (.tdata or .tbss).
- const MCSection *TLSTLVSection; // Defaults to ".tlv".
+ /// Section for thread local structure information. Contains the source code
+ /// name of the variable, visibility and a pointer to the initial value
+ /// (.tdata or .tbss).
+ MCSection *TLSTLVSection; // Defaults to ".tlv".
/// TLSThreadInitSection - Section for thread local data initialization
/// functions.
const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func".
- const MCSection *CStringSection;
- const MCSection *UStringSection;
- const MCSection *TextCoalSection;
- const MCSection *ConstTextCoalSection;
- const MCSection *ConstDataSection;
- const MCSection *DataCoalSection;
- const MCSection *DataCommonSection;
- const MCSection *DataBSSSection;
- const MCSection *FourByteConstantSection;
- const MCSection *EightByteConstantSection;
- const MCSection *SixteenByteConstantSection;
- const MCSection *LazySymbolPointerSection;
- const MCSection *NonLazySymbolPointerSection;
+ MCSection *CStringSection;
+ MCSection *UStringSection;
+ MCSection *TextCoalSection;
+ MCSection *ConstTextCoalSection;
+ MCSection *ConstDataSection;
+ MCSection *DataCoalSection;
+ MCSection *DataCommonSection;
+ MCSection *DataBSSSection;
+ MCSection *FourByteConstantSection;
+ MCSection *EightByteConstantSection;
+ MCSection *SixteenByteConstantSection;
+ MCSection *LazySymbolPointerSection;
+ MCSection *NonLazySymbolPointerSection;
/// COFF specific sections.
///
- const MCSection *DrectveSection;
- const MCSection *PDataSection;
- const MCSection *XDataSection;
+ MCSection *DrectveSection;
+ MCSection *PDataSection;
+ MCSection *XDataSection;
public:
void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM,
@@ -215,97 +210,70 @@ public:
return CompactUnwindDwarfEHFrameOnly;
}
- const MCSection *getTextSection() const { return TextSection; }
- const MCSection *getDataSection() const { return DataSection; }
- const MCSection *getBSSSection() const { return BSSSection; }
- const MCSection *getLSDASection() const { return LSDASection; }
- const MCSection *getCompactUnwindSection() const{
- return CompactUnwindSection;
- }
- const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; }
- const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; }
- const MCSection *getDwarfLineSection() const { return DwarfLineSection; }
- const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; }
- const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;}
- const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;}
- const MCSection *getDwarfGnuPubNamesSection() const {
+ MCSection *getTextSection() const { return TextSection; }
+ MCSection *getDataSection() const { return DataSection; }
+ MCSection *getBSSSection() const { return BSSSection; }
+ MCSection *getLSDASection() const { return LSDASection; }
+ MCSection *getCompactUnwindSection() const { return CompactUnwindSection; }
+ MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; }
+ MCSection *getDwarfInfoSection() const { return DwarfInfoSection; }
+ MCSection *getDwarfLineSection() const { return DwarfLineSection; }
+ MCSection *getDwarfFrameSection() const { return DwarfFrameSection; }
+ MCSection *getDwarfPubNamesSection() const { return DwarfPubNamesSection; }
+ MCSection *getDwarfPubTypesSection() const { return DwarfPubTypesSection; }
+ MCSection *getDwarfGnuPubNamesSection() const {
return DwarfGnuPubNamesSection;
}
- const MCSection *getDwarfGnuPubTypesSection() const {
+ MCSection *getDwarfGnuPubTypesSection() const {
return DwarfGnuPubTypesSection;
}
const MCSection *getDwarfDebugInlineSection() const {
return DwarfDebugInlineSection;
}
- const MCSection *getDwarfStrSection() const { return DwarfStrSection; }
- const MCSection *getDwarfLocSection() const { return DwarfLocSection; }
- const MCSection *getDwarfARangesSection() const { return DwarfARangesSection;}
- const MCSection *getDwarfRangesSection() const { return DwarfRangesSection; }
- const MCSection *getDwarfMacroInfoSection() const {
- return DwarfMacroInfoSection;
- }
+ MCSection *getDwarfStrSection() const { return DwarfStrSection; }
+ MCSection *getDwarfLocSection() const { return DwarfLocSection; }
+ MCSection *getDwarfARangesSection() const { return DwarfARangesSection; }
+ MCSection *getDwarfRangesSection() const { return DwarfRangesSection; }
// DWARF5 Experimental Debug Info Sections
- const MCSection *getDwarfAccelNamesSection() const {
+ MCSection *getDwarfAccelNamesSection() const {
return DwarfAccelNamesSection;
}
- const MCSection *getDwarfAccelObjCSection() const {
- return DwarfAccelObjCSection;
- }
- const MCSection *getDwarfAccelNamespaceSection() const {
+ MCSection *getDwarfAccelObjCSection() const { return DwarfAccelObjCSection; }
+ MCSection *getDwarfAccelNamespaceSection() const {
return DwarfAccelNamespaceSection;
}
- const MCSection *getDwarfAccelTypesSection() const {
+ MCSection *getDwarfAccelTypesSection() const {
return DwarfAccelTypesSection;
}
- const MCSection *getDwarfInfoDWOSection() const {
- return DwarfInfoDWOSection;
- }
- const MCSection *getDwarfTypesSection(uint64_t Hash) const;
- const MCSection *getDwarfTypesDWOSection() const {
- return DwarfTypesDWOSection;
- }
- const MCSection *getDwarfAbbrevDWOSection() const {
- return DwarfAbbrevDWOSection;
- }
- const MCSection *getDwarfStrDWOSection() const {
- return DwarfStrDWOSection;
- }
- const MCSection *getDwarfLineDWOSection() const {
- return DwarfLineDWOSection;
- }
- const MCSection *getDwarfLocDWOSection() const {
- return DwarfLocDWOSection;
- }
- const MCSection *getDwarfStrOffDWOSection() const {
- return DwarfStrOffDWOSection;
- }
- const MCSection *getDwarfAddrSection() const {
- return DwarfAddrSection;
- }
-
- const MCSection *getCOFFDebugSymbolsSection() const {
+ MCSection *getDwarfInfoDWOSection() const { return DwarfInfoDWOSection; }
+ MCSection *getDwarfTypesSection(uint64_t Hash) const;
+ MCSection *getDwarfTypesDWOSection() const { return DwarfTypesDWOSection; }
+ MCSection *getDwarfAbbrevDWOSection() const { return DwarfAbbrevDWOSection; }
+ MCSection *getDwarfStrDWOSection() const { return DwarfStrDWOSection; }
+ MCSection *getDwarfLineDWOSection() const { return DwarfLineDWOSection; }
+ MCSection *getDwarfLocDWOSection() const { return DwarfLocDWOSection; }
+ MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; }
+ MCSection *getDwarfAddrSection() const { return DwarfAddrSection; }
+
+ MCSection *getCOFFDebugSymbolsSection() const {
return COFFDebugSymbolsSection;
}
- const MCSection *getTLSExtraDataSection() const {
- return TLSExtraDataSection;
- }
+ MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; }
const MCSection *getTLSDataSection() const { return TLSDataSection; }
- const MCSection *getTLSBSSSection() const { return TLSBSSSection; }
+ MCSection *getTLSBSSSection() const { return TLSBSSSection; }
- const MCSection *getStackMapSection() const { return StackMapSection; }
+ MCSection *getStackMapSection() const { return StackMapSection; }
/// ELF specific sections.
///
- const MCSection *getDataRelSection() const { return DataRelSection; }
+ MCSection *getDataRelSection() const { return DataRelSection; }
const MCSection *getDataRelLocalSection() const {
return DataRelLocalSection;
}
- const MCSection *getDataRelROSection() const { return DataRelROSection; }
- const MCSection *getDataRelROLocalSection() const {
- return DataRelROLocalSection;
- }
+ MCSection *getDataRelROSection() const { return DataRelROSection; }
+ MCSection *getDataRelROLocalSection() const { return DataRelROLocalSection; }
const MCSection *getMergeableConst4Section() const {
return MergeableConst4Section;
}
@@ -324,14 +292,14 @@ public:
}
const MCSection *getCStringSection() const { return CStringSection; }
const MCSection *getUStringSection() const { return UStringSection; }
- const MCSection *getTextCoalSection() const { return TextCoalSection; }
+ MCSection *getTextCoalSection() const { return TextCoalSection; }
const MCSection *getConstTextCoalSection() const {
return ConstTextCoalSection;
}
const MCSection *getConstDataSection() const { return ConstDataSection; }
const MCSection *getDataCoalSection() const { return DataCoalSection; }
const MCSection *getDataCommonSection() const { return DataCommonSection; }
- const MCSection *getDataBSSSection() const { return DataBSSSection; }
+ MCSection *getDataBSSSection() const { return DataBSSSection; }
const MCSection *getFourByteConstantSection() const {
return FourByteConstantSection;
}
@@ -341,20 +309,20 @@ public:
const MCSection *getSixteenByteConstantSection() const {
return SixteenByteConstantSection;
}
- const MCSection *getLazySymbolPointerSection() const {
+ MCSection *getLazySymbolPointerSection() const {
return LazySymbolPointerSection;
}
- const MCSection *getNonLazySymbolPointerSection() const {
+ MCSection *getNonLazySymbolPointerSection() const {
return NonLazySymbolPointerSection;
}
/// COFF specific sections.
///
- const MCSection *getDrectveSection() const { return DrectveSection; }
- const MCSection *getPDataSection() const { return PDataSection; }
- const MCSection *getXDataSection() const { return XDataSection; }
+ MCSection *getDrectveSection() const { return DrectveSection; }
+ MCSection *getPDataSection() const { return PDataSection; }
+ MCSection *getXDataSection() const { return XDataSection; }
- const MCSection *getEHFrameSection() {
+ MCSection *getEHFrameSection() {
if (!EHFrameSection)
InitEHFrameSection();
return EHFrameSection;
diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h
index 0866ff5a9fc0..e75bc86cc131 100644
--- a/include/llvm/MC/MCObjectStreamer.h
+++ b/include/llvm/MC/MCObjectStreamer.h
@@ -12,18 +12,19 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
namespace llvm {
class MCAssembler;
class MCCodeEmitter;
-class MCSectionData;
class MCSubtargetInfo;
class MCExpr;
class MCFragment;
class MCDataFragment;
class MCAsmBackend;
class raw_ostream;
+class raw_pwrite_stream;
/// \brief Streaming object file generation interface.
///
@@ -34,8 +35,8 @@ class raw_ostream;
/// implementation.
class MCObjectStreamer : public MCStreamer {
MCAssembler *Assembler;
- MCSectionData *CurSectionData;
- MCSectionData::iterator CurInsertionPoint;
+ MCSection *CurSectionData;
+ MCSection::iterator CurInsertionPoint;
bool EmitEHFrame;
bool EmitDebugFrame;
SmallVector<MCSymbolData *, 2> PendingLabels;
@@ -44,16 +45,10 @@ class MCObjectStreamer : public MCStreamer {
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);
- MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS,
- MCCodeEmitter *_Emitter, MCAssembler *_Assembler);
- ~MCObjectStreamer();
+ MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter);
+ ~MCObjectStreamer() override;
public:
/// state management
@@ -69,9 +64,7 @@ public:
void EmitCFISections(bool EH, bool Debug) override;
protected:
- MCSectionData *getCurrentSectionData() const {
- return CurSectionData;
- }
+ MCSection *getCurrentSectionData() const { return CurSectionData; }
MCFragment *getCurrentFragment() const;
@@ -85,12 +78,20 @@ protected:
/// fragment is not a data fragment.
MCDataFragment *getOrCreateDataFragment();
+ bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection);
+
+ /// 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.
+ /// Optionally, it is also possible to provide an offset \p FOffset, which
+ /// will be used as a symbol offset within the fragment.
+ void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0);
+
public:
void visitUsedSymbol(const MCSymbol &Sym) override;
MCAssembler &getAssembler() { return *Assembler; }
- /// @name MCStreamer Interface
+ /// \name MCStreamer Interface
/// @{
void EmitLabel(MCSymbol *Symbol) override;
@@ -100,8 +101,7 @@ public:
void EmitULEB128Value(const MCExpr *Value) override;
void EmitSLEB128Value(const MCExpr *Value) override;
void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
- void ChangeSection(const MCSection *Section,
- const MCExpr *Subsection) override;
+ void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo& STI) override;
/// \brief Emit an instruction to a special fragment, because this instruction
@@ -133,9 +133,18 @@ public:
void EmitZeros(uint64_t NumBytes) override;
void FinishImpl() override;
- bool mayHaveInstructions() const override {
- return getCurrentSectionData()->hasInstructions();
- }
+ /// Emit the absolute difference between two symbols if possible.
+ ///
+ /// Emit the absolute difference between \c Hi and \c Lo, as long as we can
+ /// compute it. Currently, that requires that both symbols are in the same
+ /// data fragment. Otherwise, do nothing and return \c false.
+ ///
+ /// \pre Offset of \c Hi is greater than the offset \c Lo.
+ /// \return true on success.
+ bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
+ unsigned Size) override;
+
+ bool mayHaveInstructions(MCSection &Sec) const override;
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h
index 55c828c6c179..999d29471270 100644
--- a/include/llvm/MC/MCObjectWriter.h
+++ b/include/llvm/MC/MCObjectWriter.h
@@ -13,6 +13,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
@@ -37,17 +38,17 @@ class MCValue;
/// The object writer also contains a number of helper methods for writing
/// binary data to the output stream.
class MCObjectWriter {
- MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
- void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
+ MCObjectWriter(const MCObjectWriter &) = delete;
+ void operator=(const MCObjectWriter &) = delete;
protected:
- raw_ostream &OS;
+ raw_pwrite_stream &OS;
unsigned IsLittleEndian : 1;
protected: // Can only create subclasses.
- MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
- : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
+ MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian)
+ : OS(OS), IsLittleEndian(IsLittleEndian) {}
public:
virtual ~MCObjectWriter();
@@ -59,7 +60,7 @@ public:
raw_ostream &getStream() { return OS; }
- /// @name High-Level API
+ /// \name High-Level API
/// @{
/// \brief Perform any late binding of symbols (for example, to assign symbol
@@ -76,30 +77,31 @@ 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.
///
/// Clients are not required to answer precisely and may conservatively return
/// false, even when a difference is fully resolved.
- bool
- IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
- const MCSymbolRefExpr *A,
- const MCSymbolRefExpr *B,
- bool InSet) const;
-
- virtual bool
- IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
- const MCSymbolData &DataA,
- const MCFragment &FB,
- bool InSet,
- bool IsPCRel) const;
+ bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
+ const MCSymbolRefExpr *A,
+ const MCSymbolRefExpr *B,
+ bool InSet) const;
+
+ virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
+ const MCSymbol &SymA,
+ const MCFragment &FB,
+ bool InSet,
+ bool IsPCRel) const;
+
+ /// \brief True if this symbol (which is a variable) is weak. This is not
+ /// just STB_WEAK, but more generally whether or not we can evaluate
+ /// past it.
+ virtual bool isWeak(const MCSymbol &Sym) const;
/// \brief Write the object file.
///
@@ -110,7 +112,7 @@ public:
const MCAsmLayout &Layout) = 0;
/// @}
- /// @name Binary Output
+ /// \name Binary Output
/// @{
void Write8(uint8_t Value) {
@@ -118,33 +120,27 @@ public:
}
void WriteLE16(uint16_t Value) {
- Write8(uint8_t(Value >> 0));
- Write8(uint8_t(Value >> 8));
+ support::endian::Writer<support::little>(OS).write(Value);
}
void WriteLE32(uint32_t Value) {
- WriteLE16(uint16_t(Value >> 0));
- WriteLE16(uint16_t(Value >> 16));
+ support::endian::Writer<support::little>(OS).write(Value);
}
void WriteLE64(uint64_t Value) {
- WriteLE32(uint32_t(Value >> 0));
- WriteLE32(uint32_t(Value >> 32));
+ support::endian::Writer<support::little>(OS).write(Value);
}
void WriteBE16(uint16_t Value) {
- Write8(uint8_t(Value >> 8));
- Write8(uint8_t(Value >> 0));
+ support::endian::Writer<support::big>(OS).write(Value);
}
void WriteBE32(uint32_t Value) {
- WriteBE16(uint16_t(Value >> 16));
- WriteBE16(uint16_t(Value >> 0));
+ support::endian::Writer<support::big>(OS).write(Value);
}
void WriteBE64(uint64_t Value) {
- WriteBE32(uint32_t(Value >> 32));
- WriteBE32(uint32_t(Value >> 0));
+ support::endian::Writer<support::big>(OS).write(Value);
}
void Write16(uint16_t Value) {
diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h
index a9a30f172071..62d39b26c860 100644
--- a/include/llvm/MC/MCParser/AsmLexer.h
+++ b/include/llvm/MC/MCParser/AsmLexer.h
@@ -31,8 +31,8 @@ class AsmLexer : public MCAsmLexer {
StringRef CurBuf;
bool isAtStartOfLine;
- void operator=(const AsmLexer&) LLVM_DELETED_FUNCTION;
- AsmLexer(const AsmLexer&) LLVM_DELETED_FUNCTION;
+ void operator=(const AsmLexer&) = delete;
+ AsmLexer(const AsmLexer&) = delete;
protected:
/// LexToken - Read the next token and return its code.
@@ -40,7 +40,7 @@ protected:
public:
AsmLexer(const MCAsmInfo &MAI);
- ~AsmLexer();
+ ~AsmLexer() override;
void setBuffer(StringRef Buf, const char *ptr = nullptr);
diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h
index b05891c13250..71f15b37c331 100644
--- a/include/llvm/MC/MCParser/MCAsmLexer.h
+++ b/include/llvm/MC/MCParser/MCAsmLexer.h
@@ -63,10 +63,10 @@ private:
public:
AsmToken() {}
- AsmToken(TokenKind _Kind, StringRef _Str, APInt _IntVal)
- : Kind(_Kind), Str(_Str), IntVal(_IntVal) {}
- AsmToken(TokenKind _Kind, StringRef _Str, int64_t _IntVal = 0)
- : Kind(_Kind), Str(_Str), IntVal(64, _IntVal, true) {}
+ AsmToken(TokenKind Kind, StringRef Str, APInt IntVal)
+ : Kind(Kind), Str(Str), IntVal(IntVal) {}
+ AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0)
+ : Kind(Kind), Str(Str), IntVal(64, IntVal, true) {}
TokenKind getKind() const { return Kind; }
bool is(TokenKind K) const { return Kind == K; }
@@ -124,8 +124,8 @@ class MCAsmLexer {
SMLoc ErrLoc;
std::string Err;
- MCAsmLexer(const MCAsmLexer &) LLVM_DELETED_FUNCTION;
- void operator=(const MCAsmLexer &) LLVM_DELETED_FUNCTION;
+ MCAsmLexer(const MCAsmLexer &) = delete;
+ void operator=(const MCAsmLexer &) = delete;
protected: // Can only create subclasses.
const char *TokStart;
bool SkipSpace;
diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h
index 34188e66e62d..0538b9457f9e 100644
--- a/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/include/llvm/MC/MCParser/MCAsmParser.h
@@ -45,7 +45,7 @@ public:
}
};
-/// Generic Sema callback for assembly parser.
+/// \brief Generic Sema callback for assembly parser.
class MCAsmParserSemaCallback {
public:
virtual ~MCAsmParserSemaCallback();
@@ -59,8 +59,8 @@ public:
unsigned &Offset) = 0;
};
-/// Generic assembler parser interface, for use by target specific assembly
-/// parsers.
+/// \brief Generic assembler parser interface, for use by target specific
+/// assembly parsers.
class MCAsmParser {
public:
typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc);
@@ -68,8 +68,8 @@ public:
ExtensionDirectiveHandler;
private:
- MCAsmParser(const MCAsmParser &) LLVM_DELETED_FUNCTION;
- void operator=(const MCAsmParser &) LLVM_DELETED_FUNCTION;
+ MCAsmParser(const MCAsmParser &) = delete;
+ void operator=(const MCAsmParser &) = delete;
MCTargetAsmParser *TargetParser;
@@ -84,6 +84,8 @@ public:
virtual void addDirectiveHandler(StringRef Directive,
ExtensionDirectiveHandler Handler) = 0;
+ virtual void addAliasForDirective(StringRef Directive, StringRef Alias) = 0;
+
virtual SourceMgr &getSourceManager() = 0;
virtual MCAsmLexer &getLexer() = 0;
@@ -93,7 +95,7 @@ public:
virtual MCContext &getContext() = 0;
- /// Return the output streamer for the assembler.
+ /// \brief Return the output streamer for the assembler.
virtual MCStreamer &getStreamer() = 0;
MCTargetAsmParser &getTargetParser() const { return *TargetParser; }
@@ -105,13 +107,13 @@ public:
bool getShowParsedOperands() const { return ShowParsedOperands; }
void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; }
- /// Run the parser on the input source buffer.
+ /// \brief 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;
- /// Parse ms-style inline assembly.
+ /// \brief Parse MS-style inline assembly.
virtual bool parseMSInlineAsm(
void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
@@ -119,35 +121,35 @@ public:
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.
+ /// \brief 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;
- /// Emit a warning at the location \p L, with the message \p Msg.
+ /// \brief 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;
- /// Emit an error at the location \p L, with the message \p Msg.
+ /// \brief 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;
- /// Get the next AsmToken in the stream, possibly handling file inclusion
- /// first.
+ /// \brief Get the next AsmToken in the stream, possibly handling file
+ /// inclusion first.
virtual const AsmToken &Lex() = 0;
- /// Get the current AsmToken from the stream.
+ /// \brief 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);
- /// Parse an identifier or string (as a quoted identifier) and set \p Res to
- /// the identifier contents.
+ /// \brief 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
@@ -155,51 +157,51 @@ public:
/// will be either the EndOfStatement or EOF.
virtual StringRef parseStringToEndOfStatement() = 0;
- /// Parse the current token as a string which may include escaped characters
- /// and return the string contents.
+ /// \brief Parse the current token as a string which may include escaped
+ /// characters and return the string contents.
virtual bool parseEscapedString(std::string &Data) = 0;
- /// Skip to the end of the current statement, for error recovery.
+ /// \brief Skip to the end of the current statement, for error recovery.
virtual void eatToEndOfStatement() = 0;
- /// Parse an arbitrary expression.
+ /// \brief Parse an arbitrary expression.
///
- /// @param Res - The value of the expression. The result is undefined
+ /// \param Res - The value of the expression. The result is undefined
/// on error.
- /// @result - False on success.
+ /// \return - False on success.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0;
bool parseExpression(const MCExpr *&Res);
- /// Parse a primary expression.
+ /// \brief Parse a primary expression.
///
- /// @param Res - The value of the expression. The result is undefined
+ /// \param Res - The value of the expression. The result is undefined
/// on error.
- /// @result - False on success.
+ /// \return - False on success.
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0;
- /// Parse an arbitrary expression, assuming that an initial '(' has already
- /// been consumed.
+ /// \brief Parse an arbitrary expression, assuming that an initial '(' has
+ /// already been consumed.
///
- /// @param Res - The value of the expression. The result is undefined
+ /// \param Res - The value of the expression. The result is undefined
/// on error.
- /// @result - False on success.
+ /// \return - False on success.
virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0;
- /// Parse an expression which must evaluate to an absolute value.
+ /// \brief Parse an expression which must evaluate to an absolute value.
///
- /// @param Res - The value of the absolute expression. The result is undefined
+ /// \param Res - The value of the absolute expression. The result is undefined
/// on error.
- /// @result - False on success.
+ /// \return - False on success.
virtual bool parseAbsoluteExpression(int64_t &Res) = 0;
- /// Ensure that we have a valid section set in the streamer. Otherwise, report
- /// an error and switch to .text.
+ /// \brief Ensure that we have a valid section set in the streamer. Otherwise,
+ /// report an error and switch to .text.
virtual void checkForValidSection() = 0;
};
/// \brief Create an MCAsmParser instance.
-MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &,
- MCStreamer &, const MCAsmInfo &);
+MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &,
+ const MCAsmInfo &);
} // End llvm namespace
diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h
index bfc0afa132b7..077fd21e073c 100644
--- a/include/llvm/MC/MCParser/MCAsmParserExtension.h
+++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h
@@ -21,8 +21,8 @@ class Twine;
/// which is implemented by target and object file assembly parser
/// implementations.
class MCAsmParserExtension {
- MCAsmParserExtension(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION;
- void operator=(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION;
+ MCAsmParserExtension(const MCAsmParserExtension &) = delete;
+ void operator=(const MCAsmParserExtension &) = delete;
MCAsmParser *Parser;
@@ -48,7 +48,7 @@ public:
/// parsing routines.
virtual void Initialize(MCAsmParser &Parser);
- /// @name MCAsmParser Proxy Interfaces
+ /// \name MCAsmParser Proxy Interfaces
/// @{
MCContext &getContext() { return getParser().getContext(); }
diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h
index e8740aa10aa2..a25108a0effb 100644
--- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h
+++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h
@@ -10,8 +10,11 @@
#ifndef LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H
#define LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H
+#include <string>
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SMLoc.h"
+
namespace llvm {
-class SMLoc;
class raw_ostream;
/// MCParsedAsmOperand - This abstract class represents a source-level assembly
diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCRelocationInfo.h
index 9dab90099b7d..40e0217b8d83 100644
--- a/include/llvm/MC/MCRelocationInfo.h
+++ b/include/llvm/MC/MCRelocationInfo.h
@@ -28,8 +28,8 @@ class MCContext;
/// \brief Create MCExprs from relocations found in an object file.
class MCRelocationInfo {
- MCRelocationInfo(const MCRelocationInfo &) LLVM_DELETED_FUNCTION;
- void operator=(const MCRelocationInfo &) LLVM_DELETED_FUNCTION;
+ MCRelocationInfo(const MCRelocationInfo &) = delete;
+ void operator=(const MCRelocationInfo &) = delete;
protected:
MCContext &Ctx;
diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h
index de2678adad61..96a4ef135f21 100644
--- a/include/llvm/MC/MCSection.h
+++ b/include/llvm/MC/MCSection.h
@@ -14,66 +14,163 @@
#ifndef LLVM_MC_MCSECTION_H
#define LLVM_MC_MCSECTION_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
- class MCAsmInfo;
- class MCExpr;
- class raw_ostream;
-
- /// MCSection - Instances of this class represent a uniqued identifier for a
- /// section in the current translation unit. The MCContext class uniques and
- /// creates these.
- class MCSection {
- public:
- enum SectionVariant {
- SV_COFF = 0,
- SV_ELF,
- SV_MachO
- };
-
- private:
- MCSection(const MCSection&) LLVM_DELETED_FUNCTION;
- void operator=(const MCSection&) LLVM_DELETED_FUNCTION;
- protected:
- MCSection(SectionVariant V, SectionKind K) : Variant(V), Kind(K) {}
- SectionVariant Variant;
- SectionKind Kind;
- public:
- virtual ~MCSection();
-
- SectionKind getKind() const { return Kind; }
-
- SectionVariant getVariant() const { return Variant; }
-
- virtual void PrintSwitchToSection(const MCAsmInfo &MAI,
- raw_ostream &OS,
- const MCExpr *Subsection) const = 0;
-
- // Convenience routines to get label names for the beginning/end of a
- // section.
- virtual std::string getLabelBeginName() const = 0;
- virtual std::string getLabelEndName() const = 0;
-
- /// isBaseAddressKnownZero - Return true if we know that this section will
- /// get a base address of zero. In cases where we know that this is true we
- /// can emit section offsets as direct references to avoid a subtraction
- /// from the base of the section, saving a relocation.
- virtual bool isBaseAddressKnownZero() const {
- return false;
- }
-
- // UseCodeAlign - Return true if a .align directive should use
- // "optimized nops" to fill instead of 0s.
- virtual bool UseCodeAlign() const = 0;
-
- /// isVirtualSection - Check whether this section is "virtual", that is
- /// has no actual object file contents.
- virtual bool isVirtualSection() const = 0;
+class MCAssembler;
+class MCAsmInfo;
+class MCContext;
+class MCExpr;
+class MCFragment;
+class MCSection;
+class MCSymbol;
+class raw_ostream;
+
+/// Instances of this class represent a uniqued identifier for a section in the
+/// current translation unit. The MCContext class uniques and creates these.
+class MCSection {
+public:
+ enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO };
+
+ /// \brief Express the state of bundle locked groups while emitting code.
+ enum BundleLockStateType {
+ NotBundleLocked,
+ BundleLocked,
+ BundleLockedAlignToEnd
};
+ typedef iplist<MCFragment> FragmentListType;
+
+ typedef FragmentListType::const_iterator const_iterator;
+ typedef FragmentListType::iterator iterator;
+
+ typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
+ typedef FragmentListType::reverse_iterator reverse_iterator;
+
+private:
+ MCSection(const MCSection &) = delete;
+ void operator=(const MCSection &) = delete;
+
+ MCSymbol *Begin;
+ MCSymbol *End = nullptr;
+ /// The alignment requirement of this section.
+ unsigned Alignment = 1;
+ /// The section index in the assemblers section list.
+ unsigned Ordinal = 0;
+ /// The index of this section in the layout order.
+ unsigned LayoutOrder;
+
+ /// \brief Keeping track of bundle-locked state.
+ BundleLockStateType BundleLockState = NotBundleLocked;
+
+ /// \brief Current nesting depth of bundle_lock directives.
+ unsigned BundleLockNestingDepth = 0;
+
+ /// \brief We've seen a bundle_lock directive but not its first instruction
+ /// yet.
+ bool BundleGroupBeforeFirstInst = false;
+
+ /// Whether this section has had instructions emitted into it.
+ unsigned HasInstructions : 1;
+
+ FragmentListType Fragments;
+
+ /// Mapping from subsection number to insertion point for subsection numbers
+ /// below that number.
+ SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
+
+protected:
+ MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin);
+ SectionVariant Variant;
+ SectionKind Kind;
+
+public:
+ virtual ~MCSection();
+
+ SectionKind getKind() const { return Kind; }
+
+ SectionVariant getVariant() const { return Variant; }
+
+ MCSymbol *getBeginSymbol() { return Begin; }
+ const MCSymbol *getBeginSymbol() const {
+ return const_cast<MCSection *>(this)->getBeginSymbol();
+ }
+ void setBeginSymbol(MCSymbol *Sym) {
+ assert(!Begin);
+ Begin = Sym;
+ }
+ MCSymbol *getEndSymbol(MCContext &Ctx);
+ bool hasEnded() const;
+
+ unsigned getAlignment() const { return Alignment; }
+ void setAlignment(unsigned Value) { Alignment = Value; }
+
+ unsigned getOrdinal() const { return Ordinal; }
+ void setOrdinal(unsigned Value) { Ordinal = Value; }
+
+ unsigned getLayoutOrder() const { return LayoutOrder; }
+ void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
+
+ BundleLockStateType getBundleLockState() const { return BundleLockState; }
+ void setBundleLockState(BundleLockStateType NewState);
+ bool isBundleLocked() const { return BundleLockState != NotBundleLocked; }
+
+ bool isBundleGroupBeforeFirstInst() const {
+ return BundleGroupBeforeFirstInst;
+ }
+ void setBundleGroupBeforeFirstInst(bool IsFirst) {
+ BundleGroupBeforeFirstInst = IsFirst;
+ }
+
+ bool hasInstructions() const { return HasInstructions; }
+ void setHasInstructions(bool Value) { HasInstructions = Value; }
+
+ MCSection::FragmentListType &getFragmentList() { return Fragments; }
+ const MCSection::FragmentListType &getFragmentList() const {
+ return const_cast<MCSection *>(this)->getFragmentList();
+ }
+
+ MCSection::iterator begin();
+ MCSection::const_iterator begin() const {
+ return const_cast<MCSection *>(this)->begin();
+ }
+
+ MCSection::iterator end();
+ MCSection::const_iterator end() const {
+ return const_cast<MCSection *>(this)->end();
+ }
+
+ MCSection::reverse_iterator rbegin();
+ MCSection::const_reverse_iterator rbegin() const {
+ return const_cast<MCSection *>(this)->rbegin();
+ }
+
+ MCSection::reverse_iterator rend();
+ MCSection::const_reverse_iterator rend() const {
+ return const_cast<MCSection *>(this)->rend();
+ }
+
+ MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection);
+
+ void dump();
+
+ virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
+ const MCExpr *Subsection) const = 0;
+
+ /// Return true if a .align directive should use "optimized nops" to fill
+ /// instead of 0s.
+ virtual bool UseCodeAlign() const = 0;
+
+ /// Check whether this section is "virtual", that is has no actual object
+ /// file contents.
+ virtual bool isVirtualSection() const = 0;
+};
+
} // end namespace llvm
#endif
diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h
index 0bbf3696686e..237f6d31fb1b 100644
--- a/include/llvm/MC/MCSectionCOFF.h
+++ b/include/llvm/MC/MCSectionCOFF.h
@@ -45,14 +45,15 @@ class MCSymbol;
private:
friend class MCContext;
MCSectionCOFF(StringRef Section, unsigned Characteristics,
- MCSymbol *COMDATSymbol, int Selection, SectionKind K)
- : MCSection(SV_COFF, K), SectionName(Section),
+ MCSymbol *COMDATSymbol, int Selection, SectionKind K,
+ MCSymbol *Begin)
+ : MCSection(SV_COFF, K, Begin), SectionName(Section),
Characteristics(Characteristics), COMDATSymbol(COMDATSymbol),
Selection(Selection) {
assert ((Characteristics & 0x00F00000) == 0 &&
"alignment must not be set upon section creation");
}
- ~MCSectionCOFF();
+ ~MCSectionCOFF() override;
public:
/// ShouldOmitSectionDirective - Decides whether a '.section' directive
@@ -60,12 +61,6 @@ class MCSymbol;
bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const;
StringRef getSectionName() const { return SectionName; }
- std::string getLabelBeginName() const override {
- return SectionName.str() + "_begin";
- }
- std::string getLabelEndName() const override {
- return SectionName.str() + "_end";
- }
unsigned getCharacteristics() const { return Characteristics; }
MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; }
int getSelection() const { return Selection; }
diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h
index 5ec23f1afad2..9efe1022f295 100644
--- a/include/llvm/MC/MCSectionELF.h
+++ b/include/llvm/MC/MCSectionELF.h
@@ -39,6 +39,8 @@ class MCSectionELF : public MCSection {
/// below.
unsigned Flags;
+ unsigned UniqueID;
+
/// EntrySize - The size of each entry in this section. This size only
/// makes sense for sections that contain fixed-sized entries. If a
/// section does not contain fixed-sized entries 'EntrySize' will be 0.
@@ -46,13 +48,18 @@ class MCSectionELF : public MCSection {
const MCSymbol *Group;
+ /// Depending on the type of the section this is sh_link or sh_info.
+ const MCSectionELF *Associated;
+
private:
friend class MCContext;
- MCSectionELF(StringRef Section, unsigned type, unsigned flags,
- SectionKind K, unsigned entrySize, const MCSymbol *group)
- : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags),
- EntrySize(entrySize), Group(group) {}
- ~MCSectionELF();
+ MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K,
+ unsigned entrySize, const MCSymbol *group, unsigned UniqueID,
+ MCSymbol *Begin, const MCSectionELF *Associated)
+ : MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type),
+ Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group),
+ Associated(Associated) {}
+ ~MCSectionELF() override;
void setSectionName(StringRef Name) { SectionName = Name; }
@@ -63,16 +70,6 @@ public:
bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const;
StringRef getSectionName() const { return SectionName; }
- std::string getLabelBeginName() const override {
- if (Group)
- return (SectionName.str() + '_' + Group->getName() + "_begin").str();
- return SectionName.str() + "_begin";
- }
- std::string getLabelEndName() const override {
- if (Group)
- return (SectionName.str() + '_' + Group->getName() + "_end").str();
- return SectionName.str() + "_end";
- }
unsigned getType() const { return Type; }
unsigned getFlags() const { return Flags; }
unsigned getEntrySize() const { return EntrySize; }
@@ -83,19 +80,14 @@ public:
bool UseCodeAlign() const override;
bool isVirtualSection() const override;
- /// isBaseAddressKnownZero - We know that non-allocatable sections (like
- /// debug info) have a base of zero.
- bool isBaseAddressKnownZero() const override {
- return (getFlags() & ELF::SHF_ALLOC) == 0;
- }
+ bool isUnique() const { return UniqueID != ~0U; }
+ unsigned getUniqueID() const { return UniqueID; }
+
+ const MCSectionELF *getAssociatedSection() const { return Associated; }
static bool classof(const MCSection *S) {
return S->getVariant() == SV_ELF;
}
-
- // Return the entry size for sections with fixed-width data.
- static unsigned DetermineEntrySize(SectionKind Kind);
-
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h
index a5a2089a2974..97227517c82d 100644
--- a/include/llvm/MC/MCSectionMachO.h
+++ b/include/llvm/MC/MCSectionMachO.h
@@ -35,8 +35,8 @@ class MCSectionMachO : public MCSection {
/// size of stubs, for example.
unsigned Reserved2;
- MCSectionMachO(StringRef Segment, StringRef Section,
- unsigned TAA, unsigned reserved2, SectionKind K);
+ MCSectionMachO(StringRef Segment, StringRef Section, unsigned TAA,
+ unsigned reserved2, SectionKind K, MCSymbol *Begin);
friend class MCContext;
public:
@@ -53,14 +53,6 @@ public:
return StringRef(SectionName);
}
- std::string getLabelBeginName() const override {
- return StringRef(getSegmentName().str() + getSectionName().str() + "_begin");
- }
-
- std::string getLabelEndName() const override {
- return StringRef(getSegmentName().str() + getSectionName().str() + "_end");
- }
-
unsigned getTypeAndAttributes() const { return TypeAndAttributes; }
unsigned getStubSize() const { return Reserved2; }
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 18855f9cf03d..957913e934c4 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -16,12 +16,12 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCWinEH.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/SMLoc.h"
#include <string>
namespace llvm {
@@ -42,7 +42,7 @@ class raw_ostream;
class formatted_raw_ostream;
class AssemblerConstantPools;
-typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair;
+typedef std::pair<MCSection *, const MCExpr *> MCSectionSubPair;
/// Target specific streamer interface. This is used so that targets can
/// implement support for target specific assembly directives.
@@ -87,35 +87,12 @@ public:
virtual void finish();
};
-class AArch64TargetStreamer : public MCTargetStreamer {
-public:
- AArch64TargetStreamer(MCStreamer &S);
- ~AArch64TargetStreamer();
-
- void finish() override;
-
- /// Callback used to implement the ldr= pseudo.
- /// Add a new entry to the constant pool for the current section and return an
- /// MCExpr that can be used to refer to the constant pool location.
- const MCExpr *addConstantPoolEntry(const MCExpr *, unsigned Size);
-
- /// Callback used to implemnt the .ltorg directive.
- /// 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;
-};
-
// FIXME: declared here because it is used from
// lib/CodeGen/AsmPrinter/ARMException.cpp.
class ARMTargetStreamer : public MCTargetStreamer {
public:
ARMTargetStreamer(MCStreamer &S);
- ~ARMTargetStreamer();
+ ~ARMTargetStreamer() override;
virtual void emitFnStart();
virtual void emitFnEnd();
@@ -139,6 +116,7 @@ public:
StringRef StringValue = "");
virtual void emitFPU(unsigned FPU);
virtual void emitArch(unsigned Arch);
+ virtual void emitArchExtension(unsigned ArchExt);
virtual void emitObjectArch(unsigned Arch);
virtual void finishAttributeSection();
virtual void emitInst(uint32_t Inst, char Suffix = '\0');
@@ -162,11 +140,12 @@ private:
std::unique_ptr<AssemblerConstantPools> ConstantPools;
};
-/// MCStreamer - Streaming machine code generation interface. This interface
-/// is intended to provide a programatic interface that is very similar to the
-/// level that an assembler .s file provides. It has callbacks to emit bytes,
-/// handle directives, etc. The implementation of this interface retains
-/// state to know what the current section is etc.
+/// \brief Streaming machine code generation interface.
+///
+/// This interface is intended to provide a programatic interface that is very
+/// similar to the level that an assembler .s file provides. It has callbacks
+/// to emit bytes, handle directives, etc. The implementation of this interface
+/// retains state to know what the current section is etc.
///
/// There are multiple implementations of this interface: one for writing out
/// a .s file, and implementations that write out .o files of various formats.
@@ -175,8 +154,8 @@ class MCStreamer {
MCContext &Context;
std::unique_ptr<MCTargetStreamer> TargetStreamer;
- MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION;
- MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION;
+ MCStreamer(const MCStreamer &) = delete;
+ MCStreamer &operator=(const MCStreamer &) = delete;
std::vector<MCDwarfFrameInfo> DwarfFrameInfos;
MCDwarfFrameInfo *getCurrentDwarfFrameInfo();
@@ -188,12 +167,12 @@ class MCStreamer {
WinEH::FrameInfo *CurrentWinFrameInfo;
void EnsureValidWinFrameInfo();
- // SymbolOrdering - Tracks an index to represent the order
- // a symbol was emitted in. Zero means we did not emit that symbol.
+ /// \brief Tracks an index to represent the order a symbol was emitted in.
+ /// Zero means we did not emit that symbol.
DenseMap<const MCSymbol *, unsigned> SymbolOrdering;
- /// SectionStack - This is stack of current and previous section
- /// values saved by PushSection.
+ /// \brief This is stack of current and previous section values saved by
+ /// PushSection.
SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack;
protected:
@@ -242,22 +221,24 @@ public:
void generateCompactUnwindEncodings(MCAsmBackend *MAB);
- /// @name Assembly File Formatting.
+ /// \name Assembly File Formatting.
/// @{
- /// isVerboseAsm - Return true if this streamer supports verbose assembly
- /// and if it is enabled.
+ /// \brief Return true if this streamer supports verbose assembly and if it is
+ /// enabled.
virtual bool isVerboseAsm() const { return false; }
- /// hasRawTextSupport - Return true if this asm streamer supports emitting
- /// unformatted text to the .s file with EmitRawText.
+ /// \brief Return true if this asm streamer supports emitting unformatted text
+ /// to the .s file with EmitRawText.
virtual bool hasRawTextSupport() const { return false; }
- /// Is the integrated assembler required for this streamer to function
+ /// \brief Is the integrated assembler required for this streamer to function
/// correctly?
virtual bool isIntegratedAssemblerRequired() const { return false; }
- /// AddComment - Add a comment that can be emitted to the generated .s
+ /// \brief Add a textual command.
+ ///
+ /// Typically for comments that can be emitted to the generated .s
/// file if applicable as a QoI issue to make the output of the compiler
/// more readable. This only affects the MCAsmStreamer, and only when
/// verbose assembly output is enabled.
@@ -266,14 +247,14 @@ public:
/// prefix as appropriate. The added comment should not end with a \n.
virtual void AddComment(const Twine &T) {}
- /// GetCommentOS - Return a raw_ostream that comments can be written to.
- /// Unlike AddComment, you are required to terminate comments with \n if you
- /// use this method.
+ /// \brief Return a raw_ostream that comments can be written to. Unlike
+ /// AddComment, you are required to terminate comments with \n if you use this
+ /// method.
virtual raw_ostream &GetCommentOS();
- /// Print T and prefix it with the comment string (normally #) and optionally
- /// a tab. This prints the comment immediately, not at the end of the
- /// current line. It is basically a safe version of EmitRawText: since it
+ /// \brief Print T and prefix it with the comment string (normally #) and
+ /// optionally a tab. This prints the comment immediately, not at the end of
+ /// the current line. It is basically a safe version of EmitRawText: since it
/// only prints comments, the object streamer ignores it instead of asserting.
virtual void emitRawComment(const Twine &T, bool TabPrefix = true);
@@ -282,46 +263,43 @@ public:
/// @}
- /// @name Symbol & Section Management
+ /// \name Symbol & Section Management
/// @{
- /// getCurrentSection - Return the current section that the streamer is
- /// emitting code to.
+ /// \brief Return the current section that the streamer is emitting code to.
MCSectionSubPair getCurrentSection() const {
if (!SectionStack.empty())
return SectionStack.back().first;
return MCSectionSubPair();
}
- /// getPreviousSection - Return the previous section that the streamer is
- /// emitting code to.
+ /// \brief Return the previous section that the streamer is emitting code to.
MCSectionSubPair getPreviousSection() const {
if (!SectionStack.empty())
return SectionStack.back().second;
return MCSectionSubPair();
}
- /// GetSymbolOrder - Returns an index to represent the order
- /// a symbol was emitted in. (zero if we did not emit that symbol)
+ /// \brief Returns an index to represent the order a symbol was emitted in.
+ /// (zero if we did not emit that symbol)
unsigned GetSymbolOrder(const MCSymbol *Sym) const {
return SymbolOrdering.lookup(Sym);
}
- /// ChangeSection - Update streamer for a new active section.
+ /// \brief Update streamer for a new active section.
///
/// This is called by PopSection and SwitchSection, if the current
/// section changes.
- virtual void ChangeSection(const MCSection *, const MCExpr *);
+ virtual void ChangeSection(MCSection *, const MCExpr *);
- /// pushSection - Save the current and previous section on the
- /// section stack.
+ /// \brief Save the current and previous section on the section stack.
void PushSection() {
SectionStack.push_back(
std::make_pair(getCurrentSection(), getPreviousSection()));
}
- /// popSection - Restore the current and previous section from
- /// the section stack. Calls ChangeSection as needed.
+ /// \brief Restore the current and previous section from the section stack.
+ /// Calls ChangeSection as needed.
///
/// Returns false if the stack was empty.
bool PopSection() {
@@ -343,25 +321,17 @@ public:
return true;
}
- /// SwitchSection - Set the current section where code is being emitted to
- /// @p Section. This is required to update CurSection.
+ /// Set the current section where code is being emitted to \p Section. This
+ /// is required to update CurSection.
///
/// This corresponds to assembler directives like .section, .text, etc.
- 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;
- if (MCSectionSubPair(Section, Subsection) != curSection) {
- SectionStack.back().first = MCSectionSubPair(Section, Subsection);
- ChangeSection(Section, Subsection);
- }
- }
+ virtual void SwitchSection(MCSection *Section,
+ const MCExpr *Subsection = nullptr);
- /// SwitchSectionNoChange - Set the current section where code is being
- /// emitted to @p Section. This is required to update CurSection. This
- /// version does not call ChangeSection.
- void SwitchSectionNoChange(const MCSection *Section,
+ /// \brief Set the current section where code is being emitted to \p Section.
+ /// This is required to update CurSection. This version does not call
+ /// ChangeSection.
+ void SwitchSectionNoChange(MCSection *Section,
const MCExpr *Subsection = nullptr) {
assert(Section && "Cannot switch to a null section!");
MCSectionSubPair curSection = SectionStack.back().first;
@@ -370,21 +340,23 @@ public:
SectionStack.back().first = MCSectionSubPair(Section, Subsection);
}
- /// Create the default sections and set the initial one.
+ /// \brief Create the default sections and set the initial one.
virtual void InitSections(bool NoExecStack);
- /// AssignSection - Sets the symbol's section.
+ MCSymbol *endSection(MCSection *Section);
+
+ /// \brief Sets the symbol's section.
///
/// Each emitted symbol will be tracked in the ordering table,
/// so we can sort on them later.
- void AssignSection(MCSymbol *Symbol, const MCSection *Section);
+ void AssignSection(MCSymbol *Symbol, MCSection *Section);
- /// EmitLabel - Emit a label for @p Symbol into the current section.
+ /// \brief Emit a label for \p Symbol into the current section.
///
/// This corresponds to an assembler statement such as:
/// foo:
///
- /// @param Symbol - The symbol to emit. A given symbol should only be
+ /// \param Symbol - The symbol to emit. A given symbol should only be
/// emitted as a label once, and symbols emitted as a label should never be
/// used in an assignment.
// FIXME: These emission are non-const because we mutate the symbol to
@@ -393,25 +365,25 @@ public:
virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol);
- /// EmitAssemblerFlag - Note in the output the specified @p Flag.
+ /// \brief Note in the output the specified \p Flag.
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
- /// EmitLinkerOptions - Emit the given list @p Options of strings as linker
+ /// \brief Emit the given list \p Options of strings as linker
/// options into the output.
virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {}
- /// EmitDataRegion - Note in the output the specified region @p Kind.
+ /// \brief Note in the output the specified region \p Kind.
virtual void EmitDataRegion(MCDataRegionType Kind) {}
- /// EmitVersionMin - Specify the MachO minimum deployment target version.
+ /// \brief Specify the MachO minimum deployment target version.
virtual void EmitVersionMin(MCVersionMinType, unsigned Major, unsigned Minor,
unsigned Update) {}
- /// EmitThumbFunc - Note in the output that the specified @p Func is
- /// a Thumb mode function (ARM target only).
+ /// \brief Note in the output that the specified \p Func is a Thumb mode
+ /// function (ARM target only).
virtual void EmitThumbFunc(MCSymbol *Func);
- /// EmitAssignment - Emit an assignment of @p Value to @p Symbol.
+ /// \brief Emit an assignment of \p Value to \p Symbol.
///
/// This corresponds to an assembler statement such as:
/// symbol = value
@@ -420,133 +392,131 @@ public:
/// value in the current context. For the assembly streamer, this prints the
/// binding into the .s file.
///
- /// @param Symbol - The symbol being assigned to.
- /// @param Value - The value for the symbol.
+ /// \param Symbol - The symbol being assigned to.
+ /// \param Value - The value for the symbol.
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
- /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol.
+ /// \brief Emit an weak reference from \p Alias to \p Symbol.
///
/// This corresponds to an assembler statement such as:
/// .weakref alias, symbol
///
- /// @param Alias - The alias that is being created.
- /// @param Symbol - The symbol being aliased.
+ /// \param Alias - The alias that is being created.
+ /// \param Symbol - The symbol being aliased.
virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
- /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol.
+ /// \brief Add the given \p Attribute to \p Symbol.
virtual bool EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) = 0;
- /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol.
+ /// \brief Set the \p DescValue for the \p Symbol.
///
- /// @param Symbol - The symbol to have its n_desc field set.
- /// @param DescValue - The value to set into the n_desc field.
+ /// \param Symbol - The symbol to have its n_desc field set.
+ /// \param DescValue - The value to set into the n_desc field.
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
- /// BeginCOFFSymbolDef - Start emitting COFF symbol definition
+ /// \brief Start emitting COFF symbol definition
///
- /// @param Symbol - The symbol to have its External & Type fields set.
+ /// \param Symbol - The symbol to have its External & Type fields set.
virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol);
- /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol.
+ /// \brief Emit the storage class of the symbol.
///
- /// @param StorageClass - The storage class the symbol should have.
+ /// \param StorageClass - The storage class the symbol should have.
virtual void EmitCOFFSymbolStorageClass(int StorageClass);
- /// EmitCOFFSymbolType - Emit the type of the symbol.
+ /// \brief Emit the type of the symbol.
///
- /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h)
+ /// \param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h)
virtual void EmitCOFFSymbolType(int Type);
- /// EndCOFFSymbolDef - Marks the end of the symbol definition.
+ /// \brief Marks the end of the symbol definition.
virtual void EndCOFFSymbolDef();
- /// EmitCOFFSectionIndex - Emits a COFF section index.
+ /// \brief Emits a COFF section index.
///
- /// @param Symbol - Symbol the section number relocation should point to.
+ /// \param Symbol - Symbol the section number relocation should point to.
virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol);
- /// EmitCOFFSecRel32 - Emits a COFF section relative relocation.
+ /// \brief Emits a COFF section relative relocation.
///
- /// @param Symbol - Symbol the section relative relocation should point to.
+ /// \param Symbol - Symbol the section relative relocation should point to.
virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
- /// EmitELFSize - Emit an ELF .size directive.
+ /// \brief Emit an ELF .size directive.
///
/// This corresponds to an assembler statement such as:
/// .size symbol, expression
- ///
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
/// \brief Emit a Linker Optimization Hint (LOH) directive.
/// \param Args - Arguments of the LOH.
virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {}
- /// EmitCommonSymbol - Emit a common symbol.
+ /// \brief Emit a common symbol.
///
- /// @param Symbol - The common symbol to emit.
- /// @param Size - The size of the common symbol.
- /// @param ByteAlignment - The alignment of the symbol if
+ /// \param Symbol - The common symbol to emit.
+ /// \param Size - The size of the common symbol.
+ /// \param ByteAlignment - The alignment of the symbol if
/// non-zero. This must be a power of 2.
virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) = 0;
- /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
+ /// \brief Emit a local common (.lcomm) symbol.
///
- /// @param Symbol - The common symbol to emit.
- /// @param Size - The size of the common symbol.
- /// @param ByteAlignment - The alignment of the common symbol in bytes.
+ /// \param Symbol - The common symbol to emit.
+ /// \param Size - The size of the common symbol.
+ /// \param ByteAlignment - The alignment of the common symbol in bytes.
virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment);
- /// EmitZerofill - Emit the zerofill section and an optional symbol.
+ /// \brief Emit the zerofill section and an optional symbol.
///
- /// @param Section - The zerofill section to create and or to put the symbol
- /// @param Symbol - The zerofill symbol to emit, if non-NULL.
- /// @param Size - The size of the zerofill symbol.
- /// @param ByteAlignment - The alignment of the zerofill symbol if
+ /// \param Section - The zerofill section to create and or to put the symbol
+ /// \param Symbol - The zerofill symbol to emit, if non-NULL.
+ /// \param Size - The size of the zerofill symbol.
+ /// \param ByteAlignment - The alignment of the zerofill symbol if
/// non-zero. This must be a power of 2 on some targets.
- virtual void EmitZerofill(const MCSection *Section,
- MCSymbol *Symbol = nullptr, uint64_t Size = 0,
- unsigned ByteAlignment = 0) = 0;
+ virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+ uint64_t Size = 0, unsigned ByteAlignment = 0) = 0;
- /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol.
+ /// \brief Emit a thread local bss (.tbss) symbol.
///
- /// @param Section - The thread local common section.
- /// @param Symbol - The thread local common symbol to emit.
- /// @param Size - The size of the symbol.
- /// @param ByteAlignment - The alignment of the thread local common symbol
+ /// \param Section - The thread local common section.
+ /// \param Symbol - The thread local common symbol to emit.
+ /// \param Size - The size of the symbol.
+ /// \param ByteAlignment - The alignment of the thread local common symbol
/// if non-zero. This must be a power of 2 on some targets.
- virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
+ virtual void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment = 0);
/// @}
- /// @name Generating Data
+ /// \name Generating Data
/// @{
- /// EmitBytes - Emit the bytes in \p Data into the output.
+ /// \brief Emit the bytes in \p Data into the output.
///
/// This is used to implement assembler directives such as .byte, .ascii,
/// etc.
virtual void EmitBytes(StringRef Data);
- /// EmitValue - Emit the expression @p Value into the output as a native
- /// integer of the given @p Size bytes.
+ /// \brief Emit the expression \p Value into the output as a native
+ /// integer of the given \p Size bytes.
///
/// This is used to implement assembler directives such as .word, .quad,
/// etc.
///
- /// @param Value - The value to emit.
- /// @param Size - The size of the integer (in bytes) to emit. This must
+ /// \param Value - The value to emit.
+ /// \param Size - The size of the integer (in bytes) to emit. This must
/// match a native machine width.
- /// @param Loc - The location of the expression for error reporting.
+ /// \param Loc - The location of the expression for error reporting.
virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
const SMLoc &Loc = SMLoc());
void EmitValue(const MCExpr *Value, unsigned Size,
const SMLoc &Loc = SMLoc());
- /// EmitIntValue - Special case of EmitValue that avoids the client having
+ /// \brief Special case of EmitValue that avoids the client having
/// to pass in a MCExpr for constant integers.
virtual void EmitIntValue(uint64_t Value, unsigned Size);
@@ -554,112 +524,119 @@ public:
virtual void EmitSLEB128Value(const MCExpr *Value);
- /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
- /// client having to pass in a MCExpr for constant integers.
+ /// \brief Special case of EmitULEB128Value that avoids the client having to
+ /// pass in a MCExpr for constant integers.
void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0);
- /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
- /// client having to pass in a MCExpr for constant integers.
+ /// \brief Special case of EmitSLEB128Value that avoids the client having to
+ /// pass in a MCExpr for constant integers.
void EmitSLEB128IntValue(int64_t Value);
- /// EmitSymbolValue - Special case of EmitValue that avoids the client
- /// having to pass in a MCExpr for MCSymbols.
+ /// \brief Special case of EmitValue that avoids the client having to pass in
+ /// a MCExpr for MCSymbols.
void EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
bool IsSectionRelative = false);
- /// EmitGPRel64Value - Emit the expression @p Value into the output as a
- /// gprel64 (64-bit GP relative) value.
+ /// \brief Emit the expression \p Value into the output as a gprel64 (64-bit
+ /// GP relative) value.
///
/// This is used to implement assembler directives such as .gpdword on
/// targets that support them.
virtual void EmitGPRel64Value(const MCExpr *Value);
- /// EmitGPRel32Value - Emit the expression @p Value into the output as a
- /// gprel32 (32-bit GP relative) value.
+ /// \brief Emit the expression \p Value into the output as a gprel32 (32-bit
+ /// GP relative) value.
///
/// This is used to implement assembler directives such as .gprel32 on
/// targets that support them.
virtual void EmitGPRel32Value(const MCExpr *Value);
- /// EmitFill - Emit NumBytes bytes worth of the value specified by
- /// FillValue. This implements directives such as '.space'.
+ /// \brief Emit NumBytes bytes worth of the value specified by FillValue.
+ /// This implements directives such as '.space'.
virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue);
/// \brief Emit NumBytes worth of zeros.
/// This function properly handles data in virtual sections.
virtual void EmitZeros(uint64_t NumBytes);
- /// EmitValueToAlignment - Emit some number of copies of @p Value until
- /// the byte alignment @p ByteAlignment is reached.
+ /// \brief Emit some number of copies of \p Value until the byte alignment \p
+ /// ByteAlignment is reached.
///
/// If the number of bytes need to emit for the alignment is not a multiple
- /// of @p ValueSize, then the contents of the emitted fill bytes is
+ /// of \p ValueSize, then the contents of the emitted fill bytes is
/// undefined.
///
/// This used to implement the .align assembler directive.
///
- /// @param ByteAlignment - The alignment to reach. This must be a power of
+ /// \param ByteAlignment - The alignment to reach. This must be a power of
/// two on some targets.
- /// @param Value - The value to use when filling bytes.
- /// @param ValueSize - The size of the integer (in bytes) to emit for
- /// @p Value. This must match a native machine width.
- /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If
+ /// \param Value - The value to use when filling bytes.
+ /// \param ValueSize - The size of the integer (in bytes) to emit for
+ /// \p Value. This must match a native machine width.
+ /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If
/// the alignment cannot be reached in this many bytes, no bytes are
/// emitted.
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0);
- /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment
- /// is reached.
+ /// \brief Emit nops until the byte alignment \p ByteAlignment is reached.
///
/// This used to align code where the alignment bytes may be executed. This
/// can emit different bytes for different sizes to optimize execution.
///
- /// @param ByteAlignment - The alignment to reach. This must be a power of
+ /// \param ByteAlignment - The alignment to reach. This must be a power of
/// two on some targets.
- /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If
+ /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If
/// the alignment cannot be reached in this many bytes, no bytes are
/// emitted.
virtual void EmitCodeAlignment(unsigned ByteAlignment,
unsigned MaxBytesToEmit = 0);
- /// EmitValueToOffset - Emit some number of copies of @p Value until the
- /// byte offset @p Offset is reached.
+ /// \brief Emit some number of copies of \p Value until the byte offset \p
+ /// Offset is reached.
///
/// This is used to implement assembler directives such as .org.
///
- /// @param Offset - The offset to reach. This may be an expression, but the
+ /// \param Offset - The offset to reach. This may be an expression, but the
/// expression must be associated with the current section.
- /// @param Value - The value to use when filling bytes.
- /// @return false on success, true if the offset was invalid.
+ /// \param Value - The value to use when filling bytes.
+ /// \return false on success, true if the offset was invalid.
virtual bool EmitValueToOffset(const MCExpr *Offset,
unsigned char Value = 0);
/// @}
- /// EmitFileDirective - Switch to a new logical file. This is used to
- /// implement the '.file "foo.c"' assembler directive.
+ /// \brief Switch to a new logical file. This is used to implement the '.file
+ /// "foo.c"' assembler directive.
virtual void EmitFileDirective(StringRef Filename);
- /// Emit the "identifiers" directive. This implements the
+ /// \brief Emit the "identifiers" directive. This implements the
/// '.ident "version foo"' assembler directive.
virtual void EmitIdent(StringRef IdentString) {}
- /// EmitDwarfFileDirective - Associate a filename with a specified logical
- /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler
- /// directive.
+ /// \brief Associate a filename with a specified logical file number. This
+ /// implements the DWARF2 '.file 4 "foo.c"' assembler directive.
virtual unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename,
unsigned CUID = 0);
- /// EmitDwarfLocDirective - This implements the DWARF2
- // '.loc fileno lineno ...' assembler directive.
+ /// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler
+ /// directive.
virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
unsigned Isa, unsigned Discriminator,
StringRef FileName);
+ /// Emit the absolute difference between two symbols if possible.
+ ///
+ /// \pre Offset of \c Hi is greater than the offset \c Lo.
+ /// \return true on success.
+ virtual bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
+ unsigned Size) {
+ return false;
+ }
+
virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID);
virtual void EmitCFISections(bool EH, bool Debug);
void EmitCFIStartProc(bool IsSimple);
@@ -697,8 +674,7 @@ public:
virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except);
virtual void EmitWinEHHandlerData();
- /// EmitInstruction - Emit the given @p Instruction into the current
- /// section.
+ /// \brief Emit the given \p Instruction into the current section.
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI);
/// \brief Set the bundle alignment mode from now on in the section.
@@ -715,29 +691,28 @@ public:
/// \brief Ends a bundle-locked group.
virtual void EmitBundleUnlock();
- /// EmitRawText - If this file is backed by a assembly streamer, this dumps
- /// the specified string in the output .s file. This capability is
- /// indicated by the hasRawTextSupport() predicate. By default this aborts.
+ /// \brief If this file is backed by a assembly streamer, this dumps the
+ /// specified string in the output .s file. This capability is indicated by
+ /// the hasRawTextSupport() predicate. By default this aborts.
void EmitRawText(const Twine &String);
- /// Flush - Causes any cached state to be written out.
+ /// \brief Causes any cached state to be written out.
virtual void Flush() {}
- /// FinishImpl - Streamer specific finalization.
+ /// \brief Streamer specific finalization.
virtual void FinishImpl();
- /// Finish - Finish emission of machine code.
+ /// \brief Finish emission of machine code.
void Finish();
- virtual bool mayHaveInstructions() const { return true; }
+ virtual bool mayHaveInstructions(MCSection &Sec) const { return true; }
};
-/// createNullStreamer - Create a dummy machine code streamer, which does
-/// nothing. This is useful for timing the assembler front end.
+/// Create a dummy machine code streamer, which does nothing. This is useful for
+/// timing the assembler front end.
MCStreamer *createNullStreamer(MCContext &Ctx);
-/// createAsmStreamer - Create a machine code streamer which will print out
-/// assembly for the native target, suitable for compiling with a native
-/// assembler.
+/// Create a machine code streamer which will print out assembly for the native
+/// target, suitable for compiling with a native assembler.
///
/// \param InstPrint - If given, the instruction printer to use. If not given
/// the MCInst representation will be printed. This method takes ownership of
@@ -752,26 +727,11 @@ MCStreamer *createNullStreamer(MCContext &Ctx);
///
/// \param ShowInst - Whether to show the MCInst representation inline with
/// the assembly.
-MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
+MCStreamer *createAsmStreamer(MCContext &Ctx,
+ std::unique_ptr<formatted_raw_ostream> OS,
bool isVerboseAsm, bool useDwarfDirectory,
MCInstPrinter *InstPrint, MCCodeEmitter *CE,
MCAsmBackend *TAB, bool ShowInst);
-
-/// createMachOStreamer - Create a machine code streamer which will generate
-/// Mach-O format object files.
-///
-/// Takes ownership of \p TAB and \p CE.
-MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
- raw_ostream &OS, MCCodeEmitter *CE,
- bool RelaxAll = false,
- bool LabelSections = false);
-
-/// 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);
-
} // end namespace llvm
#endif
diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h
index 3f38bd59a576..1778a6d13fb8 100644
--- a/include/llvm/MC/MCSubtargetInfo.h
+++ b/include/llvm/MC/MCSubtargetInfo.h
@@ -28,6 +28,7 @@ class StringRef;
///
class MCSubtargetInfo {
std::string TargetTriple; // Target triple
+ std::string CPU; // CPU being targeted.
ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list
ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions
@@ -41,7 +42,7 @@ class MCSubtargetInfo {
const InstrStage *Stages; // Instruction itinerary stages
const unsigned *OperandCycles; // Itinerary operand cycles
const unsigned *ForwardingPaths; // Forwarding paths
- uint64_t FeatureBits; // Feature bits for current CPU + FS
+ FeatureBitset FeatureBits; // Feature bits for current CPU + FS
public:
void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS,
@@ -59,15 +60,20 @@ public:
return TargetTriple;
}
+ /// getCPU - Return the CPU string.
+ StringRef getCPU() const {
+ return CPU;
+ }
+
/// getFeatureBits - Return the feature bits.
///
- uint64_t getFeatureBits() const {
+ const FeatureBitset& getFeatureBits() const {
return FeatureBits;
}
/// setFeatureBits - Set the feature bits.
///
- void setFeatureBits(uint64_t FeatureBits_) { FeatureBits = FeatureBits_; }
+ void setFeatureBits(FeatureBitset& FeatureBits_) { FeatureBits = FeatureBits_; }
/// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with
/// feature string). Recompute feature bits and scheduling model.
@@ -78,11 +84,15 @@ public:
/// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version does not change the implied bits.
- uint64_t ToggleFeature(uint64_t FB);
+ FeatureBitset ToggleFeature(uint64_t FB);
/// ToggleFeature - Toggle a feature and returns the re-computed feature
- /// bits. This version will also change all implied bits.
- uint64_t ToggleFeature(StringRef FS);
+ /// bits. This version does not change the implied bits.
+ FeatureBitset ToggleFeature(const FeatureBitset& FB);
+
+ /// ToggleFeature - Toggle a set of features and returns the re-computed
+ /// feature bits. This version will also change all implied bits.
+ FeatureBitset ToggleFeature(StringRef FS);
/// getSchedModelForCPU - Get the machine model of a CPU.
///
diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h
index 47a8789d463b..cf99c919281e 100644
--- a/include/llvm/MC/MCSymbol.h
+++ b/include/llvm/MC/MCSymbol.h
@@ -14,168 +14,298 @@
#ifndef LLVM_MC_MCSYMBOL_H
#define LLVM_MC_MCSYMBOL_H
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
- class MCExpr;
- class MCSection;
- class MCContext;
- class raw_ostream;
-
- /// MCSymbol - Instances of this class represent a symbol name in the MC file,
- /// and MCSymbols are created and unique'd by the MCContext class. MCSymbols
- /// should only be constructed with valid names for the object file.
+class MCExpr;
+class MCSymbol;
+class MCFragment;
+class MCSection;
+class MCContext;
+class raw_ostream;
+
+// TODO: Merge completely with MCSymbol.
+class MCSymbolData {
+ /// 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;
+
+ 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'.
+ 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 = nullptr;
+
+ /// CommonAlign - The alignment of the symbol, if it is 'common', or -1.
+ //
+ // FIXME: Pack this in with other fields?
+ unsigned CommonAlign = -1U;
+
+ /// Flags - The Flags field is used by object file implementations to store
+ /// additional per symbol information which is not easily classified.
+ uint32_t Flags = 0;
+
+public:
+ MCSymbolData() { Offset = 0; }
+
+ MCFragment *getFragment() const { return Fragment.getPointer(); }
+ void setFragment(MCFragment *Value) { Fragment.setPointer(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 Fragment.getInt() & 1; }
+ void setExternal(bool Value) {
+ Fragment.setInt((Fragment.getInt() & ~1) | unsigned(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 CommonAlign != -1U; }
+
+ /// setCommon - Mark this symbol as being 'common'.
///
- /// If the symbol is defined/emitted into the current translation unit, the
- /// Section member is set to indicate what section it lives in. Otherwise, if
- /// it is a reference to an external entity, it has a null section.
- class MCSymbol {
- // Special sentinal value for the absolute pseudo section.
- //
- // FIXME: Use a PointerInt wrapper for this?
- static const MCSection *AbsolutePseudoSection;
-
- /// Name - The name of the symbol. The referred-to string data is actually
- /// held by the StringMap that lives in MCContext.
- StringRef Name;
-
- /// Section - The section the symbol is defined in. This is null for
- /// undefined symbols, and the special AbsolutePseudoSection value for
- /// absolute symbols.
- const MCSection *Section;
-
- /// Value - If non-null, the value for a variable symbol.
- const MCExpr *Value;
-
- /// IsTemporary - True if this is an assembler temporary label, which
- /// typically does not survive in the .o file's symbol table. Usually
- /// "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;
-
- private: // MCContext creates and uniques these.
- friend class MCExpr;
- friend class MCContext;
- MCSymbol(StringRef name, bool isTemporary)
- : Name(name), Section(nullptr), Value(nullptr),
- IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {}
-
- MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION;
- void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION;
- public:
- /// getName - Get the symbol name.
- StringRef getName() const { return Name; }
-
- /// @name Accessors
- /// @{
-
- /// isTemporary - Check if this is an assembler temporary symbol.
- bool isTemporary() const { return IsTemporary; }
-
- /// isUsed - Check if this is used.
- bool isUsed() const { return IsUsed; }
- void setUsed(bool Value) const { IsUsed = Value; }
-
- /// \brief Check if this symbol is redefinable.
- 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;
- }
- }
+ /// \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;
+ }
- /// @}
- /// @name Associated Sections
- /// @{
+ /// getCommonSize - Return the size of a 'common' symbol.
+ uint64_t getCommonSize() const {
+ assert(isCommon() && "Not a 'common' symbol!");
+ return CommonSize;
+ }
- /// isDefined - Check if this symbol is defined (i.e., it has an address).
- ///
- /// Defined symbols are either absolute or in some section.
- bool isDefined() const {
- return Section != nullptr;
- }
+ void setSize(const MCExpr *SS) { SymbolSize = SS; }
- /// isInSection - Check if this symbol is defined in some section (i.e., it
- /// is defined but not absolute).
- bool isInSection() const {
- return isDefined() && !isAbsolute();
- }
+ const MCExpr *getSize() const { return SymbolSize; }
- /// isUndefined - Check if this symbol undefined (i.e., implicitly defined).
- bool isUndefined() const {
- return !isDefined();
- }
+ /// getCommonAlignment - Return the alignment of a 'common' symbol.
+ unsigned getCommonAlignment() const {
+ assert(isCommon() && "Not a 'common' symbol!");
+ return CommonAlign;
+ }
- /// isAbsolute - Check if this is an absolute symbol.
- bool isAbsolute() const {
- return Section == AbsolutePseudoSection;
- }
+ /// getFlags - Get the (implementation defined) symbol flags.
+ uint32_t getFlags() const { return Flags; }
- /// getSection - Get the section associated with a defined, non-absolute
- /// symbol.
- const MCSection &getSection() const {
- assert(isInSection() && "Invalid accessor!");
- return *Section;
- }
+ /// setFlags - Set the (implementation defined) symbol flags.
+ void setFlags(uint32_t Value) { Flags = Value; }
- /// setSection - Mark the symbol as defined in the section \p S.
- void setSection(const MCSection &S) { Section = &S; }
+ /// modifyFlags - Modify the flags via a mask
+ void modifyFlags(uint32_t Value, uint32_t Mask) {
+ Flags = (Flags & ~Mask) | Value;
+ }
+
+ /// @}
+
+ void dump() const;
+};
+
+/// MCSymbol - Instances of this class represent a symbol name in the MC file,
+/// and MCSymbols are created and uniqued by the MCContext class. MCSymbols
+/// should only be constructed with valid names for the object file.
+///
+/// If the symbol is defined/emitted into the current translation unit, the
+/// Section member is set to indicate what section it lives in. Otherwise, if
+/// it is a reference to an external entity, it has a null section.
+class MCSymbol {
+ // Special sentinal value for the absolute pseudo section.
+ //
+ // FIXME: Use a PointerInt wrapper for this?
+ static MCSection *AbsolutePseudoSection;
+
+ /// Name - The name of the symbol. The referred-to string data is actually
+ /// held by the StringMap that lives in MCContext.
+ const StringMapEntry<bool> *Name;
+
+ /// The section the symbol is defined in. This is null for undefined symbols,
+ /// and the special AbsolutePseudoSection value for absolute symbols. If this
+ /// is a variable symbol, this caches the variable value's section.
+ mutable MCSection *Section;
+
+ /// Value - If non-null, the value for a variable symbol.
+ const MCExpr *Value;
+
+ /// IsTemporary - True if this is an assembler temporary label, which
+ /// typically does not survive in the .o file's symbol table. Usually
+ /// "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;
+
+ mutable bool HasData : 1;
+
+ /// Index field, for use by the object file implementation.
+ mutable uint64_t Index : 60;
+
+ mutable MCSymbolData Data;
+
+private: // MCContext creates and uniques these.
+ friend class MCExpr;
+ friend class MCContext;
+ MCSymbol(const StringMapEntry<bool> *Name, bool isTemporary)
+ : Name(Name), Section(nullptr), Value(nullptr), IsTemporary(isTemporary),
+ IsRedefinable(false), IsUsed(false), HasData(false), Index(0) {}
+
+ MCSymbol(const MCSymbol &) = delete;
+ void operator=(const MCSymbol &) = delete;
+ MCSection *getSectionPtr() const {
+ if (Section || !Value)
+ return Section;
+ return Section = Value->FindAssociatedSection();
+ }
+
+public:
+ /// getName - Get the symbol name.
+ StringRef getName() const { return Name ? Name->first() : ""; }
+
+ bool hasData() const { return HasData; }
+
+ /// Get associated symbol data.
+ MCSymbolData &getData() const {
+ assert(HasData && "Missing symbol data!");
+ return Data;
+ }
- /// setUndefined - Mark the symbol as undefined.
- void setUndefined() {
+ /// Initialize symbol data.
+ ///
+ /// Nothing really to do here, but this is enables an assertion that \a
+ /// MCAssembler::getOrCreateSymbolData() has actually been called before
+ /// anyone calls \a getData().
+ void initializeData() const { HasData = true; }
+
+ /// \name Accessors
+ /// @{
+
+ /// isTemporary - Check if this is an assembler temporary symbol.
+ bool isTemporary() const { return IsTemporary; }
+
+ /// isUsed - Check if this is used.
+ bool isUsed() const { return IsUsed; }
+ void setUsed(bool Value) const { IsUsed = Value; }
+
+ /// \brief Check if this symbol is redefinable.
+ 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;
}
+ }
- /// setAbsolute - Mark the symbol as absolute.
- void setAbsolute() { Section = AbsolutePseudoSection; }
+ /// @}
+ /// \name Associated Sections
+ /// @{
- /// @}
- /// @name Variable Symbols
- /// @{
+ /// isDefined - Check if this symbol is defined (i.e., it has an address).
+ ///
+ /// Defined symbols are either absolute or in some section.
+ bool isDefined() const { return getSectionPtr() != nullptr; }
- /// isVariable - Check if this is a variable symbol.
- bool isVariable() const {
- return Value != nullptr;
- }
+ /// isInSection - Check if this symbol is defined in some section (i.e., it
+ /// is defined but not absolute).
+ bool isInSection() const { return isDefined() && !isAbsolute(); }
- /// getVariableValue() - Get the value for variable symbols.
- const MCExpr *getVariableValue() const {
- assert(isVariable() && "Invalid accessor!");
- IsUsed = true;
- return Value;
- }
+ /// isUndefined - Check if this symbol undefined (i.e., implicitly defined).
+ bool isUndefined() const { return !isDefined(); }
- // AliasedSymbol() - If this is an alias (a = b), return the symbol
- // we ultimately point to. For a non-alias, this just returns the symbol
- // itself.
- const MCSymbol &AliasedSymbol() const;
+ /// isAbsolute - Check if this is an absolute symbol.
+ bool isAbsolute() const { return getSectionPtr() == AbsolutePseudoSection; }
- void setVariableValue(const MCExpr *Value);
+ /// Get the section associated with a defined, non-absolute symbol.
+ MCSection &getSection() const {
+ assert(isInSection() && "Invalid accessor!");
+ return *getSectionPtr();
+ }
- /// @}
+ /// Mark the symbol as defined in the section \p S.
+ void setSection(MCSection &S) {
+ assert(!isVariable() && "Cannot set section of variable");
+ Section = &S;
+ }
- /// print - Print the value to the stream \p OS.
- void print(raw_ostream &OS) const;
+ /// setUndefined - Mark the symbol as undefined.
+ void setUndefined() { Section = nullptr; }
- /// dump - Print the value to stderr.
- void dump() const;
- };
+ /// @}
+ /// \name Variable Symbols
+ /// @{
+
+ /// isVariable - Check if this is a variable symbol.
+ bool isVariable() const { return Value != nullptr; }
+
+ /// getVariableValue() - Get the value for variable symbols.
+ const MCExpr *getVariableValue() const {
+ assert(isVariable() && "Invalid accessor!");
+ IsUsed = true;
+ return Value;
+ }
+
+ void setVariableValue(const MCExpr *Value);
- inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
- Sym.print(OS);
- return OS;
+ /// @}
+
+ /// Get the (implementation defined) index.
+ uint64_t getIndex() const {
+ assert(HasData && "Uninitialized symbol data");
+ return Index;
+ }
+
+ /// Set the (implementation defined) index.
+ void setIndex(uint64_t Value) const {
+ assert(HasData && "Uninitialized symbol data");
+ assert(!(Value >> 60) && "Not enough bits for value");
+ Index = Value;
}
+
+ /// print - Print the value to the stream \p OS.
+ void print(raw_ostream &OS) const;
+
+ /// dump - Print the value to stderr.
+ void dump() const;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
+ Sym.print(OS);
+ return OS;
+}
} // end namespace llvm
#endif
diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h
index cbbb591f1b80..2ef17673f091 100644
--- a/include/llvm/MC/MCSymbolizer.h
+++ b/include/llvm/MC/MCSymbolizer.h
@@ -38,8 +38,8 @@ class raw_ostream;
/// operands are actually symbolizable, and in what way. I don't think this
/// information exists right now.
class MCSymbolizer {
- MCSymbolizer(const MCSymbolizer &) LLVM_DELETED_FUNCTION;
- void operator=(const MCSymbolizer &) LLVM_DELETED_FUNCTION;
+ MCSymbolizer(const MCSymbolizer &) = delete;
+ void operator=(const MCSymbolizer &) = delete;
protected:
MCContext &Ctx;
@@ -59,14 +59,14 @@ public:
/// represent this immediate in a more understandable way, for instance as a
/// symbol or an offset from a symbol. Relocations can also be used to enrich
/// the symbolic expression.
- /// @param Inst - The MCInst where to insert the symbolic operand.
- /// @param cStream - Stream to print comments and annotations on.
- /// @param Value - Operand value, pc-adjusted by the caller if necessary.
- /// @param Address - Load address of the instruction.
- /// @param IsBranch - Is the instruction a branch?
- /// @param Offset - Byte offset of the operand inside the inst.
- /// @param InstSize - Size of the instruction in bytes.
- /// @return Whether a symbolic operand was added.
+ /// \param Inst - The MCInst where to insert the symbolic operand.
+ /// \param cStream - Stream to print comments and annotations on.
+ /// \param Value - Operand value, pc-adjusted by the caller if necessary.
+ /// \param Address - Load address of the instruction.
+ /// \param IsBranch - Is the instruction a branch?
+ /// \param Offset - Byte offset of the operand inside the inst.
+ /// \param InstSize - Size of the instruction in bytes.
+ /// \return Whether a symbolic operand was added.
virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream,
int64_t Value, uint64_t Address,
bool IsBranch, uint64_t Offset,
diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h
index ea71d1f433a4..36db3914f017 100644
--- a/include/llvm/MC/MCTargetAsmParser.h
+++ b/include/llvm/MC/MCTargetAsmParser.h
@@ -75,8 +75,6 @@ struct ParseInstructionInfo {
ParseInstructionInfo() : AsmRewrites(nullptr) {}
ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites)
: AsmRewrites(rewrites) {}
-
- ~ParseInstructionInfo() {}
};
/// MCTargetAsmParser - Generic interface to target specific assembly parsers.
@@ -91,8 +89,8 @@ public:
};
private:
- MCTargetAsmParser(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION;
- void operator=(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION;
+ MCTargetAsmParser(const MCTargetAsmParser &) = delete;
+ void operator=(const MCTargetAsmParser &) = delete;
protected: // Can only create subclasses.
MCTargetAsmParser();
@@ -110,7 +108,7 @@ protected: // Can only create subclasses.
MCTargetOptions MCOptions;
public:
- virtual ~MCTargetAsmParser();
+ ~MCTargetAsmParser() override;
uint64_t getAvailableFeatures() const { return AvailableFeatures; }
void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; }
diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h
index dd86979690cf..6bdf43685f21 100644
--- a/include/llvm/MC/MCValue.h
+++ b/include/llvm/MC/MCValue.h
@@ -23,10 +23,11 @@ namespace llvm {
class MCAsmInfo;
class raw_ostream;
-/// MCValue - This represents an "assembler immediate". In its most
-/// general form, this can hold ":Kind:(SymbolA - SymbolB + imm64)".
-/// Not all targets supports relocations of this general form, but we
-/// need to represent this anyway.
+/// \brief This represents an "assembler immediate".
+///
+/// In its most general form, this can hold ":Kind:(SymbolA - SymbolB +
+/// imm64)". Not all targets supports relocations of this general form, but we
+/// need to represent this anyway.
///
/// In general both SymbolA and SymbolB will also have a modifier
/// analogous to the top-level Kind. Current targets are not expected
@@ -51,13 +52,13 @@ public:
const MCSymbolRefExpr *getSymB() const { return SymB; }
uint32_t getRefKind() const { return RefKind; }
- /// isAbsolute - Is this an absolute (as opposed to relocatable) value.
+ /// \brief Is this an absolute (as opposed to relocatable) value.
bool isAbsolute() const { return !SymA && !SymB; }
- /// print - Print the value to the stream \p OS.
- void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
+ /// \brief Print the value to the stream \p OS.
+ void print(raw_ostream &OS) const;
- /// dump - Print the value to stderr.
+ /// \brief Print the value to stderr.
void dump() const;
MCSymbolRefExpr::VariantKind getAccessVariant() const;
diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h
index dad7bb597039..e2e95c7df710 100644
--- a/include/llvm/MC/MCWinCOFFObjectWriter.h
+++ b/include/llvm/MC/MCWinCOFFObjectWriter.h
@@ -11,10 +11,12 @@
#define LLVM_MC_MCWINCOFFOBJECTWRITER_H
namespace llvm {
- class MCFixup;
- class MCObjectWriter;
- class MCValue;
- class raw_ostream;
+class MCAsmBackend;
+class MCFixup;
+class MCObjectWriter;
+class MCValue;
+class raw_ostream;
+class raw_pwrite_stream;
class MCWinCOFFObjectTargetWriter {
virtual void anchor();
@@ -27,9 +29,9 @@ namespace llvm {
virtual ~MCWinCOFFObjectTargetWriter() {}
unsigned getMachine() const { return Machine; }
- virtual unsigned getRelocType(const MCValue &Target,
- const MCFixup &Fixup,
- bool IsCrossSection) const = 0;
+ virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
+ bool IsCrossSection,
+ const MCAsmBackend &MAB) const = 0;
virtual bool recordRelocation(const MCFixup &) const { return true; }
};
@@ -39,7 +41,7 @@ namespace llvm {
/// \param OS - The stream to write to.
/// \returns The constructed object writer.
MCObjectWriter *createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
- raw_ostream &OS);
+ raw_pwrite_stream &OS);
} // End llvm namespace
#endif
diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h
index 57a75cec2204..6a83e02298ff 100644
--- a/include/llvm/MC/MCWinCOFFStreamer.h
+++ b/include/llvm/MC/MCWinCOFFStreamer.h
@@ -24,11 +24,12 @@ class MCSubtargetInfo;
class MCSymbol;
class StringRef;
class raw_ostream;
+class raw_pwrite_stream;
class MCWinCOFFStreamer : public MCObjectStreamer {
public:
MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE,
- raw_ostream &OS);
+ raw_pwrite_stream &OS);
/// state management
void reset() override {
@@ -56,9 +57,9 @@ public:
unsigned ByteAlignment) override;
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size,
+ void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size,
+ void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
void EmitFileDirective(StringRef Filename) override;
void EmitIdent(StringRef IdentString) override;
diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h
index 05b58c753b66..723d7a397c49 100644
--- a/include/llvm/MC/MCWinEH.h
+++ b/include/llvm/MC/MCWinEH.h
@@ -65,10 +65,10 @@ struct FrameInfo {
class UnwindEmitter {
public:
- static const MCSection *getPDataSection(const MCSymbol *Function,
- MCContext &Context);
- static const MCSection *getXDataSection(const MCSymbol *Function,
- MCContext &Context);
+ static MCSection *getPDataSection(const MCSymbol *Function,
+ MCContext &Context);
+ static MCSection *getXDataSection(const MCSymbol *Function,
+ MCContext &Context);
virtual ~UnwindEmitter() { }
diff --git a/include/llvm/MC/SectionKind.h b/include/llvm/MC/SectionKind.h
index 85a91c6b1698..9e8b68f4340c 100644
--- a/include/llvm/MC/SectionKind.h
+++ b/include/llvm/MC/SectionKind.h
@@ -55,7 +55,6 @@ class SectionKind {
/// MergeableConst - These are sections for merging fixed-length
/// constants together. For example, this can be used to unique
/// constant pool entries etc.
- MergeableConst,
/// MergeableConst4 - This is a section used by 4-byte constants,
/// for example, floats.
@@ -151,8 +150,8 @@ public:
bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; }
bool isMergeableConst() const {
- return K == MergeableConst || K == MergeableConst4 ||
- K == MergeableConst8 || K == MergeableConst16;
+ return K == MergeableConst4 || K == MergeableConst8 ||
+ K == MergeableConst16;
}
bool isMergeableConst4() const { return K == MergeableConst4; }
bool isMergeableConst8() const { return K == MergeableConst8; }
@@ -216,7 +215,6 @@ public:
static SectionKind getMergeable4ByteCString() {
return get(Mergeable4ByteCString);
}
- static SectionKind getMergeableConst() { return get(MergeableConst); }
static SectionKind getMergeableConst4() { return get(MergeableConst4); }
static SectionKind getMergeableConst8() { return get(MergeableConst8); }
static SectionKind getMergeableConst16() { return get(MergeableConst16); }
diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h
index bfecb8ba6ab0..6a631ffe79bd 100644
--- a/include/llvm/MC/SubtargetFeature.h
+++ b/include/llvm/MC/SubtargetFeature.h
@@ -21,11 +21,29 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/DataTypes.h"
+#include <bitset>
namespace llvm {
class raw_ostream;
class StringRef;
+// A container class for subtarget features.
+// This is convenient because std::bitset does not have a constructor
+// with an initializer list of set bits.
+const unsigned MAX_SUBTARGET_FEATURES = 64;
+class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> {
+public:
+ // Cannot inherit constructors because it's not supported by VC++..
+ FeatureBitset() : bitset() {}
+
+ FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {}
+
+ FeatureBitset(std::initializer_list<unsigned> Init) : bitset() {
+ for (auto I = Init.begin() , E = Init.end(); I != E; ++I)
+ set(*I);
+ }
+};
+
//===----------------------------------------------------------------------===//
///
/// SubtargetFeatureKV - Used to provide key value pairs for feature and
@@ -34,8 +52,8 @@ namespace llvm {
struct SubtargetFeatureKV {
const char *Key; // K-V key string
const char *Desc; // Help descriptor
- uint64_t Value; // K-V integer value
- uint64_t Implies; // K-V bit mask
+ FeatureBitset Value; // K-V integer value
+ FeatureBitset Implies; // K-V bit mask
// Compare routine for std::lower_bound
bool operator<(StringRef S) const {
@@ -78,15 +96,15 @@ public:
std::string getString() const;
/// Adding Features.
- void AddFeature(StringRef String);
+ void AddFeature(StringRef String, bool Enable = true);
/// ToggleFeature - Toggle a feature and returns the newly updated feature
/// bits.
- uint64_t ToggleFeature(uint64_t Bits, StringRef String,
+ FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String,
ArrayRef<SubtargetFeatureKV> FeatureTable);
/// Get feature bits of a CPU.
- uint64_t getFeatureBits(StringRef CPU,
+ FeatureBitset getFeatureBits(StringRef CPU,
ArrayRef<SubtargetFeatureKV> CPUTable,
ArrayRef<SubtargetFeatureKV> FeatureTable);
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 4e96205a93ba..8da6919a4655 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -41,6 +41,9 @@ struct ArchiveMemberHeader {
sys::fs::perms getAccessMode() const;
sys::TimeValue getLastModified() const;
+ llvm::StringRef getRawLastModified() const {
+ return StringRef(LastModified, sizeof(LastModified)).rtrim(" ");
+ }
unsigned getUID() const;
unsigned getGID() const;
};
@@ -78,6 +81,9 @@ public:
sys::TimeValue getLastModified() const {
return getHeader()->getLastModified();
}
+ StringRef getRawLastModified() const {
+ return getHeader()->getRawLastModified();
+ }
unsigned getUID() const { return getHeader()->getUID(); }
unsigned getGID() const { return getHeader()->getGID(); }
sys::fs::perms getAccessMode() const {
@@ -85,10 +91,13 @@ public:
}
/// \return the size of the archive member without the header or padding.
uint64_t getSize() const;
+ /// \return the size in the archive header for this member.
+ uint64_t getRawSize() const;
StringRef getBuffer() const {
return StringRef(Data.data() + StartOfFile, getSize());
}
+ uint64_t getChildOffset() const;
ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
@@ -146,9 +155,8 @@ public:
Symbol symbol;
public:
symbol_iterator(const Symbol &s) : symbol(s) {}
- const Symbol *operator->() const {
- return &symbol;
- }
+ const Symbol *operator->() const { return &symbol; }
+ const Symbol &operator*() const { return symbol; }
bool operator==(const symbol_iterator &other) const {
return symbol == other.symbol;
@@ -169,6 +177,7 @@ public:
enum Kind {
K_GNU,
+ K_MIPS64,
K_BSD,
K_COFF
};
@@ -184,6 +193,9 @@ public:
symbol_iterator symbol_begin() const;
symbol_iterator symbol_end() const;
+ iterator_range<symbol_iterator> symbols() const {
+ return iterator_range<symbol_iterator>(symbol_begin(), symbol_end());
+ }
// Cast methods.
static inline bool classof(Binary const *v) {
@@ -194,6 +206,8 @@ public:
child_iterator findSym(StringRef name) const;
bool hasSymbolTable() const;
+ child_iterator getSymbolTableChild() const { return SymbolTable; }
+ uint32_t getNumberOfSymbols() const;
private:
child_iterator SymbolTable;
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 4b2b7e6835cc..a3d6d0d4d428 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -28,8 +28,8 @@ namespace object {
class Binary {
private:
- Binary() LLVM_DELETED_FUNCTION;
- Binary(const Binary &other) LLVM_DELETED_FUNCTION;
+ Binary() = delete;
+ Binary(const Binary &other) = delete;
unsigned int TypeID;
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index 522bf68c6cbd..ccac02036adc 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -314,6 +314,10 @@ public:
return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT;
}
+ bool isAbsolute() const {
+ return getSectionNumber() == -1;
+ }
+
bool isExternal() const {
return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL;
}
@@ -350,6 +354,10 @@ public:
return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
}
+ bool isSection() const {
+ return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION;
+ }
+
bool isSectionDefinition() const {
// C++/CLI creates external ABS symbols for non-const appdomain globals.
// These are also followed by an auxiliary section definition.
@@ -441,6 +449,27 @@ struct coff_aux_clr_token {
support::ulittle32_t SymbolTableIndex;
};
+struct coff_import_header {
+ support::ulittle16_t Sig1;
+ support::ulittle16_t Sig2;
+ support::ulittle16_t Version;
+ support::ulittle16_t Machine;
+ support::ulittle32_t TimeDateStamp;
+ support::ulittle32_t SizeOfData;
+ support::ulittle16_t OrdinalHint;
+ support::ulittle16_t TypeInfo;
+ int getType() const { return TypeInfo & 0x3; }
+ int getNameType() const { return (TypeInfo & 0x7) >> 2; }
+};
+
+struct coff_import_directory_table_entry {
+ support::ulittle32_t ImportLookupTableRVA;
+ support::ulittle32_t TimeDateStamp;
+ support::ulittle32_t ForwarderChain;
+ support::ulittle32_t NameRVA;
+ support::ulittle32_t ImportAddressTableRVA;
+};
+
struct coff_load_configuration32 {
support::ulittle32_t Characteristics;
support::ulittle32_t TimeDateStamp;
@@ -612,6 +641,7 @@ protected:
std::error_code getRelocationOffset(DataRefImpl Rel,
uint64_t &Res) const override;
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
+ section_iterator getRelocationSection(DataRefImpl Rel) const override;
std::error_code getRelocationType(DataRefImpl Rel,
uint64_t &Res) const override;
std::error_code
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index 7c10bbf6e5ab..ddabf59f309e 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -94,18 +94,24 @@ public:
return *this;
}
+ ELFEntityIterator &operator+(difference_type n) {
+ assert(Current && "Attempted to increment an invalid iterator!");
+ Current += (n * EntitySize);
+ return *this;
+ }
+
+ ELFEntityIterator &operator-(difference_type n) {
+ assert(Current && "Attempted to subtract an invalid iterator!");
+ Current -= (n * EntitySize);
+ return *this;
+ }
+
ELFEntityIterator operator ++(int) {
ELFEntityIterator Tmp = *this;
++*this;
return Tmp;
}
- ELFEntityIterator &operator =(const ELFEntityIterator &Other) {
- EntitySize = Other.EntitySize;
- Current = Other.Current;
- return *this;
- }
-
difference_type operator -(const ELFEntityIterator &Other) const {
assert(EntitySize == Other.EntitySize &&
"Subtracting iterators of different EntitySize!");
@@ -203,12 +209,6 @@ public:
return *this;
}
- Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) {
- EntitySize = Other.EntitySize;
- Current = Other.Current;
- return *this;
- }
-
difference_type operator-(const Elf_Sym_Iter &Other) const {
assert(EntitySize == Other.EntitySize &&
"Subtracting iterators of different EntitySize!");
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index c2d6438f45ba..9bd4c3241118 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -86,6 +86,7 @@ protected:
std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override;
std::error_code getSymbolType(DataRefImpl Symb,
SymbolRef::Type &Res) const override;
+ section_iterator getSymbolSection(const Elf_Sym *Symb) const;
std::error_code getSymbolSection(DataRefImpl Symb,
section_iterator &Res) const override;
@@ -112,6 +113,7 @@ protected:
std::error_code getRelocationOffset(DataRefImpl Rel,
uint64_t &Res) const override;
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
+ section_iterator getRelocationSection(DataRefImpl Rel) const override;
std::error_code getRelocationType(DataRefImpl Rel,
uint64_t &Res) const override;
std::error_code
@@ -177,6 +179,20 @@ protected:
return DRI;
}
+ bool isExportedToOtherDSO(const Elf_Sym *ESym) const {
+ unsigned char Binding = ESym->getBinding();
+ unsigned char Visibility = ESym->getVisibility();
+
+ // A symbol is exported if its binding is either GLOBAL or WEAK, and its
+ // visibility is either DEFAULT or PROTECTED. All other symbols are not
+ // exported.
+ if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) &&
+ (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED))
+ return true;
+
+ return false;
+ }
+
// This flag is used for classof, to distinguish ELFObjectFile from
// its subclass. If more subclasses will be created, this flag will
// have to become an enum.
@@ -300,8 +316,11 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
ESym->getType() == ELF::STT_FUNC)
Result &= ~1;
- if (Header->e_type == ELF::ET_REL)
- Result += EF.getSection(ESym)->sh_addr;
+ if (Header->e_type == ELF::ET_REL) {
+ const typename ELFFile<ELFT>::Elf_Shdr * Section = EF.getSection(ESym);
+ if (Section != nullptr)
+ Result += Section->sh_addr;
+ }
return object_error::success;
}
@@ -389,22 +408,33 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const {
EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON)
Result |= SymbolRef::SF_Common;
+ if (isExportedToOtherDSO(ESym))
+ Result |= SymbolRef::SF_Exported;
+
+ if (ESym->getVisibility() == ELF::STV_HIDDEN)
+ Result |= SymbolRef::SF_Hidden;
+
return Result;
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
- section_iterator &Res) const {
- const Elf_Sym *ESym = getSymbol(Symb);
+section_iterator
+ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const {
const Elf_Shdr *ESec = EF.getSection(ESym);
if (!ESec)
- Res = section_end();
+ return section_end();
else {
DataRefImpl Sec;
Sec.p = reinterpret_cast<intptr_t>(ESec);
- Res = section_iterator(SectionRef(Sec, this));
+ return section_iterator(SectionRef(Sec, this));
}
+}
+
+template <class ELFT>
+std::error_code
+ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
+ section_iterator &Res) const {
+ Res = getSymbolSection(getSymbol(Symb));
return object_error::success;
}
@@ -565,6 +595,20 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
return symbol_iterator(SymbolRef(SymbolData, this));
}
+// ELF relocations can target sections, by targetting a symbol of type
+// STT_SECTION
+template <class ELFT>
+section_iterator
+ELFObjectFile<ELFT>::getRelocationSection(DataRefImpl Rel) const {
+ symbol_iterator Sym = getRelocationSymbol(Rel);
+ if (Sym == symbol_end())
+ return section_end();
+ const Elf_Sym *ESym = getSymbol(Sym->getRawDataRefImpl());
+ if (ESym->getType() != ELF::STT_SECTION)
+ return section_end();
+ return getSymbolSection(ESym);
+}
+
template <class ELFT>
std::error_code
ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel,
@@ -908,7 +952,7 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
case ELF::EM_SPARC:
case ELF::EM_SPARC32PLUS:
- return Triple::sparc;
+ return IsLittleEndian ? Triple::sparcel : Triple::sparc;
case ELF::EM_SPARCV9:
return Triple::sparcv9;
diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h
index 4bc0c7c2016e..287d3670678a 100644
--- a/include/llvm/Object/ELFTypes.h
+++ b/include/llvm/Object/ELFTypes.h
@@ -189,7 +189,15 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
}
/// Access to the STV_xxx flag stored in the first two bits of st_other.
+ /// STV_DEFAULT: 0
+ /// STV_INTERNAL: 1
+ /// STV_HIDDEN: 2
+ /// STV_PROTECTED: 3
unsigned char getVisibility() const { return st_other & 0x3; }
+ void setVisibility(unsigned char v) {
+ assert(v < 4 && "Invalid value for visibility");
+ st_other = (st_other & ~0x3) | v;
+ }
};
/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section
@@ -302,7 +310,10 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> {
assert(!isMips64EL);
return r_info;
}
- void setRInfo(uint32_t R) { r_info = R; }
+ void setRInfo(uint32_t R, bool IsMips64EL) {
+ assert(!IsMips64EL);
+ r_info = R;
+ }
};
template <endianness TargetEndianness, std::size_t MaxAlign>
@@ -321,9 +332,12 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> {
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
}
- void setRInfo(uint64_t R) {
- // FIXME: Add mips64el support.
- r_info = R;
+ void setRInfo(uint64_t R, bool IsMips64EL) {
+ if (IsMips64EL)
+ r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) |
+ ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56);
+ else
+ r_info = R;
}
};
@@ -338,7 +352,10 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> {
assert(!isMips64EL);
return r_info;
}
- void setRInfo(uint32_t R) { r_info = R; }
+ void setRInfo(uint32_t R, bool IsMips64EL) {
+ assert(!IsMips64EL);
+ r_info = R;
+ }
};
template <endianness TargetEndianness, std::size_t MaxAlign>
@@ -358,9 +375,12 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> {
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
}
- void setRInfo(uint64_t R) {
- // FIXME: Add mips64el support.
- r_info = R;
+ void setRInfo(uint64_t R, bool IsMips64EL) {
+ if (IsMips64EL)
+ r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) |
+ ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56);
+ else
+ r_info = R;
}
};
@@ -380,10 +400,14 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>,
uint32_t getType(bool isMips64EL) const {
return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL);
}
- void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
- void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); }
- void setSymbolAndType(uint32_t s, uint32_t t) {
- this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL));
+ void setSymbol(uint32_t s, bool IsMips64EL) {
+ setSymbolAndType(s, getType(), IsMips64EL);
+ }
+ void setType(uint32_t t, bool IsMips64EL) {
+ setSymbolAndType(getSymbol(), t, IsMips64EL);
+ }
+ void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) {
+ this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL);
}
};
@@ -401,10 +425,14 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>,
unsigned char getType(bool isMips64EL) const {
return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff);
}
- void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
- void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
- void setSymbolAndType(uint32_t s, unsigned char t) {
- this->setRInfo((s << 8) + t);
+ void setSymbol(uint32_t s, bool IsMips64EL) {
+ setSymbolAndType(s, getType(), IsMips64EL);
+ }
+ void setType(unsigned char t, bool IsMips64EL) {
+ setSymbolAndType(getSymbol(), t, IsMips64EL);
+ }
+ void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) {
+ this->setRInfo((s << 8) + t, IsMips64EL);
}
};
@@ -461,6 +489,59 @@ struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > {
Elf_Xword p_align; // Segment alignment constraint
};
+// MIPS .reginfo section
+template <class ELFT>
+struct Elf_Mips_RegInfo;
+
+template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
+struct Elf_Mips_RegInfo<ELFType<TargetEndianness, MaxAlign, false>> {
+ LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
+ Elf_Word ri_gprmask; // bit-mask of used general registers
+ Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
+ Elf_Addr ri_gp_value; // gp register value
+};
+
+template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
+struct Elf_Mips_RegInfo<ELFType<TargetEndianness, MaxAlign, true>> {
+ LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
+ Elf_Word ri_gprmask; // bit-mask of used general registers
+ Elf_Word ri_pad; // unused padding field
+ Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
+ Elf_Addr ri_gp_value; // gp register value
+};
+
+// .MIPS.options section
+template <class ELFT> struct Elf_Mips_Options {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ uint8_t kind; // Determines interpretation of variable part of descriptor
+ uint8_t size; // Byte size of descriptor, including this header
+ Elf_Half section; // Section header index of section affected,
+ // or 0 for global options
+ Elf_Word info; // Kind-specific information
+
+ const Elf_Mips_RegInfo<ELFT> &getRegInfo() const {
+ assert(kind == llvm::ELF::ODK_REGINFO);
+ return *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(
+ (const uint8_t *)this + sizeof(Elf_Mips_Options));
+ }
+};
+
+// .MIPS.abiflags section content
+template <class ELFT> struct Elf_Mips_ABIFlags {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ Elf_Half version; // Version of the structure
+ uint8_t isa_level; // ISA level: 1-5, 32, and 64
+ uint8_t isa_rev; // ISA revision (0 for MIPS I - MIPS V)
+ uint8_t gpr_size; // General purpose registers size
+ uint8_t cpr1_size; // Co-processor 1 registers size
+ uint8_t cpr2_size; // Co-processor 2 registers size
+ uint8_t fp_abi; // Floating-point ABI flag
+ Elf_Word isa_ext; // Processor-specific extension
+ Elf_Word ases; // ASEs flags
+ Elf_Word flags1; // General flags
+ Elf_Word flags2; // General flags
+};
+
} // end namespace object.
} // end namespace llvm.
diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h
index b71946d98b5d..b45507920a9c 100644
--- a/include/llvm/Object/ELFYAML.h
+++ b/include/llvm/Object/ELFYAML.h
@@ -41,12 +41,20 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI)
LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL)
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS)
// Just use 64, since it can hold 32-bit values too.
LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO)
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG)
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA)
+
// For now, hardcode 64 bits everywhere that 32 or 64 would be needed
// since 64-bit can hold 32-bit values too.
struct FileHeader {
@@ -71,14 +79,20 @@ struct LocalGlobalWeakSymbols {
std::vector<Symbol> Global;
std::vector<Symbol> Weak;
};
+
+struct SectionOrType {
+ StringRef sectionNameOrType;
+};
+
struct Section {
- enum class SectionKind { RawContent, Relocation };
+ enum class SectionKind { Group, RawContent, Relocation, MipsABIFlags };
SectionKind Kind;
StringRef Name;
ELF_SHT Type;
ELF_SHF Flags;
llvm::yaml::Hex64 Address;
StringRef Link;
+ StringRef Info;
llvm::yaml::Hex64 AddressAlign;
Section(SectionKind Kind) : Kind(Kind) {}
virtual ~Section();
@@ -91,6 +105,17 @@ struct RawContentSection : Section {
return S->Kind == SectionKind::RawContent;
}
};
+
+struct Group : Section {
+ // Members of a group contain a flag and a list of section indices
+ // that are part of the group.
+ std::vector<SectionOrType> Members;
+ Group() : Section(SectionKind::Group) {}
+ static bool classof(const Section *S) {
+ return S->Kind == SectionKind::Group;
+ }
+};
+
struct Relocation {
llvm::yaml::Hex64 Offset;
int64_t Addend;
@@ -98,13 +123,32 @@ struct Relocation {
StringRef Symbol;
};
struct RelocationSection : Section {
- StringRef Info;
std::vector<Relocation> Relocations;
RelocationSection() : Section(SectionKind::Relocation) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::Relocation;
}
};
+
+// Represents .MIPS.abiflags section
+struct MipsABIFlags : Section {
+ llvm::yaml::Hex16 Version;
+ MIPS_ISA ISALevel;
+ llvm::yaml::Hex8 ISARevision;
+ MIPS_AFL_REG GPRSize;
+ MIPS_AFL_REG CPR1Size;
+ MIPS_AFL_REG CPR2Size;
+ MIPS_ABI_FP FpABI;
+ MIPS_AFL_EXT ISAExtension;
+ MIPS_AFL_ASE ASEs;
+ MIPS_AFL_FLAGS1 Flags1;
+ llvm::yaml::Hex32 Flags2;
+ MipsABIFlags() : Section(SectionKind::MipsABIFlags) {}
+ static bool classof(const Section *S) {
+ return S->Kind == SectionKind::MipsABIFlags;
+ }
+};
+
struct Object {
FileHeader Header;
std::vector<std::unique_ptr<Section>> Sections;
@@ -121,6 +165,7 @@ struct Object {
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType)
namespace llvm {
namespace yaml {
@@ -186,6 +231,41 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_REL> {
};
template <>
+struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> {
+ static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value);
+};
+
+template <>
+struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG> {
+ static void enumeration(IO &IO, ELFYAML::MIPS_AFL_REG &Value);
+};
+
+template <>
+struct ScalarEnumerationTraits<ELFYAML::MIPS_ABI_FP> {
+ static void enumeration(IO &IO, ELFYAML::MIPS_ABI_FP &Value);
+};
+
+template <>
+struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_EXT> {
+ static void enumeration(IO &IO, ELFYAML::MIPS_AFL_EXT &Value);
+};
+
+template <>
+struct ScalarEnumerationTraits<ELFYAML::MIPS_ISA> {
+ static void enumeration(IO &IO, ELFYAML::MIPS_ISA &Value);
+};
+
+template <>
+struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_ASE> {
+ static void bitset(IO &IO, ELFYAML::MIPS_AFL_ASE &Value);
+};
+
+template <>
+struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1> {
+ static void bitset(IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value);
+};
+
+template <>
struct MappingTraits<ELFYAML::FileHeader> {
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
};
@@ -215,6 +295,10 @@ struct MappingTraits<ELFYAML::Object> {
static void mapping(IO &IO, ELFYAML::Object &Object);
};
+template <> struct MappingTraits<ELFYAML::SectionOrType> {
+ static void mapping(IO &IO, ELFYAML::SectionOrType &sectionOrType);
+};
+
} // end namespace yaml
} // end namespace llvm
diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h
index 74f46667ce64..ef655287c34c 100644
--- a/include/llvm/Object/IRObjectFile.h
+++ b/include/llvm/Object/IRObjectFile.h
@@ -31,7 +31,7 @@ class IRObjectFile : public SymbolicFile {
public:
IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> M);
- ~IRObjectFile();
+ ~IRObjectFile() override;
void moveSymbolNext(DataRefImpl &Symb) const override;
std::error_code printSymbolName(raw_ostream &OS,
DataRefImpl Symb) const override;
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index bee1f6ce0b01..0a9b62c9055f 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -235,6 +235,7 @@ public:
std::error_code getRelocationOffset(DataRefImpl Rel,
uint64_t &Res) const override;
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
+ section_iterator getRelocationSection(DataRefImpl Rel) const override;
std::error_code getRelocationType(DataRefImpl Rel,
uint64_t &Res) const override;
std::error_code
@@ -326,7 +327,7 @@ public:
unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
- SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const;
+ SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const;
// Walk load commands.
LoadCommandInfo getFirstLoadCommandInfo() const;
@@ -395,6 +396,7 @@ public:
MachO::symtab_command getSymtabLoadCommand() const;
MachO::dysymtab_command getDysymtabLoadCommand() const;
MachO::linkedit_data_command getDataInCodeLoadCommand() const;
+ MachO::linkedit_data_command getLinkOptHintsLoadCommand() const;
ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const;
ArrayRef<uint8_t> getDyldInfoBindOpcodes() const;
ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;
@@ -437,6 +439,7 @@ private:
const char *SymtabLoadCmd;
const char *DysymtabLoadCmd;
const char *DataInCodeLoadCmd;
+ const char *LinkOptHintsLoadCmd;
const char *DyldInfoLoadCmd;
const char *UuidLoadCmd;
bool HasPageZeroSegment;
diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h
index 93f665438821..05119b293310 100644
--- a/include/llvm/Object/MachOUniversal.h
+++ b/include/llvm/Object/MachOUniversal.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/MachO.h"
@@ -69,9 +70,8 @@ public:
ObjectForArch Obj;
public:
object_iterator(const ObjectForArch &Obj) : Obj(Obj) {}
- const ObjectForArch* operator->() const {
- return &Obj;
- }
+ const ObjectForArch *operator->() const { return &Obj; }
+ const ObjectForArch &operator*() const { return Obj; }
bool operator==(const object_iterator &Other) const {
return Obj == Other.Obj;
@@ -97,6 +97,10 @@ public:
return ObjectForArch(nullptr, 0);
}
+ iterator_range<object_iterator> objects() const {
+ return make_range(begin_objects(), end_objects());
+ }
+
uint32_t getNumberOfObjects() const { return NumberOfObjects; }
// Cast methods.
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 6aa985d7e67b..14cd082870b0 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -32,6 +32,8 @@ class MachOObjectFile;
class SymbolRef;
class symbol_iterator;
+class SectionRef;
+typedef content_iterator<SectionRef> section_iterator;
/// RelocationRef - This is a value type class that represents a single
/// relocation in the list of relocations in the object file.
@@ -51,6 +53,7 @@ public:
std::error_code getAddress(uint64_t &Result) const;
std::error_code getOffset(uint64_t &Result) const;
symbol_iterator getSymbol() const;
+ section_iterator getSection() const;
std::error_code getType(uint64_t &Result) const;
/// @brief Indicates whether this relocation should hidden when listing
@@ -76,8 +79,6 @@ typedef content_iterator<RelocationRef> relocation_iterator;
/// SectionRef - This is a value type class that represents a single section in
/// the list of sections in the object file.
-class SectionRef;
-typedef content_iterator<SectionRef> section_iterator;
class SectionRef {
friend class SymbolRef;
DataRefImpl SectionPimpl;
@@ -180,8 +181,8 @@ public:
/// figures out which type to create.
class ObjectFile : public SymbolicFile {
virtual void anchor();
- ObjectFile() LLVM_DELETED_FUNCTION;
- ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION;
+ ObjectFile() = delete;
+ ObjectFile(const ObjectFile &other) = delete;
protected:
ObjectFile(unsigned int Type, MemoryBufferRef Source);
@@ -247,6 +248,7 @@ protected:
virtual std::error_code getRelocationOffset(DataRefImpl Rel,
uint64_t &Res) const = 0;
virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
+ virtual section_iterator getRelocationSection(DataRefImpl Rel) const = 0;
virtual std::error_code getRelocationType(DataRefImpl Rel,
uint64_t &Res) const = 0;
virtual std::error_code
@@ -467,6 +469,10 @@ inline symbol_iterator RelocationRef::getSymbol() const {
return OwningObject->getRelocationSymbol(RelocationPimpl);
}
+inline section_iterator RelocationRef::getSection() const {
+ return OwningObject->getRelocationSection(RelocationPimpl);
+}
+
inline std::error_code RelocationRef::getType(uint64_t &Result) const {
return OwningObject->getRelocationType(RelocationPimpl, Result);
}
diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h
index 435799a34ebc..2bfff4c6b5a0 100644
--- a/include/llvm/Object/SymbolicFile.h
+++ b/include/llvm/Object/SymbolicFile.h
@@ -45,7 +45,9 @@ inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) {
return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0;
}
-template <class content_type> class content_iterator {
+template <class content_type>
+class content_iterator
+ : public std::iterator<std::forward_iterator_tag, content_type> {
content_type Current;
public:
@@ -87,9 +89,11 @@ public:
SF_Absolute = 1U << 3, // Absolute symbol
SF_Common = 1U << 4, // Symbol has common linkage
SF_Indirect = 1U << 5, // Symbol is an alias to another symbol
- SF_FormatSpecific = 1U << 6, // Specific to the object file format
+ SF_Exported = 1U << 6, // Symbol is visible to other DSOs
+ SF_FormatSpecific = 1U << 7, // Specific to the object file format
// (e.g. section symbols)
- SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary
+ SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary
+ SF_Hidden = 1U << 9, // Symbol has hidden visibility
};
BasicSymbolRef() : OwningObject(nullptr) { }
@@ -115,7 +119,7 @@ const uint64_t UnknownAddressOrSize = ~0ULL;
class SymbolicFile : public Binary {
public:
- virtual ~SymbolicFile();
+ ~SymbolicFile() override;
SymbolicFile(unsigned int Type, MemoryBufferRef Source);
// virtual interface.
diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h
index dcaa5405ba7c..5f6941a53d0c 100644
--- a/include/llvm/Option/Arg.h
+++ b/include/llvm/Option/Arg.h
@@ -29,8 +29,8 @@ class ArgList;
/// The Arg class encodes just enough information to be able to
/// derive the argument values efficiently.
class Arg {
- Arg(const Arg &) LLVM_DELETED_FUNCTION;
- void operator=(const Arg &) LLVM_DELETED_FUNCTION;
+ Arg(const Arg &) = delete;
+ void operator=(const Arg &) = delete;
private:
/// \brief The option this argument is an instance of.
@@ -78,9 +78,7 @@ public:
const Arg &getBaseArg() const {
return BaseArg ? *BaseArg : *this;
}
- void setBaseArg(const Arg *_BaseArg) {
- BaseArg = _BaseArg;
- }
+ void setBaseArg(const Arg *BaseArg) { this->BaseArg = BaseArg; }
bool getOwnsValues() const { return OwnsValues; }
void setOwnsValues(bool Value) const { OwnsValues = Value; }
diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h
index 3f8547e7fe41..23b04513178c 100644
--- a/include/llvm/Option/ArgList.h
+++ b/include/llvm/Option/ArgList.h
@@ -11,7 +11,9 @@
#define LLVM_OPTION_ARGLIST_H
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/Option.h"
#include <list>
@@ -52,10 +54,10 @@ public:
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
- arg_iterator(SmallVectorImpl<Arg*>::const_iterator it,
- const ArgList &_Args, OptSpecifier _Id0 = 0U,
- OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U)
- : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) {
+ arg_iterator(SmallVectorImpl<Arg *>::const_iterator it, const ArgList &Args,
+ OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
+ OptSpecifier Id2 = 0U)
+ : Current(it), Args(Args), Id0(Id0), Id1(Id1), Id2(Id2) {
SkipToNextArg();
}
@@ -91,8 +93,8 @@ public:
/// and to iterate over groups of arguments.
class ArgList {
private:
- ArgList(const ArgList &) LLVM_DELETED_FUNCTION;
- void operator=(const ArgList &) LLVM_DELETED_FUNCTION;
+ ArgList(const ArgList &) = delete;
+ void operator=(const ArgList &) = delete;
public:
typedef SmallVector<Arg*, 16> arglist_type;
@@ -188,6 +190,10 @@ 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 *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1,
+ OptSpecifier Id2) const;
+ Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
+ OptSpecifier Id3) const;
Arg *getLastArg(OptSpecifier Id) const;
Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const;
Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const;
@@ -277,16 +283,13 @@ public:
/// @name Arg Synthesis
/// @{
- /// MakeArgString - Construct a constant string pointer whose
+ /// Construct a constant string pointer whose
/// lifetime will match that of the ArgList.
- virtual const char *MakeArgString(StringRef Str) const = 0;
- const char *MakeArgString(const char *Str) const {
- return MakeArgString(StringRef(Str));
+ virtual const char *MakeArgStringRef(StringRef Str) const = 0;
+ const char *MakeArgString(const Twine &Str) const {
+ SmallString<256> Buf;
+ return MakeArgStringRef(Str.toStringRef(Buf));
}
- const char *MakeArgString(std::string Str) const {
- return MakeArgString(StringRef(Str));
- }
- const char *MakeArgString(const Twine &Str) const;
/// \brief Create an arg string for (\p LHS + \p RHS), reusing the
/// string at \p Index if possible.
@@ -317,7 +320,7 @@ private:
public:
InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
- ~InputArgList();
+ ~InputArgList() override;
const char *getArgString(unsigned Index) const override {
return ArgStrings[Index];
@@ -336,7 +339,7 @@ public:
unsigned MakeIndex(StringRef String0, StringRef String1) const;
using ArgList::MakeArgString;
- const char *MakeArgString(StringRef Str) const override;
+ const char *MakeArgStringRef(StringRef Str) const override;
/// @}
};
@@ -352,7 +355,7 @@ class DerivedArgList : public ArgList {
public:
/// Construct a new derived arg list from \p BaseArgs.
DerivedArgList(const InputArgList &BaseArgs);
- ~DerivedArgList();
+ ~DerivedArgList() override;
const char *getArgString(unsigned Index) const override {
return BaseArgs.getArgString(Index);
@@ -374,7 +377,7 @@ public:
void AddSynthesizedArg(Arg *A);
using ArgList::MakeArgString;
- const char *MakeArgString(StringRef Str) const override;
+ const char *MakeArgStringRef(StringRef Str) const override;
/// AddFlagArg - Construct a new FlagArg for the given option \p Id and
/// append it to the argument list.
diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h
index b7caa6e85a7d..0b2aaaec3afc 100644
--- a/include/llvm/Option/OptSpecifier.h
+++ b/include/llvm/Option/OptSpecifier.h
@@ -21,11 +21,11 @@ namespace opt {
unsigned ID;
private:
- explicit OptSpecifier(bool) LLVM_DELETED_FUNCTION;
+ explicit OptSpecifier(bool) = delete;
public:
OptSpecifier() : ID(0) {}
- /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {}
+ /*implicit*/ OptSpecifier(unsigned ID) : ID(ID) {}
/*implicit*/ OptSpecifier(const Option *Opt);
bool isValid() const { return ID != 0; }
diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h
index 5035940af06b..a7ff46919cd6 100644
--- a/include/llvm/Option/OptTable.h
+++ b/include/llvm/Option/OptTable.h
@@ -73,8 +73,9 @@ private:
}
protected:
- OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos,
- bool _IgnoreCase = false);
+ OptTable(const Info *OptionInfos, unsigned NumOptionInfos,
+ bool IgnoreCase = false);
+
public:
~OptTable();
diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h
index b2cfacbaf344..09be26c7cf20 100644
--- a/include/llvm/Option/Option.h
+++ b/include/llvm/Option/Option.h
@@ -70,7 +70,6 @@ protected:
public:
Option(const OptTable::Info *Info, const OptTable *Owner);
- ~Option();
bool isValid() const {
return Info != nullptr;
diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h
index c2b9f95956e8..3c4d838a4652 100644
--- a/include/llvm/Pass.h
+++ b/include/llvm/Pass.h
@@ -83,8 +83,8 @@ class Pass {
AnalysisResolver *Resolver; // Used to resolve analysis
const void *PassID;
PassKind Kind;
- void operator=(const Pass&) LLVM_DELETED_FUNCTION;
- Pass(const Pass &) LLVM_DELETED_FUNCTION;
+ void operator=(const Pass&) = delete;
+ Pass(const Pass &) = delete;
public:
explicit Pass(PassKind K, char &pid)
@@ -250,7 +250,7 @@ public:
explicit ModulePass(char &pid) : Pass(PT_Module, pid) {}
// Force out-of-line virtual method.
- virtual ~ModulePass();
+ ~ModulePass() override;
};
@@ -279,7 +279,7 @@ public:
: ModulePass(pid) {}
// Force out-of-line virtual method.
- virtual ~ImmutablePass();
+ ~ImmutablePass() override;
};
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h
index 916430541809..38adb2dbb69b 100644
--- a/include/llvm/PassAnalysisSupport.h
+++ b/include/llvm/PassAnalysisSupport.h
@@ -120,7 +120,7 @@ public:
class PMDataManager;
class AnalysisResolver {
private:
- AnalysisResolver() LLVM_DELETED_FUNCTION;
+ AnalysisResolver() = delete;
public:
explicit AnalysisResolver(PMDataManager &P) : PM(P) { }
diff --git a/include/llvm/PassInfo.h b/include/llvm/PassInfo.h
index d53daf1cf72c..d10761831b3a 100644
--- a/include/llvm/PassInfo.h
+++ b/include/llvm/PassInfo.h
@@ -138,8 +138,8 @@ public:
}
private:
- void operator=(const PassInfo &) LLVM_DELETED_FUNCTION;
- PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION;
+ void operator=(const PassInfo &) = delete;
+ PassInfo(const PassInfo &) = delete;
};
}
diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h
deleted file mode 100644
index 2a191b339931..000000000000
--- a/include/llvm/PassManager.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- llvm/PassManager.h - Container for Passes ----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is a legacy redirect header for the old PassManager. It is intended to
-// be used by clients that have not been converted to be aware of the new pass
-// management infrastructure being built for LLVM, which is every client
-// initially. Eventually this header (and the legacy management layer) will go
-// away, but we want to minimize changes to out-of-tree users of LLVM in the
-// interim.
-//
-// Note that this header *must not* be included into the same file as the new
-// pass management infrastructure is included. Things will break spectacularly.
-// If you are starting that conversion, you should switch to explicitly
-// including LegacyPassManager.h and using the legacy namespace.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_PASSMANAGER_H
-#define LLVM_PASSMANAGER_H
-
-#include "llvm/IR/LegacyPassManager.h"
-
-namespace llvm {
-
-// Pull these into the llvm namespace so that existing code that expects it
-// there can find it.
-using legacy::PassManagerBase;
-using legacy::PassManager;
-using legacy::FunctionPassManager;
-
-}
-
-#endif
diff --git a/include/llvm/Passes/PassBuilder.h b/include/llvm/Passes/PassBuilder.h
new file mode 100644
index 000000000000..1e605e374178
--- /dev/null
+++ b/include/llvm/Passes/PassBuilder.h
@@ -0,0 +1,105 @@
+//===- Parsing, selection, and construction of pass pipelines --*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Interfaces for registering analysis passes, producing common pass manager
+/// configurations, and parsing of pass pipelines.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PASSES_PASSBUILDER_H
+#define LLVM_PASSES_PASSBUILDER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class TargetMachine;
+
+/// \brief This class provides access to building LLVM's passes.
+///
+/// It's members provide the baseline state available to passes during their
+/// construction. The \c PassRegistry.def file specifies how to construct all
+/// of the built-in passes, and those may reference these members during
+/// construction.
+class PassBuilder {
+ TargetMachine *TM;
+
+public:
+ explicit PassBuilder(TargetMachine *TM = nullptr) : TM(TM) {}
+
+ /// \brief Registers all available module analysis passes.
+ ///
+ /// This is an interface that can be used to populate a \c
+ /// ModuleAnalysisManager with all registered module analyses. Callers can
+ /// still manually register any additional analyses.
+ void registerModuleAnalyses(ModuleAnalysisManager &MAM);
+
+ /// \brief Registers all available CGSCC analysis passes.
+ ///
+ /// This is an interface that can be used to populate a \c CGSCCAnalysisManager
+ /// with all registered CGSCC analyses. Callers can still manually register any
+ /// additional analyses.
+ void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM);
+
+ /// \brief Registers all available function analysis passes.
+ ///
+ /// This is an interface that can be used to populate a \c
+ /// FunctionAnalysisManager with all registered function analyses. Callers can
+ /// still manually register any additional analyses.
+ void registerFunctionAnalyses(FunctionAnalysisManager &FAM);
+
+ /// \brief Parse a textual pass pipeline description into a \c ModulePassManager.
+ ///
+ /// The format of the textual pass pipeline description looks something like:
+ ///
+ /// module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...)
+ ///
+ /// Pass managers have ()s describing the nest structure of passes. All passes
+ /// are comma separated. As a special shortcut, if the very first pass is not
+ /// a module pass (as a module pass manager is), this will automatically form
+ /// the shortest stack of pass managers that allow inserting that first pass.
+ /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes
+ /// 'lpassN', all of these are valid:
+ ///
+ /// fpass1,fpass2,fpass3
+ /// cgpass1,cgpass2,cgpass3
+ /// lpass1,lpass2,lpass3
+ ///
+ /// And they are equivalent to the following (resp.):
+ ///
+ /// module(function(fpass1,fpass2,fpass3))
+ /// module(cgscc(cgpass1,cgpass2,cgpass3))
+ /// module(function(loop(lpass1,lpass2,lpass3)))
+ ///
+ /// This shortcut is especially useful for debugging and testing small pass
+ /// combinations. Note that these shortcuts don't introduce any other magic. If
+ /// the sequence of passes aren't all the exact same kind of pass, it will be
+ /// an error. You cannot mix different levels implicitly, you must explicitly
+ /// form a pass manager in which to nest passes.
+ bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
+ bool VerifyEachPass = true, bool DebugLogging = false);
+
+private:
+ bool parseModulePassName(ModulePassManager &MPM, StringRef Name);
+ bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name);
+ bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name);
+ bool parseFunctionPassPipeline(FunctionPassManager &FPM,
+ StringRef &PipelineText, bool VerifyEachPass,
+ bool DebugLogging);
+ bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, StringRef &PipelineText,
+ bool VerifyEachPass, bool DebugLogging);
+ bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText,
+ bool VerifyEachPass, bool DebugLogging);
+};
+
+}
+
+#endif
diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h
index 38fc8ca7c77c..94e655c3edcb 100644
--- a/include/llvm/ProfileData/CoverageMapping.h
+++ b/include/llvm/ProfileData/CoverageMapping.h
@@ -18,16 +18,19 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>
+#include <tuple>
namespace llvm {
class IndexedInstrProfReader;
namespace coverage {
-class ObjectFileCoverageMappingReader;
+class CoverageMappingReader;
class CoverageMapping;
struct CounterExpressions;
@@ -62,8 +65,12 @@ public:
unsigned getExpressionID() const { return ID; }
- bool operator==(const Counter &Other) const {
- return Kind == Other.Kind && ID == Other.ID;
+ friend bool operator==(const Counter &LHS, const Counter &RHS) {
+ return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID;
+ }
+
+ friend bool operator!=(const Counter &LHS, const Counter &RHS) {
+ return !(LHS == RHS);
}
friend bool operator<(const Counter &LHS, const Counter &RHS) {
@@ -153,24 +160,40 @@ struct CounterMappingRegion {
SkippedRegion
};
- static const unsigned EncodingHasCodeBeforeBits = 1;
-
Counter Count;
unsigned FileID, ExpandedFileID;
unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
RegionKind Kind;
- /// \brief A flag that is set to true when there is already code before
- /// this region on the same line.
- /// This is useful to accurately compute the execution counts for a line.
- bool HasCodeBefore;
-
- CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart,
- unsigned ColumnStart, unsigned LineEnd,
- unsigned ColumnEnd, bool HasCodeBefore = false,
- RegionKind Kind = CodeRegion)
- : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart),
- ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
- Kind(Kind), HasCodeBefore(HasCodeBefore) {}
+
+ CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID,
+ unsigned LineStart, unsigned ColumnStart,
+ unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
+ : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID),
+ LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd),
+ ColumnEnd(ColumnEnd), Kind(Kind) {}
+
+ static CounterMappingRegion
+ makeRegion(Counter Count, unsigned FileID, unsigned LineStart,
+ unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
+ return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart,
+ LineEnd, ColumnEnd, CodeRegion);
+ }
+
+ static CounterMappingRegion
+ makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
+ unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
+ return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart,
+ ColumnStart, LineEnd, ColumnEnd,
+ ExpansionRegion);
+ }
+
+ static CounterMappingRegion
+ makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
+ unsigned LineEnd, unsigned ColumnEnd) {
+ return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart,
+ LineEnd, ColumnEnd, SkippedRegion);
+ }
+
inline std::pair<unsigned, unsigned> startLoc() const {
return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
@@ -216,8 +239,10 @@ public:
ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>())
: Expressions(Expressions), CounterValues(CounterValues) {}
+ void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
+
void dump(const Counter &C, llvm::raw_ostream &OS) const;
- void dump(const Counter &C) const { dump(C, llvm::outs()); }
+ void dump(const Counter &C) const { dump(C, dbgs()); }
/// \brief Return the number of times that a region of code associated with
/// this counter was executed.
@@ -235,10 +260,14 @@ struct FunctionRecord {
/// \brief The number of times this function was executed.
uint64_t ExecutionCount;
- FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames,
- uint64_t ExecutionCount)
- : Name(Name), Filenames(Filenames.begin(), Filenames.end()),
- ExecutionCount(ExecutionCount) {}
+ FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
+ : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
+
+ void pushRegion(CounterMappingRegion Region, uint64_t Count) {
+ if (CountedRegions.empty())
+ ExecutionCount = Count;
+ CountedRegions.emplace_back(Region, Count);
+ }
};
/// \brief Iterator over Functions, optionally filtered to a single file.
@@ -312,10 +341,22 @@ struct CoverageSegment {
CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
: Line(Line), Col(Col), Count(0), HasCount(false),
IsRegionEntry(IsRegionEntry) {}
+
+ CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
+ bool IsRegionEntry)
+ : Line(Line), Col(Col), Count(Count), HasCount(true),
+ IsRegionEntry(IsRegionEntry) {}
+
+ friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) {
+ return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) ==
+ std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry);
+ }
+
void setCount(uint64_t NewCount) {
Count = NewCount;
HasCount = true;
}
+
void addCount(uint64_t NewCount) { setCount(Count + NewCount); }
};
@@ -363,12 +404,13 @@ class CoverageMapping {
public:
/// \brief Load the coverage mapping using the given readers.
static ErrorOr<std::unique_ptr<CoverageMapping>>
- load(ObjectFileCoverageMappingReader &CoverageReader,
+ load(CoverageMappingReader &CoverageReader,
IndexedInstrProfReader &ProfileReader);
/// \brief Load the coverage mapping from the given files.
static ErrorOr<std::unique_ptr<CoverageMapping>>
- load(StringRef ObjectFilename, StringRef ProfileFilename);
+ load(StringRef ObjectFilename, StringRef ProfileFilename,
+ Triple::ArchType Arch = Triple::ArchType::UnknownArch);
/// \brief The number of functions that couldn't have their profiles mapped.
///
@@ -442,7 +484,26 @@ template<> struct DenseMapInfo<coverage::CounterExpression> {
}
};
+const std::error_category &coveragemap_category();
+
+enum class coveragemap_error {
+ success = 0,
+ eof,
+ no_data_found,
+ unsupported_version,
+ truncated,
+ malformed
+};
+
+inline std::error_code make_error_code(coveragemap_error E) {
+ return std::error_code(static_cast<int>(E), coveragemap_category());
+}
} // end namespace llvm
+namespace std {
+template <>
+struct is_error_code_enum<llvm::coveragemap_error> : std::true_type {};
+}
+
#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_
diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h
index 5a6b44b8d9ef..020edbd3e6c1 100644
--- a/include/llvm/ProfileData/CoverageMappingReader.h
+++ b/include/llvm/ProfileData/CoverageMappingReader.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ProfileData/CoverageMapping.h"
#include "llvm/ProfileData/InstrProf.h"
@@ -27,7 +28,7 @@
namespace llvm {
namespace coverage {
-class ObjectFileCoverageMappingReader;
+class CoverageMappingReader;
/// \brief Coverage mapping information for a single function.
struct CoverageMappingRecord {
@@ -41,15 +42,14 @@ struct CoverageMappingRecord {
/// \brief A file format agnostic iterator over coverage mapping data.
class CoverageMappingIterator
: public std::iterator<std::input_iterator_tag, CoverageMappingRecord> {
- ObjectFileCoverageMappingReader *Reader;
+ CoverageMappingReader *Reader;
CoverageMappingRecord Record;
void increment();
public:
CoverageMappingIterator() : Reader(nullptr) {}
- CoverageMappingIterator(ObjectFileCoverageMappingReader *Reader)
- : Reader(Reader) {
+ CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) {
increment();
}
@@ -67,17 +67,19 @@ public:
CoverageMappingRecord *operator->() { return &Record; }
};
+class CoverageMappingReader {
+public:
+ virtual std::error_code readNextRecord(CoverageMappingRecord &Record) = 0;
+ CoverageMappingIterator begin() { return CoverageMappingIterator(this); }
+ CoverageMappingIterator end() { return CoverageMappingIterator(); }
+ virtual ~CoverageMappingReader() {}
+};
+
/// \brief Base class for the raw coverage mapping and filenames data readers.
class RawCoverageReader {
protected:
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);
@@ -90,10 +92,9 @@ protected:
class RawCoverageFilenamesReader : public RawCoverageReader {
std::vector<StringRef> &Filenames;
- RawCoverageFilenamesReader(const RawCoverageFilenamesReader &)
- LLVM_DELETED_FUNCTION;
+ RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
RawCoverageFilenamesReader &
- operator=(const RawCoverageFilenamesReader &) LLVM_DELETED_FUNCTION;
+ operator=(const RawCoverageFilenamesReader &) = delete;
public:
RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
@@ -104,29 +105,27 @@ public:
/// \brief Reader for the raw coverage mapping data.
class RawCoverageMappingReader : public RawCoverageReader {
- StringRef FunctionName;
ArrayRef<StringRef> TranslationUnitFilenames;
std::vector<StringRef> &Filenames;
std::vector<CounterExpression> &Expressions;
std::vector<CounterMappingRegion> &MappingRegions;
- RawCoverageMappingReader(const RawCoverageMappingReader &)
- LLVM_DELETED_FUNCTION;
+ RawCoverageMappingReader(const RawCoverageMappingReader &) = delete;
RawCoverageMappingReader &
- operator=(const RawCoverageMappingReader &) LLVM_DELETED_FUNCTION;
+ operator=(const RawCoverageMappingReader &) = delete;
public:
- RawCoverageMappingReader(StringRef FunctionName, StringRef MappingData,
+ RawCoverageMappingReader(StringRef MappingData,
ArrayRef<StringRef> TranslationUnitFilenames,
std::vector<StringRef> &Filenames,
std::vector<CounterExpression> &Expressions,
std::vector<CounterMappingRegion> &MappingRegions)
- : RawCoverageReader(MappingData), FunctionName(FunctionName),
+ : RawCoverageReader(MappingData),
TranslationUnitFilenames(TranslationUnitFilenames),
Filenames(Filenames), Expressions(Expressions),
MappingRegions(MappingRegions) {}
- std::error_code read(CoverageMappingRecord &Record);
+ std::error_code read();
private:
std::error_code decodeCounter(unsigned Value, Counter &C);
@@ -138,7 +137,7 @@ private:
/// \brief Reader for the coverage mapping data that is emitted by the
/// frontend and stored in an object file.
-class ObjectFileCoverageMappingReader {
+class BinaryCoverageReader : public CoverageMappingReader {
public:
struct ProfileMappingRecord {
CoverageMappingVersion Version;
@@ -157,8 +156,6 @@ public:
};
private:
- std::error_code LastError;
- object::OwningBinary<object::ObjectFile> Object;
std::vector<StringRef> Filenames;
std::vector<ProfileMappingRecord> MappingRecords;
size_t CurrentRecord;
@@ -166,40 +163,17 @@ private:
std::vector<CounterExpression> Expressions;
std::vector<CounterMappingRegion> MappingRegions;
- ObjectFileCoverageMappingReader(const ObjectFileCoverageMappingReader &)
- LLVM_DELETED_FUNCTION;
- ObjectFileCoverageMappingReader &
- operator=(const ObjectFileCoverageMappingReader &) LLVM_DELETED_FUNCTION;
-
- /// \brief Set the current error_code and return same.
- std::error_code error(std::error_code EC) {
- LastError = EC;
- return EC;
- }
+ BinaryCoverageReader(const BinaryCoverageReader &) = delete;
+ BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete;
- /// \brief Clear the current error code and return a successful one.
- std::error_code success() { return error(instrprof_error::success); }
+ BinaryCoverageReader() : CurrentRecord(0) {}
public:
- ObjectFileCoverageMappingReader(StringRef FileName);
- ObjectFileCoverageMappingReader(
- std::unique_ptr<MemoryBuffer> &ObjectBuffer,
- sys::fs::file_magic Type = sys::fs::file_magic::unknown);
-
- std::error_code readHeader();
- std::error_code readNextRecord(CoverageMappingRecord &Record);
-
- /// Iterator over profile data.
- CoverageMappingIterator begin() { return CoverageMappingIterator(this); }
- CoverageMappingIterator end() { return CoverageMappingIterator(); }
+ static ErrorOr<std::unique_ptr<BinaryCoverageReader>>
+ create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
+ Triple::ArchType Arch = Triple::ArchType::UnknownArch);
- /// \brief Return true if the reader has finished reading the profile data.
- bool isEOF() { return LastError == instrprof_error::eof; }
- /// \brief Return true if the reader encountered an error reading profiling
- /// data.
- bool hasError() { return LastError && !isEOF(); }
- /// \brief Get the current error code.
- std::error_code getError() { return LastError; }
+ std::error_code readNextRecord(CoverageMappingRecord &Record) override;
};
} // end namespace coverage
diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h
index 9655d66edc92..63a6ac671f2b 100644
--- a/include/llvm/ProfileData/InstrProfReader.h
+++ b/include/llvm/ProfileData/InstrProfReader.h
@@ -95,6 +95,9 @@ public:
/// Factory method to create an appropriately typed reader for the given
/// instrprof file.
static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path);
+
+ static ErrorOr<std::unique_ptr<InstrProfReader>>
+ create(std::unique_ptr<MemoryBuffer> Buffer);
};
/// Reader for the simple text based instrprof format.
@@ -114,9 +117,8 @@ private:
/// The current set of counter values.
std::vector<uint64_t> Counts;
- TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION;
- TextInstrProfReader &operator=(const TextInstrProfReader &)
- LLVM_DELETED_FUNCTION;
+ TextInstrProfReader(const TextInstrProfReader &) = delete;
+ TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
public:
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
: DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
@@ -167,9 +169,8 @@ private:
const char *NamesStart;
const char *ProfileEnd;
- RawInstrProfReader(const RawInstrProfReader &) LLVM_DELETED_FUNCTION;
- RawInstrProfReader &operator=(const RawInstrProfReader &)
- LLVM_DELETED_FUNCTION;
+ RawInstrProfReader(const RawInstrProfReader &) = delete;
+ RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
public:
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)) { }
@@ -273,9 +274,8 @@ private:
/// The maximal execution count among all functions.
uint64_t MaxFunctionCount;
- IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION;
- IndexedInstrProfReader &operator=(const IndexedInstrProfReader &)
- LLVM_DELETED_FUNCTION;
+ IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
+ IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
public:
IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {}
@@ -295,8 +295,11 @@ public:
uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
/// Factory method to create an indexed reader.
- static std::error_code
- create(std::string Path, std::unique_ptr<IndexedInstrProfReader> &Result);
+ static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
+ create(std::string Path);
+
+ static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
+ create(std::unique_ptr<MemoryBuffer> Buffer);
};
} // end namespace llvm
diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h
index a23c56772a2f..ce0bb5242498 100644
--- a/include/llvm/ProfileData/InstrProfWriter.h
+++ b/include/llvm/ProfileData/InstrProfWriter.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <vector>
@@ -41,8 +42,13 @@ public:
std::error_code addFunctionCounts(StringRef FunctionName,
uint64_t FunctionHash,
ArrayRef<uint64_t> Counters);
- /// Ensure that all data is written to disk.
+ /// Write the profile to \c OS
void write(raw_fd_ostream &OS);
+ /// Write the profile, returning the raw data. For testing.
+ std::unique_ptr<MemoryBuffer> writeBuffer();
+
+private:
+ std::pair<uint64_t, uint64_t> writeImpl(raw_ostream &OS);
};
} // end namespace llvm
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h
index df0a055c2a79..1b82e55aa77a 100644
--- a/include/llvm/ProfileData/SampleProf.h
+++ b/include/llvm/ProfileData/SampleProf.h
@@ -59,7 +59,7 @@ static inline uint64_t SPMagic() {
static inline uint64_t SPVersion() { return 100; }
-/// \brief Represents the relative location of an instruction.
+/// 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
@@ -100,7 +100,7 @@ template <> struct DenseMapInfo<sampleprof::LineLocation> {
namespace sampleprof {
-/// \brief Representation of a single sample record.
+/// 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.
@@ -116,7 +116,7 @@ public:
SampleRecord() : NumSamples(0), CallTargets() {}
- /// \brief Increment the number of samples for this record by \p S.
+ /// Increment the number of samples for this record by \p S.
///
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
/// around unsigned integers.
@@ -127,7 +127,7 @@ public:
NumSamples = std::numeric_limits<unsigned>::max();
}
- /// \brief Add called function \p F with samples \p S.
+ /// Add called function \p F with samples \p S.
///
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
/// around unsigned integers.
@@ -139,13 +139,13 @@ public:
TargetSamples = std::numeric_limits<unsigned>::max();
}
- /// \brief Return true if this sample record contains function calls.
+ /// 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.
+ /// Merge the samples in \p Other into this record.
void merge(const SampleRecord &Other) {
addSamples(Other.getSamples());
for (const auto &I : Other.getCallTargets())
@@ -159,7 +159,7 @@ private:
typedef DenseMap<LineLocation, SampleRecord> BodySampleMap;
-/// \brief Representation of the samples collected for a function.
+/// 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
@@ -187,13 +187,13 @@ public:
Num);
}
- /// \brief Return the sample record at the given location.
+ /// 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.
+ /// 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();
@@ -201,17 +201,17 @@ public:
bool empty() const { return BodySamples.empty(); }
- /// \brief Return the total number of samples collected inside the function.
+ /// 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
+ /// 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.
+ /// 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.
+ /// Merge the samples in \p Other into this one.
void merge(const FunctionSamples &Other) {
addTotalSamples(Other.getTotalSamples());
addHeadSamples(Other.getHeadSamples());
@@ -223,16 +223,18 @@ public:
}
private:
- /// \brief Total number of samples collected inside this function.
+ /// 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.
+ /// Total number of samples collected at the head of the function.
+ /// This is an approximation of the number of calls made to this function
+ /// at runtime.
unsigned TotalHeadSamples;
- /// \brief Map instruction locations to collected samples.
+ /// 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
diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h
index 96a8219bfb85..fc14cb2d0b0c 100644
--- a/include/llvm/Support/ARMBuildAttributes.h
+++ b/include/llvm/Support/ARMBuildAttributes.h
@@ -100,13 +100,13 @@ enum CPUArch {
v5TEJ = 5, // e.g. ARM926EJ_S
v6 = 6, // e.g. ARM1136J_S
v6KZ = 7, // e.g. ARM1176JZ_S
- v6T2 = 8, // e.g. ARM1156T2F_S
- v6K = 9, // e.g. ARM1136J_S
+ v6T2 = 8, // e.g. ARM1156T2_S
+ v6K = 9, // e.g. ARM1176JZ_S
v7 = 10, // e.g. Cortex A8, Cortex M3
v6_M = 11, // e.g. Cortex M1
v6S_M = 12, // v6_M with the System extensions
v7E_M = 13, // v7_M with DSP extensions
- v8 = 14 // v8, AArch32
+ v8 = 14, // v8,v8.1a AArch32
};
enum CPUArchProfile { // (=7), uleb128
@@ -145,6 +145,7 @@ enum {
AllowNeon = 1, // SIMDv1 was permitted
AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations)
AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted
+ AllowNeonARMv8_1a = 4,// ARM v8.1-A SIMD was permitted (RDMA)
// Tag_ABI_PCS_R9_use, (=14), uleb128
R9IsGPR = 0, // R9 used as v6 (just another callee-saved register)
diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h
index 061d5acf2322..574b514aef39 100644
--- a/include/llvm/Support/AlignOf.h
+++ b/include/llvm/Support/AlignOf.h
@@ -22,6 +22,14 @@ namespace llvm {
template <typename T>
struct AlignmentCalcImpl {
char x;
+#if defined(_MSC_VER)
+// Disables "structure was padded due to __declspec(align())" warnings that are
+// generated by any class using AlignOf<T> with a manually specified alignment.
+// Although the warning is disabled in the LLVM project we need this pragma
+// as AlignOf.h is a published support header that's available for use
+// out-of-tree, and we would like that to compile cleanly at /W4.
+#pragma warning(suppress : 4324)
+#endif
T t;
private:
AlignmentCalcImpl() {} // Never instantiate.
@@ -190,12 +198,12 @@ union SizerImpl {
} // end namespace detail
/// \brief This union template exposes a suitably aligned and sized character
-/// array member which can hold elements of any of up to four types.
+/// array member which can hold elements of any of up to ten types.
///
/// These types may be arrays, structs, or any other types. The goal is to
/// expose a char array buffer member which can be used as suitable storage for
-/// a placement new of any of these types. Support for more than seven types can
-/// be added at the cost of more boiler plate.
+/// a placement new of any of these types. Support for more than ten types can
+/// be added at the cost of more boilerplate.
template <typename T1,
typename T2 = char, typename T3 = char, typename T4 = char,
typename T5 = char, typename T6 = char, typename T7 = char,
diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h
index de317719714d..f9b5cf22f97d 100644
--- a/include/llvm/Support/Allocator.h
+++ b/include/llvm/Support/Allocator.h
@@ -148,7 +148,7 @@ public:
: CurPtr(nullptr), End(nullptr), BytesAllocated(0),
Allocator(std::forward<T &&>(Allocator)) {}
- // Manually implement a move constructor as we must clear the old allocators
+ // Manually implement a move constructor as we must clear the old allocator's
// slabs as a matter of correctness.
BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
: CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)),
@@ -187,6 +187,9 @@ public:
/// \brief Deallocate all but the current slab and reset the current pointer
/// to the beginning of it, freeing all memory allocated so far.
void Reset() {
+ DeallocateCustomSizedSlabs();
+ CustomSizedSlabs.clear();
+
if (Slabs.empty())
return;
@@ -195,15 +198,14 @@ public:
CurPtr = (char *)Slabs.front();
End = CurPtr + SlabSize;
- // Deallocate all but the first slab, and all custome sized slabs.
+ // Deallocate all but the first slab, and deallocate all custom-sized slabs.
DeallocateSlabs(std::next(Slabs.begin()), Slabs.end());
Slabs.erase(std::next(Slabs.begin()), Slabs.end());
- DeallocateCustomSizedSlabs();
- CustomSizedSlabs.clear();
}
/// \brief Allocate space at the specified alignment.
- LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) {
+ LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+ Allocate(size_t Size, size_t Alignment) {
assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
// Keep track of how many bytes we've allocated.
@@ -319,14 +321,6 @@ private:
for (; I != E; ++I) {
size_t AllocatedSlabSize =
computeSlabSize(std::distance(Slabs.begin(), I));
-#ifndef NDEBUG
- // Poison the memory so stale pointers crash sooner. Note we must
- // preserve the Size and NextPtr fields at the beginning.
- if (AllocatedSlabSize != 0) {
- sys::Memory::setRangeWritable(*I, AllocatedSlabSize);
- memset(*I, 0xCD, AllocatedSlabSize);
- }
-#endif
Allocator.Deallocate(*I, AllocatedSlabSize);
}
}
@@ -336,12 +330,6 @@ private:
for (auto &PtrAndSize : CustomSizedSlabs) {
void *Ptr = PtrAndSize.first;
size_t Size = PtrAndSize.second;
-#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(Ptr, Size);
- memset(Ptr, 0xCD, Size);
-#endif
Allocator.Deallocate(Ptr, Size);
}
}
diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h
index 9aab6ace6e3f..a6429dd22a3b 100644
--- a/include/llvm/Support/BranchProbability.h
+++ b/include/llvm/Support/BranchProbability.h
@@ -31,7 +31,7 @@ class BranchProbability {
public:
BranchProbability(uint32_t n, uint32_t d) : N(n), D(d) {
- assert(d > 0 && "Denomiator cannot be 0!");
+ assert(d > 0 && "Denominator cannot be 0!");
assert(n <= d && "Probability cannot be bigger than 1!");
}
diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h
index 150bce50d9ae..7f54822d503f 100644
--- a/include/llvm/Support/COFF.h
+++ b/include/llvm/Support/COFF.h
@@ -664,16 +664,16 @@ namespace COFF {
}
};
- enum CodeViewLineTableIdentifiers {
- DEBUG_SECTION_MAGIC = 0x4,
- DEBUG_SYMBOL_SUBSECTION = 0xF1,
- DEBUG_LINE_TABLE_SUBSECTION = 0xF2,
+ enum CodeViewIdentifiers {
+ DEBUG_SECTION_MAGIC = 0x4,
+ DEBUG_SYMBOL_SUBSECTION = 0xF1,
+ DEBUG_LINE_TABLE_SUBSECTION = 0xF2,
DEBUG_STRING_TABLE_SUBSECTION = 0xF3,
- DEBUG_INDEX_SUBSECTION = 0xF4,
+ DEBUG_INDEX_SUBSECTION = 0xF4,
// Symbol subsections are split into records of different types.
DEBUG_SYMBOL_TYPE_PROC_START = 0x1147,
- DEBUG_SYMBOL_TYPE_PROC_END = 0x114F
+ DEBUG_SYMBOL_TYPE_PROC_END = 0x114F
};
inline bool isReservedSectionNumber(int32_t SectionNumber) {
diff --git a/include/llvm/Support/COM.h b/include/llvm/Support/COM.h
new file mode 100644
index 000000000000..a2d5a7a68ba9
--- /dev/null
+++ b/include/llvm/Support/COM.h
@@ -0,0 +1,36 @@
+//===- llvm/Support/COM.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Provides a library for accessing COM functionality of the Host OS.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_COM_H
+#define LLVM_SUPPORT_COM_H
+
+namespace llvm {
+namespace sys {
+
+enum class COMThreadingMode { SingleThreaded, MultiThreaded };
+
+class InitializeCOMRAII {
+public:
+ explicit InitializeCOMRAII(COMThreadingMode Threading,
+ bool SpeedOverMemory = false);
+ ~InitializeCOMRAII();
+
+private:
+ InitializeCOMRAII(const InitializeCOMRAII &) = delete;
+ void operator=(const InitializeCOMRAII &) = delete;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index 1c06bf5f8c07..bd1d1cb6dc97 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/include/llvm/Support/CommandLine.h
@@ -20,6 +20,7 @@
#ifndef LLVM_SUPPORT_COMMANDLINE_H
#define LLVM_SUPPORT_COMMANDLINE_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
@@ -72,8 +73,17 @@ void AddExtraVersionPrinter(void (*func)());
// (Currently not perfect, but best-effort.)
void PrintOptionValues();
-// MarkOptionsChanged - Internal helper function.
-void MarkOptionsChanged();
+// Forward declaration - AddLiteralOption needs to be up here to make gcc happy.
+class Option;
+
+/// \brief Adds a new option for parsing and provides the option it refers to.
+///
+/// \param O pointer to the option
+/// \param Name the string name for the option to handle during parsing
+///
+/// Literal options are used by some parsers to register special option values.
+/// This is how the PassNameParser registers pass names for opt.
+void AddLiteralOption(Option &O, const char *Name);
//===----------------------------------------------------------------------===//
// Flags permitted to be passed to command line arguments
@@ -191,13 +201,13 @@ class Option {
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.
public:
const char *ArgStr; // The argument string itself (ex: "help", "o")
const char *HelpStr; // The descriptive text message for -help
const char *ValueStr; // String describing what the value of this option is
OptionCategory *Category; // The Category this option belongs to
+ bool FullyInitialized; // Has addArguemnt been called?
inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
return (enum NumOccurrencesFlag)Occurrences;
@@ -221,7 +231,7 @@ public:
//-------------------------------------------------------------------------===
// Accessor functions set by OptionModifiers
//
- void setArgStr(const char *S) { ArgStr = S; }
+ void setArgStr(const char *S);
void setDescription(const char *S) { HelpStr = S; }
void setValueStr(const char *S) { ValueStr = S; }
void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; }
@@ -237,8 +247,8 @@ protected:
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) {}
+ AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""),
+ Category(&GeneralCategory), FullyInitialized(false) {}
inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
@@ -253,8 +263,6 @@ public:
/// For testing purposes only.
void removeArgument();
- Option *getNextRegisteredOption() const { return NextRegistered; }
-
// Return the width of the option tag for printing...
virtual size_t getOptionWidth() const = 0;
@@ -344,9 +352,14 @@ struct cat {
// Support value comparison outside the template.
struct GenericOptionValue {
- virtual ~GenericOptionValue() {}
virtual bool compare(const GenericOptionValue &V) const = 0;
+protected:
+ ~GenericOptionValue() = default;
+ GenericOptionValue() = default;
+ GenericOptionValue(const GenericOptionValue&) = default;
+ GenericOptionValue &operator=(const GenericOptionValue &) = default;
+
private:
virtual void anchor();
};
@@ -372,6 +385,9 @@ struct OptionValueBase : public GenericOptionValue {
bool compare(const GenericOptionValue & /*V*/) const override {
return false;
}
+
+protected:
+ ~OptionValueBase() = default;
};
// Simple copy of the option value.
@@ -379,6 +395,11 @@ template <class DataType> class OptionValueCopy : public GenericOptionValue {
DataType Value;
bool Valid;
+protected:
+ ~OptionValueCopy() = default;
+ OptionValueCopy(const OptionValueCopy&) = default;
+ OptionValueCopy &operator=(const OptionValueCopy&) = default;
+
public:
OptionValueCopy() : Valid(false) {}
@@ -409,12 +430,19 @@ public:
template <class DataType>
struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> {
typedef DataType WrapperType;
+
+protected:
+ ~OptionValueBase() = default;
+ OptionValueBase() = default;
+ OptionValueBase(const OptionValueBase&) = default;
+ OptionValueBase &operator=(const OptionValueBase&) = default;
};
// Top-level option class.
template <class DataType>
-struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> {
- OptionValue() {}
+struct OptionValue final
+ : OptionValueBase<DataType, std::is_class<DataType>::value> {
+ OptionValue() = default;
OptionValue(const DataType &V) { this->setValue(V); }
// Some options may take their value from a different data type.
@@ -427,7 +455,8 @@ 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 <>
-struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> {
+struct OptionValue<cl::boolOrDefault> final
+ : OptionValueCopy<cl::boolOrDefault> {
typedef cl::boolOrDefault WrapperType;
OptionValue() {}
@@ -442,7 +471,8 @@ private:
void anchor() override;
};
-template <> struct OptionValue<std::string> : OptionValueCopy<std::string> {
+template <>
+struct OptionValue<std::string> final : OptionValueCopy<std::string> {
typedef StringRef WrapperType;
OptionValue() {}
@@ -531,6 +561,8 @@ protected:
};
public:
+ generic_parser_base(Option &O) : Owner(O) {}
+
virtual ~generic_parser_base() {} // Base class should have virtual-dtor
// getNumOptions - Virtual function implemented by generic subclass to
@@ -569,18 +601,13 @@ public:
printGenericOptionDiff(O, V, Default, GlobalWidth);
}
- void initialize(Option &O) {
- // All of the modifiers for the option have been processed by now, so the
- // argstr field should be stable, copy it down now.
- //
- hasArgStr = O.hasArgStr();
- }
+ void initialize() {}
void getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) {
// If there has been no argstr specified, that means that we need to add an
// argument for every possible option. This ensures that our options are
// vectored to us.
- if (!hasArgStr)
+ if (!Owner.hasArgStr())
for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
OptionNames.push_back(getOption(i));
}
@@ -597,7 +624,7 @@ public:
//
// If this is the case, we cannot allow a value.
//
- if (hasArgStr)
+ if (Owner.hasArgStr())
return ValueRequired;
else
return ValueDisallowed;
@@ -609,7 +636,7 @@ public:
unsigned findOption(const char *Name);
protected:
- bool hasArgStr;
+ Option &Owner;
};
// Default parser implementation - This implementation depends on having a
@@ -629,6 +656,7 @@ protected:
SmallVector<OptionInfo, 8> Values;
public:
+ parser(Option &O) : generic_parser_base(O) {}
typedef DataType parser_data_type;
// Implement virtual functions needed by generic_parser_base
@@ -646,7 +674,7 @@ public:
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) {
StringRef ArgVal;
- if (hasArgStr)
+ if (Owner.hasArgStr())
ArgVal = Arg;
else
ArgVal = ArgName;
@@ -667,7 +695,7 @@ public:
assert(findOption(Name) == Values.size() && "Option already exists!");
OptionInfo X(Name, static_cast<DataType>(V), HelpStr);
Values.push_back(X);
- MarkOptionsChanged();
+ AddLiteralOption(Owner, Name);
}
/// removeLiteralOption - Remove the specified option.
@@ -684,7 +712,8 @@ public:
//
class basic_parser_impl { // non-template implementation of basic_parser<t>
public:
- virtual ~basic_parser_impl() {}
+ basic_parser_impl(Option &O) {}
+
enum ValueExpected getValueExpectedFlagDefault() const {
return ValueRequired;
@@ -692,7 +721,7 @@ public:
void getExtraOptionNames(SmallVectorImpl<const char *> &) {}
- void initialize(Option &) {}
+ void initialize() {}
// Return the width of the option tag for printing...
size_t getOptionWidth(const Option &O) const;
@@ -713,6 +742,7 @@ public:
virtual void anchor();
protected:
+ ~basic_parser_impl() = default;
// A helper for basic_parser::printOptionDiff.
void printOptionName(const Option &O, size_t GlobalWidth) const;
};
@@ -722,21 +752,26 @@ protected:
//
template <class DataType> class basic_parser : public basic_parser_impl {
public:
+ basic_parser(Option &O) : basic_parser_impl(O) {}
typedef DataType parser_data_type;
typedef OptionValue<DataType> OptVal;
+
+protected:
+ // Workaround Clang PR22793
+ ~basic_parser() {}
};
//--------------------------------------------------
// parser<bool>
//
-template <> class parser<bool> : public basic_parser<bool> {
- const char *ArgStr;
-
+template <> class parser<bool> final : public basic_parser<bool> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val);
- template <class Opt> void initialize(Opt &O) { ArgStr = O.ArgStr; }
+ void initialize() {}
enum ValueExpected getValueExpectedFlagDefault() const {
return ValueOptional;
@@ -756,8 +791,11 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>);
//--------------------------------------------------
// parser<boolOrDefault>
-template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
+template <>
+class parser<boolOrDefault> final : public basic_parser<boolOrDefault> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val);
@@ -780,8 +818,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
//--------------------------------------------------
// parser<int>
//
-template <> class parser<int> : public basic_parser<int> {
+template <> class parser<int> final : public basic_parser<int> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val);
@@ -800,8 +840,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>);
//--------------------------------------------------
// parser<unsigned>
//
-template <> class parser<unsigned> : public basic_parser<unsigned> {
+template <> class parser<unsigned> final : public basic_parser<unsigned> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val);
@@ -821,8 +863,11 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
// parser<unsigned long long>
//
template <>
-class parser<unsigned long long> : public basic_parser<unsigned long long> {
+class parser<unsigned long long> final
+ : public basic_parser<unsigned long long> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg,
unsigned long long &Val);
@@ -842,8 +887,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>);
//--------------------------------------------------
// parser<double>
//
-template <> class parser<double> : public basic_parser<double> {
+template <> class parser<double> final : public basic_parser<double> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val);
@@ -862,8 +909,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>);
//--------------------------------------------------
// parser<float>
//
-template <> class parser<float> : public basic_parser<float> {
+template <> class parser<float> final : public basic_parser<float> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val);
@@ -882,8 +931,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>);
//--------------------------------------------------
// parser<std::string>
//
-template <> class parser<std::string> : public basic_parser<std::string> {
+template <> class parser<std::string> final : public basic_parser<std::string> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &, StringRef, StringRef Arg, std::string &Value) {
Value = Arg.str();
@@ -905,8 +956,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>);
//--------------------------------------------------
// parser<char>
//
-template <> class parser<char> : public basic_parser<char> {
+template <> class parser<char> final : public basic_parser<char> {
public:
+ parser(Option &O) : basic_parser(O) {}
+
// parse - Return true on error.
bool parse(Option &, StringRef, StringRef Arg, char &Value) {
Value = Arg[0];
@@ -942,7 +995,7 @@ 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*/,
+ void print(const Option &O, const parser<ParserDT> &P, const ValDT & /*V*/,
const OptionValue<ValDT> & /*Default*/, size_t GlobalWidth) {
P.printOptionNoValue(O, GlobalWidth);
}
@@ -951,7 +1004,7 @@ template <class ParserDT, class ValDT> struct OptionDiffPrinter {
// 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> {
- void print(const Option &O, const parser<DT> P, const DT &V,
+ 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);
}
@@ -1015,8 +1068,14 @@ template <> struct applicator<MiscFlags> {
static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); }
};
-// apply method - Apply a modifier to an option in a type safe way.
-template <class Mod, class Opt> void apply(const Mod &M, Opt *O) {
+// apply method - Apply modifiers to an option in a type safe way.
+template <class Opt, class Mod, class... Mods>
+void apply(Opt *O, const Mod &M, const Mods &... Ms) {
+ applicator<Mod>::opt(M, *O);
+ apply(O, Ms...);
+}
+
+template <class Opt, class Mod> void apply(Opt *O, const Mod &M) {
applicator<Mod>::opt(M, *O);
}
@@ -1166,9 +1225,13 @@ class opt : public Option,
void done() {
addArgument();
- Parser.initialize(*this);
+ Parser.initialize();
}
+ // Command line options should not be copyable
+ opt(const opt &) = delete;
+ opt &operator=(const opt &) = delete;
+
public:
// setInitialValue - Used by the cl::init modifier...
void setInitialValue(const DataType &V) { this->setValue(V, true); }
@@ -1180,95 +1243,10 @@ public:
return this->getValue();
}
- // One option...
- template <class M0t>
- explicit opt(const M0t &M0)
- : Option(Optional, NotHidden) {
- apply(M0, this);
- done();
- }
-
- // Two options...
- template <class M0t, class M1t>
- opt(const M0t &M0, const M1t &M1)
- : Option(Optional, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- done();
- }
-
- // Three options...
- template <class M0t, class M1t, class M2t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(Optional, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- done();
- }
- // Four options...
- template <class M0t, class M1t, class M2t, class M3t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(Optional, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- done();
- }
- // Five options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4)
- : Option(Optional, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- done();
- }
- // Six options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
- const M5t &M5)
- : Option(Optional, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- done();
- }
- // Seven options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
- const M5t &M5, const M6t &M6)
- : Option(Optional, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- done();
- }
- // Eight options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t, class M7t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
- const M5t &M5, const M6t &M6, const M7t &M7)
- : Option(Optional, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- apply(M7, this);
+ template <class... Mods>
+ explicit opt(const Mods &... Ms)
+ : Option(Optional, NotHidden), Parser(*this) {
+ apply(this, Ms...);
done();
}
};
@@ -1361,9 +1339,13 @@ class list : public Option, public list_storage<DataType, Storage> {
void done() {
addArgument();
- Parser.initialize(*this);
+ Parser.initialize();
}
+ // Command line options should not be copyable
+ list(const list &) = delete;
+ list &operator=(const list &) = delete;
+
public:
ParserClass &getParser() { return Parser; }
@@ -1374,94 +1356,10 @@ public:
void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); }
- // One option...
- template <class M0t>
- explicit list(const M0t &M0)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- done();
- }
- // Two options...
- template <class M0t, class M1t>
- list(const M0t &M0, const M1t &M1)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- done();
- }
- // Three options...
- template <class M0t, class M1t, class M2t>
- list(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- done();
- }
- // Four options...
- template <class M0t, class M1t, class M2t, class M3t>
- list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- done();
- }
- // Five options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t>
- list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- done();
- }
- // Six options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
- list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- done();
- }
- // Seven options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t>
- list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5, const M6t &M6)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- done();
- }
- // Eight options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t, class M7t>
- list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- apply(M7, this);
+ template <class... Mods>
+ explicit list(const Mods &... Ms)
+ : Option(ZeroOrMore, NotHidden), Parser(*this) {
+ apply(this, Ms...);
done();
}
};
@@ -1581,9 +1479,13 @@ class bits : public Option, public bits_storage<DataType, Storage> {
void done() {
addArgument();
- Parser.initialize(*this);
+ Parser.initialize();
}
+ // Command line options should not be copyable
+ bits(const bits &) = delete;
+ bits &operator=(const bits &) = delete;
+
public:
ParserClass &getParser() { return Parser; }
@@ -1592,94 +1494,10 @@ public:
return Positions[optnum];
}
- // One option...
- template <class M0t>
- explicit bits(const M0t &M0)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- done();
- }
- // Two options...
- template <class M0t, class M1t>
- bits(const M0t &M0, const M1t &M1)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- done();
- }
- // Three options...
- template <class M0t, class M1t, class M2t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- done();
- }
- // Four options...
- template <class M0t, class M1t, class M2t, class M3t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- done();
- }
- // Five options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- done();
- }
- // Six options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- done();
- }
- // Seven options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5, const M6t &M6)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- done();
- }
- // Eight options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t, class M7t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7)
- : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- apply(M7, this);
+ template <class... Mods>
+ explicit bits(const Mods &... Ms)
+ : Option(ZeroOrMore, NotHidden), Parser(*this) {
+ apply(this, Ms...);
done();
}
};
@@ -1718,6 +1536,10 @@ class alias : public Option {
addArgument();
}
+ // Command line options should not be copyable
+ alias(const alias &) = delete;
+ alias &operator=(const alias &) = delete;
+
public:
void setAliasFor(Option &O) {
if (AliasFor)
@@ -1725,38 +1547,10 @@ public:
AliasFor = &O;
}
- // One option...
- template <class M0t>
- explicit alias(const M0t &M0)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- done();
- }
- // Two options...
- template <class M0t, class M1t>
- alias(const M0t &M0, const M1t &M1)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- apply(M1, this);
- done();
- }
- // Three options...
- template <class M0t, class M1t, class M2t>
- alias(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- done();
- }
- // Four options...
- template <class M0t, class M1t, class M2t, class M3t>
- alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
+ template <class... Mods>
+ explicit alias(const Mods &... Ms)
: Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
+ apply(this, Ms...);
done();
}
};
@@ -1795,9 +1589,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
/// \brief Use this to get a StringMap to all registered named options
/// (e.g. -help). Note \p Map Should be an empty StringMap.
///
-/// \param [out] Map will be filled with mappings where the key is the
-/// Option argument string (e.g. "help") and value is the corresponding
-/// Option*.
+/// \return A reference to the StringMap used by the cl APIs to parse options.
///
/// Access to unnamed arguments (i.e. positional) are not provided because
/// it is expected that the client already has access to these.
@@ -1805,8 +1597,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
/// Typical usage:
/// \code
/// main(int argc,char* argv[]) {
-/// StringMap<llvm::cl::Option*> opts;
-/// llvm::cl::getRegisteredOptions(opts);
+/// StringMap<llvm::cl::Option*> &opts = llvm::cl::getRegisteredOptions();
/// assert(opts.count("help") == 1)
/// opts["help"]->setDescription("Show alphabetical help information")
/// // More code
@@ -1818,7 +1609,11 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
/// This interface is useful for modifying options in libraries that are out of
/// the control of the client. The options should be modified before calling
/// llvm::cl::ParseCommandLineOptions().
-void getRegisteredOptions(StringMap<Option *> &Map);
+///
+/// Hopefully this API can be depricated soon. Any situation where options need
+/// to be modified by tools or libraries should be handled by sane APIs rather
+/// than just handing around a global list.
+StringMap<Option *> &getRegisteredOptions();
//===----------------------------------------------------------------------===//
// Standalone command line processing utilities.
@@ -1889,6 +1684,24 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv,
bool MarkEOLs = false);
+/// \brief Mark all options not part of this category as cl::ReallyHidden.
+///
+/// \param Category the category of options to keep displaying
+///
+/// Some tools (like clang-format) like to be able to hide all options that are
+/// not specific to the tool. This function allows a tool to specify a single
+/// option category to display in the -help output.
+void HideUnrelatedOptions(cl::OptionCategory &Category);
+
+/// \brief Mark all options not part of the categories as cl::ReallyHidden.
+///
+/// \param Categories the categories of options to keep displaying.
+///
+/// Some tools (like clang-format) like to be able to hide all options that are
+/// not specific to the tool. This function allows a tool to specify a single
+/// option category to display in the -help output.
+void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories);
+
} // End namespace cl
} // End namespace llvm
diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h
index d008fec89d64..c81fbaff9dba 100644
--- a/include/llvm/Support/Compiler.h
+++ b/include/llvm/Support/Compiler.h
@@ -52,14 +52,14 @@
/// \macro LLVM_MSC_PREREQ
/// \brief Is the compiler MSVC of at least the specified version?
/// The common \param version values to check for are:
-/// * 1700: Microsoft Visual Studio 2012 / 11.0
/// * 1800: Microsoft Visual Studio 2013 / 12.0
+/// * 1900: Microsoft Visual Studio 2015 / 14.0
#ifdef _MSC_VER
#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
-// We require at least MSVC 2012.
-#if !LLVM_MSC_PREREQ(1700)
-#error LLVM requires at least MSVC 2012.
+// We require at least MSVC 2013.
+#if !LLVM_MSC_PREREQ(1800)
+#error LLVM requires at least MSVC 2013.
#endif
#else
@@ -72,54 +72,26 @@
#define LLVM_NOEXCEPT
#endif
-/// \brief Does the compiler support r-value reference *this?
+/// \brief Does the compiler support ref-qualifiers for *this?
///
-/// Sadly, this is separate from just r-value reference support because GCC
-/// implemented this later than everything else.
+/// Sadly, this is separate from just rvalue reference support because GCC
+/// and MSVC 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
#endif
-/// \macro LLVM_HAS_VARIADIC_TEMPLATES
-/// \brief Does this compiler support variadic templates.
+/// Expands to '&' if ref-qualifiers for *this are supported.
///
-/// Implies LLVM_HAS_RVALUE_REFERENCES and the existence of std::forward.
-#if __has_feature(cxx_variadic_templates) || LLVM_MSC_PREREQ(1800)
-# define LLVM_HAS_VARIADIC_TEMPLATES 1
-#else
-# define LLVM_HAS_VARIADIC_TEMPLATES 0
-#endif
-
-/// Expands to '&' if r-value references are supported.
-///
-/// This can be used to provide l-value/r-value overrides of member functions.
-/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
+/// This can be used to provide lvalue/rvalue overrides of member functions.
+/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
#if LLVM_HAS_RVALUE_REFERENCE_THIS
#define LLVM_LVALUE_FUNCTION &
#else
#define LLVM_LVALUE_FUNCTION
#endif
-/// LLVM_DELETED_FUNCTION - Expands to = delete if the compiler supports it.
-/// Use to mark functions as uncallable. Member functions with this should
-/// be declared private so that some behavior is kept in C++03 mode.
-///
-/// class DontCopy {
-/// private:
-/// DontCopy(const DontCopy&) LLVM_DELETED_FUNCTION;
-/// DontCopy &operator =(const DontCopy&) LLVM_DELETED_FUNCTION;
-/// public:
-/// ...
-/// };
-#if __has_feature(cxx_deleted_functions) || \
- defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800)
-#define LLVM_DELETED_FUNCTION = delete
-#else
-#define LLVM_DELETED_FUNCTION
-#endif
-
#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__)
# define LLVM_CONSTEXPR constexpr
#else
@@ -251,6 +223,16 @@
#define LLVM_ATTRIBUTE_RETURNS_NONNULL
#endif
+/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a
+/// pointer that does not alias any other valid pointer.
+#ifdef __GNUC__
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
+#else
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS
+#endif
+
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
/// pedantic diagnostics.
#ifdef __GNUC__
@@ -287,6 +269,12 @@
/// which causes the program to exit abnormally.
#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0)
# define LLVM_BUILTIN_TRAP __builtin_trap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC, does not require forward
+// declarations involving platform-specific typedefs (unlike RaiseException),
+// results in a call to vectored exception handlers, and encodes to a short
+// instruction that still causes the trapping behavior we want.
+# define LLVM_BUILTIN_TRAP __debugbreak()
#else
# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
#endif
@@ -303,6 +291,37 @@
# define LLVM_ASSUME_ALIGNED(p, a) (p)
#endif
+/// \macro LLVM_ALIGNAS
+/// \brief Used to specify a minimum alignment for a structure or variable. The
+/// alignment must be a constant integer. Use LLVM_PTR_SIZE to compute
+/// alignments in terms of the size of a pointer.
+///
+/// Note that __declspec(align) has special quirks, it's not legal to pass a
+/// structure with __declspec(align) as a formal parameter.
+#ifdef _MSC_VER
+# define LLVM_ALIGNAS(x) __declspec(align(x))
+#elif __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 0)
+# define LLVM_ALIGNAS(x) __attribute__((aligned(x)))
+#else
+# define LLVM_ALIGNAS(x) alignas(x)
+#endif
+
+/// \macro LLVM_PTR_SIZE
+/// \brief A constant integer equivalent to the value of sizeof(void*).
+/// Generally used in combination with LLVM_ALIGNAS or when doing computation in
+/// the preprocessor.
+#ifdef __SIZEOF_POINTER__
+# define LLVM_PTR_SIZE __SIZEOF_POINTER__
+#elif defined(_WIN64)
+# define LLVM_PTR_SIZE 8
+#elif defined(_WIN32)
+# define LLVM_PTR_SIZE 4
+#elif defined(_MSC_VER)
+# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC"
+#else
+# define LLVM_PTR_SIZE sizeof(void *)
+#endif
+
/// \macro LLVM_FUNCTION_NAME
/// \brief Expands to __func__ on compilers which support it. Otherwise,
/// expands to a compiler-dependent replacement.
@@ -344,26 +363,6 @@
# define LLVM_IS_UNALIGNED_ACCESS_FAST 0
#endif
-/// \macro LLVM_EXPLICIT
-/// \brief Expands to explicit on compilers which support explicit conversion
-/// operators. Otherwise expands to nothing.
-#if __has_feature(cxx_explicit_conversions) || \
- defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800)
-#define LLVM_EXPLICIT explicit
-#else
-#define LLVM_EXPLICIT
-#endif
-
-/// \brief Does the compiler support generalized initializers (using braced
-/// lists and std::initializer_list). While clang may claim it supports general
-/// initializers, if we're using MSVC's headers, we might not have a usable
-/// std::initializer list type from the STL. Disable this for now.
-#if __has_feature(cxx_generalized_initializers) && !defined(_MSC_VER)
-#define LLVM_HAS_INITIALIZER_LISTS 1
-#else
-#define LLVM_HAS_INITIALIZER_LISTS 0
-#endif
-
/// \brief Mark debug helper function definitions like dump() that should not be
/// stripped from debug builds.
// FIXME: Move this to a private config.h as it's not usable in public headers.
@@ -373,4 +372,33 @@
#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
#endif
+/// \macro LLVM_THREAD_LOCAL
+/// \brief A thread-local storage specifier which can be used with globals,
+/// extern globals, and static globals.
+///
+/// This is essentially an extremely restricted analog to C++11's thread_local
+/// support, and uses that when available. However, it falls back on
+/// platform-specific or vendor-provided extensions when necessary. These
+/// extensions don't support many of the C++11 thread_local's features. You
+/// should only use this for PODs that you can statically initialize to
+/// some constant value. In almost all circumstances this is most appropriate
+/// for use with a pointer, integer, or small aggregation of pointers and
+/// integers.
+#if LLVM_ENABLE_THREADS
+#if __has_feature(cxx_thread_local)
+#define LLVM_THREAD_LOCAL thread_local
+#elif defined(_MSC_VER)
+// MSVC supports this with a __declspec.
+#define LLVM_THREAD_LOCAL __declspec(thread)
+#else
+// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
+// we only need the restricted functionality that provides.
+#define LLVM_THREAD_LOCAL __thread
+#endif
+#else // !LLVM_ENABLE_THREADS
+// If threading is disabled entirely, this compiles to nothing and you get
+// a normal global variable.
+#define LLVM_THREAD_LOCAL
+#endif
+
#endif
diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h
index 88727fa3fcfc..28274d67aad2 100644
--- a/include/llvm/Support/Compression.h
+++ b/include/llvm/Support/Compression.h
@@ -14,12 +14,10 @@
#ifndef LLVM_SUPPORT_COMPRESSION_H
#define LLVM_SUPPORT_COMPRESSION_H
-#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
-#include <memory>
namespace llvm {
-
+template <typename T> class SmallVectorImpl;
class StringRef;
namespace zlib {
diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h
index a184d0df2132..38952ec99e61 100644
--- a/include/llvm/Support/ConvertUTF.h
+++ b/include/llvm/Support/ConvertUTF.h
@@ -251,6 +251,14 @@ bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes);
*/
bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out);
+/**
+ * Converts a UTF-8 string into a UTF-16 string with native endianness.
+ *
+ * \returns true on success
+ */
+bool convertUTF8ToUTF16String(StringRef SrcUTF8,
+ SmallVectorImpl<UTF16> &DstUTF16);
+
} /* end namespace llvm */
#endif
diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h
index 1f3965c8ade4..c08c3c1f0d21 100644
--- a/include/llvm/Support/CrashRecoveryContext.h
+++ b/include/llvm/Support/CrashRecoveryContext.h
@@ -14,8 +14,6 @@
#include <string>
namespace llvm {
-class StringRef;
-
class CrashRecoveryContextCleanup;
/// \brief Crash recovery helper object.
diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h
index 48235d4145bd..3ffa9bc90dd1 100644
--- a/include/llvm/Support/DataExtractor.h
+++ b/include/llvm/Support/DataExtractor.h
@@ -10,7 +10,6 @@
#ifndef LLVM_SUPPORT_DATAEXTRACTOR_H
#define LLVM_SUPPORT_DATAEXTRACTOR_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h
index e93e6ca34498..fff4f986a6c0 100644
--- a/include/llvm/Support/Debug.h
+++ b/include/llvm/Support/Debug.h
@@ -28,9 +28,8 @@
#ifndef LLVM_SUPPORT_DEBUG_H
#define LLVM_SUPPORT_DEBUG_H
-#include "llvm/Support/raw_ostream.h"
-
namespace llvm {
+class raw_ostream;
#ifndef NDEBUG
/// DebugFlag - This boolean is set to true if the '-debug' command line option
diff --git a/include/llvm/Support/Dwarf.def b/include/llvm/Support/Dwarf.def
new file mode 100644
index 000000000000..4b923b897e6f
--- /dev/null
+++ b/include/llvm/Support/Dwarf.def
@@ -0,0 +1,350 @@
+//===- llvm/Support/Dwarf.def - Dwarf definitions ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Macros for running through Dwarf enumerators.
+//
+//===----------------------------------------------------------------------===//
+
+// TODO: Add other DW-based macros.
+#if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \
+ defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \
+ defined HANDLE_DW_VIRTUALITY)
+#error "Missing macro definition of HANDLE_DW*"
+#endif
+
+#ifndef HANDLE_DW_TAG
+#define HANDLE_DW_TAG(ID, NAME)
+#endif
+
+#ifndef HANDLE_DW_OP
+#define HANDLE_DW_OP(ID, NAME)
+#endif
+
+#ifndef HANDLE_DW_LANG
+#define HANDLE_DW_LANG(ID, NAME)
+#endif
+
+#ifndef HANDLE_DW_ATE
+#define HANDLE_DW_ATE(ID, NAME)
+#endif
+
+#ifndef HANDLE_DW_VIRTUALITY
+#define HANDLE_DW_VIRTUALITY(ID, NAME)
+#endif
+
+HANDLE_DW_TAG(0x0001, array_type)
+HANDLE_DW_TAG(0x0002, class_type)
+HANDLE_DW_TAG(0x0003, entry_point)
+HANDLE_DW_TAG(0x0004, enumeration_type)
+HANDLE_DW_TAG(0x0005, formal_parameter)
+HANDLE_DW_TAG(0x0008, imported_declaration)
+HANDLE_DW_TAG(0x000a, label)
+HANDLE_DW_TAG(0x000b, lexical_block)
+HANDLE_DW_TAG(0x000d, member)
+HANDLE_DW_TAG(0x000f, pointer_type)
+HANDLE_DW_TAG(0x0010, reference_type)
+HANDLE_DW_TAG(0x0011, compile_unit)
+HANDLE_DW_TAG(0x0012, string_type)
+HANDLE_DW_TAG(0x0013, structure_type)
+HANDLE_DW_TAG(0x0015, subroutine_type)
+HANDLE_DW_TAG(0x0016, typedef)
+HANDLE_DW_TAG(0x0017, union_type)
+HANDLE_DW_TAG(0x0018, unspecified_parameters)
+HANDLE_DW_TAG(0x0019, variant)
+HANDLE_DW_TAG(0x001a, common_block)
+HANDLE_DW_TAG(0x001b, common_inclusion)
+HANDLE_DW_TAG(0x001c, inheritance)
+HANDLE_DW_TAG(0x001d, inlined_subroutine)
+HANDLE_DW_TAG(0x001e, module)
+HANDLE_DW_TAG(0x001f, ptr_to_member_type)
+HANDLE_DW_TAG(0x0020, set_type)
+HANDLE_DW_TAG(0x0021, subrange_type)
+HANDLE_DW_TAG(0x0022, with_stmt)
+HANDLE_DW_TAG(0x0023, access_declaration)
+HANDLE_DW_TAG(0x0024, base_type)
+HANDLE_DW_TAG(0x0025, catch_block)
+HANDLE_DW_TAG(0x0026, const_type)
+HANDLE_DW_TAG(0x0027, constant)
+HANDLE_DW_TAG(0x0028, enumerator)
+HANDLE_DW_TAG(0x0029, file_type)
+HANDLE_DW_TAG(0x002a, friend)
+HANDLE_DW_TAG(0x002b, namelist)
+HANDLE_DW_TAG(0x002c, namelist_item)
+HANDLE_DW_TAG(0x002d, packed_type)
+HANDLE_DW_TAG(0x002e, subprogram)
+HANDLE_DW_TAG(0x002f, template_type_parameter)
+HANDLE_DW_TAG(0x0030, template_value_parameter)
+HANDLE_DW_TAG(0x0031, thrown_type)
+HANDLE_DW_TAG(0x0032, try_block)
+HANDLE_DW_TAG(0x0033, variant_part)
+HANDLE_DW_TAG(0x0034, variable)
+HANDLE_DW_TAG(0x0035, volatile_type)
+HANDLE_DW_TAG(0x0036, dwarf_procedure)
+HANDLE_DW_TAG(0x0037, restrict_type)
+HANDLE_DW_TAG(0x0038, interface_type)
+HANDLE_DW_TAG(0x0039, namespace)
+HANDLE_DW_TAG(0x003a, imported_module)
+HANDLE_DW_TAG(0x003b, unspecified_type)
+HANDLE_DW_TAG(0x003c, partial_unit)
+HANDLE_DW_TAG(0x003d, imported_unit)
+HANDLE_DW_TAG(0x003f, condition)
+HANDLE_DW_TAG(0x0040, shared_type)
+HANDLE_DW_TAG(0x0041, type_unit)
+HANDLE_DW_TAG(0x0042, rvalue_reference_type)
+HANDLE_DW_TAG(0x0043, template_alias)
+
+// Mock tags we use as discriminators.
+HANDLE_DW_TAG(0x0100, auto_variable) // Tag for local (auto) variables.
+HANDLE_DW_TAG(0x0101, arg_variable) // Tag for argument variables.
+
+// New in DWARF v5.
+HANDLE_DW_TAG(0x0044, coarray_type)
+HANDLE_DW_TAG(0x0045, generic_subrange)
+HANDLE_DW_TAG(0x0046, dynamic_type)
+
+// User-defined tags.
+HANDLE_DW_TAG(0x4081, MIPS_loop)
+HANDLE_DW_TAG(0x4101, format_label)
+HANDLE_DW_TAG(0x4102, function_template)
+HANDLE_DW_TAG(0x4103, class_template)
+HANDLE_DW_TAG(0x4106, GNU_template_template_param)
+HANDLE_DW_TAG(0x4107, GNU_template_parameter_pack)
+HANDLE_DW_TAG(0x4108, GNU_formal_parameter_pack)
+HANDLE_DW_TAG(0x4200, APPLE_property)
+
+HANDLE_DW_OP(0x03, addr)
+HANDLE_DW_OP(0x06, deref)
+HANDLE_DW_OP(0x08, const1u)
+HANDLE_DW_OP(0x09, const1s)
+HANDLE_DW_OP(0x0a, const2u)
+HANDLE_DW_OP(0x0b, const2s)
+HANDLE_DW_OP(0x0c, const4u)
+HANDLE_DW_OP(0x0d, const4s)
+HANDLE_DW_OP(0x0e, const8u)
+HANDLE_DW_OP(0x0f, const8s)
+HANDLE_DW_OP(0x10, constu)
+HANDLE_DW_OP(0x11, consts)
+HANDLE_DW_OP(0x12, dup)
+HANDLE_DW_OP(0x13, drop)
+HANDLE_DW_OP(0x14, over)
+HANDLE_DW_OP(0x15, pick)
+HANDLE_DW_OP(0x16, swap)
+HANDLE_DW_OP(0x17, rot)
+HANDLE_DW_OP(0x18, xderef)
+HANDLE_DW_OP(0x19, abs)
+HANDLE_DW_OP(0x1a, and)
+HANDLE_DW_OP(0x1b, div)
+HANDLE_DW_OP(0x1c, minus)
+HANDLE_DW_OP(0x1d, mod)
+HANDLE_DW_OP(0x1e, mul)
+HANDLE_DW_OP(0x1f, neg)
+HANDLE_DW_OP(0x20, not)
+HANDLE_DW_OP(0x21, or )
+HANDLE_DW_OP(0x22, plus)
+HANDLE_DW_OP(0x23, plus_uconst)
+HANDLE_DW_OP(0x24, shl)
+HANDLE_DW_OP(0x25, shr)
+HANDLE_DW_OP(0x26, shra)
+HANDLE_DW_OP(0x27, xor)
+HANDLE_DW_OP(0x2f, skip)
+HANDLE_DW_OP(0x28, bra)
+HANDLE_DW_OP(0x29, eq)
+HANDLE_DW_OP(0x2a, ge)
+HANDLE_DW_OP(0x2b, gt)
+HANDLE_DW_OP(0x2c, le)
+HANDLE_DW_OP(0x2d, lt)
+HANDLE_DW_OP(0x2e, ne)
+HANDLE_DW_OP(0x30, lit0)
+HANDLE_DW_OP(0x31, lit1)
+HANDLE_DW_OP(0x32, lit2)
+HANDLE_DW_OP(0x33, lit3)
+HANDLE_DW_OP(0x34, lit4)
+HANDLE_DW_OP(0x35, lit5)
+HANDLE_DW_OP(0x36, lit6)
+HANDLE_DW_OP(0x37, lit7)
+HANDLE_DW_OP(0x38, lit8)
+HANDLE_DW_OP(0x39, lit9)
+HANDLE_DW_OP(0x3a, lit10)
+HANDLE_DW_OP(0x3b, lit11)
+HANDLE_DW_OP(0x3c, lit12)
+HANDLE_DW_OP(0x3d, lit13)
+HANDLE_DW_OP(0x3e, lit14)
+HANDLE_DW_OP(0x3f, lit15)
+HANDLE_DW_OP(0x40, lit16)
+HANDLE_DW_OP(0x41, lit17)
+HANDLE_DW_OP(0x42, lit18)
+HANDLE_DW_OP(0x43, lit19)
+HANDLE_DW_OP(0x44, lit20)
+HANDLE_DW_OP(0x45, lit21)
+HANDLE_DW_OP(0x46, lit22)
+HANDLE_DW_OP(0x47, lit23)
+HANDLE_DW_OP(0x48, lit24)
+HANDLE_DW_OP(0x49, lit25)
+HANDLE_DW_OP(0x4a, lit26)
+HANDLE_DW_OP(0x4b, lit27)
+HANDLE_DW_OP(0x4c, lit28)
+HANDLE_DW_OP(0x4d, lit29)
+HANDLE_DW_OP(0x4e, lit30)
+HANDLE_DW_OP(0x4f, lit31)
+HANDLE_DW_OP(0x50, reg0)
+HANDLE_DW_OP(0x51, reg1)
+HANDLE_DW_OP(0x52, reg2)
+HANDLE_DW_OP(0x53, reg3)
+HANDLE_DW_OP(0x54, reg4)
+HANDLE_DW_OP(0x55, reg5)
+HANDLE_DW_OP(0x56, reg6)
+HANDLE_DW_OP(0x57, reg7)
+HANDLE_DW_OP(0x58, reg8)
+HANDLE_DW_OP(0x59, reg9)
+HANDLE_DW_OP(0x5a, reg10)
+HANDLE_DW_OP(0x5b, reg11)
+HANDLE_DW_OP(0x5c, reg12)
+HANDLE_DW_OP(0x5d, reg13)
+HANDLE_DW_OP(0x5e, reg14)
+HANDLE_DW_OP(0x5f, reg15)
+HANDLE_DW_OP(0x60, reg16)
+HANDLE_DW_OP(0x61, reg17)
+HANDLE_DW_OP(0x62, reg18)
+HANDLE_DW_OP(0x63, reg19)
+HANDLE_DW_OP(0x64, reg20)
+HANDLE_DW_OP(0x65, reg21)
+HANDLE_DW_OP(0x66, reg22)
+HANDLE_DW_OP(0x67, reg23)
+HANDLE_DW_OP(0x68, reg24)
+HANDLE_DW_OP(0x69, reg25)
+HANDLE_DW_OP(0x6a, reg26)
+HANDLE_DW_OP(0x6b, reg27)
+HANDLE_DW_OP(0x6c, reg28)
+HANDLE_DW_OP(0x6d, reg29)
+HANDLE_DW_OP(0x6e, reg30)
+HANDLE_DW_OP(0x6f, reg31)
+HANDLE_DW_OP(0x70, breg0)
+HANDLE_DW_OP(0x71, breg1)
+HANDLE_DW_OP(0x72, breg2)
+HANDLE_DW_OP(0x73, breg3)
+HANDLE_DW_OP(0x74, breg4)
+HANDLE_DW_OP(0x75, breg5)
+HANDLE_DW_OP(0x76, breg6)
+HANDLE_DW_OP(0x77, breg7)
+HANDLE_DW_OP(0x78, breg8)
+HANDLE_DW_OP(0x79, breg9)
+HANDLE_DW_OP(0x7a, breg10)
+HANDLE_DW_OP(0x7b, breg11)
+HANDLE_DW_OP(0x7c, breg12)
+HANDLE_DW_OP(0x7d, breg13)
+HANDLE_DW_OP(0x7e, breg14)
+HANDLE_DW_OP(0x7f, breg15)
+HANDLE_DW_OP(0x80, breg16)
+HANDLE_DW_OP(0x81, breg17)
+HANDLE_DW_OP(0x82, breg18)
+HANDLE_DW_OP(0x83, breg19)
+HANDLE_DW_OP(0x84, breg20)
+HANDLE_DW_OP(0x85, breg21)
+HANDLE_DW_OP(0x86, breg22)
+HANDLE_DW_OP(0x87, breg23)
+HANDLE_DW_OP(0x88, breg24)
+HANDLE_DW_OP(0x89, breg25)
+HANDLE_DW_OP(0x8a, breg26)
+HANDLE_DW_OP(0x8b, breg27)
+HANDLE_DW_OP(0x8c, breg28)
+HANDLE_DW_OP(0x8d, breg29)
+HANDLE_DW_OP(0x8e, breg30)
+HANDLE_DW_OP(0x8f, breg31)
+HANDLE_DW_OP(0x90, regx)
+HANDLE_DW_OP(0x91, fbreg)
+HANDLE_DW_OP(0x92, bregx)
+HANDLE_DW_OP(0x93, piece)
+HANDLE_DW_OP(0x94, deref_size)
+HANDLE_DW_OP(0x95, xderef_size)
+HANDLE_DW_OP(0x96, nop)
+HANDLE_DW_OP(0x97, push_object_address)
+HANDLE_DW_OP(0x98, call2)
+HANDLE_DW_OP(0x99, call4)
+HANDLE_DW_OP(0x9a, call_ref)
+HANDLE_DW_OP(0x9b, form_tls_address)
+HANDLE_DW_OP(0x9c, call_frame_cfa)
+HANDLE_DW_OP(0x9d, bit_piece)
+HANDLE_DW_OP(0x9e, implicit_value)
+HANDLE_DW_OP(0x9f, stack_value)
+
+// Extensions for GNU-style thread-local storage.
+HANDLE_DW_OP(0xe0, GNU_push_tls_address)
+
+// Extensions for Fission proposal.
+HANDLE_DW_OP(0xfb, GNU_addr_index)
+HANDLE_DW_OP(0xfc, GNU_const_index)
+
+// DWARF languages.
+HANDLE_DW_LANG(0x0001, C89)
+HANDLE_DW_LANG(0x0002, C)
+HANDLE_DW_LANG(0x0003, Ada83)
+HANDLE_DW_LANG(0x0004, C_plus_plus)
+HANDLE_DW_LANG(0x0005, Cobol74)
+HANDLE_DW_LANG(0x0006, Cobol85)
+HANDLE_DW_LANG(0x0007, Fortran77)
+HANDLE_DW_LANG(0x0008, Fortran90)
+HANDLE_DW_LANG(0x0009, Pascal83)
+HANDLE_DW_LANG(0x000a, Modula2)
+HANDLE_DW_LANG(0x000b, Java)
+HANDLE_DW_LANG(0x000c, C99)
+HANDLE_DW_LANG(0x000d, Ada95)
+HANDLE_DW_LANG(0x000e, Fortran95)
+HANDLE_DW_LANG(0x000f, PLI)
+HANDLE_DW_LANG(0x0010, ObjC)
+HANDLE_DW_LANG(0x0011, ObjC_plus_plus)
+HANDLE_DW_LANG(0x0012, UPC)
+HANDLE_DW_LANG(0x0013, D)
+
+// New in DWARF 5:
+HANDLE_DW_LANG(0x0014, Python)
+HANDLE_DW_LANG(0x0015, OpenCL)
+HANDLE_DW_LANG(0x0016, Go)
+HANDLE_DW_LANG(0x0017, Modula3)
+HANDLE_DW_LANG(0x0018, Haskell)
+HANDLE_DW_LANG(0x0019, C_plus_plus_03)
+HANDLE_DW_LANG(0x001a, C_plus_plus_11)
+HANDLE_DW_LANG(0x001b, OCaml)
+HANDLE_DW_LANG(0x001c, Rust)
+HANDLE_DW_LANG(0x001d, C11)
+HANDLE_DW_LANG(0x001e, Swift)
+HANDLE_DW_LANG(0x001f, Julia)
+HANDLE_DW_LANG(0x0020, Dylan)
+HANDLE_DW_LANG(0x0021, C_plus_plus_14)
+HANDLE_DW_LANG(0x0022, Fortran03)
+HANDLE_DW_LANG(0x0023, Fortran08)
+HANDLE_DW_LANG(0x8001, Mips_Assembler)
+
+// DWARF attribute type encodings.
+HANDLE_DW_ATE(0x01, address)
+HANDLE_DW_ATE(0x02, boolean)
+HANDLE_DW_ATE(0x03, complex_float)
+HANDLE_DW_ATE(0x04, float)
+HANDLE_DW_ATE(0x05, signed)
+HANDLE_DW_ATE(0x06, signed_char)
+HANDLE_DW_ATE(0x07, unsigned)
+HANDLE_DW_ATE(0x08, unsigned_char)
+HANDLE_DW_ATE(0x09, imaginary_float)
+HANDLE_DW_ATE(0x0a, packed_decimal)
+HANDLE_DW_ATE(0x0b, numeric_string)
+HANDLE_DW_ATE(0x0c, edited)
+HANDLE_DW_ATE(0x0d, signed_fixed)
+HANDLE_DW_ATE(0x0e, unsigned_fixed)
+HANDLE_DW_ATE(0x0f, decimal_float)
+HANDLE_DW_ATE(0x10, UTF)
+
+// DWARF virtuality codes.
+HANDLE_DW_VIRTUALITY(0x00, none)
+HANDLE_DW_VIRTUALITY(0x01, virtual)
+HANDLE_DW_VIRTUALITY(0x02, pure_virtual)
+
+#undef HANDLE_DW_TAG
+#undef HANDLE_DW_OP
+#undef HANDLE_DW_LANG
+#undef HANDLE_DW_ATE
+#undef HANDLE_DW_VIRTUALITY
diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h
index 47b00b1f09d8..c3d94d19f919 100644
--- a/include/llvm/Support/Dwarf.h
+++ b/include/llvm/Support/Dwarf.h
@@ -20,6 +20,7 @@
#ifndef LLVM_SUPPORT_DWARF_H
#define LLVM_SUPPORT_DWARF_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
@@ -36,15 +37,11 @@ namespace dwarf {
// enumeration base type.
enum LLVMConstants : uint32_t {
- // llvm mock tags
- DW_TAG_invalid = ~0U, // Tag for invalid results.
-
- DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables.
- DW_TAG_arg_variable = 0x101, // Tag for argument variables.
- DW_TAG_expression = 0x102, // Tag for complex address expressions.
-
- DW_TAG_user_base = 0x1000, // Recommended base for user tags.
+ // LLVM mock tags (see also llvm/Support/Dwarf.def).
+ DW_TAG_invalid = ~0U, // Tag for invalid results.
+ DW_VIRTUALITY_invalid = ~0U, // Virtuality for invalid results.
+ // Other constants.
DWARF_VERSION = 4, // Default dwarf version we output.
DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes.
DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames.
@@ -57,82 +54,11 @@ const uint32_t DW_CIE_ID = UINT32_MAX;
const uint64_t DW64_CIE_ID = UINT64_MAX;
enum Tag : uint16_t {
- DW_TAG_array_type = 0x01,
- DW_TAG_class_type = 0x02,
- DW_TAG_entry_point = 0x03,
- DW_TAG_enumeration_type = 0x04,
- DW_TAG_formal_parameter = 0x05,
- DW_TAG_imported_declaration = 0x08,
- DW_TAG_label = 0x0a,
- DW_TAG_lexical_block = 0x0b,
- DW_TAG_member = 0x0d,
- DW_TAG_pointer_type = 0x0f,
- DW_TAG_reference_type = 0x10,
- DW_TAG_compile_unit = 0x11,
- DW_TAG_string_type = 0x12,
- DW_TAG_structure_type = 0x13,
- DW_TAG_subroutine_type = 0x15,
- DW_TAG_typedef = 0x16,
- DW_TAG_union_type = 0x17,
- DW_TAG_unspecified_parameters = 0x18,
- DW_TAG_variant = 0x19,
- DW_TAG_common_block = 0x1a,
- DW_TAG_common_inclusion = 0x1b,
- DW_TAG_inheritance = 0x1c,
- DW_TAG_inlined_subroutine = 0x1d,
- DW_TAG_module = 0x1e,
- DW_TAG_ptr_to_member_type = 0x1f,
- DW_TAG_set_type = 0x20,
- DW_TAG_subrange_type = 0x21,
- DW_TAG_with_stmt = 0x22,
- DW_TAG_access_declaration = 0x23,
- DW_TAG_base_type = 0x24,
- DW_TAG_catch_block = 0x25,
- DW_TAG_const_type = 0x26,
- DW_TAG_constant = 0x27,
- DW_TAG_enumerator = 0x28,
- DW_TAG_file_type = 0x29,
- DW_TAG_friend = 0x2a,
- DW_TAG_namelist = 0x2b,
- DW_TAG_namelist_item = 0x2c,
- DW_TAG_packed_type = 0x2d,
- DW_TAG_subprogram = 0x2e,
- DW_TAG_template_type_parameter = 0x2f,
- DW_TAG_template_value_parameter = 0x30,
- DW_TAG_thrown_type = 0x31,
- DW_TAG_try_block = 0x32,
- DW_TAG_variant_part = 0x33,
- DW_TAG_variable = 0x34,
- DW_TAG_volatile_type = 0x35,
- DW_TAG_dwarf_procedure = 0x36,
- DW_TAG_restrict_type = 0x37,
- DW_TAG_interface_type = 0x38,
- DW_TAG_namespace = 0x39,
- DW_TAG_imported_module = 0x3a,
- DW_TAG_unspecified_type = 0x3b,
- DW_TAG_partial_unit = 0x3c,
- DW_TAG_imported_unit = 0x3d,
- DW_TAG_condition = 0x3f,
- DW_TAG_shared_type = 0x40,
- DW_TAG_type_unit = 0x41,
- DW_TAG_rvalue_reference_type = 0x42,
- DW_TAG_template_alias = 0x43,
-
- // New in DWARF 5:
- DW_TAG_coarray_type = 0x44,
- DW_TAG_generic_subrange = 0x45,
- DW_TAG_dynamic_type = 0x46,
-
- DW_TAG_MIPS_loop = 0x4081,
- DW_TAG_format_label = 0x4101,
- DW_TAG_function_template = 0x4102,
- DW_TAG_class_template = 0x4103,
- DW_TAG_GNU_template_template_param = 0x4106,
- DW_TAG_GNU_template_parameter_pack = 0x4107,
- DW_TAG_GNU_formal_parameter_pack = 0x4108,
+#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_TAG_lo_user = 0x4080,
- DW_TAG_APPLE_property = 0x4200,
- DW_TAG_hi_user = 0xffff
+ DW_TAG_hi_user = 0xffff,
+ DW_TAG_user_base = 0x1000 // Recommended base for user tags.
};
inline bool isType(Tag T) {
@@ -359,194 +285,23 @@ enum Form : uint16_t {
// Extensions for Fission proposal
DW_FORM_GNU_addr_index = 0x1f01,
- DW_FORM_GNU_str_index = 0x1f02
+ DW_FORM_GNU_str_index = 0x1f02,
+
+ // Alternate debug sections proposal (output of "dwz" tool).
+ DW_FORM_GNU_ref_alt = 0x1f20,
+ DW_FORM_GNU_strp_alt = 0x1f21
};
enum LocationAtom {
- // Operation encodings
- DW_OP_addr = 0x03,
- DW_OP_deref = 0x06,
- DW_OP_const1u = 0x08,
- DW_OP_const1s = 0x09,
- DW_OP_const2u = 0x0a,
- DW_OP_const2s = 0x0b,
- DW_OP_const4u = 0x0c,
- DW_OP_const4s = 0x0d,
- DW_OP_const8u = 0x0e,
- DW_OP_const8s = 0x0f,
- DW_OP_constu = 0x10,
- DW_OP_consts = 0x11,
- DW_OP_dup = 0x12,
- DW_OP_drop = 0x13,
- DW_OP_over = 0x14,
- DW_OP_pick = 0x15,
- DW_OP_swap = 0x16,
- DW_OP_rot = 0x17,
- DW_OP_xderef = 0x18,
- DW_OP_abs = 0x19,
- DW_OP_and = 0x1a,
- DW_OP_div = 0x1b,
- DW_OP_minus = 0x1c,
- DW_OP_mod = 0x1d,
- DW_OP_mul = 0x1e,
- DW_OP_neg = 0x1f,
- DW_OP_not = 0x20,
- DW_OP_or = 0x21,
- DW_OP_plus = 0x22,
- DW_OP_plus_uconst = 0x23,
- DW_OP_shl = 0x24,
- DW_OP_shr = 0x25,
- DW_OP_shra = 0x26,
- DW_OP_xor = 0x27,
- DW_OP_skip = 0x2f,
- DW_OP_bra = 0x28,
- DW_OP_eq = 0x29,
- DW_OP_ge = 0x2a,
- DW_OP_gt = 0x2b,
- DW_OP_le = 0x2c,
- DW_OP_lt = 0x2d,
- DW_OP_ne = 0x2e,
- DW_OP_lit0 = 0x30,
- DW_OP_lit1 = 0x31,
- DW_OP_lit2 = 0x32,
- DW_OP_lit3 = 0x33,
- DW_OP_lit4 = 0x34,
- DW_OP_lit5 = 0x35,
- DW_OP_lit6 = 0x36,
- DW_OP_lit7 = 0x37,
- DW_OP_lit8 = 0x38,
- DW_OP_lit9 = 0x39,
- DW_OP_lit10 = 0x3a,
- DW_OP_lit11 = 0x3b,
- DW_OP_lit12 = 0x3c,
- DW_OP_lit13 = 0x3d,
- DW_OP_lit14 = 0x3e,
- DW_OP_lit15 = 0x3f,
- DW_OP_lit16 = 0x40,
- DW_OP_lit17 = 0x41,
- DW_OP_lit18 = 0x42,
- DW_OP_lit19 = 0x43,
- DW_OP_lit20 = 0x44,
- DW_OP_lit21 = 0x45,
- DW_OP_lit22 = 0x46,
- DW_OP_lit23 = 0x47,
- DW_OP_lit24 = 0x48,
- DW_OP_lit25 = 0x49,
- DW_OP_lit26 = 0x4a,
- DW_OP_lit27 = 0x4b,
- DW_OP_lit28 = 0x4c,
- DW_OP_lit29 = 0x4d,
- DW_OP_lit30 = 0x4e,
- DW_OP_lit31 = 0x4f,
- DW_OP_reg0 = 0x50,
- DW_OP_reg1 = 0x51,
- DW_OP_reg2 = 0x52,
- DW_OP_reg3 = 0x53,
- DW_OP_reg4 = 0x54,
- DW_OP_reg5 = 0x55,
- DW_OP_reg6 = 0x56,
- DW_OP_reg7 = 0x57,
- DW_OP_reg8 = 0x58,
- DW_OP_reg9 = 0x59,
- DW_OP_reg10 = 0x5a,
- DW_OP_reg11 = 0x5b,
- DW_OP_reg12 = 0x5c,
- DW_OP_reg13 = 0x5d,
- DW_OP_reg14 = 0x5e,
- DW_OP_reg15 = 0x5f,
- DW_OP_reg16 = 0x60,
- DW_OP_reg17 = 0x61,
- DW_OP_reg18 = 0x62,
- DW_OP_reg19 = 0x63,
- DW_OP_reg20 = 0x64,
- DW_OP_reg21 = 0x65,
- DW_OP_reg22 = 0x66,
- DW_OP_reg23 = 0x67,
- DW_OP_reg24 = 0x68,
- DW_OP_reg25 = 0x69,
- DW_OP_reg26 = 0x6a,
- DW_OP_reg27 = 0x6b,
- DW_OP_reg28 = 0x6c,
- DW_OP_reg29 = 0x6d,
- DW_OP_reg30 = 0x6e,
- DW_OP_reg31 = 0x6f,
- DW_OP_breg0 = 0x70,
- DW_OP_breg1 = 0x71,
- DW_OP_breg2 = 0x72,
- DW_OP_breg3 = 0x73,
- DW_OP_breg4 = 0x74,
- DW_OP_breg5 = 0x75,
- DW_OP_breg6 = 0x76,
- DW_OP_breg7 = 0x77,
- DW_OP_breg8 = 0x78,
- DW_OP_breg9 = 0x79,
- DW_OP_breg10 = 0x7a,
- DW_OP_breg11 = 0x7b,
- DW_OP_breg12 = 0x7c,
- DW_OP_breg13 = 0x7d,
- DW_OP_breg14 = 0x7e,
- DW_OP_breg15 = 0x7f,
- DW_OP_breg16 = 0x80,
- DW_OP_breg17 = 0x81,
- DW_OP_breg18 = 0x82,
- DW_OP_breg19 = 0x83,
- DW_OP_breg20 = 0x84,
- DW_OP_breg21 = 0x85,
- DW_OP_breg22 = 0x86,
- DW_OP_breg23 = 0x87,
- DW_OP_breg24 = 0x88,
- DW_OP_breg25 = 0x89,
- DW_OP_breg26 = 0x8a,
- DW_OP_breg27 = 0x8b,
- DW_OP_breg28 = 0x8c,
- DW_OP_breg29 = 0x8d,
- DW_OP_breg30 = 0x8e,
- DW_OP_breg31 = 0x8f,
- DW_OP_regx = 0x90,
- DW_OP_fbreg = 0x91,
- DW_OP_bregx = 0x92,
- DW_OP_piece = 0x93,
- DW_OP_deref_size = 0x94,
- DW_OP_xderef_size = 0x95,
- DW_OP_nop = 0x96,
- DW_OP_push_object_address = 0x97,
- DW_OP_call2 = 0x98,
- DW_OP_call4 = 0x99,
- DW_OP_call_ref = 0x9a,
- DW_OP_form_tls_address = 0x9b,
- DW_OP_call_frame_cfa = 0x9c,
- DW_OP_bit_piece = 0x9d,
- DW_OP_implicit_value = 0x9e,
- DW_OP_stack_value = 0x9f,
+#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_OP_lo_user = 0xe0,
- DW_OP_hi_user = 0xff,
-
- // Extensions for GNU-style thread-local storage.
- DW_OP_GNU_push_tls_address = 0xe0,
-
- // Extensions for Fission proposal.
- DW_OP_GNU_addr_index = 0xfb,
- DW_OP_GNU_const_index = 0xfc
+ DW_OP_hi_user = 0xff
};
enum TypeKind {
- // Encoding attribute values
- DW_ATE_address = 0x01,
- DW_ATE_boolean = 0x02,
- DW_ATE_complex_float = 0x03,
- DW_ATE_float = 0x04,
- DW_ATE_signed = 0x05,
- DW_ATE_signed_char = 0x06,
- DW_ATE_unsigned = 0x07,
- DW_ATE_unsigned_char = 0x08,
- DW_ATE_imaginary_float = 0x09,
- DW_ATE_packed_decimal = 0x0a,
- DW_ATE_numeric_string = 0x0b,
- DW_ATE_edited = 0x0c,
- DW_ATE_signed_fixed = 0x0d,
- DW_ATE_unsigned_fixed = 0x0e,
- DW_ATE_decimal_float = 0x0f,
- DW_ATE_UTF = 0x10,
+#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_ATE_lo_user = 0x80,
DW_ATE_hi_user = 0xff
};
@@ -584,45 +339,15 @@ enum VisibilityAttribute {
};
enum VirtualityAttribute {
- // Virtuality codes
- DW_VIRTUALITY_none = 0x00,
- DW_VIRTUALITY_virtual = 0x01,
- DW_VIRTUALITY_pure_virtual = 0x02
+#define HANDLE_DW_VIRTUALITY(ID, NAME) DW_VIRTUALITY_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
+ DW_VIRTUALITY_max = 0x02
};
enum SourceLanguage {
- // Language names
- DW_LANG_C89 = 0x0001,
- DW_LANG_C = 0x0002,
- DW_LANG_Ada83 = 0x0003,
- DW_LANG_C_plus_plus = 0x0004,
- DW_LANG_Cobol74 = 0x0005,
- DW_LANG_Cobol85 = 0x0006,
- DW_LANG_Fortran77 = 0x0007,
- DW_LANG_Fortran90 = 0x0008,
- DW_LANG_Pascal83 = 0x0009,
- DW_LANG_Modula2 = 0x000a,
- DW_LANG_Java = 0x000b,
- DW_LANG_C99 = 0x000c,
- DW_LANG_Ada95 = 0x000d,
- DW_LANG_Fortran95 = 0x000e,
- DW_LANG_PLI = 0x000f,
- DW_LANG_ObjC = 0x0010,
- DW_LANG_ObjC_plus_plus = 0x0011,
- DW_LANG_UPC = 0x0012,
- DW_LANG_D = 0x0013,
- // New in DWARF 5:
- DW_LANG_Python = 0x0014,
- DW_LANG_OpenCL = 0x0015,
- DW_LANG_Go = 0x0016,
- DW_LANG_Modula3 = 0x0017,
- DW_LANG_Haskell = 0x0018,
- DW_LANG_C_plus_plus_03 = 0x0019,
- DW_LANG_C_plus_plus_11 = 0x001a,
- DW_LANG_OCaml = 0x001b,
-
+#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_LANG_lo_user = 0x8000,
- DW_LANG_Mips_Assembler = 0x8001,
DW_LANG_hi_user = 0xffff
};
@@ -859,6 +584,22 @@ const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind);
const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage);
/// @}
+/// \defgroup DwarfConstantsParsing Dwarf constants parsing functions
+///
+/// These functions map their strings back to the corresponding enumeration
+/// value or return 0 if there is none, except for these exceptions:
+///
+/// \li \a getTag() returns \a DW_TAG_invalid on invalid input.
+/// \li \a getVirtuality() returns \a DW_VIRTUALITY_invalid on invalid input.
+///
+/// @{
+unsigned getTag(StringRef TagString);
+unsigned getOperationEncoding(StringRef OperationEncodingString);
+unsigned getVirtuality(StringRef VirtualityString);
+unsigned getLanguage(StringRef LanguageString);
+unsigned getAttributeEncoding(StringRef EncodingString);
+/// @}
+
/// \brief Returns the symbolic string representing Val when used as a value
/// for attribute Attr.
const char *AttributeValueString(uint16_t Attr, unsigned Val);
diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h
index 3d49205fa168..8b915ff0581d 100644
--- a/include/llvm/Support/ELF.h
+++ b/include/llvm/Support/ELF.h
@@ -344,6 +344,7 @@ enum {
ELFOSABI_NSK = 14, // Hewlett-Packard Non-Stop Kernel
ELFOSABI_AROS = 15, // AROS
ELFOSABI_FENIXOS = 16, // FenixOS
+ ELFOSABI_CLOUDABI = 17, // Nuxi CloudABI
ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000
ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000
ELFOSABI_ARM = 97, // ARM
@@ -431,22 +432,50 @@ enum : unsigned {
EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions
EF_MIPS_PIC = 0x00000002, // Position independent code
EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code
- EF_MIPS_ABI2 = 0x00000020,
- EF_MIPS_32BITMODE = 0x00000100,
+ EF_MIPS_ABI2 = 0x00000020, // File uses N32 ABI
+ EF_MIPS_32BITMODE = 0x00000100, // Code compiled for a 64-bit machine
+ // in 32-bit mode
+ EF_MIPS_FP64 = 0x00000200, // Code compiled for a 32-bit machine
+ // but uses 64-bit FP registers
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_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
+ // MIPS machine variant
+ EF_MIPS_MACH_3900 = 0x00810000, // Toshiba R3900
+ EF_MIPS_MACH_4010 = 0x00820000, // LSI R4010
+ EF_MIPS_MACH_4100 = 0x00830000, // NEC VR4100
+ EF_MIPS_MACH_4650 = 0x00850000, // MIPS R4650
+ EF_MIPS_MACH_4120 = 0x00870000, // NEC VR4120
+ EF_MIPS_MACH_4111 = 0x00880000, // NEC VR4111/VR4181
+ EF_MIPS_MACH_SB1 = 0x008a0000, // Broadcom SB-1
+ EF_MIPS_MACH_OCTEON = 0x008b0000, // Cavium Networks Octeon
+ EF_MIPS_MACH_XLR = 0x008c0000, // RMI Xlr
+ EF_MIPS_MACH_OCTEON2 = 0x008d0000, // Cavium Networks Octeon2
+ EF_MIPS_MACH_OCTEON3 = 0x008e0000, // Cavium Networks Octeon3
+ EF_MIPS_MACH_5400 = 0x00910000, // NEC VR5400
+ EF_MIPS_MACH_5900 = 0x00920000, // MIPS R5900
+ EF_MIPS_MACH_5500 = 0x00980000, // NEC VR5500
+ EF_MIPS_MACH_9000 = 0x00990000, // Unknown
+ EF_MIPS_MACH_LS2E = 0x00a00000, // ST Microelectronics Loongson 2E
+ EF_MIPS_MACH_LS2F = 0x00a10000, // ST Microelectronics Loongson 2F
+ EF_MIPS_MACH_LS3A = 0x00a20000, // Loongson 3A
+ EF_MIPS_MACH = 0x00ff0000, // EF_MIPS_MACH_xxx selection mask
+
+ // ARCH_ASE
EF_MIPS_MICROMIPS = 0x02000000, // microMIPS
EF_MIPS_ARCH_ASE_M16 =
0x04000000, // Has Mips-16 ISA extensions
- //ARCH
+ EF_MIPS_ARCH_ASE_MDMX =
+ 0x08000000, // Has MDMX multimedia extensions
+ EF_MIPS_ARCH_ASE = 0x0f000000, // Mask for EF_MIPS_ARCH_ASE_xxx flags
+
+ // ARCH
EF_MIPS_ARCH_1 = 0x00000000, // MIPS1 instruction set
EF_MIPS_ARCH_2 = 0x10000000, // MIPS2 instruction set
EF_MIPS_ARCH_3 = 0x20000000, // MIPS3 instruction set
@@ -454,8 +483,8 @@ enum : unsigned {
EF_MIPS_ARCH_5 = 0x40000000, // MIPS5 instruction set
EF_MIPS_ARCH_32 = 0x50000000, // MIPS32 instruction set per linux not elf.h
EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h
- EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2
- EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2
+ EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2, mips32r3, mips32r5
+ EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2, mips64r3, mips64r5
EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6
EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6
EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant
@@ -475,6 +504,22 @@ enum {
STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16
};
+// .MIPS.options section descriptor kinds
+enum {
+ ODK_NULL = 0, // Undefined
+ ODK_REGINFO = 1, // Register usage information
+ ODK_EXCEPTIONS = 2, // Exception processing options
+ ODK_PAD = 3, // Section padding options
+ ODK_HWPATCH = 4, // Hardware patches applied
+ ODK_FILL = 5, // Linker fill value
+ ODK_TAGS = 6, // Space for tool identification
+ ODK_HWAND = 7, // Hardware AND patches applied
+ ODK_HWOR = 8, // Hardware OR patches applied
+ ODK_GP_GROUP = 9, // GP group to use for text/data sections
+ ODK_IDENT = 10, // ID information
+ ODK_PAGESIZE = 11 // Page size information
+};
+
// Hexagon Specific e_flags
// Release 5 ABI
enum {
@@ -761,6 +806,7 @@ enum {
STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def
STB_GLOBAL = 1, // Global symbol, visible to all object files being combined
STB_WEAK = 2, // Weak symbol, like global but lower-precedence
+ STB_GNU_UNIQUE = 10,
STB_LOOS = 10, // Lowest operating system-specific binding type
STB_HIOS = 12, // Highest operating system-specific binding type
STB_LOPROC = 13, // Lowest processor-specific binding type
@@ -795,6 +841,14 @@ enum {
STN_UNDEF = 0
};
+// Special relocation symbols used in the MIPS64 ELF relocation entries
+enum {
+ RSS_UNDEF = 0, // None
+ RSS_GP = 1, // Value of gp
+ RSS_GP0 = 2, // Value of gp used to create object being relocated
+ RSS_LOC = 3 // Address of location being relocated
+};
+
// Relocation entry, without explicit addend.
struct Elf32_Rel {
Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr)
@@ -1114,7 +1168,16 @@ enum {
DF_1_CONFALT = 0x00002000, // Configuration alternative created.
DF_1_ENDFILTEE = 0x00004000, // Filtee terminates filters search.
DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time.
- DF_1_DISPRELPND = 0x00010000 // Disp reloc applied at run-time.
+ DF_1_DISPRELPND = 0x00010000, // Disp reloc applied at run-time.
+ DF_1_NODIRECT = 0x00020000, // Object has no-direct binding.
+ DF_1_IGNMULDEF = 0x00040000,
+ DF_1_NOKSYMS = 0x00080000,
+ DF_1_NOHDR = 0x00100000,
+ DF_1_EDITED = 0x00200000, // Object is modified after built.
+ DF_1_NORELOC = 0x00400000,
+ DF_1_SYMINTPOSE = 0x00800000, // Object has individual interposers.
+ DF_1_GLOBAUDIT = 0x01000000, // Global auditing required.
+ DF_1_SINGLETON = 0x02000000 // Singleton symbols are used.
};
// DT_MIPS_FLAGS values.
diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def
index dc573464dcf2..77e7f8e8712b 100644
--- a/include/llvm/Support/ELFRelocs/Mips.def
+++ b/include/llvm/Support/ELFRelocs/Mips.def
@@ -108,5 +108,10 @@ 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_MICROMIPS_PC21_S2, 174)
+ELF_RELOC(R_MICROMIPS_PC26_S2, 175)
+ELF_RELOC(R_MICROMIPS_PC18_S3, 176)
+ELF_RELOC(R_MICROMIPS_PC19_S2, 177)
ELF_RELOC(R_MIPS_NUM, 218)
ELF_RELOC(R_MIPS_PC32, 248)
+ELF_RELOC(R_MIPS_EH, 249)
diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h
index 47b82fdc4975..e9fe22e5eda8 100644
--- a/include/llvm/Support/Endian.h
+++ b/include/llvm/Support/Endian.h
@@ -58,8 +58,9 @@ inline value_type read(const void *memory) {
/// Read a value of a particular endianness from a buffer, and increment the
/// buffer past that value.
-template<typename value_type, endianness endian, std::size_t alignment>
-inline value_type readNext(const unsigned char *&memory) {
+template<typename value_type, endianness endian, std::size_t alignment,
+ typename CharT>
+inline value_type readNext(const CharT *&memory) {
value_type ret = read<value_type, endian, alignment>(memory);
memory += sizeof(value_type);
return ret;
@@ -195,7 +196,23 @@ typedef detail::packed_endian_specific_integral
<int32_t, native, unaligned> unaligned_int32_t;
typedef detail::packed_endian_specific_integral
<int64_t, native, unaligned> unaligned_int64_t;
-} // end namespace llvm
+
+namespace endian {
+inline uint16_t read16le(const void *p) { return *(const ulittle16_t *)p; }
+inline uint32_t read32le(const void *p) { return *(const ulittle32_t *)p; }
+inline uint64_t read64le(const void *p) { return *(const ulittle64_t *)p; }
+inline uint16_t read16be(const void *p) { return *(const ubig16_t *)p; }
+inline uint32_t read32be(const void *p) { return *(const ubig32_t *)p; }
+inline uint64_t read64be(const void *p) { return *(const ubig64_t *)p; }
+
+inline void write16le(void *p, uint16_t v) { *(ulittle16_t *)p = v; }
+inline void write32le(void *p, uint32_t v) { *(ulittle32_t *)p = v; }
+inline void write64le(void *p, uint64_t v) { *(ulittle64_t *)p = v; }
+inline void write16be(void *p, uint16_t v) { *(ubig16_t *)p = v; }
+inline void write32be(void *p, uint32_t v) { *(ubig32_t *)p = v; }
+inline void write64be(void *p, uint64_t v) { *(ubig64_t *)p = v; }
+} // end namespace endian
} // end namespace support
+} // end namespace llvm
#endif
diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h
index 94f372f020b4..d44a9b3b7ce8 100644
--- a/include/llvm/Support/EndianStream.h
+++ b/include/llvm/Support/EndianStream.h
@@ -31,6 +31,31 @@ template <endianness endian> struct Writer {
OS.write((const char *)&Val, sizeof(value_type));
}
};
+
+template <>
+template <>
+inline void Writer<little>::write<float>(float Val) {
+ write(FloatToBits(Val));
+}
+
+template <>
+template <>
+inline void Writer<little>::write<double>(double Val) {
+ write(DoubleToBits(Val));
+}
+
+template <>
+template <>
+inline void Writer<big>::write<float>(float Val) {
+ write(FloatToBits(Val));
+}
+
+template <>
+template <>
+inline void Writer<big>::write<double>(double Val) {
+ write(DoubleToBits(Val));
+}
+
} // end namespace endian
} // end namespace support
diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h
index 84763deea0f9..589404f9b4ee 100644
--- a/include/llvm/Support/ErrorOr.h
+++ b/include/llvm/Support/ErrorOr.h
@@ -168,7 +168,7 @@ public:
}
/// \brief Return false if there is an error.
- LLVM_EXPLICIT operator bool() const {
+ explicit operator bool() const {
return !HasError;
}
@@ -281,8 +281,8 @@ template <class T, class E>
typename std::enable_if<std::is_error_code_enum<E>::value ||
std::is_error_condition_enum<E>::value,
bool>::type
-operator==(ErrorOr<T> &Err, E Code) {
- return std::error_code(Err) == Code;
+operator==(const ErrorOr<T> &Err, E Code) {
+ return Err.getError() == Code;
}
} // end namespace llvm
diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h
index 9f02a16e3d65..fd8879c84622 100644
--- a/include/llvm/Support/FileOutputBuffer.h
+++ b/include/llvm/Support/FileOutputBuffer.h
@@ -74,8 +74,8 @@ public:
~FileOutputBuffer();
private:
- FileOutputBuffer(const FileOutputBuffer &) LLVM_DELETED_FUNCTION;
- FileOutputBuffer &operator=(const FileOutputBuffer &) LLVM_DELETED_FUNCTION;
+ FileOutputBuffer(const FileOutputBuffer &) = delete;
+ FileOutputBuffer &operator=(const FileOutputBuffer &) = delete;
FileOutputBuffer(std::unique_ptr<llvm::sys::fs::mapped_file_region> R,
StringRef Path, StringRef TempPath);
diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h
index b60c1b07043b..a736c324f8aa 100644
--- a/include/llvm/Support/FileSystem.h
+++ b/include/llvm/Support/FileSystem.h
@@ -120,7 +120,7 @@ class UniqueID {
uint64_t File;
public:
- UniqueID() {}
+ UniqueID() = default;
UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
bool operator==(const UniqueID &Other) const {
return Device == Other.Device && File == Other.File;
@@ -241,6 +241,7 @@ struct file_magic {
macho_bundle, ///< Mach-O Bundle file
macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub
macho_dsym_companion, ///< Mach-O dSYM companion file
+ macho_kext_bundle, ///< Mach-O kext bundle file
macho_universal_binary, ///< Mach-O universal binary
coff_object, ///< COFF object file
coff_import_library, ///< COFF import library
@@ -624,9 +625,9 @@ std::error_code getUniqueID(const Twine Path, UniqueID &Result);
/// This class represents a memory mapped file. It is based on
/// boost::iostreams::mapped_file.
class mapped_file_region {
- mapped_file_region() LLVM_DELETED_FUNCTION;
- mapped_file_region(mapped_file_region&) LLVM_DELETED_FUNCTION;
- mapped_file_region &operator =(mapped_file_region&) LLVM_DELETED_FUNCTION;
+ mapped_file_region() = delete;
+ mapped_file_region(mapped_file_region&) = delete;
+ mapped_file_region &operator =(mapped_file_region&) = delete;
public:
enum mapmode {
diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h
index 3f2f176eb469..2ee2c60b9964 100644
--- a/include/llvm/Support/FileUtilities.h
+++ b/include/llvm/Support/FileUtilities.h
@@ -51,7 +51,7 @@ namespace llvm {
~FileRemover() {
if (DeleteIt) {
// Ignore problems deleting the file.
- sys::fs::remove(Filename.str());
+ sys::fs::remove(Filename);
}
}
@@ -61,7 +61,7 @@ namespace llvm {
void setFile(const Twine& filename, bool deleteIt = true) {
if (DeleteIt) {
// Ignore problems deleting the file.
- sys::fs::remove(Filename.str());
+ sys::fs::remove(Filename);
}
Filename.clear();
diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h
index 5d599e96ec3a..4319a3ba2745 100644
--- a/include/llvm/Support/Format.h
+++ b/include/llvm/Support/Format.h
@@ -23,18 +23,12 @@
#ifndef LLVM_SUPPORT_FORMAT_H
#define LLVM_SUPPORT_FORMAT_H
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <cstdio>
-#ifdef _MSC_VER
-// FIXME: This define is wrong:
-// - _snprintf does not guarantee that trailing null is always added - if
-// there is no space for null, it does not report any error.
-// - According to C++ standard, snprintf should be visible in the 'std'
-// namespace - this define makes this impossible.
-#define snprintf _snprintf
-#endif
+#include <tuple>
namespace llvm {
@@ -43,7 +37,8 @@ namespace llvm {
class format_object_base {
protected:
const char *Fmt;
- ~format_object_base() {} // Disallow polymorphic deletion.
+ ~format_object_base() = default; // Disallow polymorphic deletion.
+ format_object_base(const format_object_base &) = default;
virtual void home(); // Out of line virtual method.
/// Call snprintf() for this object, on the given buffer and size.
@@ -80,101 +75,26 @@ public:
/// printed, this synthesizes the string into a temporary buffer provided and
/// returns whether or not it is big enough.
-template <typename T>
-class format_object1 final : public format_object_base {
- T Val;
-public:
- format_object1(const char *fmt, const T &val)
- : format_object_base(fmt), Val(val) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val);
- }
-};
-
-template <typename T1, typename T2>
-class format_object2 final : public format_object_base {
- T1 Val1;
- T2 Val2;
-public:
- format_object2(const char *fmt, const T1 &val1, const T2 &val2)
- : format_object_base(fmt), Val1(val1), Val2(val2) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2);
- }
-};
-
-template <typename T1, typename T2, typename T3>
-class format_object3 final : public format_object_base {
- T1 Val1;
- T2 Val2;
- T3 Val3;
-public:
- format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3)
- : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3);
- }
-};
-
-template <typename T1, typename T2, typename T3, typename T4>
-class format_object4 final : public format_object_base {
- T1 Val1;
- T2 Val2;
- T3 Val3;
- T4 Val4;
-public:
- format_object4(const char *fmt, const T1 &val1, const T2 &val2,
- const T3 &val3, const T4 &val4)
- : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) {
- }
+template <typename... Ts>
+class format_object final : public format_object_base {
+ std::tuple<Ts...> Vals;
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4);
- }
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-class format_object5 final : public format_object_base {
- T1 Val1;
- T2 Val2;
- T3 Val3;
- T4 Val4;
- T5 Val5;
-public:
- format_object5(const char *fmt, const T1 &val1, const T2 &val2,
- const T3 &val3, const T4 &val4, const T5 &val5)
- : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4),
- Val5(val5) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5);
+ template <std::size_t... Is>
+ int snprint_tuple(char *Buffer, unsigned BufferSize,
+ index_sequence<Is...>) const {
+#ifdef _MSC_VER
+ return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
+#else
+ return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
+#endif
}
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
-class format_object6 final : public format_object_base {
- T1 Val1;
- T2 Val2;
- T3 Val3;
- T4 Val4;
- T5 Val5;
- T6 Val6;
public:
- format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2,
- const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6)
- : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4),
- Val5(Val5), Val6(Val6) { }
+ format_object(const char *fmt, const Ts &... vals)
+ : format_object_base(fmt), Vals(vals...) {}
int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6);
+ return snprint_tuple(Buffer, BufferSize, index_sequence_for<Ts...>());
}
};
@@ -187,44 +107,9 @@ public:
/// OS << format("%0.4f", myfloat) << '\n';
/// \endcode
-template <typename T>
-inline format_object1<T> format(const char *Fmt, const T &Val) {
- return format_object1<T>(Fmt, Val);
-}
-
-template <typename T1, typename T2>
-inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1,
- const T2 &Val2) {
- return format_object2<T1, T2>(Fmt, Val1, Val2);
-}
-
-template <typename T1, typename T2, typename T3>
- inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1,
- const T2 &Val2, const T3 &Val3) {
- return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3);
-}
-
-template <typename T1, typename T2, typename T3, typename T4>
-inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1,
- const T2 &Val2, const T3 &Val3,
- const T4 &Val4) {
- return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4);
-}
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1,
- const T2 &Val2, const T3 &Val3,
- const T4 &Val4, const T5 &Val5) {
- return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5);
-}
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
-inline format_object6<T1, T2, T3, T4, T5, T6>
-format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3,
- const T4 &Val4, const T5 &Val5, const T6 &Val6) {
- return format_object6<T1, T2, T3, T4, T5, T6>(Fmt, Val1, Val2, Val3, Val4,
- Val5, Val6);
+template <typename... Ts>
+inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) {
+ return format_object<Ts...>(Fmt, Vals...);
}
/// This is a helper class used for left_justify() and right_justify().
@@ -259,21 +144,38 @@ class FormattedNumber {
unsigned Width;
bool Hex;
bool Upper;
+ bool HexPrefix;
friend class raw_ostream;
public:
- FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U)
- : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U) { }
+ FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U,
+ bool Prefix)
+ : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U),
+ HexPrefix(Prefix) {}
};
/// format_hex - Output \p N as a fixed width hexadecimal. If number will not
/// fit in width, full number is still printed. Examples:
-/// OS << format_hex(255, 4) => 0xff
-/// OS << format_hex(255, 4, true) => 0xFF
-/// OS << format_hex(255, 6) => 0x00ff
-/// OS << format_hex(255, 2) => 0xff
-inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) {
+/// OS << format_hex(255, 4) => 0xff
+/// OS << format_hex(255, 4, true) => 0xFF
+/// OS << format_hex(255, 6) => 0x00ff
+/// OS << format_hex(255, 2) => 0xff
+inline FormattedNumber format_hex(uint64_t N, unsigned Width,
+ bool Upper = false) {
+ assert(Width <= 18 && "hex width must be <= 18");
+ return FormattedNumber(N, 0, Width, true, Upper, true);
+}
+
+/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not
+/// prepend '0x' to the outputted string. If number will not fit in width,
+/// full number is still printed. Examples:
+/// OS << format_hex_no_prefix(255, 4) => ff
+/// OS << format_hex_no_prefix(255, 4, true) => FF
+/// OS << format_hex_no_prefix(255, 6) => 00ff
+/// OS << format_hex_no_prefix(255, 2) => ff
+inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width,
+ bool Upper = false) {
assert(Width <= 18 && "hex width must be <= 18");
- return FormattedNumber(N, 0, Width, true, Upper);
+ return FormattedNumber(N, 0, Width, true, Upper, false);
}
/// format_decimal - Output \p N as a right justified, fixed-width decimal. If
@@ -283,7 +185,7 @@ inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
/// OS << format_decimal(-1, 3) => " -1"
/// OS << format_decimal(12345, 3) => "12345"
inline FormattedNumber format_decimal(int64_t N, unsigned Width) {
- return FormattedNumber(0, N, Width, false, false);
+ return FormattedNumber(0, N, Width, false, false, false);
}
diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h
index 8137daaff1f8..4a135cd23174 100644
--- a/include/llvm/Support/FormattedStream.h
+++ b/include/llvm/Support/FormattedStream.h
@@ -25,27 +25,11 @@ namespace llvm {
/// boundaries and querying the number of lines written to the stream.
///
class formatted_raw_ostream : public raw_ostream {
-public:
- /// DELETE_STREAM - Tell the destructor to delete the held stream.
- ///
- static const bool DELETE_STREAM = true;
-
- /// PRESERVE_STREAM - Tell the destructor to not delete the held
- /// stream.
- ///
- static const bool PRESERVE_STREAM = false;
-
-private:
/// TheStream - The real stream we output to. We set it to be
/// unbuffered, since we're already doing our own buffering.
///
raw_ostream *TheStream;
- /// DeleteStream - Do we need to delete TheStream in the
- /// destructor?
- ///
- bool DeleteStream;
-
/// Position - The current output column and line of the data that's
/// been flushed and the portion of the buffer that's been
/// scanned. The line and column scheme is zero-based.
@@ -73,6 +57,24 @@ private:
///
void ComputePosition(const char *Ptr, size_t size);
+ void setStream(raw_ostream &Stream) {
+ releaseStream();
+
+ TheStream = &Stream;
+
+ // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
+ // own buffering, and it doesn't need or want TheStream to do another
+ // layer of buffering underneath. Resize the buffer to what TheStream
+ // had been using, and tell TheStream not to do its own buffering.
+ if (size_t BufferSize = TheStream->GetBufferSize())
+ SetBufferSize(BufferSize);
+ else
+ SetUnbuffered();
+ TheStream->SetUnbuffered();
+
+ Scanned = nullptr;
+ }
+
public:
/// formatted_raw_ostream - Open the specified file for
/// writing. If an error occurs, information about the error is
@@ -84,39 +86,19 @@ public:
/// so it doesn't want another layer of buffering to be happening
/// underneath it.
///
- formatted_raw_ostream(raw_ostream &Stream, bool Delete = false)
- : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) {
- setStream(Stream, Delete);
+ formatted_raw_ostream(raw_ostream &Stream)
+ : TheStream(nullptr), Position(0, 0) {
+ setStream(Stream);
}
- explicit formatted_raw_ostream()
- : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) {
+ explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) {
Scanned = nullptr;
}
- ~formatted_raw_ostream() {
+ ~formatted_raw_ostream() override {
flush();
releaseStream();
}
- void setStream(raw_ostream &Stream, bool Delete = false) {
- releaseStream();
-
- TheStream = &Stream;
- DeleteStream = Delete;
-
- // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
- // own buffering, and it doesn't need or want TheStream to do another
- // layer of buffering underneath. Resize the buffer to what TheStream
- // had been using, and tell TheStream not to do its own buffering.
- if (size_t BufferSize = TheStream->GetBufferSize())
- SetBufferSize(BufferSize);
- else
- SetUnbuffered();
- TheStream->SetUnbuffered();
-
- Scanned = nullptr;
- }
-
/// PadToColumn - Align the output to some column number. If the current
/// column is already equal to or more than NewCol, PadToColumn inserts one
/// space.
@@ -151,13 +133,11 @@ public:
private:
void releaseStream() {
- // Delete the stream if needed. Otherwise, transfer the buffer
- // settings from this raw_ostream back to the underlying stream.
+ // Transfer the buffer settings from this raw_ostream back to the underlying
+ // stream.
if (!TheStream)
return;
- if (DeleteStream)
- delete TheStream;
- else if (size_t BufferSize = GetBufferSize())
+ if (size_t BufferSize = GetBufferSize())
TheStream->SetBufferSize(BufferSize);
else
TheStream->SetUnbuffered();
diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h
index e378602c7bb3..c2e34bd3eaeb 100644
--- a/include/llvm/Support/GCOV.h
+++ b/include/llvm/Support/GCOV.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
@@ -29,10 +30,7 @@ class GCOVBlock;
class FileInfo;
namespace GCOV {
- enum GCOVVersion {
- V402,
- V404
- };
+enum GCOVVersion { V402, V404 };
} // end GCOV namespace
/// GCOVOptions - A struct for passing gcov options between functions.
@@ -56,7 +54,7 @@ struct GCOVOptions {
class GCOVBuffer {
public:
GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
-
+
/// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
bool readGCNOFormat() {
StringRef File = Buffer->getBuffer().slice(0, 4);
@@ -81,7 +79,7 @@ public:
/// readGCOVVersion - Read GCOV version.
bool readGCOVVersion(GCOV::GCOVVersion &Version) {
- StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4);
+ StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4);
if (VersionStr == "*204") {
Cursor += 4;
Version = GCOV::V402;
@@ -99,10 +97,9 @@ public:
/// readFunctionTag - If cursor points to a function tag then increment the
/// cursor and return true otherwise return false.
bool readFunctionTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\0' || Tag[3] != '\1') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
+ Tag[3] != '\1') {
return false;
}
Cursor += 4;
@@ -112,10 +109,9 @@ public:
/// readBlockTag - If cursor points to a block tag then increment the
/// cursor and return true otherwise return false.
bool readBlockTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\x41' || Tag[3] != '\x01') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
+ Tag[3] != '\x01') {
return false;
}
Cursor += 4;
@@ -125,10 +121,9 @@ public:
/// readEdgeTag - If cursor points to an edge tag then increment the
/// cursor and return true otherwise return false.
bool readEdgeTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\x43' || Tag[3] != '\x01') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
+ Tag[3] != '\x01') {
return false;
}
Cursor += 4;
@@ -138,10 +133,9 @@ public:
/// readLineTag - If cursor points to a line tag then increment the
/// cursor and return true otherwise return false.
bool readLineTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\x45' || Tag[3] != '\x01') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
+ Tag[3] != '\x01') {
return false;
}
Cursor += 4;
@@ -151,10 +145,9 @@ public:
/// readArcTag - If cursor points to an gcda arc tag then increment the
/// cursor and return true otherwise return false.
bool readArcTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\xa1' || Tag[3] != '\1') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
+ Tag[3] != '\1') {
return false;
}
Cursor += 4;
@@ -164,10 +157,9 @@ public:
/// readObjectTag - If cursor points to an object summary tag then increment
/// the cursor and return true otherwise return false.
bool readObjectTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\0' || Tag[3] != '\xa1') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
+ Tag[3] != '\xa1') {
return false;
}
Cursor += 4;
@@ -177,10 +169,9 @@ public:
/// readProgramTag - If cursor points to a program summary tag then increment
/// the cursor and return true otherwise return false.
bool readProgramTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\0' || Tag[3] != '\xa3') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
+ Tag[3] != '\xa3') {
return false;
}
Cursor += 4;
@@ -188,11 +179,11 @@ public:
}
bool readInt(uint32_t &Val) {
- if (Buffer->getBuffer().size() < Cursor+4) {
- errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
+ if (Buffer->getBuffer().size() < Cursor + 4) {
+ errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
return false;
}
- StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
+ StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
Cursor += 4;
Val = *(const uint32_t *)(Str.data());
return true;
@@ -200,7 +191,8 @@ public:
bool readInt64(uint64_t &Val) {
uint32_t Lo, Hi;
- if (!readInt(Lo) || !readInt(Hi)) return false;
+ if (!readInt(Lo) || !readInt(Hi))
+ return false;
Val = ((uint64_t)Hi << 32) | Lo;
return true;
}
@@ -210,19 +202,21 @@ public:
// Keep reading until we find a non-zero length. This emulates gcov's
// behaviour, which appears to do the same.
while (Len == 0)
- if (!readInt(Len)) return false;
+ if (!readInt(Len))
+ return false;
Len *= 4;
- if (Buffer->getBuffer().size() < Cursor+Len) {
- errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
+ if (Buffer->getBuffer().size() < Cursor + Len) {
+ errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
return false;
}
- Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
+ Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
Cursor += Len;
return true;
}
uint64_t getCursor() const { return Cursor; }
- void advanceCursor(uint32_t n) { Cursor += n*4; }
+ void advanceCursor(uint32_t n) { Cursor += n * 4; }
+
private:
MemoryBuffer *Buffer;
uint64_t Cursor;
@@ -232,13 +226,15 @@ private:
/// (.gcno and .gcda).
class GCOVFile {
public:
- GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
- ProgramCount(0) {}
+ GCOVFile()
+ : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
+ ProgramCount(0) {}
bool readGCNO(GCOVBuffer &Buffer);
bool readGCDA(GCOVBuffer &Buffer);
uint32_t getChecksum() const { return Checksum; }
void dump() const;
void collectLineCounts(FileInfo &FI);
+
private:
bool GCNOInitialized;
GCOV::GCOVVersion Version;
@@ -260,8 +256,8 @@ struct GCOVEdge {
/// GCOVFunction - Collects function information.
class GCOVFunction {
public:
- typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator
- BlockIterator;
+ typedef pointee_iterator<SmallVectorImpl<
+ std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator;
GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
@@ -274,9 +270,13 @@ public:
BlockIterator block_begin() const { return Blocks.begin(); }
BlockIterator block_end() const { return Blocks.end(); }
+ iterator_range<BlockIterator> blocks() const {
+ return make_range(block_begin(), block_end());
+ }
void dump() const;
void collectLineCounts(FileInfo &FI);
+
private:
GCOVFile &Parent;
uint32_t Ident;
@@ -291,7 +291,7 @@ private:
/// GCOVBlock - Collects block information.
class GCOVBlock {
struct EdgeWeight {
- EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {}
+ EdgeWeight(GCOVBlock *D) : Dst(D), Count(0) {}
GCOVBlock *Dst;
uint64_t Count;
@@ -302,11 +302,13 @@ class GCOVBlock {
return E1->Dst.Number < E2->Dst.Number;
}
};
+
public:
typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
- GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0),
- DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {}
+ GCOVBlock(GCOVFunction &P, uint32_t N)
+ : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(),
+ DstEdges(), Lines() {}
~GCOVBlock();
const GCOVFunction &getParent() const { return Parent; }
void addLine(uint32_t N) { Lines.push_back(N); }
@@ -331,11 +333,19 @@ public:
EdgeIterator src_begin() const { return SrcEdges.begin(); }
EdgeIterator src_end() const { return SrcEdges.end(); }
+ iterator_range<EdgeIterator> srcs() const {
+ return make_range(src_begin(), src_end());
+ }
+
EdgeIterator dst_begin() const { return DstEdges.begin(); }
EdgeIterator dst_end() const { return DstEdges.end(); }
+ iterator_range<EdgeIterator> dsts() const {
+ return make_range(dst_begin(), dst_end());
+ }
void dump() const;
void collectLineCounts(FileInfo &FI);
+
private:
GCOVFunction &Parent;
uint32_t Number;
@@ -347,8 +357,10 @@ private:
};
class FileInfo {
- // It is unlikely--but possible--for multiple functions to be on the same line.
- // Therefore this typedef allows LineData.Functions to store multiple functions
+ // It is unlikely--but possible--for multiple functions to be on the same
+ // line.
+ // Therefore this typedef allows LineData.Functions to store multiple
+ // functions
// per instance. This is rare, however, so optimize for the common case.
typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
@@ -363,9 +375,9 @@ class FileInfo {
};
struct GCOVCoverage {
- GCOVCoverage(StringRef Name) :
- Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0),
- BranchesTaken(0) {}
+ GCOVCoverage(StringRef Name)
+ : Name(Name), LogicalLines(0), LinesExec(0), Branches(0),
+ BranchesExec(0), BranchesTaken(0) {}
StringRef Name;
@@ -376,30 +388,31 @@ class FileInfo {
uint32_t BranchesExec;
uint32_t BranchesTaken;
};
+
public:
- FileInfo(const GCOVOptions &Options) :
- Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
+ FileInfo(const GCOVOptions &Options)
+ : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
if (Line > LineInfo[Filename].LastLine)
LineInfo[Filename].LastLine = Line;
- LineInfo[Filename].Blocks[Line-1].push_back(Block);
+ LineInfo[Filename].Blocks[Line - 1].push_back(Block);
}
void addFunctionLine(StringRef Filename, uint32_t Line,
const GCOVFunction *Function) {
if (Line > LineInfo[Filename].LastLine)
LineInfo[Filename].LastLine = Line;
- LineInfo[Filename].Functions[Line-1].push_back(Function);
+ LineInfo[Filename].Functions[Line - 1].push_back(Function);
}
void setRunCount(uint32_t Runs) { RunCount = Runs; }
void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
- void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile);
+ void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
+ StringRef GCDAFile);
private:
std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
- void printFunctionSummary(raw_ostream &OS,
- const FunctionVector &Funcs) const;
+ void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
uint32_t LineIndex, uint32_t &BlockNo) const;
void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
@@ -407,23 +420,21 @@ private:
void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
uint64_t Count) const;
- void printCoverage(const GCOVCoverage &Coverage) const;
- void printFuncCoverage() const;
- void printFileCoverage() const;
+ void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
+ void printFuncCoverage(raw_ostream &OS) const;
+ void printFileCoverage(raw_ostream &OS) const;
const GCOVOptions &Options;
StringMap<LineData> LineInfo;
uint32_t RunCount;
uint32_t ProgramCount;
- typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4>
- FileCoverageList;
+ typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList;
typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
FileCoverageList FileCoverages;
FuncCoverageMap FuncCoverages;
};
-
}
#endif
diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h
index fde56135a962..63678bb98bb1 100644
--- a/include/llvm/Support/GenericDomTree.h
+++ b/include/llvm/Support/GenericDomTree.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
@@ -93,8 +94,9 @@ public:
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom)
: TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) {}
- DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) {
- Children.push_back(C);
+ std::unique_ptr<DomTreeNodeBase<NodeT>>
+ addChild(std::unique_ptr<DomTreeNodeBase<NodeT>> C) {
+ Children.push_back(C.get());
return C;
}
@@ -182,8 +184,8 @@ void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT,
/// 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;
+ DominatorTreeBase(const DominatorTreeBase &) = delete;
+ DominatorTreeBase &operator=(const DominatorTreeBase &) = delete;
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
const DomTreeNodeBase<NodeT> *B) const {
@@ -210,7 +212,8 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
}
protected:
- typedef DenseMap<NodeT *, DomTreeNodeBase<NodeT> *> DomTreeNodeMapType;
+ typedef DenseMap<NodeT *, std::unique_ptr<DomTreeNodeBase<NodeT>>>
+ DomTreeNodeMapType;
DomTreeNodeMapType DomTreeNodes;
DomTreeNodeBase<NodeT> *RootNode;
@@ -235,15 +238,13 @@ protected:
DenseMap<NodeT *, InfoRec> Info;
void reset() {
- for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(),
- E = DomTreeNodes.end();
- I != E; ++I)
- delete I->second;
DomTreeNodes.clear();
IDoms.clear();
this->Roots.clear();
Vertex.clear();
RootNode = nullptr;
+ DFSInfoValid = false;
+ SlowQueries = 0;
}
// NewBB is split and now it has one successor. Update dominator tree to
@@ -314,7 +315,6 @@ protected:
public:
explicit DominatorTreeBase(bool isPostDom)
: DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
- ~DominatorTreeBase() { reset(); }
DominatorTreeBase(DominatorTreeBase &&Arg)
: DominatorBase<NodeT>(
@@ -358,10 +358,10 @@ public:
if (OI == OtherDomTreeNodes.end())
return true;
- DomTreeNodeBase<NodeT> *MyNd = I->second;
- DomTreeNodeBase<NodeT> *OtherNd = OI->second;
+ DomTreeNodeBase<NodeT> &MyNd = *I->second;
+ DomTreeNodeBase<NodeT> &OtherNd = *OI->second;
- if (MyNd->compare(OtherNd))
+ if (MyNd.compare(&OtherNd))
return true;
}
@@ -374,7 +374,10 @@ public:
/// block. This is the same as using operator[] on this class.
///
DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
- return DomTreeNodes.lookup(BB);
+ auto I = DomTreeNodes.find(BB);
+ if (I != DomTreeNodes.end())
+ return I->second.get();
+ return nullptr;
}
DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { return getNode(BB); }
@@ -555,8 +558,8 @@ public:
DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
assert(IDomNode && "Not immediate dominator specified for block!");
DFSInfoValid = false;
- return DomTreeNodes[BB] =
- IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode));
+ return (DomTreeNodes[BB] = IDomNode->addChild(
+ llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
}
/// changeImmediateDominator - This method is used to update the dominator
@@ -593,15 +596,6 @@ public:
}
DomTreeNodes.erase(BB);
- delete Node;
- }
-
- /// removeNode - Removes a node from the dominator tree. Block must not
- /// dominate any other blocks. Invalidates any node pointing to removed
- /// block.
- void removeNode(NodeT *BB) {
- assert(getNode(BB) && "Removing node that isn't in dominator tree.");
- DomTreeNodes.erase(BB);
}
/// splitBlock - BB is split and now it has one successor. Update dominator
@@ -645,9 +639,38 @@ protected:
friend void
Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, FuncT &F);
+
+ DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) {
+ if (DomTreeNodeBase<NodeT> *Node = getNode(BB))
+ return Node;
+
+ // Haven't calculated this node yet? Get or calculate the node for the
+ // immediate dominator.
+ NodeT *IDom = getIDom(BB);
+
+ assert(IDom || this->DomTreeNodes[nullptr]);
+ DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom);
+
+ // Add a new tree node for this NodeT, and link it as a child of
+ // IDomNode
+ return (this->DomTreeNodes[BB] = IDomNode->addChild(
+ llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
+ }
+
+ NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); }
+
+ void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
+
+public:
/// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
/// dominator tree in dfs order.
void updateDFSNumbers() const {
+
+ if (DFSInfoValid) {
+ SlowQueries = 0;
+ return;
+ }
+
unsigned DFSNum = 0;
SmallVector<std::pair<const DomTreeNodeBase<NodeT> *,
@@ -690,28 +713,6 @@ protected:
DFSInfoValid = true;
}
- DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) {
- if (DomTreeNodeBase<NodeT> *Node = getNode(BB))
- return Node;
-
- // Haven't calculated this node yet? Get or calculate the node for the
- // immediate dominator.
- NodeT *IDom = getIDom(BB);
-
- assert(IDom || this->DomTreeNodes[nullptr]);
- DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom);
-
- // Add a new tree node for this NodeT, and link it as a child of
- // IDomNode
- DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode);
- return this->DomTreeNodes[BB] = IDomNode->addChild(C);
- }
-
- NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(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;
diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h
index ad4f8a9f429a..7c065f939256 100644
--- a/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/include/llvm/Support/GenericDomTreeConstruction.h
@@ -251,15 +251,18 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
// an infinite loop.
typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : nullptr;
- DT.DomTreeNodes[Root] = DT.RootNode =
- new DomTreeNodeBase<typename GraphT::NodeType>(Root, nullptr);
+ DT.RootNode =
+ (DT.DomTreeNodes[Root] =
+ llvm::make_unique<DomTreeNodeBase<typename GraphT::NodeType>>(
+ Root, nullptr)).get();
// Loop over all of the reachable blocks in the function...
for (unsigned i = 2; i <= N; ++i) {
typename GraphT::NodeType* W = DT.Vertex[i];
- DomTreeNodeBase<typename GraphT::NodeType> *BBNode = DT.DomTreeNodes[W];
- if (BBNode) continue; // Haven't calculated this node yet?
+ // Don't replace this with 'count', the insertion side effect is important
+ if (DT.DomTreeNodes[W])
+ continue; // Haven't calculated this node yet?
typename GraphT::NodeType* ImmDom = DT.getIDom(W);
@@ -271,15 +274,16 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
// Add a new tree node for this BasicBlock, and link it as a child of
// IDomNode
- DomTreeNodeBase<typename GraphT::NodeType> *C =
- new DomTreeNodeBase<typename GraphT::NodeType>(W, IDomNode);
- DT.DomTreeNodes[W] = IDomNode->addChild(C);
+ DT.DomTreeNodes[W] = IDomNode->addChild(
+ llvm::make_unique<DomTreeNodeBase<typename GraphT::NodeType>>(
+ W, IDomNode));
}
// Free temporary memory used to construct idom's
DT.IDoms.clear();
DT.Info.clear();
- std::vector<typename GraphT::NodeType*>().swap(DT.Vertex);
+ DT.Vertex.clear();
+ DT.Vertex.shrink_to_fit();
DT.updateDFSNumbers();
}
diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h
index 2f02aa7a1c19..7d1c273c988d 100644
--- a/include/llvm/Support/GraphWriter.h
+++ b/include/llvm/Support/GraphWriter.h
@@ -24,10 +24,9 @@
#define LLVM_SUPPORT_GRAPHWRITER_H
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/DOTGraphTraits.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <cassert>
#include <vector>
namespace llvm {
diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h
index 61c65dabae3c..8e88d4279bd8 100644
--- a/include/llvm/Support/LockFileManager.h
+++ b/include/llvm/Support/LockFileManager.h
@@ -57,8 +57,8 @@ private:
Optional<std::pair<std::string, int> > Owner;
Optional<std::error_code> Error;
- LockFileManager(const LockFileManager &) LLVM_DELETED_FUNCTION;
- LockFileManager &operator=(const LockFileManager &) LLVM_DELETED_FUNCTION;
+ LockFileManager(const LockFileManager &) = delete;
+ LockFileManager &operator=(const LockFileManager &) = delete;
static Optional<std::pair<std::string, int> >
readLockFile(StringRef LockFileName);
@@ -77,6 +77,10 @@ public:
/// \brief For a shared lock, wait until the owner releases the lock.
WaitForUnlockResult waitForUnlock();
+
+ /// \brief Remove the lock file. This may delete a different lock file than
+ /// the one previously read if there is a race.
+ std::error_code unsafeRemoveLockFile();
};
} // end namespace llvm
diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h
index 698363614ac5..e3166165a483 100644
--- a/include/llvm/Support/MathExtras.h
+++ b/include/llvm/Support/MathExtras.h
@@ -24,6 +24,10 @@
#include <intrin.h>
#endif
+#ifdef __ANDROID_NDK__
+#include <android/api-level.h>
+#endif
+
namespace llvm {
/// \brief The behavior an operation has on an input of 0.
enum ZeroBehavior {
@@ -35,78 +39,66 @@ enum ZeroBehavior {
ZB_Width
};
-/// \brief Count number of 0's from the least significant bit to the most
-/// stopping at the first 1.
-///
-/// Only unsigned integral types are allowed.
-///
-/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
-/// valid arguments.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- !std::numeric_limits<T>::is_signed, std::size_t>::type
-countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
- (void)ZB;
-
- if (!Val)
- return std::numeric_limits<T>::digits;
- if (Val & 0x1)
- return 0;
-
- // Bisection method.
- std::size_t ZeroBits = 0;
- T Shift = std::numeric_limits<T>::digits >> 1;
- T Mask = std::numeric_limits<T>::max() >> Shift;
- while (Shift) {
- if ((Val & Mask) == 0) {
- Val >>= Shift;
- ZeroBits |= Shift;
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
+ static std::size_t count(T Val, ZeroBehavior) {
+ if (!Val)
+ return std::numeric_limits<T>::digits;
+ if (Val & 0x1)
+ return 0;
+
+ // Bisection method.
+ std::size_t ZeroBits = 0;
+ T Shift = std::numeric_limits<T>::digits >> 1;
+ T Mask = std::numeric_limits<T>::max() >> Shift;
+ while (Shift) {
+ if ((Val & Mask) == 0) {
+ Val >>= Shift;
+ ZeroBits |= Shift;
+ }
+ Shift >>= 1;
+ Mask >>= Shift;
}
- Shift >>= 1;
- Mask >>= Shift;
+ return ZeroBits;
}
- return ZeroBits;
-}
-
-// Disable signed.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- std::numeric_limits<T>::is_signed, std::size_t>::type
-countTrailingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION;
+};
#if __GNUC__ >= 4 || _MSC_VER
-template <>
-inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
- if (ZB != ZB_Undefined && Val == 0)
- return 32;
+template <typename T> struct TrailingZerosCounter<T, 4> {
+ static std::size_t count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 32;
#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0)
- return __builtin_ctz(Val);
+ return __builtin_ctz(Val);
#elif _MSC_VER
- unsigned long Index;
- _BitScanForward(&Index, Val);
- return Index;
+ unsigned long Index;
+ _BitScanForward(&Index, Val);
+ return Index;
#endif
-}
+ }
+};
#if !defined(_MSC_VER) || defined(_M_X64)
-template <>
-inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
- if (ZB != ZB_Undefined && Val == 0)
- return 64;
+template <typename T> struct TrailingZerosCounter<T, 8> {
+ static std::size_t count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 64;
#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0)
- return __builtin_ctzll(Val);
+ return __builtin_ctzll(Val);
#elif _MSC_VER
- unsigned long Index;
- _BitScanForward64(&Index, Val);
- return Index;
+ unsigned long Index;
+ _BitScanForward64(&Index, Val);
+ return Index;
#endif
-}
+ }
+};
#endif
#endif
+} // namespace detail
-/// \brief Count number of 0's from the most significant bit to the least
+/// \brief Count number of 0's from the least significant bit to the most
/// stopping at the first 1.
///
/// Only unsigned integral types are allowed.
@@ -114,63 +106,81 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
/// valid arguments.
template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- !std::numeric_limits<T>::is_signed, std::size_t>::type
-countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
- (void)ZB;
-
- if (!Val)
- return std::numeric_limits<T>::digits;
-
- // Bisection method.
- std::size_t ZeroBits = 0;
- for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
- T Tmp = Val >> Shift;
- if (Tmp)
- Val = Tmp;
- else
- ZeroBits |= Shift;
+std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
+}
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
+ static std::size_t count(T Val, ZeroBehavior) {
+ if (!Val)
+ return std::numeric_limits<T>::digits;
+
+ // Bisection method.
+ std::size_t ZeroBits = 0;
+ for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
+ T Tmp = Val >> Shift;
+ if (Tmp)
+ Val = Tmp;
+ else
+ ZeroBits |= Shift;
+ }
+ return ZeroBits;
}
- return ZeroBits;
-}
-
-// Disable signed.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- std::numeric_limits<T>::is_signed, std::size_t>::type
-countLeadingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION;
+};
#if __GNUC__ >= 4 || _MSC_VER
-template <>
-inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
- if (ZB != ZB_Undefined && Val == 0)
- return 32;
+template <typename T> struct LeadingZerosCounter<T, 4> {
+ static std::size_t count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 32;
#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0)
- return __builtin_clz(Val);
+ return __builtin_clz(Val);
#elif _MSC_VER
- unsigned long Index;
- _BitScanReverse(&Index, Val);
- return Index ^ 31;
+ unsigned long Index;
+ _BitScanReverse(&Index, Val);
+ return Index ^ 31;
#endif
-}
+ }
+};
#if !defined(_MSC_VER) || defined(_M_X64)
-template <>
-inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
- if (ZB != ZB_Undefined && Val == 0)
- return 64;
+template <typename T> struct LeadingZerosCounter<T, 8> {
+ static std::size_t count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 64;
#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0)
- return __builtin_clzll(Val);
+ return __builtin_clzll(Val);
#elif _MSC_VER
- unsigned long Index;
- _BitScanReverse64(&Index, Val);
- return Index ^ 63;
+ unsigned long Index;
+ _BitScanReverse64(&Index, Val);
+ return Index ^ 63;
#endif
-}
+ }
+};
#endif
#endif
+} // namespace detail
+
+/// \brief Count number of 0's from the most significant bit to the least
+/// stopping at the first 1.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
+/// valid arguments.
+template <typename T>
+std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
+}
/// \brief Get the index of the first set bit starting from the least
/// significant bit.
@@ -179,22 +189,13 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
///
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
/// valid arguments.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- !std::numeric_limits<T>::is_signed, T>::type
-findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
+template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return std::numeric_limits<T>::max();
return countTrailingZeros(Val, ZB_Undefined);
}
-// Disable signed.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- std::numeric_limits<T>::is_signed, T>::type
-findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION;
-
/// \brief Get the index of the last set bit starting from the least
/// significant bit.
///
@@ -202,10 +203,7 @@ findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION;
///
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
/// valid arguments.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- !std::numeric_limits<T>::is_signed, T>::type
-findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
+template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return std::numeric_limits<T>::max();
@@ -215,12 +213,6 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
(std::numeric_limits<T>::digits - 1);
}
-// Disable signed.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- std::numeric_limits<T>::is_signed, T>::type
-findLastSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION;
-
/// \brief Macro compressed bit reversal table for 256 bits.
///
/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
@@ -330,31 +322,31 @@ inline bool isIntN(unsigned N, int64_t x) {
return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
}
-/// isMask_32 - This function returns true if the argument is a sequence of ones
-/// starting at the least significant bit with the remainder zero (32 bit
-/// version). Ex. isMask_32(0x0000FFFFU) == true.
+/// isMask_32 - This function returns true if the argument is a non-empty
+/// sequence of ones starting at the least significant bit with the remainder
+/// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true.
inline bool isMask_32(uint32_t Value) {
return Value && ((Value + 1) & Value) == 0;
}
-/// isMask_64 - This function returns true if the argument is a sequence of ones
-/// starting at the least significant bit with the remainder zero (64 bit
-/// version).
+/// isMask_64 - This function returns true if the argument is a non-empty
+/// sequence of ones starting at the least significant bit with the remainder
+/// zero (64 bit version).
inline bool isMask_64(uint64_t Value) {
return Value && ((Value + 1) & Value) == 0;
}
/// isShiftedMask_32 - This function returns true if the argument contains a
-/// sequence of ones with the remainder zero (32 bit version.)
+/// non-empty sequence of ones with the remainder zero (32 bit version.)
/// Ex. isShiftedMask_32(0x0000FF00U) == true.
inline bool isShiftedMask_32(uint32_t Value) {
- return isMask_32((Value - 1) | Value);
+ return Value && isMask_32((Value - 1) | Value);
}
/// isShiftedMask_64 - This function returns true if the argument contains a
-/// sequence of ones with the remainder zero (64 bit version.)
+/// non-empty sequence of ones with the remainder zero (64 bit version.)
inline bool isShiftedMask_64(uint64_t Value) {
- return isMask_64((Value - 1) | Value);
+ return Value && isMask_64((Value - 1) | Value);
}
/// isPowerOf2_32 - This function returns true if the argument is a power of
@@ -387,61 +379,86 @@ inline uint64_t ByteSwap_64(uint64_t Value) {
return sys::SwapByteOrder_64(Value);
}
-/// CountLeadingOnes_32 - this function performs the operation of
-/// counting the number of ones from the most significant bit to the first zero
-/// bit. Ex. CountLeadingOnes_32(0xFF0FFF00) == 8.
-/// Returns 32 if the word is all ones.
-inline unsigned CountLeadingOnes_32(uint32_t Value) {
- return countLeadingZeros(~Value);
-}
-
-/// CountLeadingOnes_64 - This function performs the operation
-/// of counting the number of ones from the most significant bit to the first
-/// zero bit (64 bit edition.)
-/// Returns 64 if the word is all ones.
-inline unsigned CountLeadingOnes_64(uint64_t Value) {
- return countLeadingZeros(~Value);
-}
-
-/// CountTrailingOnes_32 - this function performs the operation of
-/// counting the number of ones from the least significant bit to the first zero
-/// bit. Ex. CountTrailingOnes_32(0x00FF00FF) == 8.
-/// Returns 32 if the word is all ones.
-inline unsigned CountTrailingOnes_32(uint32_t Value) {
- return countTrailingZeros(~Value);
+/// \brief Count the number of ones from the most significant bit to the first
+/// zero bit.
+///
+/// Ex. CountLeadingOnes(0xFF0FFF00) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of all ones. Only ZB_Width and
+/// ZB_Undefined are valid arguments.
+template <typename T>
+std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return countLeadingZeros(~Value, ZB);
}
-/// CountTrailingOnes_64 - This function performs the operation
-/// of counting the number of ones from the least significant bit to the first
-/// zero bit (64 bit edition.)
-/// Returns 64 if the word is all ones.
-inline unsigned CountTrailingOnes_64(uint64_t Value) {
- return countTrailingZeros(~Value);
-}
+/// \brief Count the number of ones from the least significant bit to the first
+/// zero bit.
+///
+/// Ex. countTrailingOnes(0x00FF00FF) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of all ones. Only ZB_Width and
+/// ZB_Undefined are valid arguments.
+template <typename T>
+std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return countTrailingZeros(~Value, ZB);
+}
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct PopulationCounter {
+ static unsigned count(T Value) {
+ // Generic version, forward to 32 bits.
+ static_assert(SizeOfT <= 4, "Not implemented!");
+#if __GNUC__ >= 4
+ return __builtin_popcount(Value);
+#else
+ uint32_t v = Value;
+ v = v - ((v >> 1) & 0x55555555);
+ v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+ return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
+#endif
+ }
+};
-/// CountPopulation_32 - this function counts the number of set bits in a value.
-/// Ex. CountPopulation(0xF000F000) = 8
-/// Returns 0 if the word is zero.
-inline unsigned CountPopulation_32(uint32_t Value) {
+template <typename T> struct PopulationCounter<T, 8> {
+ static unsigned count(T Value) {
#if __GNUC__ >= 4
- return __builtin_popcount(Value);
+ return __builtin_popcountll(Value);
#else
- uint32_t v = Value - ((Value >> 1) & 0x55555555);
- v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
- return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
+ uint64_t v = Value;
+ v = v - ((v >> 1) & 0x5555555555555555ULL);
+ v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
+ v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
+ return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
#endif
+ }
+};
+} // namespace detail
+
+/// \brief Count the number of set bits in a value.
+/// Ex. countPopulation(0xF000F000) = 8
+/// Returns 0 if the word is zero.
+template <typename T>
+inline unsigned countPopulation(T Value) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return detail::PopulationCounter<T, sizeof(T)>::count(Value);
}
-/// CountPopulation_64 - this function counts the number of set bits in a value,
-/// (64 bit edition.)
-inline unsigned CountPopulation_64(uint64_t Value) {
-#if __GNUC__ >= 4
- return __builtin_popcountll(Value);
+/// Log2 - This function returns the log base 2 of the specified value
+inline double Log2(double Value) {
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
+ return __builtin_log(Value) / __builtin_log(2.0);
#else
- uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL);
- v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
- v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
- return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
+ return log2(Value);
#endif
}
@@ -530,14 +547,6 @@ inline uint32_t FloatToBits(float Float) {
return T.I;
}
-/// Platform-independent wrappers for the C99 isnan() function.
-int IsNAN(float f);
-int IsNAN(double d);
-
-/// Platform-independent wrappers for the C99 isinf() function.
-int IsInf(float f);
-int IsInf(double d);
-
/// MinAlign - A and B are either alignments or offsets. Return the minimum
/// alignment that may be assumed after adding the two together.
inline uint64_t MinAlign(uint64_t A, uint64_t B) {
@@ -608,13 +617,6 @@ inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) {
return RoundUpToAlignment(Value, Align) - Value;
}
-/// abs64 - absolute value of a 64-bit int. Not all environments support
-/// "abs" on whatever their name for the 64-bit int type is. The absolute
-/// value of the largest negative number is undefined, as with "abs".
-inline int64_t abs64(int64_t x) {
- return (x < 0) ? -x : x;
-}
-
/// SignExtend32 - Sign extend B-bit number x to 32-bit int.
/// Usage int32_t r = SignExtend32<5>(x);
template <unsigned B> inline int32_t SignExtend32(uint32_t x) {
diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h
index e2f8d7e90fef..35a7bdb004a9 100644
--- a/include/llvm/Support/MemoryBuffer.h
+++ b/include/llvm/Support/MemoryBuffer.h
@@ -17,11 +17,9 @@
#include "llvm-c/Support.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CBindingWrapping.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorOr.h"
#include <memory>
-#include <system_error>
namespace llvm {
class MemoryBufferRef;
@@ -40,8 +38,8 @@ class MemoryBuffer {
const char *BufferStart; // Start of the buffer.
const char *BufferEnd; // End of the buffer.
- MemoryBuffer(const MemoryBuffer &) LLVM_DELETED_FUNCTION;
- MemoryBuffer &operator=(const MemoryBuffer &) LLVM_DELETED_FUNCTION;
+ MemoryBuffer(const MemoryBuffer &) = delete;
+ MemoryBuffer &operator=(const MemoryBuffer &) = delete;
protected:
MemoryBuffer() {}
void init(const char *BufStart, const char *BufEnd,
diff --git a/include/llvm/Support/MipsABIFlags.h b/include/llvm/Support/MipsABIFlags.h
new file mode 100644
index 000000000000..93f6b416ba88
--- /dev/null
+++ b/include/llvm/Support/MipsABIFlags.h
@@ -0,0 +1,102 @@
+//===--- MipsABIFlags.h - MIPS ABI flags ----------------------------------===//
+//
+// 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 constants for the ABI flags structure contained
+// in the .MIPS.abiflags section.
+//
+// https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MIPSABIFLAGS_H
+#define LLVM_SUPPORT_MIPSABIFLAGS_H
+
+namespace llvm {
+namespace Mips {
+
+// Values for the xxx_size bytes of an ABI flags structure.
+enum AFL_REG {
+ AFL_REG_NONE = 0x00, // No registers
+ AFL_REG_32 = 0x01, // 32-bit registers
+ AFL_REG_64 = 0x02, // 64-bit registers
+ AFL_REG_128 = 0x03 // 128-bit registers
+};
+
+// Masks for the ases word of an ABI flags structure.
+enum AFL_ASE {
+ AFL_ASE_DSP = 0x00000001, // DSP ASE
+ AFL_ASE_DSPR2 = 0x00000002, // DSP R2 ASE
+ AFL_ASE_EVA = 0x00000004, // Enhanced VA Scheme
+ AFL_ASE_MCU = 0x00000008, // MCU (MicroController) ASE
+ AFL_ASE_MDMX = 0x00000010, // MDMX ASE
+ AFL_ASE_MIPS3D = 0x00000020, // MIPS-3D ASE
+ AFL_ASE_MT = 0x00000040, // MT ASE
+ AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE
+ AFL_ASE_VIRT = 0x00000100, // VZ ASE
+ AFL_ASE_MSA = 0x00000200, // MSA ASE
+ AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE
+ AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE
+ AFL_ASE_XPA = 0x00001000 // XPA ASE
+};
+
+// Values for the isa_ext word of an ABI flags structure.
+enum AFL_EXT {
+ AFL_EXT_NONE = 0, // None
+ AFL_EXT_XLR = 1, // RMI Xlr instruction
+ AFL_EXT_OCTEON2 = 2, // Cavium Networks Octeon2
+ AFL_EXT_OCTEONP = 3, // Cavium Networks OcteonP
+ AFL_EXT_LOONGSON_3A = 4, // Loongson 3A
+ AFL_EXT_OCTEON = 5, // Cavium Networks Octeon
+ AFL_EXT_5900 = 6, // MIPS R5900 instruction
+ AFL_EXT_4650 = 7, // MIPS R4650 instruction
+ AFL_EXT_4010 = 8, // LSI R4010 instruction
+ AFL_EXT_4100 = 9, // NEC VR4100 instruction
+ AFL_EXT_3900 = 10, // Toshiba R3900 instruction
+ AFL_EXT_10000 = 11, // MIPS R10000 instruction
+ AFL_EXT_SB1 = 12, // Broadcom SB-1 instruction
+ AFL_EXT_4111 = 13, // NEC VR4111/VR4181 instruction
+ AFL_EXT_4120 = 14, // NEC VR4120 instruction
+ AFL_EXT_5400 = 15, // NEC VR5400 instruction
+ AFL_EXT_5500 = 16, // NEC VR5500 instruction
+ AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E
+ AFL_EXT_LOONGSON_2F = 18, // ST Microelectronics Loongson 2F
+ AFL_EXT_OCTEON3 = 19 // Cavium Networks Octeon3
+};
+
+// Values for the flags1 word of an ABI flags structure.
+enum AFL_FLAGS1 { AFL_FLAGS1_ODDSPREG = 1 };
+
+// MIPS object attribute tags
+enum {
+ Tag_GNU_MIPS_ABI_FP = 4, // Floating-point ABI used by this object file
+ Tag_GNU_MIPS_ABI_MSA = 8, // MSA ABI used by this object file
+};
+
+// Values for the fp_abi word of an ABI flags structure
+// and for the Tag_GNU_MIPS_ABI_FP attribute tag.
+enum Val_GNU_MIPS_ABI_FP {
+ Val_GNU_MIPS_ABI_FP_ANY = 0, // not tagged
+ Val_GNU_MIPS_ABI_FP_DOUBLE = 1, // hard float / -mdouble-float
+ Val_GNU_MIPS_ABI_FP_SINGLE = 2, // hard float / -msingle-float
+ Val_GNU_MIPS_ABI_FP_SOFT = 3, // soft float
+ Val_GNU_MIPS_ABI_FP_OLD_64 = 4, // -mips32r2 -mfp64
+ Val_GNU_MIPS_ABI_FP_XX = 5, // -mfpxx
+ Val_GNU_MIPS_ABI_FP_64 = 6, // -mips32r2 -mfp64
+ Val_GNU_MIPS_ABI_FP_64A = 7 // -mips32r2 -mfp64 -mno-odd-spreg
+};
+
+// Values for the Tag_GNU_MIPS_ABI_MSA attribute tag.
+enum Val_GNU_MIPS_ABI_MSA {
+ Val_GNU_MIPS_ABI_MSA_ANY = 0, // not tagged
+ Val_GNU_MIPS_ABI_MSA_128 = 1 // 128-bit MSA
+};
+}
+}
+
+#endif
diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h
index 97dd50115322..0f4e61af4439 100644
--- a/include/llvm/Support/Mutex.h
+++ b/include/llvm/Support/Mutex.h
@@ -70,14 +70,16 @@ namespace llvm
/// @name Platform Dependent Data
/// @{
private:
+#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
void* data_; ///< We don't know what the data will be
+#endif
/// @}
/// @name Do Not Implement
/// @{
private:
- MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION;
- void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION;
+ MutexImpl(const MutexImpl &) = delete;
+ void operator=(const MutexImpl &) = delete;
/// @}
};
diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h
index b9f941dab323..07b64b611960 100644
--- a/include/llvm/Support/MutexGuard.h
+++ b/include/llvm/Support/MutexGuard.h
@@ -26,8 +26,8 @@ namespace llvm {
/// @brief Guard a section of code with a Mutex.
class MutexGuard {
sys::Mutex &M;
- MutexGuard(const MutexGuard &) LLVM_DELETED_FUNCTION;
- void operator=(const MutexGuard &) LLVM_DELETED_FUNCTION;
+ MutexGuard(const MutexGuard &) = delete;
+ void operator=(const MutexGuard &) = delete;
public:
MutexGuard(sys::Mutex &m) : M(m) { M.lock(); }
~MutexGuard() { M.unlock(); }
diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h
index 52f133ccff68..0f097f287286 100644
--- a/include/llvm/Support/OnDiskHashTable.h
+++ b/include/llvm/Support/OnDiskHashTable.h
@@ -75,13 +75,10 @@ template <typename Info> class OnDiskChainedHashTableGenerator {
llvm::SpecificBumpPtrAllocator<Item> BA;
/// \brief A linked list of values in a particular hash bucket.
- class Bucket {
- public:
+ struct Bucket {
offset_type Off;
- Item *Head;
unsigned Length;
-
- Bucket() {}
+ Item *Head;
};
Bucket *Buckets;
diff --git a/include/llvm/Support/Options.h b/include/llvm/Support/Options.h
index 4fd1bff358fd..2742d3907c62 100644
--- a/include/llvm/Support/Options.h
+++ b/include/llvm/Support/Options.h
@@ -61,7 +61,7 @@ char OptionKey<ValT, Base, Mem>::ID = 0;
/// 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.
+/// options are registered in the same place.
class OptionRegistry {
private:
DenseMap<void *, cl::Option *> Options;
diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h
index 914141ad3c4b..96afb60d8e51 100644
--- a/include/llvm/Support/PrettyStackTrace.h
+++ b/include/llvm/Support/PrettyStackTrace.h
@@ -30,8 +30,8 @@ namespace llvm {
/// virtual stack trace. This gets dumped out if the program crashes.
class PrettyStackTraceEntry {
const PrettyStackTraceEntry *NextEntry;
- PrettyStackTraceEntry(const PrettyStackTraceEntry &) LLVM_DELETED_FUNCTION;
- void operator=(const PrettyStackTraceEntry&) LLVM_DELETED_FUNCTION;
+ PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete;
+ void operator=(const PrettyStackTraceEntry&) = delete;
public:
PrettyStackTraceEntry();
virtual ~PrettyStackTraceEntry();
diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h
index 40dc60fa30d6..b89a0f73ec68 100644
--- a/include/llvm/Support/Program.h
+++ b/include/llvm/Support/Program.h
@@ -16,10 +16,11 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/Path.h"
#include <system_error>
namespace llvm {
+class StringRef;
+
namespace sys {
/// This is the OS-specific separator for PATH like environment variables:
diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h
index b80b8557576b..4be931337765 100644
--- a/include/llvm/Support/RWMutex.h
+++ b/include/llvm/Support/RWMutex.h
@@ -70,14 +70,16 @@ namespace llvm
/// @name Platform Dependent Data
/// @{
private:
+#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
void* data_; ///< We don't know what the data will be
+#endif
/// @}
/// @name Do Not Implement
/// @{
private:
- RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION;
- void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION;
+ RWMutexImpl(const RWMutexImpl & original) = delete;
+ void operator=(const RWMutexImpl &) = delete;
/// @}
};
diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h
index 7ada34f075e4..7446558f0c88 100644
--- a/include/llvm/Support/RandomNumberGenerator.h
+++ b/include/llvm/Support/RandomNumberGenerator.h
@@ -48,10 +48,8 @@ private:
std::mt19937_64 Generator;
// Noncopyable.
- RandomNumberGenerator(const RandomNumberGenerator &other)
- LLVM_DELETED_FUNCTION;
- RandomNumberGenerator &
- operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION;
+ RandomNumberGenerator(const RandomNumberGenerator &other) = delete;
+ RandomNumberGenerator &operator=(const RandomNumberGenerator &other) = delete;
friend class Module;
};
diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h
index bf533ca1aa60..31b35ed0cad6 100644
--- a/include/llvm/Support/Regex.h
+++ b/include/llvm/Support/Regex.h
@@ -17,7 +17,6 @@
#ifndef LLVM_SUPPORT_REGEX_H
#define LLVM_SUPPORT_REGEX_H
-#include "llvm/Support/Compiler.h"
#include <string>
struct llvm_regex;
@@ -46,7 +45,7 @@ namespace llvm {
/// Compiles the given regular expression \p Regex.
Regex(StringRef Regex, unsigned Flags = NoFlags);
- Regex(const Regex &) LLVM_DELETED_FUNCTION;
+ Regex(const Regex &) = delete;
Regex &operator=(Regex regex) {
std::swap(preg, regex.preg);
std::swap(error, regex.error);
diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h
index e21269b2f1d5..95c4e96f7f29 100644
--- a/include/llvm/Support/Registry.h
+++ b/include/llvm/Support/Registry.h
@@ -14,6 +14,7 @@
#ifndef LLVM_SUPPORT_REGISTRY_H
#define LLVM_SUPPORT_REGISTRY_H
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <memory>
@@ -41,7 +42,7 @@ namespace llvm {
/// is necessary to define an alternate traits class.
template <typename T>
class RegistryTraits {
- RegistryTraits() LLVM_DELETED_FUNCTION;
+ RegistryTraits() = delete;
public:
typedef SimpleRegistryEntry<T> entry;
@@ -67,7 +68,7 @@ namespace llvm {
class iterator;
private:
- Registry() LLVM_DELETED_FUNCTION;
+ Registry() = delete;
static void Announce(const entry &E) {
for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
@@ -120,6 +121,10 @@ namespace llvm {
static iterator begin() { return iterator(Head); }
static iterator end() { return iterator(nullptr); }
+ static iterator_range<iterator> entries() {
+ return iterator_range<iterator>(begin(), end());
+ }
+
/// Abstract base class for registry listeners, which are informed when new
/// entries are added to the registry. Simply subclass and instantiate:
diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h
index a1c4c80c356f..0a4262b7eec5 100644
--- a/include/llvm/Support/ScaledNumber.h
+++ b/include/llvm/Support/ScaledNumber.h
@@ -514,7 +514,7 @@ public:
: Digits(Digits), Scale(Scale) {}
private:
- ScaledNumber(const std::pair<uint64_t, int16_t> &X)
+ ScaledNumber(const std::pair<DigitsT, int16_t> &X)
: Digits(X.first), Scale(X.second) {}
public:
@@ -670,14 +670,7 @@ public:
return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale);
}
int compareTo(uint64_t N) const {
- ScaledNumber Scaled = get(N);
- int Compare = compare(Scaled);
- if (Width == 64 || Compare != 0)
- return Compare;
-
- // Check for precision loss. We know *this == RoundTrip.
- uint64_t RoundTrip = Scaled.template toInt<uint64_t>();
- return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1;
+ return ScaledNumbers::compare<uint64_t>(Digits, Scale, N, 0);
}
int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); }
@@ -732,11 +725,21 @@ SCALED_NUMBER_BOP(+, += )
SCALED_NUMBER_BOP(-, -= )
SCALED_NUMBER_BOP(*, *= )
SCALED_NUMBER_BOP(/, /= )
-SCALED_NUMBER_BOP(<<, <<= )
-SCALED_NUMBER_BOP(>>, >>= )
#undef SCALED_NUMBER_BOP
template <class DigitsT>
+ScaledNumber<DigitsT> operator<<(const ScaledNumber<DigitsT> &L,
+ int16_t Shift) {
+ return ScaledNumber<DigitsT>(L) <<= Shift;
+}
+
+template <class DigitsT>
+ScaledNumber<DigitsT> operator>>(const ScaledNumber<DigitsT> &L,
+ int16_t Shift) {
+ return ScaledNumber<DigitsT>(L) >>= Shift;
+}
+
+template <class DigitsT>
raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) {
return X.print(OS, 10);
}
diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h
index 6cbc1f6854a6..7e165d7f3a42 100644
--- a/include/llvm/Support/Signals.h
+++ b/include/llvm/Support/Signals.h
@@ -15,10 +15,12 @@
#ifndef LLVM_SUPPORT_SIGNALS_H
#define LLVM_SUPPORT_SIGNALS_H
-#include "llvm/Support/Path.h"
-#include <cstdio>
+#include <string>
namespace llvm {
+class StringRef;
+class raw_ostream;
+
namespace sys {
/// This function runs all the registered interrupt handlers, including the
@@ -37,10 +39,13 @@ namespace sys {
/// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the
/// process, print a stack trace and then exit.
/// @brief Print a stack trace if a fatal signal occurs.
- void PrintStackTraceOnErrorSignal();
+ void PrintStackTraceOnErrorSignal(bool DisableCrashReporting = false);
+
+ /// Disable all system dialog boxes that appear when the process crashes.
+ void DisableSystemDialogsOnCrash();
- /// \brief Print the stack trace using the given \c FILE object.
- void PrintStackTrace(FILE *);
+ /// \brief Print the stack trace using the given \c raw_ostream object.
+ void PrintStackTrace(raw_ostream &OS);
/// AddSignalHandler - Add a function to be called when an abort/kill signal
/// is delivered to the process. The handler can have a cookie passed to it
diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h
index f9e114b67cb4..d492748e7781 100644
--- a/include/llvm/Support/SourceMgr.h
+++ b/include/llvm/Support/SourceMgr.h
@@ -73,8 +73,8 @@ private:
bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); }
- SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION;
- void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION;
+ SourceMgr(const SourceMgr&) = delete;
+ void operator=(const SourceMgr&) = delete;
public:
SourceMgr()
: LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {}
diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h
index 313212e59dd2..ce693c501312 100644
--- a/include/llvm/Support/SpecialCaseList.h
+++ b/include/llvm/Support/SpecialCaseList.h
@@ -49,6 +49,8 @@
#define LLVM_SUPPORT_SPECIALCASELIST_H
#include "llvm/ADT/StringMap.h"
+#include <string>
+#include <vector>
namespace llvm {
class MemoryBuffer;
@@ -57,18 +59,18 @@ class StringRef;
class SpecialCaseList {
public:
- /// Parses the special case list from a file. If Path is empty, returns
- /// an empty special case list. On failure, returns 0 and writes an error
- /// message to string.
- static std::unique_ptr<SpecialCaseList> create(StringRef Path,
- std::string &Error);
+ /// Parses the special case list entries from files. On failure, returns
+ /// 0 and writes an error message to string.
+ static std::unique_ptr<SpecialCaseList>
+ create(const std::vector<std::string> &Paths, std::string &Error);
/// Parses the special case list from a memory buffer. On failure, returns
/// 0 and writes an error message to string.
static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB,
- std::string &Error);
- /// Parses the special case list from a file. On failure, reports a fatal
- /// error.
- static std::unique_ptr<SpecialCaseList> createOrDie(StringRef Path);
+ std::string &Error);
+ /// Parses the special case list entries from files. On failure, reports a
+ /// fatal error.
+ static std::unique_ptr<SpecialCaseList>
+ createOrDie(const std::vector<std::string> &Paths);
~SpecialCaseList();
@@ -81,15 +83,19 @@ public:
StringRef Category = StringRef()) const;
private:
- SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
- SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
+ SpecialCaseList(SpecialCaseList const &) = delete;
+ SpecialCaseList &operator=(SpecialCaseList const &) = delete;
struct Entry;
- StringMap<StringMap<Entry> > Entries;
+ StringMap<StringMap<Entry>> Entries;
+ StringMap<StringMap<std::string>> Regexps;
+ bool IsCompiled;
SpecialCaseList();
/// Parses just-constructed SpecialCaseList entries from a memory buffer.
bool parse(const MemoryBuffer *MB, std::string &Error);
+ /// compile() should be called once, after parsing all the memory buffers.
+ void compile();
};
} // namespace llvm
diff --git a/include/llvm/Support/StreamingMemoryObject.h b/include/llvm/Support/StreamingMemoryObject.h
index 66ed521a411c..932e635cd072 100644
--- a/include/llvm/Support/StreamingMemoryObject.h
+++ b/include/llvm/Support/StreamingMemoryObject.h
@@ -14,7 +14,6 @@
#include "llvm/Support/DataStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryObject.h"
-#include <cassert>
#include <memory>
#include <vector>
@@ -30,11 +29,12 @@ public:
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");
+ // FIXME: 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 (any
+ // that need Blobs) don't stream.
+ report_fatal_error("getPointer in streaming memory objects not allowed");
return nullptr;
}
bool isValidAddress(uint64_t address) const override;
@@ -59,30 +59,31 @@ private:
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
+ // Fetch enough bytes such that Pos can be read (i.e. BytesRead >
+ // Pos). Returns 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) {
+ if (EOFReached)
+ return false;
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;
+ if (bytes == 0) { // reached EOF/ran out of bytes
+ if (ObjectSize == 0)
+ ObjectSize = BytesRead;
EOFReached = true;
- break;
}
}
- return Pos < BytesRead;
+ return !ObjectSize || Pos < ObjectSize;
}
- StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
- void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
+ StreamingMemoryObject(const StreamingMemoryObject&) = delete;
+ void operator=(const StreamingMemoryObject&) = delete;
};
MemoryObject *getNonStreamedMemoryObject(
diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h
index b51974c946e0..2ec0c3b76c11 100644
--- a/include/llvm/Support/StringPool.h
+++ b/include/llvm/Support/StringPool.h
@@ -30,9 +30,7 @@
#define LLVM_SUPPORT_STRINGPOOL_H
#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/Compiler.h"
#include <cassert>
-#include <new>
namespace llvm {
@@ -129,7 +127,7 @@ namespace llvm {
}
inline const char *operator*() const { return begin(); }
- inline LLVM_EXPLICIT operator bool() const { return S != nullptr; }
+ inline explicit operator bool() const { return S != nullptr; }
inline bool operator==(const PooledStringPtr &That) const { return S == That.S; }
inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; }
diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h
index 9c5a3c59122e..7761fa1d7e01 100644
--- a/include/llvm/Support/SwapByteOrder.h
+++ b/include/llvm/Support/SwapByteOrder.h
@@ -94,6 +94,26 @@ inline signed long long getSwappedBytes(signed long long C) {
return SwapByteOrder_64(C);
}
+inline float getSwappedBytes(float C) {
+ union {
+ uint32_t i;
+ float f;
+ } in, out;
+ in.f = C;
+ out.i = SwapByteOrder_32(in.i);
+ return out.f;
+}
+
+inline double getSwappedBytes(double C) {
+ union {
+ uint64_t i;
+ double d;
+ } in, out;
+ in.d = C;
+ out.i = SwapByteOrder_64(in.i);
+ return out.d;
+}
+
template<typename T>
inline void swapByteOrder(T &Value) {
Value = getSwappedBytes(Value);
diff --git a/include/llvm/Support/SystemUtils.h b/include/llvm/Support/SystemUtils.h
index d2d08b234272..2997b1b0c9cf 100644
--- a/include/llvm/Support/SystemUtils.h
+++ b/include/llvm/Support/SystemUtils.h
@@ -15,8 +15,6 @@
#ifndef LLVM_SUPPORT_SYSTEMUTILS_H
#define LLVM_SUPPORT_SYSTEMUTILS_H
-#include <string>
-
namespace llvm {
class raw_ostream;
diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h
new file mode 100644
index 000000000000..ca626f271d51
--- /dev/null
+++ b/include/llvm/Support/TargetParser.h
@@ -0,0 +1,155 @@
+//===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise hardware features such as
+// FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TARGETPARSER_H
+#define LLVM_SUPPORT_TARGETPARSER_H
+
+namespace llvm {
+ class StringRef;
+
+// Target specific information into their own namespaces. These should be
+// generated from TableGen because the information is already there, and there
+// is where new information about targets will be added.
+// FIXME: To TableGen this we need to make some table generated files available
+// even if the back-end is not compiled with LLVM, plus we need to create a new
+// back-end to TableGen to create these clean tables.
+namespace ARM {
+ // FPU names.
+ enum FPUKind {
+ FK_INVALID = 0,
+ FK_VFP,
+ FK_VFPV2,
+ FK_VFPV3,
+ FK_VFPV3_D16,
+ FK_VFPV4,
+ FK_VFPV4_D16,
+ FK_FPV5_D16,
+ FK_FP_ARMV8,
+ FK_NEON,
+ FK_NEON_VFPV4,
+ FK_NEON_FP_ARMV8,
+ FK_CRYPTO_NEON_FP_ARMV8,
+ FK_SOFTVFP,
+ FK_LAST
+ };
+
+ // Arch names.
+ enum ArchKind {
+ AK_INVALID = 0,
+ AK_ARMV2,
+ AK_ARMV2A,
+ AK_ARMV3,
+ AK_ARMV3M,
+ AK_ARMV4,
+ AK_ARMV4T,
+ AK_ARMV5,
+ AK_ARMV5T,
+ AK_ARMV5TE,
+ AK_ARMV6,
+ AK_ARMV6J,
+ AK_ARMV6K,
+ AK_ARMV6T2,
+ AK_ARMV6Z,
+ AK_ARMV6ZK,
+ AK_ARMV6M,
+ AK_ARMV7,
+ AK_ARMV7A,
+ AK_ARMV7R,
+ AK_ARMV7M,
+ AK_ARMV8A,
+ AK_ARMV8_1A,
+ // Non-standard Arch names.
+ AK_IWMMXT,
+ AK_IWMMXT2,
+ AK_XSCALE,
+ AK_ARMV5E,
+ AK_ARMV5TEJ,
+ AK_ARMV6SM,
+ AK_ARMV6HL,
+ AK_ARMV7L,
+ AK_ARMV7HL,
+ AK_ARMV7S,
+ AK_ARMV7EM,
+ AK_LAST
+ };
+
+ // Arch extension modifiers for CPUs.
+ enum ArchExtKind {
+ AEK_INVALID = 0,
+ AEK_CRC,
+ AEK_CRYPTO,
+ AEK_FP,
+ AEK_HWDIV,
+ AEK_MP,
+ AEK_SEC,
+ AEK_VIRT,
+ AEK_LAST
+ };
+
+ // ISA kinds.
+ enum ISAKind {
+ IK_INVALID = 0,
+ IK_ARM,
+ IK_THUMB,
+ IK_AARCH64
+ };
+
+ // Endianness
+ // FIXME: BE8 vs. BE32?
+ enum EndianKind {
+ EK_INVALID = 0,
+ EK_LITTLE,
+ EK_BIG
+ };
+
+ // v6/v7/v8 Profile
+ enum ProfileKind {
+ PK_INVALID = 0,
+ PK_A,
+ PK_R,
+ PK_M
+ };
+} // namespace ARM
+
+// Target Parsers, one per architecture.
+class ARMTargetParser {
+ static StringRef getFPUSynonym(StringRef FPU);
+ static StringRef getArchSynonym(StringRef Arch);
+
+public:
+ static StringRef getCanonicalArchName(StringRef Arch);
+
+ // Information by ID
+ static const char * getFPUName(unsigned FPUKind);
+ static const char * getArchName(unsigned ArchKind);
+ static unsigned getArchDefaultCPUArch(unsigned ArchKind);
+ static const char * getArchDefaultCPUName(unsigned ArchKind);
+ static const char * getArchExtName(unsigned ArchExtKind);
+ static const char * getDefaultCPU(StringRef Arch);
+
+ // Parser
+ static unsigned parseFPU(StringRef FPU);
+ static unsigned parseArch(StringRef Arch);
+ static unsigned parseArchExt(StringRef ArchExt);
+ static unsigned parseCPUArch(StringRef CPU);
+ static unsigned parseArchISA(StringRef Arch);
+ static unsigned parseArchEndian(StringRef Arch);
+ static unsigned parseArchProfile(StringRef Arch);
+ static unsigned parseArchVersion(StringRef Arch);
+
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h
index 8ac4b904bb88..408e908aa04c 100644
--- a/include/llvm/Support/TargetRegistry.h
+++ b/include/llvm/Support/TargetRegistry.h
@@ -22,1133 +22,1161 @@
#include "llvm-c/Disassembler.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/FormattedStream.h"
#include <cassert>
+#include <memory>
#include <string>
namespace llvm {
- class AsmPrinter;
- class Module;
- class MCAssembler;
- class MCAsmBackend;
- class MCAsmInfo;
- class MCAsmParser;
- class MCCodeEmitter;
- class MCCodeGenInfo;
- class MCContext;
- class MCDisassembler;
- class MCInstrAnalysis;
- class MCInstPrinter;
- class MCInstrInfo;
- class MCRegisterInfo;
- class MCStreamer;
- class MCSubtargetInfo;
- class MCSymbolizer;
- class MCRelocationInfo;
- class MCTargetAsmParser;
- class MCTargetOptions;
- class TargetMachine;
- class TargetOptions;
- class raw_ostream;
- class formatted_raw_ostream;
-
- MCStreamer *createNullStreamer(MCContext &Ctx);
- MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
- bool isVerboseAsm, bool useDwarfDirectory,
- MCInstPrinter *InstPrint, MCCodeEmitter *CE,
- MCAsmBackend *TAB, bool ShowInst);
-
- MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx);
-
- MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp,
- void *DisInfo,
- MCContext *Ctx,
- MCRelocationInfo *RelInfo);
-
- /// Target - Wrapper for Target specific information.
- ///
- /// For registration purposes, this is a POD type so that targets can be
- /// registered without the use of static constructors.
- ///
- /// Targets should implement a single global instance of this class (which
- /// will be zero initialized), and pass that instance to the TargetRegistry as
- /// part of their initialization.
- class Target {
- public:
- friend struct TargetRegistry;
-
- typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch);
-
- typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI,
- StringRef TT);
- typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT,
- Reloc::Model RM,
- CodeModel::Model CM,
- CodeGenOpt::Level OL);
- typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void);
- typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo*Info);
- typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT);
- typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT,
- StringRef CPU,
- StringRef Features);
- typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T,
- StringRef TT,
- StringRef CPU,
- StringRef Features,
- const TargetOptions &Options,
- Reloc::Model RM,
+class AsmPrinter;
+class MCAsmBackend;
+class MCAsmInfo;
+class MCAsmParser;
+class MCCodeEmitter;
+class MCCodeGenInfo;
+class MCContext;
+class MCDisassembler;
+class MCInstrAnalysis;
+class MCInstPrinter;
+class MCInstrInfo;
+class MCRegisterInfo;
+class MCStreamer;
+class MCSubtargetInfo;
+class MCSymbolizer;
+class MCRelocationInfo;
+class MCTargetAsmParser;
+class MCTargetOptions;
+class MCTargetStreamer;
+class TargetMachine;
+class TargetOptions;
+class raw_ostream;
+class raw_pwrite_stream;
+class formatted_raw_ostream;
+
+MCStreamer *createNullStreamer(MCContext &Ctx);
+MCStreamer *createAsmStreamer(MCContext &Ctx,
+ std::unique_ptr<formatted_raw_ostream> OS,
+ bool isVerboseAsm, bool useDwarfDirectory,
+ MCInstPrinter *InstPrint, MCCodeEmitter *CE,
+ MCAsmBackend *TAB, bool ShowInst);
+
+/// Takes ownership of \p TAB and \p CE.
+MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB,
+ raw_pwrite_stream &OS, MCCodeEmitter *CE,
+ bool RelaxAll);
+MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
+ raw_pwrite_stream &OS, MCCodeEmitter *CE,
+ bool RelaxAll, bool DWARFMustBeAtTheEnd,
+ bool LabelSections = false);
+
+MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx);
+
+MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp,
+ void *DisInfo, MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo);
+
+/// Target - Wrapper for Target specific information.
+///
+/// For registration purposes, this is a POD type so that targets can be
+/// registered without the use of static constructors.
+///
+/// Targets should implement a single global instance of this class (which
+/// will be zero initialized), and pass that instance to the TargetRegistry as
+/// part of their initialization.
+class Target {
+public:
+ friend struct TargetRegistry;
+
+ typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch);
+
+ typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI,
+ StringRef TT);
+ typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM,
CodeModel::Model CM,
CodeGenOpt::Level OL);
- typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM,
- MCStreamer &Streamer);
- typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T,
- const MCRegisterInfo &MRI,
- StringRef TT,
- StringRef CPU);
- typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(
- MCSubtargetInfo &STI,
- MCAsmParser &P,
- const MCInstrInfo &MII,
- const MCTargetOptions &Options);
- typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T,
- const MCSubtargetInfo &STI,
- MCContext &Ctx);
- typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T,
- unsigned SyntaxVariant,
- const MCAsmInfo &MAI,
- const MCInstrInfo &MII,
- const MCRegisterInfo &MRI,
- const MCSubtargetInfo &STI);
- typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II,
- const MCRegisterInfo &MRI,
+ typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void);
+ typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo *Info);
+ typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT);
+ typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT,
+ StringRef CPU,
+ StringRef Features);
+ typedef TargetMachine *(*TargetMachineCtorTy)(
+ const Target &T, StringRef TT, StringRef CPU, StringRef Features,
+ const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
+ CodeGenOpt::Level OL);
+ // If it weren't for layering issues (this header is in llvm/Support, but
+ // depends on MC?) this should take the Streamer by value rather than rvalue
+ // reference.
+ typedef AsmPrinter *(*AsmPrinterCtorTy)(
+ TargetMachine &TM, std::unique_ptr<MCStreamer> &&Streamer);
+ typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T,
+ const MCRegisterInfo &MRI,
+ StringRef TT, StringRef CPU);
+ typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(
+ MCSubtargetInfo &STI, MCAsmParser &P, const MCInstrInfo &MII,
+ const MCTargetOptions &Options);
+ typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T,
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);
- typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx,
- formatted_raw_ostream &OS,
- bool isVerboseAsm,
- bool useDwarfDirectory,
- MCInstPrinter *InstPrint,
- MCCodeEmitter *CE,
- MCAsmBackend *TAB,
- bool ShowInst);
- typedef MCStreamer *(*NullStreamerCtorTy)(MCContext &Ctx);
- typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT,
- MCContext &Ctx);
- typedef MCSymbolizer *(*MCSymbolizerCtorTy)(StringRef TT,
- LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp,
- void *DisInfo,
- MCContext *Ctx,
- MCRelocationInfo *RelInfo);
-
- private:
- /// Next - The next registered target in the linked list, maintained by the
- /// TargetRegistry.
- Target *Next;
-
- /// The target function for checking if an architecture is supported.
- ArchMatchFnTy ArchMatchFn;
-
- /// Name - The target name.
- const char *Name;
-
- /// ShortDesc - A short description of the target.
- const char *ShortDesc;
-
- /// HasJIT - Whether this target supports the JIT.
- bool HasJIT;
-
- /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if
- /// registered.
- MCAsmInfoCtorFnTy MCAsmInfoCtorFn;
-
- /// MCCodeGenInfoCtorFn - Constructor function for this target's
- /// MCCodeGenInfo, if registered.
- MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn;
-
- /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo,
- /// if registered.
- MCInstrInfoCtorFnTy MCInstrInfoCtorFn;
-
- /// MCInstrAnalysisCtorFn - Constructor function for this target's
- /// MCInstrAnalysis, if registered.
- MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn;
-
- /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo,
- /// if registered.
- MCRegInfoCtorFnTy MCRegInfoCtorFn;
-
- /// MCSubtargetInfoCtorFn - Constructor function for this target's
- /// MCSubtargetInfo, if registered.
- MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn;
-
- /// TargetMachineCtorFn - Construction function for this target's
- /// TargetMachine, if registered.
- TargetMachineCtorTy TargetMachineCtorFn;
-
- /// MCAsmBackendCtorFn - Construction function for this target's
- /// MCAsmBackend, if registered.
- MCAsmBackendCtorTy MCAsmBackendCtorFn;
-
- /// MCAsmParserCtorFn - Construction function for this target's
- /// MCTargetAsmParser, if registered.
- MCAsmParserCtorTy MCAsmParserCtorFn;
-
- /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter,
- /// if registered.
- AsmPrinterCtorTy AsmPrinterCtorFn;
-
- /// MCDisassemblerCtorFn - Construction function for this target's
- /// MCDisassembler, if registered.
- MCDisassemblerCtorTy MCDisassemblerCtorFn;
-
- /// MCInstPrinterCtorFn - Construction function for this target's
- /// MCInstPrinter, if registered.
- MCInstPrinterCtorTy MCInstPrinterCtorFn;
-
- /// MCCodeEmitterCtorFn - Construction function for this target's
- /// CodeEmitter, if registered.
- MCCodeEmitterCtorTy MCCodeEmitterCtorFn;
-
- /// MCObjectStreamerCtorFn - Construction function for this target's
- /// MCObjectStreamer, if registered.
- MCObjectStreamerCtorTy MCObjectStreamerCtorFn;
-
- /// AsmStreamerCtorFn - Construction function for this target's
- /// AsmStreamer, if registered (default = llvm::createAsmStreamer).
- AsmStreamerCtorTy AsmStreamerCtorFn;
-
- /// Construction function for this target's NullStreamer, if registered
- /// (default = llvm::createNullStreamer).
- NullStreamerCtorTy NullStreamerCtorFn;
-
- /// MCRelocationInfoCtorFn - Construction function for this target's
- /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo)
- MCRelocationInfoCtorTy MCRelocationInfoCtorFn;
-
- /// MCSymbolizerCtorFn - Construction function for this target's
- /// MCSymbolizer, if registered (default = llvm::createMCSymbolizer)
- MCSymbolizerCtorTy MCSymbolizerCtorFn;
+ typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Triple &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI);
+ typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx);
+ typedef MCStreamer *(*ELFStreamerCtorTy)(const Triple &T, MCContext &Ctx,
+ MCAsmBackend &TAB,
+ raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter,
+ bool RelaxAll);
+ typedef MCStreamer *(*MachOStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB,
+ raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter,
+ bool RelaxAll,
+ bool DWARFMustBeAtTheEnd);
+ typedef MCStreamer *(*COFFStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB,
+ raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter,
+ bool RelaxAll);
+ typedef MCTargetStreamer *(*NullTargetStreamerCtorTy)(MCStreamer &S);
+ typedef MCTargetStreamer *(*AsmTargetStreamerCtorTy)(
+ MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint,
+ bool IsVerboseAsm);
+ typedef MCTargetStreamer *(*ObjectTargetStreamerCtorTy)(
+ MCStreamer &S, const MCSubtargetInfo &STI);
+ typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT,
+ MCContext &Ctx);
+ typedef MCSymbolizer *(*MCSymbolizerCtorTy)(
+ StringRef TT, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo);
+
+private:
+ /// Next - The next registered target in the linked list, maintained by the
+ /// TargetRegistry.
+ Target *Next;
+
+ /// The target function for checking if an architecture is supported.
+ ArchMatchFnTy ArchMatchFn;
+
+ /// Name - The target name.
+ const char *Name;
+
+ /// ShortDesc - A short description of the target.
+ const char *ShortDesc;
+
+ /// HasJIT - Whether this target supports the JIT.
+ bool HasJIT;
+
+ /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if
+ /// registered.
+ MCAsmInfoCtorFnTy MCAsmInfoCtorFn;
+
+ /// MCCodeGenInfoCtorFn - Constructor function for this target's
+ /// MCCodeGenInfo, if registered.
+ MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn;
+
+ /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo,
+ /// if registered.
+ MCInstrInfoCtorFnTy MCInstrInfoCtorFn;
+
+ /// MCInstrAnalysisCtorFn - Constructor function for this target's
+ /// MCInstrAnalysis, if registered.
+ MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn;
+
+ /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo,
+ /// if registered.
+ MCRegInfoCtorFnTy MCRegInfoCtorFn;
+
+ /// MCSubtargetInfoCtorFn - Constructor function for this target's
+ /// MCSubtargetInfo, if registered.
+ MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn;
+
+ /// TargetMachineCtorFn - Construction function for this target's
+ /// TargetMachine, if registered.
+ TargetMachineCtorTy TargetMachineCtorFn;
+
+ /// MCAsmBackendCtorFn - Construction function for this target's
+ /// MCAsmBackend, if registered.
+ MCAsmBackendCtorTy MCAsmBackendCtorFn;
+
+ /// MCAsmParserCtorFn - Construction function for this target's
+ /// MCTargetAsmParser, if registered.
+ MCAsmParserCtorTy MCAsmParserCtorFn;
+
+ /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter,
+ /// if registered.
+ AsmPrinterCtorTy AsmPrinterCtorFn;
+
+ /// MCDisassemblerCtorFn - Construction function for this target's
+ /// MCDisassembler, if registered.
+ MCDisassemblerCtorTy MCDisassemblerCtorFn;
+
+ /// MCInstPrinterCtorFn - Construction function for this target's
+ /// MCInstPrinter, if registered.
+ MCInstPrinterCtorTy MCInstPrinterCtorFn;
+
+ /// MCCodeEmitterCtorFn - Construction function for this target's
+ /// CodeEmitter, if registered.
+ MCCodeEmitterCtorTy MCCodeEmitterCtorFn;
+
+ // Construction functions for the various object formats, if registered.
+ COFFStreamerCtorTy COFFStreamerCtorFn;
+ MachOStreamerCtorTy MachOStreamerCtorFn;
+ ELFStreamerCtorTy ELFStreamerCtorFn;
+
+ /// Construction function for this target's null TargetStreamer, if
+ /// registered (default = nullptr).
+ NullTargetStreamerCtorTy NullTargetStreamerCtorFn;
+
+ /// Construction function for this target's asm TargetStreamer, if
+ /// registered (default = nullptr).
+ AsmTargetStreamerCtorTy AsmTargetStreamerCtorFn;
+
+ /// Construction function for this target's obj TargetStreamer, if
+ /// registered (default = nullptr).
+ ObjectTargetStreamerCtorTy ObjectTargetStreamerCtorFn;
+
+ /// MCRelocationInfoCtorFn - Construction function for this target's
+ /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo)
+ MCRelocationInfoCtorTy MCRelocationInfoCtorFn;
- public:
- Target()
- : AsmStreamerCtorFn(nullptr), NullStreamerCtorFn(nullptr),
- MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {}
-
- /// @name Target Information
- /// @{
-
- // getNext - Return the next registered target.
- const Target *getNext() const { return Next; }
-
- /// getName - Get the target name.
- const char *getName() const { return Name; }
-
- /// getShortDescription - Get a short description of the target.
- const char *getShortDescription() const { return ShortDesc; }
-
- /// @}
- /// @name Feature Predicates
- /// @{
-
- /// hasJIT - Check if this targets supports the just-in-time compilation.
- bool hasJIT() const { return HasJIT; }
-
- /// hasTargetMachine - Check if this target supports code generation.
- bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; }
-
- /// hasMCAsmBackend - Check if this target supports .o generation.
- bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; }
-
- /// @}
- /// @name Feature Constructors
- /// @{
-
- /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified
- /// target triple.
- ///
- /// \param Triple This argument is used to determine the target machine
- /// feature set; it should always be provided. Generally this should be
- /// either the target triple from the module, or the target triple of the
- /// host if that does not exist.
- MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI,
- StringRef Triple) const {
- if (!MCAsmInfoCtorFn)
- return nullptr;
- return MCAsmInfoCtorFn(MRI, Triple);
- }
+ /// MCSymbolizerCtorFn - Construction function for this target's
+ /// MCSymbolizer, if registered (default = llvm::createMCSymbolizer)
+ MCSymbolizerCtorTy MCSymbolizerCtorFn;
- /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation.
- ///
- MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM,
- CodeModel::Model CM,
- CodeGenOpt::Level OL) const {
- if (!MCCodeGenInfoCtorFn)
- return nullptr;
- return MCCodeGenInfoCtorFn(Triple, RM, CM, OL);
- }
+public:
+ Target()
+ : COFFStreamerCtorFn(nullptr), MachOStreamerCtorFn(nullptr),
+ ELFStreamerCtorFn(nullptr), NullTargetStreamerCtorFn(nullptr),
+ AsmTargetStreamerCtorFn(nullptr), ObjectTargetStreamerCtorFn(nullptr),
+ MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {}
- /// createMCInstrInfo - Create a MCInstrInfo implementation.
- ///
- MCInstrInfo *createMCInstrInfo() const {
- if (!MCInstrInfoCtorFn)
- return nullptr;
- return MCInstrInfoCtorFn();
- }
+ /// @name Target Information
+ /// @{
- /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation.
- ///
- MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const {
- if (!MCInstrAnalysisCtorFn)
- return nullptr;
- return MCInstrAnalysisCtorFn(Info);
- }
+ // getNext - Return the next registered target.
+ const Target *getNext() const { return Next; }
- /// createMCRegInfo - Create a MCRegisterInfo implementation.
- ///
- MCRegisterInfo *createMCRegInfo(StringRef Triple) const {
- if (!MCRegInfoCtorFn)
- return nullptr;
- return MCRegInfoCtorFn(Triple);
- }
+ /// getName - Get the target name.
+ const char *getName() const { return Name; }
- /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
- ///
- /// \param Triple This argument is used to determine the target machine
- /// feature set; it should always be provided. Generally this should be
- /// either the target triple from the module, or the target triple of the
- /// host if that does not exist.
- /// \param CPU This specifies the name of the target CPU.
- /// \param Features This specifies the string representation of the
- /// additional target features.
- MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU,
- StringRef Features) const {
- if (!MCSubtargetInfoCtorFn)
- return nullptr;
- return MCSubtargetInfoCtorFn(Triple, CPU, Features);
- }
+ /// getShortDescription - Get a short description of the target.
+ const char *getShortDescription() const { return ShortDesc; }
- /// createTargetMachine - Create a target specific machine implementation
- /// for the specified \p Triple.
- ///
- /// \param Triple This argument is used to determine the target machine
- /// feature set; it should always be provided. Generally this should be
- /// either the target triple from the module, or the target triple of the
- /// host if that does not exist.
- TargetMachine *createTargetMachine(StringRef Triple, StringRef CPU,
- StringRef Features, const TargetOptions &Options,
- Reloc::Model RM = Reloc::Default,
- CodeModel::Model CM = CodeModel::Default,
- CodeGenOpt::Level OL = CodeGenOpt::Default) const {
- if (!TargetMachineCtorFn)
- return nullptr;
- return TargetMachineCtorFn(*this, Triple, CPU, Features, Options,
- RM, CM, OL);
- }
+ /// @}
+ /// @name Feature Predicates
+ /// @{
- /// createMCAsmBackend - Create a target specific assembly parser.
- ///
- /// \param Triple The target triple string.
- MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI,
- StringRef Triple, StringRef CPU) const {
- if (!MCAsmBackendCtorFn)
- return nullptr;
- return MCAsmBackendCtorFn(*this, MRI, Triple, CPU);
- }
+ /// hasJIT - Check if this targets supports the just-in-time compilation.
+ bool hasJIT() const { return HasJIT; }
- /// createMCAsmParser - Create a target specific assembly parser.
- ///
- /// \param Parser The target independent parser implementation to use for
- /// parsing and lexing.
- MCTargetAsmParser *createMCAsmParser(
- MCSubtargetInfo &STI,
- MCAsmParser &Parser,
- const MCInstrInfo &MII,
- const MCTargetOptions &Options) const {
- if (!MCAsmParserCtorFn)
- return nullptr;
- return MCAsmParserCtorFn(STI, Parser, MII, Options);
- }
+ /// hasTargetMachine - Check if this target supports code generation.
+ bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; }
- /// createAsmPrinter - Create a target specific assembly printer pass. This
- /// takes ownership of the MCStreamer object.
- AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{
- if (!AsmPrinterCtorFn)
- return nullptr;
- return AsmPrinterCtorFn(TM, Streamer);
- }
+ /// hasMCAsmBackend - Check if this target supports .o generation.
+ bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; }
- MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI,
- MCContext &Ctx) const {
- if (!MCDisassemblerCtorFn)
- return nullptr;
- return MCDisassemblerCtorFn(*this, STI, Ctx);
- }
+ /// @}
+ /// @name Feature Constructors
+ /// @{
- MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant,
- const MCAsmInfo &MAI,
- const MCInstrInfo &MII,
- const MCRegisterInfo &MRI,
- const MCSubtargetInfo &STI) const {
- if (!MCInstPrinterCtorFn)
- return nullptr;
- return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, MII, MRI, STI);
- }
+ /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified
+ /// target triple.
+ ///
+ /// \param Triple This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI,
+ StringRef Triple) const {
+ if (!MCAsmInfoCtorFn)
+ return nullptr;
+ return MCAsmInfoCtorFn(MRI, Triple);
+ }
+
+ /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation.
+ ///
+ MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM,
+ CodeModel::Model CM,
+ CodeGenOpt::Level OL) const {
+ if (!MCCodeGenInfoCtorFn)
+ return nullptr;
+ return MCCodeGenInfoCtorFn(Triple, RM, CM, OL);
+ }
+
+ /// createMCInstrInfo - Create a MCInstrInfo implementation.
+ ///
+ MCInstrInfo *createMCInstrInfo() const {
+ if (!MCInstrInfoCtorFn)
+ return nullptr;
+ return MCInstrInfoCtorFn();
+ }
+ /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation.
+ ///
+ MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const {
+ if (!MCInstrAnalysisCtorFn)
+ return nullptr;
+ return MCInstrAnalysisCtorFn(Info);
+ }
- /// createMCCodeEmitter - Create a target specific code emitter.
- MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II,
- const MCRegisterInfo &MRI,
- const MCSubtargetInfo &STI,
+ /// createMCRegInfo - Create a MCRegisterInfo implementation.
+ ///
+ MCRegisterInfo *createMCRegInfo(StringRef Triple) const {
+ if (!MCRegInfoCtorFn)
+ return nullptr;
+ return MCRegInfoCtorFn(Triple);
+ }
+
+ /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
+ ///
+ /// \param Triple This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ /// \param CPU This specifies the name of the target CPU.
+ /// \param Features This specifies the string representation of the
+ /// additional target features.
+ MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU,
+ StringRef Features) const {
+ if (!MCSubtargetInfoCtorFn)
+ return nullptr;
+ return MCSubtargetInfoCtorFn(Triple, CPU, Features);
+ }
+
+ /// createTargetMachine - Create a target specific machine implementation
+ /// for the specified \p Triple.
+ ///
+ /// \param Triple This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ TargetMachine *
+ createTargetMachine(StringRef Triple, StringRef CPU, StringRef Features,
+ const TargetOptions &Options,
+ Reloc::Model RM = Reloc::Default,
+ CodeModel::Model CM = CodeModel::Default,
+ CodeGenOpt::Level OL = CodeGenOpt::Default) const {
+ if (!TargetMachineCtorFn)
+ return nullptr;
+ return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, RM, CM,
+ OL);
+ }
+
+ /// createMCAsmBackend - Create a target specific assembly parser.
+ ///
+ /// \param Triple The target triple string.
+ MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, StringRef Triple,
+ StringRef CPU) const {
+ if (!MCAsmBackendCtorFn)
+ return nullptr;
+ return MCAsmBackendCtorFn(*this, MRI, Triple, CPU);
+ }
+
+ /// createMCAsmParser - Create a target specific assembly parser.
+ ///
+ /// \param Parser The target independent parser implementation to use for
+ /// parsing and lexing.
+ MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI,
+ MCAsmParser &Parser,
+ const MCInstrInfo &MII,
+ const MCTargetOptions &Options) const {
+ if (!MCAsmParserCtorFn)
+ return nullptr;
+ return MCAsmParserCtorFn(STI, Parser, MII, Options);
+ }
+
+ /// createAsmPrinter - Create a target specific assembly printer pass. This
+ /// takes ownership of the MCStreamer object.
+ AsmPrinter *createAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> &&Streamer) const {
+ if (!AsmPrinterCtorFn)
+ return nullptr;
+ return AsmPrinterCtorFn(TM, std::move(Streamer));
+ }
+
+ MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI,
MCContext &Ctx) const {
- if (!MCCodeEmitterCtorFn)
- return nullptr;
- return MCCodeEmitterCtorFn(II, MRI, STI, Ctx);
- }
+ if (!MCDisassemblerCtorFn)
+ return nullptr;
+ return MCDisassemblerCtorFn(*this, STI, Ctx);
+ }
+
+ MCInstPrinter *createMCInstPrinter(const Triple &T, unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI) const {
+ if (!MCInstPrinterCtorFn)
+ return nullptr;
+ return MCInstPrinterCtorFn(T, SyntaxVariant, MAI, MII, MRI);
+ }
+
+ /// createMCCodeEmitter - Create a target specific code emitter.
+ MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx) const {
+ if (!MCCodeEmitterCtorFn)
+ return nullptr;
+ return MCCodeEmitterCtorFn(II, MRI, Ctx);
+ }
+
+ /// Create a target specific MCStreamer.
+ ///
+ /// \param T The target triple.
+ /// \param Ctx The target context.
+ /// \param TAB The target assembler backend object. Takes ownership.
+ /// \param OS The stream object.
+ /// \param Emitter The target independent assembler object.Takes ownership.
+ /// \param RelaxAll Relax all fixups?
+ MCStreamer *createMCObjectStreamer(const Triple &T, MCContext &Ctx,
+ MCAsmBackend &TAB, raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter,
+ const MCSubtargetInfo &STI, bool RelaxAll,
+ bool DWARFMustBeAtTheEnd) const {
+ MCStreamer *S;
+ switch (T.getObjectFormat()) {
+ default:
+ llvm_unreachable("Unknown object format");
+ case Triple::COFF:
+ assert(T.isOSWindows() && "only Windows COFF is supported");
+ S = COFFStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll);
+ break;
+ case Triple::MachO:
+ if (MachOStreamerCtorFn)
+ S = MachOStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll,
+ DWARFMustBeAtTheEnd);
+ else
+ S = createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll,
+ DWARFMustBeAtTheEnd);
+ break;
+ case Triple::ELF:
+ if (ELFStreamerCtorFn)
+ S = ELFStreamerCtorFn(T, Ctx, TAB, OS, Emitter, RelaxAll);
+ else
+ S = createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll);
+ break;
+ }
+ if (ObjectTargetStreamerCtorFn)
+ ObjectTargetStreamerCtorFn(*S, STI);
+ return S;
+ }
+
+ MCStreamer *createAsmStreamer(MCContext &Ctx,
+ std::unique_ptr<formatted_raw_ostream> OS,
+ bool IsVerboseAsm, bool UseDwarfDirectory,
+ MCInstPrinter *InstPrint, MCCodeEmitter *CE,
+ MCAsmBackend *TAB, bool ShowInst) const {
+ formatted_raw_ostream &OSRef = *OS;
+ MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IsVerboseAsm,
+ UseDwarfDirectory, InstPrint, CE,
+ TAB, ShowInst);
+ createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm);
+ return S;
+ }
+
+ MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS,
+ MCInstPrinter *InstPrint,
+ bool IsVerboseAsm) const {
+ if (AsmTargetStreamerCtorFn)
+ return AsmTargetStreamerCtorFn(S, OS, InstPrint, IsVerboseAsm);
+ return nullptr;
+ }
+
+ MCStreamer *createNullStreamer(MCContext &Ctx) const {
+ MCStreamer *S = llvm::createNullStreamer(Ctx);
+ createNullTargetStreamer(*S);
+ return S;
+ }
+
+ MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) const {
+ if (NullTargetStreamerCtorFn)
+ return NullTargetStreamerCtorFn(S);
+ return nullptr;
+ }
+
+ /// createMCRelocationInfo - Create a target specific MCRelocationInfo.
+ ///
+ /// \param TT The target triple.
+ /// \param Ctx The target context.
+ MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx) const {
+ MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn
+ ? MCRelocationInfoCtorFn
+ : llvm::createMCRelocationInfo;
+ return Fn(TT, Ctx);
+ }
+
+ /// createMCSymbolizer - Create a target specific MCSymbolizer.
+ ///
+ /// \param TT The target triple.
+ /// \param GetOpInfo The function to get the symbolic information for
+ /// operands.
+ /// \param SymbolLookUp The function to lookup a symbol name.
+ /// \param DisInfo The pointer to the block of symbolic information for above
+ /// call
+ /// back.
+ /// \param Ctx The target context.
+ /// \param RelInfo The relocation information for this target. Takes
+ /// ownership.
+ MCSymbolizer *
+ createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo,
+ MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo) const {
+ MCSymbolizerCtorTy Fn =
+ MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer;
+ return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, std::move(RelInfo));
+ }
+
+ /// @}
+};
+
+/// TargetRegistry - Generic interface to target specific features.
+struct TargetRegistry {
+ // FIXME: Make this a namespace, probably just move all the Register*
+ // functions into Target (currently they all just set members on the Target
+ // anyway, and Target friends this class so those functions can...
+ // function).
+ TargetRegistry() = delete;
+
+ class iterator
+ : public std::iterator<std::forward_iterator_tag, Target, ptrdiff_t> {
+ const Target *Current;
+ explicit iterator(Target *T) : Current(T) {}
+ friend struct TargetRegistry;
- /// createMCObjectStreamer - Create a target specific MCStreamer.
- ///
- /// \param TT The target triple.
- /// \param Ctx The target context.
- /// \param TAB The target assembler backend object. Takes ownership.
- /// \param _OS The stream object.
- /// \param _Emitter The target independent assembler object.Takes ownership.
- /// \param RelaxAll Relax all fixups?
- MCStreamer *createMCObjectStreamer(StringRef TT, MCContext &Ctx,
- MCAsmBackend &TAB, raw_ostream &_OS,
- MCCodeEmitter *_Emitter,
- const MCSubtargetInfo &STI,
- bool RelaxAll) const {
- if (!MCObjectStreamerCtorFn)
- return nullptr;
- return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, STI,
- RelaxAll);
- }
+ public:
+ iterator() : Current(nullptr) {}
- /// createAsmStreamer - Create a target specific MCStreamer.
- MCStreamer *createAsmStreamer(MCContext &Ctx,
- formatted_raw_ostream &OS,
- bool isVerboseAsm,
- bool useDwarfDirectory,
- MCInstPrinter *InstPrint,
- MCCodeEmitter *CE,
- MCAsmBackend *TAB,
- bool ShowInst) const {
- if (AsmStreamerCtorFn)
- return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useDwarfDirectory,
- InstPrint, CE, TAB, ShowInst);
- return llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useDwarfDirectory,
- InstPrint, CE, TAB, ShowInst);
- }
+ bool operator==(const iterator &x) const { return Current == x.Current; }
+ bool operator!=(const iterator &x) const { return !operator==(x); }
- MCStreamer *createNullStreamer(MCContext &Ctx) const {
- if (NullStreamerCtorFn)
- return NullStreamerCtorFn(Ctx);
- return llvm::createNullStreamer(Ctx);
+ // Iterator traversal: forward iteration only
+ iterator &operator++() { // Preincrement
+ assert(Current && "Cannot increment end iterator!");
+ Current = Current->getNext();
+ return *this;
}
-
- /// createMCRelocationInfo - Create a target specific MCRelocationInfo.
- ///
- /// \param TT The target triple.
- /// \param Ctx The target context.
- MCRelocationInfo *
- createMCRelocationInfo(StringRef TT, MCContext &Ctx) const {
- MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn
- ? MCRelocationInfoCtorFn
- : llvm::createMCRelocationInfo;
- return Fn(TT, Ctx);
+ iterator operator++(int) { // Postincrement
+ iterator tmp = *this;
+ ++*this;
+ return tmp;
}
- /// createMCSymbolizer - Create a target specific MCSymbolizer.
- ///
- /// \param TT The target triple.
- /// \param GetOpInfo The function to get the symbolic information for operands.
- /// \param SymbolLookUp The function to lookup a symbol name.
- /// \param DisInfo The pointer to the block of symbolic information for above call
- /// back.
- /// \param Ctx The target context.
- /// \param RelInfo The relocation information for this target. Takes ownership.
- MCSymbolizer *
- createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp,
- void *DisInfo,
- MCContext *Ctx, MCRelocationInfo *RelInfo) const {
- MCSymbolizerCtorTy Fn =
- MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer;
- return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo);
+ const Target &operator*() const {
+ assert(Current && "Cannot dereference end iterator!");
+ return *Current;
}
- /// @}
+ const Target *operator->() const { return &operator*(); }
};
- /// TargetRegistry - Generic interface to target specific features.
- struct TargetRegistry {
- class iterator {
- const Target *Current;
- explicit iterator(Target *T) : Current(T) {}
- friend struct TargetRegistry;
- public:
- iterator() : Current(nullptr) {}
-
- bool operator==(const iterator &x) const {
- return Current == x.Current;
- }
- bool operator!=(const iterator &x) const {
- return !operator==(x);
- }
-
- // Iterator traversal: forward iteration only
- iterator &operator++() { // Preincrement
- assert(Current && "Cannot increment end iterator!");
- Current = Current->getNext();
- return *this;
- }
- iterator operator++(int) { // Postincrement
- iterator tmp = *this;
- ++*this;
- return tmp;
- }
-
- const Target &operator*() const {
- assert(Current && "Cannot dereference end iterator!");
- return *Current;
- }
-
- const Target *operator->() const {
- return &operator*();
- }
- };
-
- /// printRegisteredTargetsForVersion - Print the registered targets
- /// appropriately for inclusion in a tool's version output.
- static void printRegisteredTargetsForVersion();
-
- /// @name Registry Access
- /// @{
-
- static iterator begin();
-
- static iterator end() { return iterator(); }
-
- /// lookupTarget - Lookup a target based on a target triple.
- ///
- /// \param Triple - The triple to use for finding a target.
- /// \param Error - On failure, an error string describing why no target was
- /// found.
- static const Target *lookupTarget(const std::string &Triple,
- std::string &Error);
-
- /// lookupTarget - Lookup a target based on an architecture name
- /// and a target triple. If the architecture name is non-empty,
- /// then the lookup is done by architecture. Otherwise, the target
- /// triple is used.
- ///
- /// \param ArchName - The architecture to use for finding a target.
- /// \param TheTriple - The triple to use for finding a target. The
- /// triple is updated with canonical architecture name if a lookup
- /// by architecture is done.
- /// \param Error - On failure, an error string describing why no target was
- /// found.
- static const Target *lookupTarget(const std::string &ArchName,
- Triple &TheTriple,
- std::string &Error);
-
- /// @}
- /// @name Target Registration
- /// @{
-
- /// RegisterTarget - Register the given target. Attempts to register a
- /// target which has already been registered will be ignored.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Name - The target name. This should be a static string.
- /// @param ShortDesc - A short target description. This should be a static
- /// string.
- /// @param ArchMatchFn - The arch match checking function for this target.
- /// @param HasJIT - Whether the target supports JIT code
- /// generation.
- static void RegisterTarget(Target &T,
- const char *Name,
- const char *ShortDesc,
- Target::ArchMatchFnTy ArchMatchFn,
- bool HasJIT = false);
-
- /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCAsmInfo for the target.
- static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
- T.MCAsmInfoCtorFn = Fn;
- }
-
- /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCCodeGenInfo for the target.
- static void RegisterMCCodeGenInfo(Target &T,
- Target::MCCodeGenInfoCtorFnTy Fn) {
- T.MCCodeGenInfoCtorFn = Fn;
- }
-
- /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCInstrInfo for the target.
- static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
- T.MCInstrInfoCtorFn = Fn;
- }
-
- /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for
- /// the given target.
- static void RegisterMCInstrAnalysis(Target &T,
- Target::MCInstrAnalysisCtorFnTy Fn) {
- T.MCInstrAnalysisCtorFn = Fn;
- }
-
- /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCRegisterInfo for the target.
- static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) {
- T.MCRegInfoCtorFn = Fn;
- }
-
- /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for
- /// the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCSubtargetInfo for the target.
- static void RegisterMCSubtargetInfo(Target &T,
- Target::MCSubtargetInfoCtorFnTy Fn) {
- T.MCSubtargetInfoCtorFn = Fn;
- }
-
- /// RegisterTargetMachine - Register a TargetMachine implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a TargetMachine for the target.
- static void RegisterTargetMachine(Target &T,
- Target::TargetMachineCtorTy Fn) {
- T.TargetMachineCtorFn = Fn;
- }
-
- /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an AsmBackend for the target.
- static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) {
- T.MCAsmBackendCtorFn = Fn;
- }
-
- /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for
- /// the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCTargetAsmParser for the target.
- static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) {
- T.MCAsmParserCtorFn = Fn;
- }
-
- /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given
- /// target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an AsmPrinter for the target.
- static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) {
- T.AsmPrinterCtorFn = Fn;
- }
-
- /// RegisterMCDisassembler - Register a MCDisassembler implementation for
- /// the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCDisassembler for the target.
- static void RegisterMCDisassembler(Target &T,
- Target::MCDisassemblerCtorTy Fn) {
- T.MCDisassemblerCtorFn = Fn;
- }
+ /// printRegisteredTargetsForVersion - Print the registered targets
+ /// appropriately for inclusion in a tool's version output.
+ static void printRegisteredTargetsForVersion();
- /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCInstPrinter for the target.
- static void RegisterMCInstPrinter(Target &T,
- Target::MCInstPrinterCtorTy Fn) {
- T.MCInstPrinterCtorFn = Fn;
- }
+ /// @name Registry Access
+ /// @{
- /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCCodeEmitter for the target.
- static void RegisterMCCodeEmitter(Target &T,
- Target::MCCodeEmitterCtorTy Fn) {
- T.MCCodeEmitterCtorFn = Fn;
- }
+ static iterator_range<iterator> targets();
- /// RegisterMCObjectStreamer - Register a object code MCStreamer
- /// implementation for the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCStreamer for the target.
- static void RegisterMCObjectStreamer(Target &T,
- Target::MCObjectStreamerCtorTy Fn) {
- T.MCObjectStreamerCtorFn = Fn;
- }
-
- /// RegisterAsmStreamer - Register an assembly MCStreamer implementation
- /// for the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCStreamer for the target.
- static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) {
- T.AsmStreamerCtorFn = Fn;
- }
-
- static void RegisterNullStreamer(Target &T, Target::NullStreamerCtorTy Fn) {
- T.NullStreamerCtorFn = Fn;
- }
-
- /// RegisterMCRelocationInfo - Register an MCRelocationInfo
- /// implementation for the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCRelocationInfo for the target.
- static void RegisterMCRelocationInfo(Target &T,
- Target::MCRelocationInfoCtorTy Fn) {
- T.MCRelocationInfoCtorFn = Fn;
- }
-
- /// RegisterMCSymbolizer - Register an MCSymbolizer
- /// implementation for the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCSymbolizer for the target.
- static void RegisterMCSymbolizer(Target &T,
- Target::MCSymbolizerCtorTy Fn) {
- T.MCSymbolizerCtorFn = Fn;
- }
-
- /// @}
- };
-
-
- //===--------------------------------------------------------------------===//
-
- /// RegisterTarget - Helper template for registering a target, for use in the
- /// target's initialization function. Usage:
+ /// lookupTarget - Lookup a target based on a target triple.
///
+ /// \param Triple - The triple to use for finding a target.
+ /// \param Error - On failure, an error string describing why no target was
+ /// found.
+ static const Target *lookupTarget(const std::string &Triple,
+ std::string &Error);
+
+ /// lookupTarget - Lookup a target based on an architecture name
+ /// and a target triple. If the architecture name is non-empty,
+ /// then the lookup is done by architecture. Otherwise, the target
+ /// triple is used.
///
- /// Target TheFooTarget; // The global target instance.
+ /// \param ArchName - The architecture to use for finding a target.
+ /// \param TheTriple - The triple to use for finding a target. The
+ /// triple is updated with canonical architecture name if a lookup
+ /// by architecture is done.
+ /// \param Error - On failure, an error string describing why no target was
+ /// found.
+ static const Target *lookupTarget(const std::string &ArchName,
+ Triple &TheTriple, std::string &Error);
+
+ /// @}
+ /// @name Target Registration
+ /// @{
+
+ /// RegisterTarget - Register the given target. Attempts to register a
+ /// target which has already been registered will be ignored.
///
- /// extern "C" void LLVMInitializeFooTargetInfo() {
- /// RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description");
- /// }
- template<Triple::ArchType TargetArchType = Triple::UnknownArch,
- bool HasJIT = false>
- struct RegisterTarget {
- RegisterTarget(Target &T, const char *Name, const char *Desc) {
- TargetRegistry::RegisterTarget(T, Name, Desc, &getArchMatch, HasJIT);
- }
-
- static bool getArchMatch(Triple::ArchType Arch) {
- return Arch == TargetArchType;
- }
- };
-
- /// RegisterMCAsmInfo - Helper template for registering a target assembly info
- /// implementation. This invokes the static "Create" method on the class to
- /// actually do the construction. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget);
- /// }
- template<class MCAsmInfoImpl>
- struct RegisterMCAsmInfo {
- RegisterMCAsmInfo(Target &T) {
- TargetRegistry::RegisterMCAsmInfo(T, &Allocator);
- }
- private:
- static MCAsmInfo *Allocator(const MCRegisterInfo &/*MRI*/, StringRef TT) {
- return new MCAsmInfoImpl(TT);
- }
-
- };
-
- /// RegisterMCAsmInfoFn - Helper template for registering a target assembly info
- /// implementation. This invokes the specified function to do the
- /// construction. Usage:
+ /// @param T - The target being registered.
+ /// @param Name - The target name. This should be a static string.
+ /// @param ShortDesc - A short target description. This should be a static
+ /// string.
+ /// @param ArchMatchFn - The arch match checking function for this target.
+ /// @param HasJIT - Whether the target supports JIT code
+ /// generation.
+ static void RegisterTarget(Target &T, const char *Name, const char *ShortDesc,
+ Target::ArchMatchFnTy ArchMatchFn,
+ bool HasJIT = false);
+
+ /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the
+ /// given target.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCAsmInfoFn {
- RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCAsmInfo(T, Fn);
- }
- };
-
- /// RegisterMCCodeGenInfo - Helper template for registering a target codegen info
- /// implementation. This invokes the static "Create" method on the class
- /// to actually do the construction. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget);
- /// }
- template<class MCCodeGenInfoImpl>
- struct RegisterMCCodeGenInfo {
- RegisterMCCodeGenInfo(Target &T) {
- TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator);
- }
- private:
- static MCCodeGenInfo *Allocator(StringRef /*TT*/, Reloc::Model /*RM*/,
- CodeModel::Model /*CM*/,
- CodeGenOpt::Level /*OL*/) {
- return new MCCodeGenInfoImpl();
- }
- };
-
- /// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen
- /// info implementation. This invokes the specified function to do the
- /// construction. Usage:
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCAsmInfo for the target.
+ static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
+ T.MCAsmInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the
+ /// given target.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCCodeGenInfoFn {
- RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCCodeGenInfo(T, Fn);
- }
- };
-
- /// RegisterMCInstrInfo - Helper template for registering a target instruction
- /// info implementation. This invokes the static "Create" method on the class
- /// to actually do the construction. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget);
- /// }
- template<class MCInstrInfoImpl>
- struct RegisterMCInstrInfo {
- RegisterMCInstrInfo(Target &T) {
- TargetRegistry::RegisterMCInstrInfo(T, &Allocator);
- }
- private:
- static MCInstrInfo *Allocator() {
- return new MCInstrInfoImpl();
- }
- };
-
- /// RegisterMCInstrInfoFn - Helper template for registering a target
- /// instruction info implementation. This invokes the specified function to
- /// do the construction. Usage:
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCCodeGenInfo for the target.
+ static void RegisterMCCodeGenInfo(Target &T,
+ Target::MCCodeGenInfoCtorFnTy Fn) {
+ T.MCCodeGenInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the
+ /// given target.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCInstrInfoFn {
- RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCInstrInfo(T, Fn);
- }
- };
-
- /// RegisterMCInstrAnalysis - Helper template for registering a target
- /// instruction analyzer implementation. This invokes the static "Create"
- /// method on the class to actually do the construction. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCInstrAnalysis<FooMCInstrAnalysis> X(TheFooTarget);
- /// }
- template<class MCInstrAnalysisImpl>
- struct RegisterMCInstrAnalysis {
- RegisterMCInstrAnalysis(Target &T) {
- TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator);
- }
- private:
- static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) {
- return new MCInstrAnalysisImpl(Info);
- }
- };
-
- /// RegisterMCInstrAnalysisFn - Helper template for registering a target
- /// instruction analyzer implementation. This invokes the specified function
- /// to do the construction. Usage:
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCInstrInfo for the target.
+ static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
+ T.MCInstrInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for
+ /// the given target.
+ static void RegisterMCInstrAnalysis(Target &T,
+ Target::MCInstrAnalysisCtorFnTy Fn) {
+ T.MCInstrAnalysisCtorFn = Fn;
+ }
+
+ /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the
+ /// given target.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCInstrAnalysisFn {
- RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) {
- TargetRegistry::RegisterMCInstrAnalysis(T, Fn);
- }
- };
-
- /// RegisterMCRegInfo - Helper template for registering a target register info
- /// implementation. This invokes the static "Create" method on the class to
- /// actually do the construction. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget);
- /// }
- template<class MCRegisterInfoImpl>
- struct RegisterMCRegInfo {
- RegisterMCRegInfo(Target &T) {
- TargetRegistry::RegisterMCRegInfo(T, &Allocator);
- }
- private:
- static MCRegisterInfo *Allocator(StringRef /*TT*/) {
- return new MCRegisterInfoImpl();
- }
- };
-
- /// RegisterMCRegInfoFn - Helper template for registering a target register
- /// info implementation. This invokes the specified function to do the
- /// construction. Usage:
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCRegisterInfo for the target.
+ static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) {
+ T.MCRegInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for
+ /// the given target.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCRegInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCRegInfoFn {
- RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCRegInfo(T, Fn);
- }
- };
-
- /// RegisterMCSubtargetInfo - Helper template for registering a target
- /// subtarget info implementation. This invokes the static "Create" method
- /// on the class to actually do the construction. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget);
- /// }
- template<class MCSubtargetInfoImpl>
- struct RegisterMCSubtargetInfo {
- RegisterMCSubtargetInfo(Target &T) {
- TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator);
- }
- private:
- static MCSubtargetInfo *Allocator(StringRef /*TT*/, StringRef /*CPU*/,
- StringRef /*FS*/) {
- return new MCSubtargetInfoImpl();
- }
- };
-
- /// RegisterMCSubtargetInfoFn - Helper template for registering a target
- /// subtarget info implementation. This invokes the specified function to
- /// do the construction. Usage:
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCSubtargetInfo for the target.
+ static void RegisterMCSubtargetInfo(Target &T,
+ Target::MCSubtargetInfoCtorFnTy Fn) {
+ T.MCSubtargetInfoCtorFn = Fn;
+ }
+
+ /// RegisterTargetMachine - Register a TargetMachine implementation for the
+ /// given target.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCSubtargetInfoFn {
- RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCSubtargetInfo(T, Fn);
- }
- };
-
- /// RegisterTargetMachine - Helper template for registering a target machine
- /// implementation, for use in the target machine initialization
- /// function. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget);
- /// }
- template<class TargetMachineImpl>
- struct RegisterTargetMachine {
- RegisterTargetMachine(Target &T) {
- TargetRegistry::RegisterTargetMachine(T, &Allocator);
- }
-
- private:
- static TargetMachine *Allocator(const Target &T, StringRef TT,
- StringRef CPU, StringRef FS,
- const TargetOptions &Options,
- Reloc::Model RM,
- CodeModel::Model CM,
- CodeGenOpt::Level OL) {
- return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL);
- }
- };
-
- /// RegisterMCAsmBackend - Helper template for registering a target specific
- /// assembler backend. Usage:
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a TargetMachine for the target.
+ static void RegisterTargetMachine(Target &T, Target::TargetMachineCtorTy Fn) {
+ T.TargetMachineCtorFn = Fn;
+ }
+
+ /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the
+ /// given target.
///
- /// extern "C" void LLVMInitializeFooMCAsmBackend() {
- /// extern Target TheFooTarget;
- /// RegisterMCAsmBackend<FooAsmLexer> X(TheFooTarget);
- /// }
- template<class MCAsmBackendImpl>
- struct RegisterMCAsmBackend {
- RegisterMCAsmBackend(Target &T) {
- TargetRegistry::RegisterMCAsmBackend(T, &Allocator);
- }
-
- private:
- static MCAsmBackend *Allocator(const Target &T,
- const MCRegisterInfo &MRI,
- StringRef Triple, StringRef CPU) {
- return new MCAsmBackendImpl(T, MRI, Triple, CPU);
- }
- };
-
- /// RegisterMCAsmParser - Helper template for registering a target specific
- /// assembly parser, for use in the target machine initialization
- /// function. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooMCAsmParser() {
- /// extern Target TheFooTarget;
- /// RegisterMCAsmParser<FooAsmParser> X(TheFooTarget);
- /// }
- template<class MCAsmParserImpl>
- struct RegisterMCAsmParser {
- RegisterMCAsmParser(Target &T) {
- TargetRegistry::RegisterMCAsmParser(T, &Allocator);
- }
-
- private:
- static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P,
- const MCInstrInfo &MII,
- const MCTargetOptions &Options) {
- return new MCAsmParserImpl(STI, P, MII, Options);
- }
- };
-
- /// RegisterAsmPrinter - Helper template for registering a target specific
- /// assembly printer, for use in the target machine initialization
- /// function. Usage:
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an AsmBackend for the target.
+ static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) {
+ T.MCAsmBackendCtorFn = Fn;
+ }
+
+ /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for
+ /// the given target.
///
- /// extern "C" void LLVMInitializeFooAsmPrinter() {
- /// extern Target TheFooTarget;
- /// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget);
- /// }
- template<class AsmPrinterImpl>
- struct RegisterAsmPrinter {
- RegisterAsmPrinter(Target &T) {
- TargetRegistry::RegisterAsmPrinter(T, &Allocator);
- }
-
- private:
- static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) {
- return new AsmPrinterImpl(TM, Streamer);
- }
- };
-
- /// RegisterMCCodeEmitter - Helper template for registering a target specific
- /// machine code emitter, for use in the target initialization
- /// function. Usage:
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
///
- /// extern "C" void LLVMInitializeFooMCCodeEmitter() {
- /// extern Target TheFooTarget;
- /// RegisterMCCodeEmitter<FooCodeEmitter> X(TheFooTarget);
- /// }
- template<class MCCodeEmitterImpl>
- struct RegisterMCCodeEmitter {
- RegisterMCCodeEmitter(Target &T) {
- TargetRegistry::RegisterMCCodeEmitter(T, &Allocator);
- }
-
- private:
- static MCCodeEmitter *Allocator(const MCInstrInfo &/*II*/,
- const MCRegisterInfo &/*MRI*/,
- const MCSubtargetInfo &/*STI*/,
- MCContext &/*Ctx*/) {
- return new MCCodeEmitterImpl();
- }
- };
-
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCTargetAsmParser for the target.
+ static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) {
+ T.MCAsmParserCtorFn = Fn;
+ }
+
+ /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given
+ /// target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an AsmPrinter for the target.
+ static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) {
+ T.AsmPrinterCtorFn = Fn;
+ }
+
+ /// RegisterMCDisassembler - Register a MCDisassembler implementation for
+ /// the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCDisassembler for the target.
+ static void RegisterMCDisassembler(Target &T,
+ Target::MCDisassemblerCtorTy Fn) {
+ T.MCDisassemblerCtorFn = Fn;
+ }
+
+ /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCInstPrinter for the target.
+ static void RegisterMCInstPrinter(Target &T, Target::MCInstPrinterCtorTy Fn) {
+ T.MCInstPrinterCtorFn = Fn;
+ }
+
+ /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCCodeEmitter for the target.
+ static void RegisterMCCodeEmitter(Target &T, Target::MCCodeEmitterCtorTy Fn) {
+ T.MCCodeEmitterCtorFn = Fn;
+ }
+
+ static void RegisterCOFFStreamer(Target &T, Target::COFFStreamerCtorTy Fn) {
+ T.COFFStreamerCtorFn = Fn;
+ }
+
+ static void RegisterMachOStreamer(Target &T, Target::MachOStreamerCtorTy Fn) {
+ T.MachOStreamerCtorFn = Fn;
+ }
+
+ static void RegisterELFStreamer(Target &T, Target::ELFStreamerCtorTy Fn) {
+ T.ELFStreamerCtorFn = Fn;
+ }
+
+ static void RegisterNullTargetStreamer(Target &T,
+ Target::NullTargetStreamerCtorTy Fn) {
+ T.NullTargetStreamerCtorFn = Fn;
+ }
+
+ static void RegisterAsmTargetStreamer(Target &T,
+ Target::AsmTargetStreamerCtorTy Fn) {
+ T.AsmTargetStreamerCtorFn = Fn;
+ }
+
+ static void
+ RegisterObjectTargetStreamer(Target &T,
+ Target::ObjectTargetStreamerCtorTy Fn) {
+ T.ObjectTargetStreamerCtorFn = Fn;
+ }
+
+ /// RegisterMCRelocationInfo - Register an MCRelocationInfo
+ /// implementation for the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCRelocationInfo for the target.
+ static void RegisterMCRelocationInfo(Target &T,
+ Target::MCRelocationInfoCtorTy Fn) {
+ T.MCRelocationInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCSymbolizer - Register an MCSymbolizer
+ /// implementation for the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCSymbolizer for the target.
+ static void RegisterMCSymbolizer(Target &T, Target::MCSymbolizerCtorTy Fn) {
+ T.MCSymbolizerCtorFn = Fn;
+ }
+
+ /// @}
+};
+
+//===--------------------------------------------------------------------===//
+
+/// RegisterTarget - Helper template for registering a target, for use in the
+/// target's initialization function. Usage:
+///
+///
+/// Target TheFooTarget; // The global target instance.
+///
+/// extern "C" void LLVMInitializeFooTargetInfo() {
+/// RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description");
+/// }
+template <Triple::ArchType TargetArchType = Triple::UnknownArch,
+ bool HasJIT = false>
+struct RegisterTarget {
+ RegisterTarget(Target &T, const char *Name, const char *Desc) {
+ TargetRegistry::RegisterTarget(T, Name, Desc, &getArchMatch, HasJIT);
+ }
+
+ static bool getArchMatch(Triple::ArchType Arch) {
+ return Arch == TargetArchType;
+ }
+};
+
+/// RegisterMCAsmInfo - Helper template for registering a target assembly info
+/// implementation. This invokes the static "Create" method on the class to
+/// actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget);
+/// }
+template <class MCAsmInfoImpl> struct RegisterMCAsmInfo {
+ RegisterMCAsmInfo(Target &T) {
+ TargetRegistry::RegisterMCAsmInfo(T, &Allocator);
+ }
+
+private:
+ static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/, StringRef TT) {
+ return new MCAsmInfoImpl(TT);
+ }
+};
+
+/// RegisterMCAsmInfoFn - Helper template for registering a target assembly info
+/// implementation. This invokes the specified function to do the
+/// construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCAsmInfoFn {
+ RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCAsmInfo(T, Fn);
+ }
+};
+
+/// RegisterMCCodeGenInfo - Helper template for registering a target codegen
+/// info
+/// implementation. This invokes the static "Create" method on the class
+/// to actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget);
+/// }
+template <class MCCodeGenInfoImpl> struct RegisterMCCodeGenInfo {
+ RegisterMCCodeGenInfo(Target &T) {
+ TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator);
+ }
+
+private:
+ static MCCodeGenInfo *Allocator(StringRef /*TT*/, Reloc::Model /*RM*/,
+ CodeModel::Model /*CM*/,
+ CodeGenOpt::Level /*OL*/) {
+ return new MCCodeGenInfoImpl();
+ }
+};
+
+/// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen
+/// info implementation. This invokes the specified function to do the
+/// construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCCodeGenInfoFn {
+ RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCCodeGenInfo(T, Fn);
+ }
+};
+
+/// RegisterMCInstrInfo - Helper template for registering a target instruction
+/// info implementation. This invokes the static "Create" method on the class
+/// to actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget);
+/// }
+template <class MCInstrInfoImpl> struct RegisterMCInstrInfo {
+ RegisterMCInstrInfo(Target &T) {
+ TargetRegistry::RegisterMCInstrInfo(T, &Allocator);
+ }
+
+private:
+ static MCInstrInfo *Allocator() { return new MCInstrInfoImpl(); }
+};
+
+/// RegisterMCInstrInfoFn - Helper template for registering a target
+/// instruction info implementation. This invokes the specified function to
+/// do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCInstrInfoFn {
+ RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCInstrInfo(T, Fn);
+ }
+};
+
+/// RegisterMCInstrAnalysis - Helper template for registering a target
+/// instruction analyzer implementation. This invokes the static "Create"
+/// method on the class to actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCInstrAnalysis<FooMCInstrAnalysis> X(TheFooTarget);
+/// }
+template <class MCInstrAnalysisImpl> struct RegisterMCInstrAnalysis {
+ RegisterMCInstrAnalysis(Target &T) {
+ TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator);
+ }
+
+private:
+ static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) {
+ return new MCInstrAnalysisImpl(Info);
+ }
+};
+
+/// RegisterMCInstrAnalysisFn - Helper template for registering a target
+/// instruction analyzer implementation. This invokes the specified function
+/// to do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCInstrAnalysisFn {
+ RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) {
+ TargetRegistry::RegisterMCInstrAnalysis(T, Fn);
+ }
+};
+
+/// RegisterMCRegInfo - Helper template for registering a target register info
+/// implementation. This invokes the static "Create" method on the class to
+/// actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget);
+/// }
+template <class MCRegisterInfoImpl> struct RegisterMCRegInfo {
+ RegisterMCRegInfo(Target &T) {
+ TargetRegistry::RegisterMCRegInfo(T, &Allocator);
+ }
+
+private:
+ static MCRegisterInfo *Allocator(StringRef /*TT*/) {
+ return new MCRegisterInfoImpl();
+ }
+};
+
+/// RegisterMCRegInfoFn - Helper template for registering a target register
+/// info implementation. This invokes the specified function to do the
+/// construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCRegInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCRegInfoFn {
+ RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCRegInfo(T, Fn);
+ }
+};
+
+/// RegisterMCSubtargetInfo - Helper template for registering a target
+/// subtarget info implementation. This invokes the static "Create" method
+/// on the class to actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget);
+/// }
+template <class MCSubtargetInfoImpl> struct RegisterMCSubtargetInfo {
+ RegisterMCSubtargetInfo(Target &T) {
+ TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator);
+ }
+
+private:
+ static MCSubtargetInfo *Allocator(StringRef /*TT*/, StringRef /*CPU*/,
+ StringRef /*FS*/) {
+ return new MCSubtargetInfoImpl();
+ }
+};
+
+/// RegisterMCSubtargetInfoFn - Helper template for registering a target
+/// subtarget info implementation. This invokes the specified function to
+/// do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCSubtargetInfoFn {
+ RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCSubtargetInfo(T, Fn);
+ }
+};
+
+/// RegisterTargetMachine - Helper template for registering a target machine
+/// implementation, for use in the target machine initialization
+/// function. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget);
+/// }
+template <class TargetMachineImpl> struct RegisterTargetMachine {
+ RegisterTargetMachine(Target &T) {
+ TargetRegistry::RegisterTargetMachine(T, &Allocator);
+ }
+
+private:
+ static TargetMachine *Allocator(const Target &T, StringRef TT, StringRef CPU,
+ StringRef FS, const TargetOptions &Options,
+ Reloc::Model RM, CodeModel::Model CM,
+ CodeGenOpt::Level OL) {
+ return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL);
+ }
+};
+
+/// RegisterMCAsmBackend - Helper template for registering a target specific
+/// assembler backend. Usage:
+///
+/// extern "C" void LLVMInitializeFooMCAsmBackend() {
+/// extern Target TheFooTarget;
+/// RegisterMCAsmBackend<FooAsmLexer> X(TheFooTarget);
+/// }
+template <class MCAsmBackendImpl> struct RegisterMCAsmBackend {
+ RegisterMCAsmBackend(Target &T) {
+ TargetRegistry::RegisterMCAsmBackend(T, &Allocator);
+ }
+
+private:
+ static MCAsmBackend *Allocator(const Target &T, const MCRegisterInfo &MRI,
+ StringRef Triple, StringRef CPU) {
+ return new MCAsmBackendImpl(T, MRI, Triple, CPU);
+ }
+};
+
+/// RegisterMCAsmParser - Helper template for registering a target specific
+/// assembly parser, for use in the target machine initialization
+/// function. Usage:
+///
+/// extern "C" void LLVMInitializeFooMCAsmParser() {
+/// extern Target TheFooTarget;
+/// RegisterMCAsmParser<FooAsmParser> X(TheFooTarget);
+/// }
+template <class MCAsmParserImpl> struct RegisterMCAsmParser {
+ RegisterMCAsmParser(Target &T) {
+ TargetRegistry::RegisterMCAsmParser(T, &Allocator);
+ }
+
+private:
+ static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P,
+ const MCInstrInfo &MII,
+ const MCTargetOptions &Options) {
+ return new MCAsmParserImpl(STI, P, MII, Options);
+ }
+};
+
+/// RegisterAsmPrinter - Helper template for registering a target specific
+/// assembly printer, for use in the target machine initialization
+/// function. Usage:
+///
+/// extern "C" void LLVMInitializeFooAsmPrinter() {
+/// extern Target TheFooTarget;
+/// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget);
+/// }
+template <class AsmPrinterImpl> struct RegisterAsmPrinter {
+ RegisterAsmPrinter(Target &T) {
+ TargetRegistry::RegisterAsmPrinter(T, &Allocator);
+ }
+
+private:
+ static AsmPrinter *Allocator(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> &&Streamer) {
+ return new AsmPrinterImpl(TM, std::move(Streamer));
+ }
+};
+
+/// RegisterMCCodeEmitter - Helper template for registering a target specific
+/// machine code emitter, for use in the target initialization
+/// function. Usage:
+///
+/// extern "C" void LLVMInitializeFooMCCodeEmitter() {
+/// extern Target TheFooTarget;
+/// RegisterMCCodeEmitter<FooCodeEmitter> X(TheFooTarget);
+/// }
+template <class MCCodeEmitterImpl> struct RegisterMCCodeEmitter {
+ RegisterMCCodeEmitter(Target &T) {
+ TargetRegistry::RegisterMCCodeEmitter(T, &Allocator);
+ }
+
+private:
+ static MCCodeEmitter *Allocator(const MCInstrInfo & /*II*/,
+ const MCRegisterInfo & /*MRI*/,
+ MCContext & /*Ctx*/) {
+ return new MCCodeEmitterImpl();
+ }
+};
}
#endif
diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h
index 45c182831b2a..2cd30e2aaf32 100644
--- a/include/llvm/Support/Timer.h
+++ b/include/llvm/Support/Timer.h
@@ -11,7 +11,6 @@
#define LLVM_SUPPORT_TIMER_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <string>
@@ -126,7 +125,7 @@ private:
///
class TimeRegion {
Timer *T;
- TimeRegion(const TimeRegion &) LLVM_DELETED_FUNCTION;
+ TimeRegion(const TimeRegion &) = delete;
public:
explicit TimeRegion(Timer &t) : T(&t) {
T->startTimer();
@@ -164,8 +163,8 @@ class TimerGroup {
std::vector<std::pair<TimeRecord, std::string> > TimersToPrint;
TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's.
- TimerGroup(const TimerGroup &TG) LLVM_DELETED_FUNCTION;
- void operator=(const TimerGroup &TG) LLVM_DELETED_FUNCTION;
+ TimerGroup(const TimerGroup &TG) = delete;
+ void operator=(const TimerGroup &TG) = delete;
public:
explicit TimerGroup(StringRef name);
~TimerGroup();
diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h
index d98e7bbd51d4..1be26c2cb58b 100644
--- a/include/llvm/Support/ToolOutputFile.h
+++ b/include/llvm/Support/ToolOutputFile.h
@@ -18,16 +18,16 @@
namespace llvm {
-/// tool_output_file - This class contains a raw_fd_ostream and adds a
-/// few extra features commonly needed for compiler-like tool output files:
+/// This class contains a raw_fd_ostream and adds a few extra features commonly
+/// needed for compiler-like tool output files:
/// - The file is automatically deleted if the process is killed.
/// - The file is automatically deleted when the tool_output_file
/// object is destroyed unless the client calls keep().
class tool_output_file {
- /// Installer - This class is declared before the raw_fd_ostream so that
- /// it is constructed before the raw_fd_ostream is constructed and
- /// destructed after the raw_fd_ostream is destructed. It installs
- /// cleanups in its constructor and uninstalls them in its destructor.
+ /// This class is declared before the raw_fd_ostream so that it is constructed
+ /// before the raw_fd_ostream is constructed and destructed after the
+ /// raw_fd_ostream is destructed. It installs cleanups in its constructor and
+ /// uninstalls them in its destructor.
class CleanupInstaller {
/// The name of the file.
std::string Filename;
@@ -39,8 +39,7 @@ class tool_output_file {
~CleanupInstaller();
} Installer;
- /// OS - The contained stream. This is intentionally declared after
- /// Installer.
+ /// The contained stream. This is intentionally declared after Installer.
raw_fd_ostream OS;
public:
@@ -51,11 +50,11 @@ public:
tool_output_file(StringRef Filename, int FD);
- /// os - Return the contained raw_fd_ostream.
+ /// Return the contained raw_fd_ostream.
raw_fd_ostream &os() { return OS; }
- /// keep - Indicate that the tool's job wrt this output file has been
- /// successful and the file should not be deleted.
+ /// Indicate that the tool's job wrt this output file has been successful and
+ /// the file should not be deleted.
void keep() { Installer.Keep = true; }
};
diff --git a/include/llvm/Support/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h
index 79137bf35363..9f738dff1107 100644
--- a/include/llvm/Support/UnicodeCharRanges.h
+++ b/include/llvm/Support/UnicodeCharRanges.h
@@ -50,9 +50,13 @@ public:
/// the UnicodeCharSet instance, and should not change. Array is validated by
/// the constructor, so it makes sense to create as few UnicodeCharSet
/// instances per each array of ranges, as possible.
+#ifdef NDEBUG
+ LLVM_CONSTEXPR UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) {}
+#else
UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) {
assert(rangesAreValid());
}
+#endif
/// \brief Returns true if the character set contains the Unicode code point
/// \p C.
diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h
index 5a4c273e83e2..529284d3868b 100644
--- a/include/llvm/Support/UniqueLock.h
+++ b/include/llvm/Support/UniqueLock.h
@@ -29,8 +29,8 @@ namespace llvm {
MutexT *M;
bool locked;
- unique_lock(const unique_lock &) LLVM_DELETED_FUNCTION;
- void operator=(const unique_lock &) LLVM_DELETED_FUNCTION;
+ unique_lock(const unique_lock &) = delete;
+ void operator=(const unique_lock &) = delete;
public:
unique_lock() : M(nullptr), locked(false) {}
explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); }
diff --git a/include/llvm/Support/Watchdog.h b/include/llvm/Support/Watchdog.h
index b58496b2fb8e..01e1d926eb95 100644
--- a/include/llvm/Support/Watchdog.h
+++ b/include/llvm/Support/Watchdog.h
@@ -29,8 +29,8 @@ namespace llvm {
~Watchdog();
private:
// Noncopyable.
- Watchdog(const Watchdog &other) LLVM_DELETED_FUNCTION;
- Watchdog &operator=(const Watchdog &other) LLVM_DELETED_FUNCTION;
+ Watchdog(const Watchdog &other) = delete;
+ Watchdog &operator=(const Watchdog &other) = delete;
};
}
}
diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h
index de6e6544e25b..0fbb7d2e6c7e 100644
--- a/include/llvm/Support/YAMLParser.h
+++ b/include/llvm/Support/YAMLParser.h
@@ -38,19 +38,18 @@
#ifndef LLVM_SUPPORT_YAMLPARSER_H
#define LLVM_SUPPORT_YAMLPARSER_H
-#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 MemoryBufferRef;
class SourceMgr;
-class raw_ostream;
class Twine;
+class raw_ostream;
namespace yaml {
@@ -77,9 +76,9 @@ std::string escape(StringRef Input);
class Stream {
public:
/// \brief This keeps a reference to the string referenced by \p Input.
- Stream(StringRef Input, SourceMgr &);
+ Stream(StringRef Input, SourceMgr &, bool ShowColors = true);
- Stream(MemoryBufferRef InputBuffer, SourceMgr &);
+ Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true);
~Stream();
document_iterator begin();
@@ -108,6 +107,7 @@ public:
enum NodeKind {
NK_Null,
NK_Scalar,
+ NK_BlockScalar,
NK_KeyValue,
NK_Mapping,
NK_Sequence,
@@ -159,7 +159,7 @@ protected:
void operator delete(void *) throw() {}
- virtual ~Node() {}
+ ~Node() = default;
private:
unsigned int TypeID;
@@ -172,7 +172,7 @@ private:
///
/// Example:
/// !!null null
-class NullNode : public Node {
+class NullNode final : public Node {
void anchor() override;
public:
@@ -187,7 +187,7 @@ public:
///
/// Example:
/// Adena
-class ScalarNode : public Node {
+class ScalarNode final : public Node {
void anchor() override;
public:
@@ -223,6 +223,36 @@ private:
SmallVectorImpl<char> &Storage) const;
};
+/// \brief A block scalar node is an opaque datum that can be presented as a
+/// series of zero or more Unicode scalar values.
+///
+/// Example:
+/// |
+/// Hello
+/// World
+class BlockScalarNode final : public Node {
+ void anchor() override;
+
+public:
+ BlockScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag,
+ StringRef Value, StringRef RawVal)
+ : Node(NK_BlockScalar, D, Anchor, Tag), Value(Value) {
+ SMLoc Start = SMLoc::getFromPointer(RawVal.begin());
+ SMLoc End = SMLoc::getFromPointer(RawVal.end());
+ SourceRange = SMRange(Start, End);
+ }
+
+ /// \brief Gets the value of this node as a StringRef.
+ StringRef getValue() const { return Value; }
+
+ static inline bool classof(const Node *N) {
+ return N->getType() == NK_BlockScalar;
+ }
+
+private:
+ StringRef Value;
+};
+
/// \brief A key and value pair. While not technically a Node under the YAML
/// representation graph, it is easier to treat them this way.
///
@@ -230,7 +260,7 @@ private:
///
/// Example:
/// Section: .text
-class KeyValueNode : public Node {
+class KeyValueNode final : public Node {
void anchor() override;
public:
@@ -254,7 +284,8 @@ public:
void skip() override {
getKey()->skip();
- getValue()->skip();
+ if (Node *Val = getValue())
+ Val->skip();
}
static inline bool classof(const Node *N) {
@@ -340,7 +371,7 @@ template <class CollectionType> void skip(CollectionType &C) {
/// Example:
/// Name: _main
/// Scope: Global
-class MappingNode : public Node {
+class MappingNode final : public Node {
void anchor() override;
public:
@@ -387,7 +418,7 @@ private:
/// Example:
/// - Hello
/// - World
-class SequenceNode : public Node {
+class SequenceNode final : public Node {
void anchor() override;
public:
@@ -440,7 +471,7 @@ private:
///
/// Example:
/// *AnchorName
-class AliasNode : public Node {
+class AliasNode final : public Node {
void anchor() override;
public:
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index 023dcee7d54c..3bdff2091809 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -46,6 +46,10 @@ struct MappingTraits {
// static void mapping(IO &io, T &fields);
// Optionally may provide:
// static StringRef validate(IO &io, T &fields);
+ //
+ // The optional flow flag will cause generated YAML to use a flow mapping
+ // (e.g. { a: 0, b: 1 }):
+ // static const bool flow = true;
};
@@ -117,6 +121,35 @@ struct ScalarTraits {
};
+/// This class should be specialized by type that requires custom conversion
+/// to/from a YAML literal block scalar. For example:
+///
+/// template <>
+/// struct BlockScalarTraits<MyType> {
+/// static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
+/// {
+/// // stream out custom formatting
+/// Out << Val;
+/// }
+/// static StringRef input(StringRef Scalar, void*, MyType &Value) {
+/// // parse scalar and set `value`
+/// // return empty string on success, or error string
+/// return StringRef();
+/// }
+/// };
+template <typename T>
+struct BlockScalarTraits {
+ // Must provide:
+ //
+ // Function to write the value as a string:
+ // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
+ //
+ // Function to convert a string to a value. Returns the empty
+ // StringRef on success or an error string if string is malformed:
+ // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
+};
+
+
/// This class should be specialized by any type that needs to be converted
/// to/from a YAML sequence. For example:
///
@@ -220,6 +253,26 @@ public:
};
+// Test if BlockScalarTraits<T> is defined on type T.
+template <class T>
+struct has_BlockScalarTraits
+{
+ typedef StringRef (*Signature_input)(StringRef, void *, T &);
+ typedef void (*Signature_output)(const T &, void *, llvm::raw_ostream &);
+
+ template <typename U>
+ static char test(SameType<Signature_input, &U::input> *,
+ SameType<Signature_output, &U::output> *);
+
+ template <typename U>
+ static double test(...);
+
+public:
+ static bool const value =
+ (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
+};
+
+
// Test if MappingTraits<T> is defined on type T.
template <class T>
struct has_MappingTraits
@@ -406,6 +459,7 @@ struct missingTraits : public std::integral_constant<bool,
!has_ScalarEnumerationTraits<T>::value
&& !has_ScalarBitSetTraits<T>::value
&& !has_ScalarTraits<T>::value
+ && !has_BlockScalarTraits<T>::value
&& !has_MappingTraits<T>::value
&& !has_SequenceTraits<T>::value
&& !has_DocumentListTraits<T>::value > {};
@@ -445,8 +499,12 @@ public:
virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
virtual void postflightKey(void*) = 0;
+ virtual void beginFlowMapping() = 0;
+ virtual void endFlowMapping() = 0;
+
virtual void beginEnumScalar() = 0;
virtual bool matchEnumScalar(const char*, bool) = 0;
+ virtual bool matchEnumFallback() = 0;
virtual void endEnumScalar() = 0;
virtual bool beginBitSetScalar(bool &) = 0;
@@ -454,6 +512,7 @@ public:
virtual void endBitSetScalar() = 0;
virtual void scalarString(StringRef &, bool) = 0;
+ virtual void blockScalarString(StringRef &) = 0;
virtual void setError(const Twine &) = 0;
@@ -472,6 +531,16 @@ public:
}
}
+ template <typename FBT, typename T>
+ void enumFallback(T &Val) {
+ if ( matchEnumFallback() ) {
+ // FIXME: Force integral conversion to allow strong typedefs to convert.
+ FBT Res = (uint64_t)Val;
+ yamlize(*this, Res, true);
+ Val = (uint64_t)Res;
+ }
+ }
+
template <typename T>
void bitSetCase(T &Val, const char* Str, const T ConstVal) {
if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
@@ -532,7 +601,7 @@ public:
void mapOptional(const char* Key, T& Val, const T& Default) {
this->processKeyWithDefault(Key, Val, Default, false);
}
-
+
private:
template <typename T>
void processKeyWithDefault(const char *Key, Optional<T> &Val,
@@ -628,11 +697,32 @@ yamlize(IO &io, T &Val, bool) {
}
}
+template <typename T>
+typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
+yamlize(IO &YamlIO, T &Val, bool) {
+ if (YamlIO.outputting()) {
+ std::string Storage;
+ llvm::raw_string_ostream Buffer(Storage);
+ BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
+ StringRef Str = Buffer.str();
+ YamlIO.blockScalarString(Str);
+ } else {
+ StringRef Str;
+ YamlIO.blockScalarString(Str);
+ StringRef Result =
+ BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
+ if (!Result.empty())
+ YamlIO.setError(llvm::Twine(Result));
+ }
+}
template<typename T>
typename std::enable_if<validatedMappingTraits<T>::value, void>::type
yamlize(IO &io, T &Val, bool) {
- io.beginMapping();
+ if (has_FlowTraits<MappingTraits<T>>::value)
+ io.beginFlowMapping();
+ else
+ io.beginMapping();
if (io.outputting()) {
StringRef Err = MappingTraits<T>::validate(io, Val);
if (!Err.empty()) {
@@ -646,15 +736,24 @@ yamlize(IO &io, T &Val, bool) {
if (!Err.empty())
io.setError(Err);
}
- io.endMapping();
+ if (has_FlowTraits<MappingTraits<T>>::value)
+ io.endFlowMapping();
+ else
+ io.endMapping();
}
template<typename T>
typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type
yamlize(IO &io, T &Val, bool) {
- io.beginMapping();
- MappingTraits<T>::mapping(io, Val);
- io.endMapping();
+ if (has_FlowTraits<MappingTraits<T>>::value) {
+ io.beginFlowMapping();
+ MappingTraits<T>::mapping(io, Val);
+ io.endFlowMapping();
+ } else {
+ io.beginMapping();
+ MappingTraits<T>::mapping(io, Val);
+ io.endMapping();
+ }
}
template<typename T>
@@ -706,7 +805,7 @@ struct ScalarTraits<StringRef> {
static StringRef input(StringRef, void*, StringRef &);
static bool mustQuote(StringRef S) { return needsQuotes(S); }
};
-
+
template<>
struct ScalarTraits<std::string> {
static void output(const std::string &, void*, llvm::raw_ostream &);
@@ -877,7 +976,7 @@ public:
void *Ctxt = nullptr,
SourceMgr::DiagHandlerTy DiagHandler = nullptr,
void *DiagHandlerCtxt = nullptr);
- ~Input();
+ ~Input() override;
// Check if there was an syntax or semantic error during parsing.
std::error_code error();
@@ -889,6 +988,8 @@ private:
void endMapping() override;
bool preflightKey(const char *, bool, bool, bool &, void *&) override;
void postflightKey(void *) override;
+ void beginFlowMapping() override;
+ void endFlowMapping() override;
unsigned beginSequence() override;
void endSequence() override;
bool preflightElement(unsigned index, void *&) override;
@@ -899,11 +1000,13 @@ private:
void endFlowSequence() override;
void beginEnumScalar() override;
bool matchEnumScalar(const char*, bool) override;
+ bool matchEnumFallback() override;
void endEnumScalar() override;
bool beginBitSetScalar(bool &) override;
bool bitSetMatch(const char *, bool ) override;
void endBitSetScalar() override;
void scalarString(StringRef &, bool) override;
+ void blockScalarString(StringRef &) override;
void setError(const Twine &message) override;
bool canElideEmptySequence() override;
@@ -935,7 +1038,8 @@ private:
StringRef value() const { return _value; }
static inline bool classof(const HNode *n) {
- return ScalarNode::classof(n->_node);
+ return ScalarNode::classof(n->_node) ||
+ BlockScalarNode::classof(n->_node);
}
static inline bool classof(const ScalarHNode *) { return true; }
protected:
@@ -943,7 +1047,7 @@ private:
};
class MapHNode : public HNode {
- virtual void anchor();
+ void anchor() override;
public:
MapHNode(Node *n) : HNode(n) { }
@@ -962,7 +1066,7 @@ private:
};
class SequenceHNode : public HNode {
- virtual void anchor();
+ void anchor() override;
public:
SequenceHNode(Node *n) : HNode(n) { }
@@ -1008,7 +1112,7 @@ private:
class Output : public IO {
public:
Output(llvm::raw_ostream &, void *Ctxt=nullptr);
- virtual ~Output();
+ ~Output() override;
bool outputting() override;
bool mapTag(StringRef, bool) override;
@@ -1016,6 +1120,8 @@ public:
void endMapping() override;
bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
void postflightKey(void *) override;
+ void beginFlowMapping() override;
+ void endFlowMapping() override;
unsigned beginSequence() override;
void endSequence() override;
bool preflightElement(unsigned, void *&) override;
@@ -1026,11 +1132,13 @@ public:
void endFlowSequence() override;
void beginEnumScalar() override;
bool matchEnumScalar(const char*, bool) override;
+ bool matchEnumFallback() override;
void endEnumScalar() override;
bool beginBitSetScalar(bool &) override;
bool bitSetMatch(const char *, bool ) override;
void endBitSetScalar() override;
void scalarString(StringRef &, bool) override;
+ void blockScalarString(StringRef &) override;
void setError(const Twine &message) override;
bool canElideEmptySequence() override;
public:
@@ -1047,13 +1155,22 @@ private:
void newLineCheck();
void outputNewLine();
void paddedKey(StringRef key);
-
- enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey };
+ void flowKey(StringRef Key);
+
+ enum InState {
+ inSeq,
+ inFlowSeq,
+ inMapFirstKey,
+ inMapOtherKey,
+ inFlowMapFirstKey,
+ inFlowMapOtherKey
+ };
llvm::raw_ostream &Out;
SmallVector<InState, 8> StateStack;
int Column;
int ColumnAtFlowStart;
+ int ColumnAtMapFlowStart;
bool NeedBitValueComma;
bool NeedFlowSequenceComma;
bool EnumerationMatchFound;
@@ -1163,6 +1280,16 @@ operator>>(Input &yin, T &docSeq) {
return yin;
}
+// Define non-member operator>> so that Input can stream in a block scalar.
+template <typename T>
+inline
+typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
+operator>>(Input &In, T &Val) {
+ if (In.setCurrentDocument())
+ yamlize(In, Val, true);
+ return In;
+}
+
// Provide better error message about types missing a trait specialization
template <typename T>
inline
@@ -1218,6 +1345,20 @@ operator<<(Output &yout, T &seq) {
return yout;
}
+// Define non-member operator<< so that Output can stream out a block scalar.
+template <typename T>
+inline
+typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
+operator<<(Output &Out, T &Val) {
+ Out.beginDocuments();
+ if (Out.preflightDocument(0)) {
+ yamlize(Out, Val, true);
+ Out.postflightDocument();
+ }
+ Out.endDocuments();
+ return Out;
+}
+
// Provide better error message about types missing a trait specialization
template <typename T>
inline
diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h
index ee7b89fe8c8d..19f9c2c4b155 100644
--- a/include/llvm/Support/circular_raw_ostream.h
+++ b/include/llvm/Support/circular_raw_ostream.h
@@ -107,30 +107,17 @@ namespace llvm
/// management of it, etc.
///
circular_raw_ostream(raw_ostream &Stream, const char *Header,
- size_t BuffSize = 0, bool Owns = REFERENCE_ONLY)
- : raw_ostream(/*unbuffered*/true),
- TheStream(nullptr),
- OwnsStream(Owns),
- BufferSize(BuffSize),
- BufferArray(nullptr),
- Filled(false),
- Banner(Header) {
+ size_t BuffSize = 0, bool Owns = REFERENCE_ONLY)
+ : raw_ostream(/*unbuffered*/ true), TheStream(nullptr),
+ OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr),
+ Filled(false), Banner(Header) {
if (BufferSize != 0)
BufferArray = new char[BufferSize];
Cur = BufferArray;
setStream(Stream, Owns);
}
- explicit circular_raw_ostream()
- : raw_ostream(/*unbuffered*/true),
- TheStream(nullptr),
- OwnsStream(REFERENCE_ONLY),
- BufferArray(nullptr),
- Filled(false),
- Banner("") {
- Cur = BufferArray;
- }
- ~circular_raw_ostream() {
+ ~circular_raw_ostream() override {
flush();
flushBufferWithBanner();
releaseStream();
diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h
index 04cf3b6202c4..a983aeb90879 100644
--- a/include/llvm/Support/raw_os_ostream.h
+++ b/include/llvm/Support/raw_os_ostream.h
@@ -34,7 +34,7 @@ class raw_os_ostream : public raw_ostream {
public:
raw_os_ostream(std::ostream &O) : OS(O) {}
- ~raw_os_ostream();
+ ~raw_os_ostream() override;
};
} // end llvm namespace
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
index c9ef637940db..b59317112c44 100644
--- a/include/llvm/Support/raw_ostream.h
+++ b/include/llvm/Support/raw_ostream.h
@@ -14,32 +14,31 @@
#ifndef LLVM_SUPPORT_RAW_OSTREAM_H
#define LLVM_SUPPORT_RAW_OSTREAM_H
+#include "llvm/ADT/SmallVector.h"
#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;
-
- namespace sys {
- namespace fs {
- enum OpenFlags : unsigned;
- }
- }
-
-/// raw_ostream - This class implements an extremely fast bulk output stream
-/// that can *only* output to a stream. It does not support seeking, reopening,
-/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs
+class format_object_base;
+class FormattedString;
+class FormattedNumber;
+template <typename T> class SmallVectorImpl;
+
+namespace sys {
+namespace fs {
+enum OpenFlags : unsigned;
+}
+}
+
+/// This class implements an extremely fast bulk output stream that can *only*
+/// output to a stream. It does not support seeking, reopening, rewinding, line
+/// buffered disciplines etc. It is a simple buffer that outputs
/// a chunk at a time.
class raw_ostream {
private:
- void operator=(const raw_ostream &) LLVM_DELETED_FUNCTION;
- raw_ostream(const raw_ostream &) LLVM_DELETED_FUNCTION;
+ void operator=(const raw_ostream &) = delete;
+ raw_ostream(const raw_ostream &) = delete;
/// The buffer is handled in such a way that the buffer is
/// uninitialized, unbuffered, or out of space when OutBufCur >=
@@ -81,8 +80,8 @@ public:
SAVEDCOLOR
};
- explicit raw_ostream(bool unbuffered=false)
- : BufferMode(unbuffered ? Unbuffered : InternalBuffer) {
+ explicit raw_ostream(bool unbuffered = false)
+ : BufferMode(unbuffered ? Unbuffered : InternalBuffer) {
// Start out ready to flush.
OutBufStart = OutBufEnd = OutBufCur = nullptr;
}
@@ -96,12 +95,11 @@ public:
// Configuration Interface
//===--------------------------------------------------------------------===//
- /// SetBuffered - Set the stream to be buffered, with an automatically
- /// determined buffer size.
+ /// Set the stream to be buffered, with an automatically determined buffer
+ /// size.
void SetBuffered();
- /// SetBufferSize - Set the stream to be buffered, using the
- /// specified buffer size.
+ /// Set the stream to be buffered, using the specified buffer size.
void SetBufferSize(size_t Size) {
flush();
SetBufferAndMode(new char[Size], Size, InternalBuffer);
@@ -117,10 +115,9 @@ public:
return OutBufEnd - OutBufStart;
}
- /// SetUnbuffered - Set the stream to be unbuffered. When
- /// unbuffered, the stream will flush after every write. This routine
- /// will also flush the buffer immediately when the stream is being
- /// set to unbuffered.
+ /// Set the stream to be unbuffered. When unbuffered, the stream will flush
+ /// after every write. This routine will also flush the buffer immediately
+ /// when the stream is being set to unbuffered.
void SetUnbuffered() {
flush();
SetBufferAndMode(nullptr, 0, Unbuffered);
@@ -185,6 +182,10 @@ public:
return write(Str.data(), Str.length());
}
+ raw_ostream &operator<<(const llvm::SmallVectorImpl<char> &Str) {
+ return write(Str.data(), Str.size());
+ }
+
raw_ostream &operator<<(unsigned long N);
raw_ostream &operator<<(long N);
raw_ostream &operator<<(unsigned long long N);
@@ -200,11 +201,11 @@ public:
raw_ostream &operator<<(double N);
- /// write_hex - Output \p N in hexadecimal, without any prefix or padding.
+ /// Output \p N in hexadecimal, without any prefix or padding.
raw_ostream &write_hex(unsigned long long N);
- /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and
- /// anything that doesn't satisfy std::isprint into an escape sequence.
+ /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't
+ /// satisfy std::isprint into an escape sequence.
raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false);
raw_ostream &write(unsigned char C);
@@ -259,8 +260,8 @@ public:
//===--------------------------------------------------------------------===//
private:
- /// write_impl - The is the piece of the class that is implemented
- /// by subclasses. This writes the \p Size bytes starting at
+ /// The is the piece of the class that is implemented by subclasses. This
+ /// writes the \p Size bytes starting at
/// \p Ptr to the underlying stream.
///
/// This function is guaranteed to only be called at a point at which it is
@@ -277,51 +278,69 @@ private:
// An out of line virtual method to provide a home for the class vtable.
virtual void handle();
- /// current_pos - Return the current position within the stream, not
- /// counting the bytes currently in the buffer.
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
virtual uint64_t current_pos() const = 0;
protected:
- /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is
- /// intended for use only by subclasses which can arrange for the output to go
- /// directly into the desired output buffer, instead of being copied on each
- /// flush.
+ /// Use the provided buffer as the raw_ostream buffer. This is intended for
+ /// use only by subclasses which can arrange for the output to go directly
+ /// into the desired output buffer, instead of being copied on each flush.
void SetBuffer(char *BufferStart, size_t Size) {
SetBufferAndMode(BufferStart, Size, ExternalBuffer);
}
- /// preferred_buffer_size - Return an efficient buffer size for the
- /// underlying output mechanism.
+ /// Return an efficient buffer size for the underlying output mechanism.
virtual size_t preferred_buffer_size() const;
- /// getBufferStart - Return the beginning of the current stream buffer, or 0
- /// if the stream is unbuffered.
+ /// Return the beginning of the current stream buffer, or 0 if the stream is
+ /// unbuffered.
const char *getBufferStart() const { return OutBufStart; }
//===--------------------------------------------------------------------===//
// Private Interface
//===--------------------------------------------------------------------===//
private:
- /// SetBufferAndMode - Install the given buffer and mode.
+ /// Install the given buffer and mode.
void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode);
- /// flush_nonempty - Flush the current buffer, which is known to be
- /// non-empty. This outputs the currently buffered data and resets
- /// the buffer to empty.
+ /// Flush the current buffer, which is known to be non-empty. This outputs the
+ /// currently buffered data and resets the buffer to empty.
void flush_nonempty();
- /// copy_to_buffer - Copy data into the buffer. Size must not be
- /// greater than the number of unused bytes in the buffer.
+ /// Copy data into the buffer. Size must not be greater than the number of
+ /// unused bytes in the buffer.
void copy_to_buffer(const char *Ptr, size_t Size);
};
+/// An abstract base class for streams implementations that also support a
+/// pwrite operation. This is usefull for code that can mostly stream out data,
+/// but needs to patch in a header that needs to know the output size.
+class raw_pwrite_stream : public raw_ostream {
+ virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0;
+
+public:
+ explicit raw_pwrite_stream(bool Unbuffered = false)
+ : raw_ostream(Unbuffered) {}
+ void pwrite(const char *Ptr, size_t Size, uint64_t Offset) {
+#ifndef NDBEBUG
+ uint64_t Pos = tell();
+ // /dev/null always reports a pos of 0, so we cannot perform this check
+ // in that case.
+ if (Pos)
+ assert(Size + Offset <= Pos && "We don't support extending the stream");
+#endif
+ pwrite_impl(Ptr, Size, Offset);
+ }
+};
+
//===----------------------------------------------------------------------===//
// File Output Streams
//===----------------------------------------------------------------------===//
-/// raw_fd_ostream - A raw_ostream that writes to a file descriptor.
+/// A raw_ostream that writes to a file descriptor.
///
-class raw_fd_ostream : public raw_ostream {
+class raw_fd_ostream : public raw_pwrite_stream {
int FD;
bool ShouldClose;
@@ -335,18 +354,21 @@ class raw_fd_ostream : public raw_ostream {
uint64_t pos;
- /// write_impl - See raw_ostream::write_impl.
+ bool SupportsSeeking;
+
+ /// See raw_ostream::write_impl.
void write_impl(const char *Ptr, size_t Size) override;
- /// current_pos - Return the current position within the stream, not
- /// counting the bytes currently in the buffer.
+ void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
+
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
uint64_t current_pos() const override { return pos; }
- /// preferred_buffer_size - Determine an efficient buffer size.
+ /// Determine an efficient buffer size.
size_t preferred_buffer_size() const override;
- /// error_detected - Set the flag indicating that an output error has
- /// been encountered.
+ /// Set the flag indicating that an output error has been encountered.
void error_detected() { Error = true; }
public:
@@ -363,22 +385,24 @@ public:
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
- /// ShouldClose is true, this closes the file when the stream is destroyed.
+ /// FD is the file descriptor that this writes to. If ShouldClose is true,
+ /// this closes the file when the stream is destroyed.
raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false);
- ~raw_fd_ostream();
+ ~raw_fd_ostream() override;
- /// close - Manually flush the stream and close the file.
- /// Note that this does not call fsync.
+ /// Manually flush the stream and close the file. Note that this does not call
+ /// fsync.
void close();
- /// seek - Flushes the stream and repositions the underlying file descriptor
- /// position to the offset specified from the beginning of the file.
+ bool supportsSeeking() { return SupportsSeeking; }
+
+ /// Flushes the stream and repositions the underlying file descriptor position
+ /// to the offset specified from the beginning of the file.
uint64_t seek(uint64_t off);
- /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for
- /// individual output routines where possible.
+ /// Set the stream to attempt to use atomic writes for individual output
+ /// routines where possible.
///
/// Note that because raw_ostream's are typically buffered, this flag is only
/// sensible when used on unbuffered streams which will flush their output
@@ -397,18 +421,18 @@ public:
bool has_colors() const override;
- /// has_error - Return the value of the flag in this raw_fd_ostream indicating
- /// whether an output error has been encountered.
+ /// Return the value of the flag in this raw_fd_ostream indicating whether an
+ /// output error has been encountered.
/// This doesn't implicitly flush any pending output. Also, it doesn't
/// guarantee to detect all errors unless the stream has been closed.
bool has_error() const {
return Error;
}
- /// clear_error - Set the flag read by has_error() to false. If the error
- /// flag is set at the time when this raw_ostream's destructor is called,
- /// report_fatal_error is called to report the error. Use clear_error()
- /// after handling the error to avoid this behavior.
+ /// Set the flag read by has_error() to false. If the error flag is set at the
+ /// time when this raw_ostream's destructor is called, report_fatal_error is
+ /// called to report the error. Use clear_error() after handling the error to
+ /// avoid this behavior.
///
/// "Errors should never pass silently.
/// Unless explicitly silenced."
@@ -419,87 +443,106 @@ public:
}
};
-/// outs() - This returns a reference to a raw_ostream for standard output.
-/// Use it like: outs() << "foo" << "bar";
+/// This returns a reference to a raw_ostream for standard output. Use it like:
+/// outs() << "foo" << "bar";
raw_ostream &outs();
-/// errs() - This returns a reference to a raw_ostream for standard error.
-/// Use it like: errs() << "foo" << "bar";
+/// This returns a reference to a raw_ostream for standard error. Use it like:
+/// errs() << "foo" << "bar";
raw_ostream &errs();
-/// nulls() - This returns a reference to a raw_ostream which simply discards
-/// output.
+/// This returns a reference to a raw_ostream which simply discards output.
raw_ostream &nulls();
//===----------------------------------------------------------------------===//
// Output Stream Adaptors
//===----------------------------------------------------------------------===//
-/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a
-/// simple adaptor class. This class does not encounter output errors.
+/// A raw_ostream that writes to an std::string. This is a simple adaptor
+/// class. This class does not encounter output errors.
class raw_string_ostream : public raw_ostream {
std::string &OS;
- /// write_impl - See raw_ostream::write_impl.
+ /// See raw_ostream::write_impl.
void write_impl(const char *Ptr, size_t Size) override;
- /// current_pos - Return the current position within the stream, not
- /// counting the bytes currently in the buffer.
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
uint64_t current_pos() const override { return OS.size(); }
public:
explicit raw_string_ostream(std::string &O) : OS(O) {}
- ~raw_string_ostream();
+ ~raw_string_ostream() override;
- /// str - Flushes the stream contents to the target string and returns
- /// the string's reference.
+ /// Flushes the stream contents to the target string and returns the string's
+ /// reference.
std::string& str() {
flush();
return OS;
}
};
-/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or
-/// SmallString. This is a simple adaptor class. This class does not
-/// encounter output errors.
-class raw_svector_ostream : public raw_ostream {
+/// A raw_ostream that writes to an SmallVector or SmallString. This is a
+/// simple adaptor class. This class does not encounter output errors.
+class raw_svector_ostream : public raw_pwrite_stream {
SmallVectorImpl<char> &OS;
- /// write_impl - See raw_ostream::write_impl.
+ /// See raw_ostream::write_impl.
void write_impl(const char *Ptr, size_t Size) override;
- /// current_pos - Return the current position within the stream, not
- /// counting the bytes currently in the buffer.
+ void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
+
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
uint64_t current_pos() const override;
+
+protected:
+ // Like the regular constructor, but doesn't call init.
+ explicit raw_svector_ostream(SmallVectorImpl<char> &O, unsigned);
+ void init();
+
public:
/// Construct a new raw_svector_ostream.
///
/// \param O The vector to write to; this should generally have at least 128
/// bytes free to avoid any extraneous memory overhead.
explicit raw_svector_ostream(SmallVectorImpl<char> &O);
- ~raw_svector_ostream();
+ ~raw_svector_ostream() override;
- /// resync - This is called when the SmallVector we're appending to is changed
- /// outside of the raw_svector_ostream's control. It is only safe to do this
- /// if the raw_svector_ostream has previously been flushed.
+
+ /// This is called when the SmallVector we're appending to is changed outside
+ /// of the raw_svector_ostream's control. It is only safe to do this if the
+ /// raw_svector_ostream has previously been flushed.
void resync();
- /// str - Flushes the stream contents to the target vector and return a
- /// StringRef for the vector contents.
+ /// Flushes the stream contents to the target vector and return a StringRef
+ /// for the vector contents.
StringRef str();
};
-/// raw_null_ostream - A raw_ostream that discards all output.
-class raw_null_ostream : public raw_ostream {
- /// write_impl - See raw_ostream::write_impl.
+/// A raw_ostream that discards all output.
+class raw_null_ostream : public raw_pwrite_stream {
+ /// See raw_ostream::write_impl.
void write_impl(const char *Ptr, size_t size) override;
+ void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
- /// current_pos - Return the current position within the stream, not
- /// counting the bytes currently in the buffer.
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
uint64_t current_pos() const override;
public:
explicit raw_null_ostream() {}
- ~raw_null_ostream();
+ ~raw_null_ostream() override;
+};
+
+class buffer_ostream : public raw_svector_ostream {
+ raw_ostream &OS;
+ SmallVector<char, 0> Buffer;
+
+public:
+ buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer, 0), OS(OS) {
+ init();
+ }
+ ~buffer_ostream() { OS << str(); }
};
} // end llvm namespace
diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h
index 70953a9cb70e..45465aea004b 100644
--- a/include/llvm/Support/type_traits.h
+++ b/include/llvm/Support/type_traits.h
@@ -28,9 +28,17 @@ namespace llvm {
/// type can be copied around with memcpy instead of running ctors etc.
template <typename T>
struct isPodLike {
-#if __has_feature(is_trivially_copyable)
+ // std::is_trivially_copyable is available in libc++ with clang, libstdc++
+ // that comes with GCC 5.
+#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
+ (defined(__GNUC__) && __GNUC__ >= 5)
// If the compiler supports the is_trivially_copyable trait use it, as it
// matches the definition of isPodLike closely.
+ static const bool value = std::is_trivially_copyable<T>::value;
+#elif __has_feature(is_trivially_copyable)
+ // Use the internal name if the compiler supports is_trivially_copyable but we
+ // don't know if the standard library does. This is the case for clang in
+ // conjunction with libstdc++ from GCC 4.x.
static const bool value = __is_trivially_copyable(T);
#else
// If we don't know anything else, we can (at least) assume that all non-class
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 4abeddd6be29..75765557a776 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -26,7 +26,6 @@
#include <map>
namespace llvm {
-class raw_ostream;
// RecTy subclasses.
class BitRecTy;
@@ -81,7 +80,7 @@ public:
private:
RecTyKind Kind;
- ListRecTy *ListTy;
+ std::unique_ptr<ListRecTy> ListTy;
virtual void anchor();
public:
@@ -108,14 +107,14 @@ public: // These methods should only be called from subclasses of Init
virtual Init *convertValue( IntInit *II) { return nullptr; }
virtual Init *convertValue(StringInit *SI) { return nullptr; }
virtual Init *convertValue( ListInit *LI) { return nullptr; }
- virtual Init *convertValue( UnOpInit *UI) {
- return convertValue((TypedInit*)UI);
+ virtual Init *convertValue( UnOpInit *UO) {
+ return convertValue((TypedInit*)UO);
}
- virtual Init *convertValue( BinOpInit *UI) {
- return convertValue((TypedInit*)UI);
+ virtual Init *convertValue( BinOpInit *BO) {
+ return convertValue((TypedInit*)BO);
}
- virtual Init *convertValue( TernOpInit *UI) {
- return convertValue((TypedInit*)UI);
+ virtual Init *convertValue( TernOpInit *TO) {
+ return convertValue((TypedInit*)TO);
}
virtual Init *convertValue(VarBitInit *VB) { return nullptr; }
virtual Init *convertValue( DefInit *DI) { return nullptr; }
@@ -150,21 +149,13 @@ public:
static BitRecTy *get() { return &Shared; }
+ using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
Init *convertValue( BitInit *BI) override { return (Init*)BI; }
Init *convertValue( BitsInit *BI) override;
Init *convertValue( IntInit *II) override;
- Init *convertValue(StringInit *SI) override { return nullptr; }
- Init *convertValue( ListInit *LI) override { return nullptr; }
Init *convertValue(VarBitInit *VB) override { return (Init*)VB; }
- Init *convertValue( DefInit *DI) override { return nullptr; }
- Init *convertValue( DagInit *DI) override { return nullptr; }
- Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);}
Init *convertValue( TypedInit *TI) override;
- Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);}
- Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}
std::string getAsString() const override { return "bit"; }
@@ -189,21 +180,12 @@ public:
unsigned getNumBits() const { return Size; }
+ using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override;
Init *convertValue( BitInit *UI) override;
Init *convertValue( BitsInit *BI) override;
Init *convertValue( IntInit *II) override;
- Init *convertValue(StringInit *SI) override { return nullptr; }
- Init *convertValue( ListInit *LI) override { return nullptr; }
- Init *convertValue(VarBitInit *VB) override { return nullptr; }
- Init *convertValue( DefInit *DI) override { return nullptr; }
- Init *convertValue( DagInit *DI) override { return nullptr; }
- Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue(TernOpInit *UI) override { return RecTy::convertValue(UI);}
Init *convertValue( TypedInit *TI) override;
- Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);}
- Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}
std::string getAsString() const override;
@@ -226,21 +208,12 @@ public:
static IntRecTy *get() { return &Shared; }
+ using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
Init *convertValue( BitInit *BI) override;
Init *convertValue( BitsInit *BI) override;
Init *convertValue( IntInit *II) override { return (Init*)II; }
- Init *convertValue(StringInit *SI) override { return nullptr; }
- Init *convertValue( ListInit *LI) override { return nullptr; }
- Init *convertValue(VarBitInit *VB) override { return nullptr; }
- Init *convertValue( DefInit *DI) override { return nullptr; }
- Init *convertValue( DagInit *DI) override { return nullptr; }
- Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);}
Init *convertValue( TypedInit *TI) override;
- Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);}
- Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}
std::string getAsString() const override { return "int"; }
@@ -264,22 +237,12 @@ public:
static StringRecTy *get() { return &Shared; }
+ using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
- Init *convertValue( BitInit *BI) override { return nullptr; }
- Init *convertValue( BitsInit *BI) override { return nullptr; }
- Init *convertValue( IntInit *II) override { return nullptr; }
Init *convertValue(StringInit *SI) override { return (Init*)SI; }
- Init *convertValue( ListInit *LI) override { return nullptr; }
- Init *convertValue( UnOpInit *BO) override;
+ Init *convertValue( UnOpInit *UO) override;
Init *convertValue( BinOpInit *BO) override;
- Init *convertValue( TernOpInit *BO) override {return RecTy::convertValue(BO);}
-
- Init *convertValue(VarBitInit *VB) override { return nullptr; }
- Init *convertValue( DefInit *DI) override { return nullptr; }
- Init *convertValue( DagInit *DI) override { return nullptr; }
Init *convertValue( TypedInit *TI) override;
- Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);}
- Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}
std::string getAsString() const override { return "string"; }
@@ -304,21 +267,10 @@ public:
static ListRecTy *get(RecTy *T) { return T->getListTy(); }
RecTy *getElementType() const { return Ty; }
+ using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
- Init *convertValue( BitInit *BI) override { return nullptr; }
- Init *convertValue( BitsInit *BI) override { return nullptr; }
- Init *convertValue( IntInit *II) override { return nullptr; }
- Init *convertValue(StringInit *SI) override { return nullptr; }
Init *convertValue( ListInit *LI) override;
- Init *convertValue(VarBitInit *VB) override { return nullptr; }
- Init *convertValue( DefInit *DI) override { return nullptr; }
- Init *convertValue( DagInit *DI) override { return nullptr; }
- Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue(TernOpInit *UI) override { return RecTy::convertValue(UI);}
Init *convertValue( TypedInit *TI) override;
- Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);}
- Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}
std::string getAsString() const override;
@@ -342,21 +294,12 @@ public:
static DagRecTy *get() { return &Shared; }
+ using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
- Init *convertValue( BitInit *BI) override { return nullptr; }
- Init *convertValue( BitsInit *BI) override { return nullptr; }
- Init *convertValue( IntInit *II) override { return nullptr; }
- Init *convertValue(StringInit *SI) override { return nullptr; }
- Init *convertValue( ListInit *LI) override { return nullptr; }
- Init *convertValue(VarBitInit *VB) override { return nullptr; }
- Init *convertValue( DefInit *DI) override { return nullptr; }
- Init *convertValue( UnOpInit *BO) override;
+ Init *convertValue( UnOpInit *UO) override;
Init *convertValue( BinOpInit *BO) override;
- Init *convertValue( TernOpInit *BO) override {return RecTy::convertValue(BO);}
- Init *convertValue( DagInit *CI) override { return (Init*)CI; }
+ Init *convertValue( DagInit *DI) override { return (Init*)DI; }
Init *convertValue( TypedInit *TI) override;
- Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);}
- Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}
std::string getAsString() const override { return "dag"; }
@@ -382,21 +325,10 @@ public:
Record *getRecord() const { return Rec; }
+ using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
- Init *convertValue( BitInit *BI) override { return nullptr; }
- Init *convertValue( BitsInit *BI) override { return nullptr; }
- Init *convertValue( IntInit *II) override { return nullptr; }
- Init *convertValue(StringInit *SI) override { return nullptr; }
- Init *convertValue( ListInit *LI) override { return nullptr; }
- Init *convertValue(VarBitInit *VB) override { return nullptr; }
- Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);}
- Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);}
Init *convertValue( DefInit *DI) override;
- Init *convertValue( DagInit *DI) override { return nullptr; }
- Init *convertValue( TypedInit *VI) override;
- Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);}
- Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);}
+ Init *convertValue( TypedInit *TI) override;
std::string getAsString() const override;
@@ -454,8 +386,8 @@ protected:
private:
const InitKind Kind;
- Init(const Init &) LLVM_DELETED_FUNCTION;
- Init &operator=(const Init &) LLVM_DELETED_FUNCTION;
+ Init(const Init &) = delete;
+ Init &operator=(const Init &) = delete;
virtual void anchor();
public:
@@ -561,11 +493,16 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
class TypedInit : public Init {
RecTy *Ty;
- TypedInit(const TypedInit &Other) LLVM_DELETED_FUNCTION;
- TypedInit &operator=(const TypedInit &Other) LLVM_DELETED_FUNCTION;
+ TypedInit(const TypedInit &Other) = delete;
+ TypedInit &operator=(const TypedInit &Other) = delete;
protected:
explicit TypedInit(InitKind K, RecTy *T) : Init(K), Ty(T) {}
+ ~TypedInit() {
+ // If this is a DefInit we need to delete the RecordRecTy.
+ if (getKind() == IK_DefInit)
+ delete Ty;
+ }
public:
static bool classof(const Init *I) {
@@ -596,8 +533,8 @@ public:
///
class UnsetInit : public Init {
UnsetInit() : Init(IK_UnsetInit) {}
- UnsetInit(const UnsetInit &) LLVM_DELETED_FUNCTION;
- UnsetInit &operator=(const UnsetInit &Other) LLVM_DELETED_FUNCTION;
+ UnsetInit(const UnsetInit &) = delete;
+ UnsetInit &operator=(const UnsetInit &Other) = delete;
void anchor() override;
public:
@@ -624,8 +561,8 @@ class BitInit : public Init {
bool Value;
explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {}
- BitInit(const BitInit &Other) LLVM_DELETED_FUNCTION;
- BitInit &operator=(BitInit &Other) LLVM_DELETED_FUNCTION;
+ BitInit(const BitInit &Other) = delete;
+ BitInit &operator=(BitInit &Other) = delete;
void anchor() override;
public:
@@ -658,8 +595,8 @@ class BitsInit : public TypedInit, public FoldingSetNode {
: TypedInit(IK_BitsInit, BitsRecTy::get(Range.size())),
Bits(Range.begin(), Range.end()) {}
- BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION;
- BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION;
+ BitsInit(const BitsInit &Other) = delete;
+ BitsInit &operator=(const BitsInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -713,8 +650,8 @@ class IntInit : public TypedInit {
explicit IntInit(int64_t V)
: TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {}
- IntInit(const IntInit &Other) LLVM_DELETED_FUNCTION;
- IntInit &operator=(const IntInit &Other) LLVM_DELETED_FUNCTION;
+ IntInit(const IntInit &Other) = delete;
+ IntInit &operator=(const IntInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -753,8 +690,8 @@ class StringInit : public TypedInit {
explicit StringInit(const std::string &V)
: TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
- StringInit(const StringInit &Other) LLVM_DELETED_FUNCTION;
- StringInit &operator=(const StringInit &Other) LLVM_DELETED_FUNCTION;
+ StringInit(const StringInit &Other) = delete;
+ StringInit &operator=(const StringInit &Other) = delete;
void anchor() override;
public:
@@ -798,8 +735,8 @@ private:
: TypedInit(IK_ListInit, ListRecTy::get(EltTy)),
Values(Range.begin(), Range.end()) {}
- ListInit(const ListInit &Other) LLVM_DELETED_FUNCTION;
- ListInit &operator=(const ListInit &Other) LLVM_DELETED_FUNCTION;
+ ListInit(const ListInit &Other) = delete;
+ ListInit &operator=(const ListInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -838,7 +775,6 @@ public:
inline const_iterator begin() const { return Values.begin(); }
inline const_iterator end () const { return Values.end(); }
- inline size_t size () const { return Values.size(); }
inline bool empty() const { return Values.empty(); }
/// resolveListElementReference - This method is used to implement
@@ -855,8 +791,8 @@ public:
/// OpInit - Base class for operators
///
class OpInit : public TypedInit {
- OpInit(const OpInit &Other) LLVM_DELETED_FUNCTION;
- OpInit &operator=(OpInit &Other) LLVM_DELETED_FUNCTION;
+ OpInit(const OpInit &Other) = delete;
+ OpInit &operator=(OpInit &Other) = delete;
protected:
explicit OpInit(InitKind K, RecTy *Type) : TypedInit(K, Type) {}
@@ -899,8 +835,8 @@ private:
UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type)
: OpInit(IK_UnOpInit, Type), Opc(opc), LHS(lhs) {}
- UnOpInit(const UnOpInit &Other) LLVM_DELETED_FUNCTION;
- UnOpInit &operator=(const UnOpInit &Other) LLVM_DELETED_FUNCTION;
+ UnOpInit(const UnOpInit &Other) = delete;
+ UnOpInit &operator=(const UnOpInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -946,8 +882,8 @@ private:
BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
OpInit(IK_BinOpInit, Type), Opc(opc), LHS(lhs), RHS(rhs) {}
- BinOpInit(const BinOpInit &Other) LLVM_DELETED_FUNCTION;
- BinOpInit &operator=(const BinOpInit &Other) LLVM_DELETED_FUNCTION;
+ BinOpInit(const BinOpInit &Other) = delete;
+ BinOpInit &operator=(const BinOpInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1000,8 +936,8 @@ private:
RecTy *Type) :
OpInit(IK_TernOpInit, Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {}
- TernOpInit(const TernOpInit &Other) LLVM_DELETED_FUNCTION;
- TernOpInit &operator=(const TernOpInit &Other) LLVM_DELETED_FUNCTION;
+ TernOpInit(const TernOpInit &Other) = delete;
+ TernOpInit &operator=(const TernOpInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1058,8 +994,8 @@ class VarInit : public TypedInit {
explicit VarInit(Init *VN, RecTy *T)
: TypedInit(IK_VarInit, T), VarName(VN) {}
- VarInit(const VarInit &Other) LLVM_DELETED_FUNCTION;
- VarInit &operator=(const VarInit &Other) LLVM_DELETED_FUNCTION;
+ VarInit(const VarInit &Other) = delete;
+ VarInit &operator=(const VarInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1111,8 +1047,8 @@ class VarBitInit : public Init {
"Illegal VarBitInit expression!");
}
- VarBitInit(const VarBitInit &Other) LLVM_DELETED_FUNCTION;
- VarBitInit &operator=(const VarBitInit &Other) LLVM_DELETED_FUNCTION;
+ VarBitInit(const VarBitInit &Other) = delete;
+ VarBitInit &operator=(const VarBitInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1150,8 +1086,8 @@ class VarListElementInit : public TypedInit {
"Illegal VarBitInit expression!");
}
- VarListElementInit(const VarListElementInit &Other) LLVM_DELETED_FUNCTION;
- void operator=(const VarListElementInit &Other) LLVM_DELETED_FUNCTION;
+ VarListElementInit(const VarListElementInit &Other) = delete;
+ void operator=(const VarListElementInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1186,8 +1122,8 @@ class DefInit : public TypedInit {
DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {}
friend class Record;
- DefInit(const DefInit &Other) LLVM_DELETED_FUNCTION;
- DefInit &operator=(const DefInit &Other) LLVM_DELETED_FUNCTION;
+ DefInit(const DefInit &Other) = delete;
+ DefInit &operator=(const DefInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1233,8 +1169,8 @@ class FieldInit : public TypedInit {
assert(getType() && "FieldInit with non-record type!");
}
- FieldInit(const FieldInit &Other) LLVM_DELETED_FUNCTION;
- FieldInit &operator=(const FieldInit &Other) LLVM_DELETED_FUNCTION;
+ FieldInit(const FieldInit &Other) = delete;
+ FieldInit &operator=(const FieldInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1276,8 +1212,8 @@ class DagInit : public TypedInit, public FoldingSetNode {
Args(ArgRange.begin(), ArgRange.end()),
ArgNames(NameRange.begin(), NameRange.end()) {}
- DagInit(const DagInit &Other) LLVM_DELETED_FUNCTION;
- DagInit &operator=(const DagInit &Other) LLVM_DELETED_FUNCTION;
+ DagInit(const DagInit &Other) = delete;
+ DagInit &operator=(const DagInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1442,8 +1378,6 @@ public:
TheInit(O.TheInit), IsAnonymous(O.IsAnonymous),
ResolveFirst(O.ResolveFirst) { }
- ~Record() {}
-
static unsigned getNewUID() { return LastID++; }
unsigned getID() const { return ID; }
@@ -1477,7 +1411,7 @@ public:
return false;
}
bool isTemplateArg(StringRef Name) const {
- return isTemplateArg(StringInit::get(Name.str()));
+ return isTemplateArg(StringInit::get(Name));
}
const RecordVal *getValue(const Init *Name) const {
@@ -1502,7 +1436,7 @@ public:
TemplateArgs.push_back(Name);
}
void addTemplateArg(StringRef Name) {
- addTemplateArg(StringInit::get(Name.str()));
+ addTemplateArg(StringInit::get(Name));
}
void addValue(const RecordVal &RV) {
@@ -1527,7 +1461,7 @@ public:
}
void removeValue(StringRef Name) {
- removeValue(StringInit::get(Name.str()));
+ removeValue(StringInit::get(Name));
}
bool isSubClassOf(const Record *R) const {
diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h
index 76e56ec6443e..595c29f2ee1d 100644
--- a/include/llvm/TableGen/SetTheory.h
+++ b/include/llvm/TableGen/SetTheory.h
@@ -95,17 +95,17 @@ private:
ExpandMap Expansions;
// Known DAG operators by name.
- StringMap<Operator*> Operators;
+ StringMap<std::unique_ptr<Operator>> Operators;
// Typed expanders by class name.
- StringMap<Expander*> Expanders;
+ StringMap<std::unique_ptr<Expander>> Expanders;
public:
/// Create a SetTheory instance with only the standard operators.
SetTheory();
/// addExpander - Add an expander for Records with the named super class.
- void addExpander(StringRef ClassName, Expander*);
+ void addExpander(StringRef ClassName, std::unique_ptr<Expander>);
/// addFieldExpander - Add an expander for ClassName that simply evaluates
/// FieldName in the Record to get the set elements. That is all that is
@@ -118,7 +118,7 @@ public:
void addFieldExpander(StringRef ClassName, StringRef FieldName);
/// addOperator - Add a DAG operator.
- void addOperator(StringRef Name, Operator*);
+ void addOperator(StringRef Name, std::unique_ptr<Operator>);
/// evaluate - Evaluate Expr and append the resulting set to Elts.
void evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc);
diff --git a/include/llvm/TableGen/TableGenBackend.h b/include/llvm/TableGen/TableGenBackend.h
index 3e4f3cc917a8..d226f1f1af7b 100644
--- a/include/llvm/TableGen/TableGenBackend.h
+++ b/include/llvm/TableGen/TableGenBackend.h
@@ -14,10 +14,9 @@
#ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H
#define LLVM_TABLEGEN_TABLEGENBACKEND_H
-#include "llvm/ADT/StringRef.h"
-
namespace llvm {
+class StringRef;
class raw_ostream;
/// emitSourceFileHeader - Output an LLVM style file header to the specified
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 6c970d0c19db..ec8a12df9fc6 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -207,6 +207,12 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
// The function should return 0 to select the default order defined by
// MemberList, 1 to select the first AltOrders entry and so on.
code AltOrderSelect = [{}];
+
+ // Specify allocation priority for register allocators using a greedy
+ // heuristic. Classes with higher priority values are assigned first. This is
+ // useful as it is sometimes beneficial to assign registers to highly
+ // constrained classes first. The value has to be in the range [0,63].
+ int AllocationPriority = 0;
}
// The memberList in a RegisterClass is a dag of set operations. TableGen
@@ -1000,6 +1006,15 @@ class InstAlias<string Asm, dag Result, int Emit = 1> {
// Predicates - Predicates that must be true for this to match.
list<Predicate> Predicates = [];
+
+ // If the instruction specified in Result has defined an AsmMatchConverter
+ // then setting this to 1 will cause the alias to use the AsmMatchConverter
+ // function when converting the OperandVector into an MCInst instead of the
+ // function that is generated by the dag Result.
+ // Setting this to 0 will cause the alias to ignore the Result instruction's
+ // defined AsmMatchConverter and instead use the function generated by the
+ // dag Result.
+ bit UseInstAsmMatchConverter = 1;
}
//===----------------------------------------------------------------------===//
@@ -1015,6 +1030,11 @@ class AsmWriter {
// name.
string AsmWriterClassName = "InstPrinter";
+ // PassSubtarget - Determines whether MCSubtargetInfo should be passed to
+ // the various print methods.
+ // FIXME: Remove after all ports are updated.
+ int PassSubtarget = 0;
+
// Variant - AsmWriters can be of multiple different variants. Variants are
// used to support targets that need to emit assembly code in ways that are
// mostly the same for different targets, but have minor differences in
diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h
index 9071bfeec7ed..9d4e7a04d905 100644
--- a/include/llvm/Target/TargetCallingConv.h
+++ b/include/llvm/Target/TargetCallingConv.h
@@ -18,6 +18,7 @@
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include <string>
+#include <limits.h>
namespace llvm {
diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h
index 277bd98d371c..0e317247a59f 100644
--- a/include/llvm/Target/TargetFrameLowering.h
+++ b/include/llvm/Target/TargetFrameLowering.h
@@ -130,21 +130,26 @@ public:
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
- virtual void emitPrologue(MachineFunction &MF) const = 0;
+ virtual void emitPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const = 0;
virtual void emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const = 0;
/// Adjust the prologue to have the function use segmented stacks. This works
/// by adding a check even before the "normal" function prologue.
- virtual void adjustForSegmentedStacks(MachineFunction &MF) const { }
+ virtual void adjustForSegmentedStacks(MachineFunction &MF,
+ MachineBasicBlock &PrologueMBB) const {}
/// Adjust the prologue to add Erlang Run-Time System (ERTS) specific code in
/// the assembly prologue to explicitly handle the stack.
- virtual void adjustForHiPEPrologue(MachineFunction &MF) const { }
+ virtual void adjustForHiPEPrologue(MachineFunction &MF,
+ MachineBasicBlock &PrologueMBB) const {}
/// Adjust the prologue to add an allocation at a fixed offset from the frame
/// pointer.
- virtual void adjustForFrameAllocatePrologue(MachineFunction &MF) const { }
+ virtual void
+ adjustForFrameAllocatePrologue(MachineFunction &MF,
+ MachineBasicBlock &PrologueMBB) const {}
/// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee
/// saved registers and returns true if it isn't possible / profitable to do
@@ -168,6 +173,9 @@ public:
return false;
}
+ /// Return true if the target needs to disable frame pointer elimination.
+ virtual bool noFramePointerElim(const MachineFunction &MF) const;
+
/// hasFP - Return true if the specified function should have a dedicated
/// frame pointer register. For most targets this is true only if the function
/// has variable sized allocas or if frame pointer elimination is disabled.
@@ -193,6 +201,11 @@ public:
return hasReservedCallFrame(MF) || hasFP(MF);
}
+ // needsFrameIndexResolution - Do we need to perform FI resolution for
+ // this function. Normally, this is required only when the function
+ // has any stack objects. However, targets may want to override this.
+ virtual bool needsFrameIndexResolution(const MachineFunction &MF) const;
+
/// getFrameIndexOffset - Returns the displacement from the frame register to
/// the stack frame of the specified index.
virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
@@ -244,6 +257,30 @@ public:
llvm_unreachable("Call Frame Pseudo Instructions do not exist on this "
"target!");
}
+
+ /// Check whether or not the given \p MBB can be used as a prologue
+ /// for the target.
+ /// The prologue will be inserted first in this basic block.
+ /// This method is used by the shrink-wrapping pass to decide if
+ /// \p MBB will be correctly handled by the target.
+ /// As soon as the target enable shrink-wrapping without overriding
+ /// this method, we assume that each basic block is a valid
+ /// prologue.
+ virtual bool canUseAsPrologue(const MachineBasicBlock &MBB) const {
+ return true;
+ }
+
+ /// Check whether or not the given \p MBB can be used as a epilogue
+ /// for the target.
+ /// The epilogue will be inserted before the first terminator of that block.
+ /// This method is used by the shrink-wrapping pass to decide if
+ /// \p MBB will be correctly handled by the target.
+ /// As soon as the target enable shrink-wrapping without overriding
+ /// this method, we assume that each basic block is a valid
+ /// epilogue.
+ virtual bool canUseAsEpilogue(const MachineBasicBlock &MBB) const {
+ return true;
+ }
};
} // End llvm namespace
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index e8a50fff1fe8..5ec15658b696 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -50,26 +50,28 @@ template<class T> class SmallVectorImpl;
/// TargetInstrInfo - Interface to description of machine instruction set
///
class TargetInstrInfo : public MCInstrInfo {
- TargetInstrInfo(const TargetInstrInfo &) LLVM_DELETED_FUNCTION;
- void operator=(const TargetInstrInfo &) LLVM_DELETED_FUNCTION;
+ TargetInstrInfo(const TargetInstrInfo &) = delete;
+ void operator=(const TargetInstrInfo &) = delete;
public:
- TargetInstrInfo(int CFSetupOpcode = -1, int CFDestroyOpcode = -1)
+ TargetInstrInfo(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u)
: CallFrameSetupOpcode(CFSetupOpcode),
CallFrameDestroyOpcode(CFDestroyOpcode) {
}
virtual ~TargetInstrInfo();
- /// getRegClass - Givem a machine instruction descriptor, returns the register
+ /// Given a machine instruction descriptor, returns the register
/// class constraint for OpNum, or NULL.
const TargetRegisterClass *getRegClass(const MCInstrDesc &TID,
unsigned OpNum,
const TargetRegisterInfo *TRI,
const MachineFunction &MF) const;
- /// isTriviallyReMaterializable - Return true if the instruction is trivially
- /// rematerializable, meaning it has no side effects and requires no operands
- /// that aren't always available.
+ /// Return true if the instruction is trivially rematerializable, meaning it
+ /// has no side effects and requires no operands that aren't always available.
+ /// This means the only allowed uses are constants and unallocatable physical
+ /// registers so that the instructions result is independent of the place
+ /// in the function.
bool isTriviallyReMaterializable(const MachineInstr *MI,
AliasAnalysis *AA = nullptr) const {
return MI->getOpcode() == TargetOpcode::IMPLICIT_DEF ||
@@ -79,35 +81,34 @@ public:
}
protected:
- /// isReallyTriviallyReMaterializable - For instructions with opcodes for
- /// which the M_REMATERIALIZABLE flag is set, this hook lets the target
- /// specify whether the instruction is actually trivially rematerializable,
- /// taking into consideration its operands. This predicate must return false
- /// if the instruction has any side effects other than producing a value, or
- /// if it requres any address registers that are not always available.
+ /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is
+ /// set, this hook lets the target specify whether the instruction is actually
+ /// trivially rematerializable, taking into consideration its operands. This
+ /// predicate must return false if the instruction has any side effects other
+ /// than producing a value, or if it requres any address registers that are
+ /// not always available.
+ /// Requirements must be check as stated in isTriviallyReMaterializable() .
virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI,
AliasAnalysis *AA) const {
return false;
}
private:
- /// isReallyTriviallyReMaterializableGeneric - For instructions with opcodes
- /// for which the M_REMATERIALIZABLE flag is set and the target hook
- /// isReallyTriviallyReMaterializable returns false, this function does
- /// target-independent tests to determine if the instruction is really
- /// trivially rematerializable.
+ /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is
+ /// set and the target hook isReallyTriviallyReMaterializable returns false,
+ /// this function does target-independent tests to determine if the
+ /// instruction is really trivially rematerializable.
bool isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI,
AliasAnalysis *AA) const;
public:
- /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the
- /// frame setup/destroy instructions if they exist (-1 otherwise). Some
- /// targets use pseudo instructions in order to abstract away the difference
- /// between operating with a frame pointer and operating without, through the
- /// use of these two instructions.
+ /// These methods return the opcode of the frame setup/destroy instructions
+ /// if they exist (-1 otherwise). Some targets use pseudo instructions in
+ /// order to abstract away the difference between operating with a frame
+ /// pointer and operating without, through the use of these two instructions.
///
- int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; }
- int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; }
+ unsigned getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; }
+ unsigned 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
@@ -115,19 +116,18 @@ public:
/// 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
- /// true, then it's expected the pre-extension value is available as a subreg
- /// of the result register. This also returns the sub-register index in
- /// SubIdx.
+ /// 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 true, then it's
+ /// expected the pre-extension value is available as a subreg of the result
+ /// register. This also returns the sub-register index in SubIdx.
virtual bool isCoalescableExtInstr(const MachineInstr &MI,
unsigned &SrcReg, unsigned &DstReg,
unsigned &SubIdx) const {
return false;
}
- /// isLoadFromStackSlot - If the specified machine instruction is a direct
+ /// If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
@@ -137,26 +137,24 @@ public:
return 0;
}
- /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination
- /// stack locations as well. This uses a heuristic so it isn't
- /// reliable for correctness.
+ /// Check for post-frame ptr elimination stack locations as well.
+ /// This uses a heuristic so it isn't reliable for correctness.
virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI,
int &FrameIndex) const {
return 0;
}
- /// hasLoadFromStackSlot - If the specified machine instruction has
- /// a load from a stack slot, return true along with the FrameIndex
- /// of the loaded stack slot and the machine mem operand containing
- /// the reference. If not, return false. Unlike
- /// isLoadFromStackSlot, this returns true for any instructions that
- /// loads from the stack. This is just a hint, as some cases may be
- /// missed.
+ /// If the specified machine instruction has a load from a stack slot,
+ /// return true along with the FrameIndex of the loaded stack slot and the
+ /// machine mem operand containing the reference.
+ /// If not, return false. Unlike isLoadFromStackSlot, this returns true for
+ /// any instructions that loads from the stack. This is just a hint, as some
+ /// cases may be missed.
virtual bool hasLoadFromStackSlot(const MachineInstr *MI,
const MachineMemOperand *&MMO,
int &FrameIndex) const;
- /// isStoreToStackSlot - If the specified machine instruction is a direct
+ /// If the specified machine instruction is a direct
/// store to a stack slot, return the virtual or physical register number of
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
@@ -166,25 +164,24 @@ public:
return 0;
}
- /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination
- /// stack locations as well. This uses a heuristic so it isn't
- /// reliable for correctness.
+ /// Check for post-frame ptr elimination stack locations as well.
+ /// This uses a heuristic, so it isn't reliable for correctness.
virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI,
int &FrameIndex) const {
return 0;
}
- /// hasStoreToStackSlot - If the specified machine instruction has a
- /// store to a stack slot, return true along with the FrameIndex of
- /// the loaded stack slot and the machine mem operand containing the
- /// reference. If not, return false. Unlike isStoreToStackSlot,
+ /// If the specified machine instruction has a store to a stack slot,
+ /// return true along with the FrameIndex of the loaded stack slot and the
+ /// machine mem operand containing the reference.
+ /// If not, return false. Unlike isStoreToStackSlot,
/// this returns true for any instructions that stores to the
/// stack. This is just a hint, as some cases may be missed.
virtual bool hasStoreToStackSlot(const MachineInstr *MI,
const MachineMemOperand *&MMO,
int &FrameIndex) const;
- /// isStackSlotCopy - Return true if the specified machine instruction
+ /// Return true if the specified machine instruction
/// is a copy of one stack slot to another and has no other effect.
/// Provide the identity of the two frame indices.
virtual bool isStackSlotCopy(const MachineInstr *MI, int &DestFrameIndex,
@@ -207,10 +204,9 @@ public:
/// this, particularly to support spilled vector registers.
virtual bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx,
unsigned &Size, unsigned &Offset,
- const TargetMachine *TM) const;
+ const MachineFunction &MF) const;
- /// isAsCheapAsAMove - Return true if the instruction is as cheap as a move
- /// instruction.
+ /// 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.
@@ -218,7 +214,7 @@ public:
return MI->isAsCheapAsAMove();
}
- /// reMaterialize - Re-issue the specified 'original' instruction at the
+ /// 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
/// DestReg:SubIdx. Any existing subreg index is preserved or composed with
@@ -229,7 +225,7 @@ public:
const MachineInstr *Orig,
const TargetRegisterInfo &TRI) const;
- /// duplicate - Create a duplicate of the Orig instruction in MF. This is like
+ /// Create a duplicate of the Orig instruction in MF. This is like
/// MachineFunction::CloneMachineInstr(), but the target may update operands
/// that are required to be unique.
///
@@ -237,7 +233,7 @@ public:
virtual MachineInstr *duplicate(MachineInstr *Orig,
MachineFunction &MF) const;
- /// convertToThreeAddress - This method must be implemented by targets that
+ /// This method must be implemented by targets that
/// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target
/// may be able to convert a two-address instruction into one or more true
/// three-address instructions on demand. This allows the X86 target (for
@@ -253,10 +249,10 @@ public:
return nullptr;
}
- /// commuteInstruction - If a target has any instructions that are
- /// commutable but require converting to different instructions or making
- /// non-trivial changes to commute them, this method can overloaded to do
- /// that. The default implementation simply swaps the commutable operands.
+ /// If a target has any instructions that are commutable but require
+ /// converting to different instructions or making non-trivial changes to
+ /// commute them, this method can overloaded to do that.
+ /// The default implementation simply swaps the commutable operands.
/// If NewMI is false, MI is modified in place and returned; otherwise, a
/// new machine instruction is created and returned. Do not call this
/// method for a non-commutable instruction, but there may be some cases
@@ -264,8 +260,8 @@ public:
virtual MachineInstr *commuteInstruction(MachineInstr *MI,
bool NewMI = false) const;
- /// findCommutedOpIndices - If specified MI is commutable, return the two
- /// operand indices that would swap value. Return false if the instruction
+ /// If specified MI is commutable, return the two operand indices that would
+ /// swap value. Return false if the instruction
/// is not in a form which this routine understands.
virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
unsigned &SrcOpIdx2) const;
@@ -349,8 +345,8 @@ public:
RegSubRegPairAndIdx &InsertedReg) const;
- /// produceSameValue - Return true if two machine instructions would produce
- /// identical values. By default, this is only true when the two instructions
+ /// 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
/// IR is still in SSA form, the caller can pass the MachineRegisterInfo for
/// aggressive checks.
@@ -358,7 +354,7 @@ public:
const MachineInstr *MI1,
const MachineRegisterInfo *MRI = nullptr) const;
- /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
+ /// Analyze the branching code at the end of MBB, returning
/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
/// implemented for a target). Upon success, this returns false and returns
/// with the following information in various cases:
@@ -390,15 +386,15 @@ public:
return true;
}
- /// RemoveBranch - Remove the branching code at the end of the specific MBB.
+ /// Remove the branching code at the end of the specific MBB.
/// This is only invoked in cases where AnalyzeBranch returns success. It
/// returns the number of instructions that were removed.
virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const {
llvm_unreachable("Target didn't implement TargetInstrInfo::RemoveBranch!");
}
- /// InsertBranch - Insert branch code into the end of the specified
- /// MachineBasicBlock. The operands to this method are the same as those
+ /// Insert branch code into the end of the specified MachineBasicBlock.
+ /// The operands to this method are the same as those
/// returned by AnalyzeBranch. This is only invoked in cases where
/// AnalyzeBranch returns success. It returns the number of instructions
/// inserted.
@@ -414,14 +410,13 @@ public:
llvm_unreachable("Target didn't implement TargetInstrInfo::InsertBranch!");
}
- /// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything
- /// after it, replacing it with an unconditional branch to NewDest. This is
- /// used by the tail merging pass.
+ /// Delete the instruction OldInst and everything after it, replacing it with
+ /// an unconditional branch to NewDest. This is used by the tail merging pass.
virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail,
MachineBasicBlock *NewDest) const;
- /// getUnconditionalBranch - Get an instruction that performs an unconditional
- /// branch to the given symbol.
+ /// Get an instruction that performs an unconditional branch to the given
+ /// symbol.
virtual void
getUnconditionalBranch(MCInst &MI,
const MCSymbolRefExpr *BranchTarget) const {
@@ -429,12 +424,12 @@ public:
"TargetInstrInfo::getUnconditionalBranch!");
}
- /// getTrap - Get a machine trap instruction
+ /// Get a machine trap instruction.
virtual void getTrap(MCInst &MI) const {
llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!");
}
- /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold
+ /// 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
@@ -454,7 +449,7 @@ public:
return 0;
}
- /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic
+ /// 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).
virtual bool isLegalToSplitMBBAt(MachineBasicBlock &MBB,
@@ -462,7 +457,7 @@ public:
return true;
}
- /// isProfitableToIfCvt - Return true if it's profitable to predicate
+ /// Return true if it's profitable to predicate
/// instructions with accumulated instruction latency of "NumCycles"
/// of the specified basic block, where the probability of the instructions
/// being executed is given by Probability, and Confidence is a measure
@@ -474,7 +469,7 @@ public:
return false;
}
- /// isProfitableToIfCvt - Second variant of isProfitableToIfCvt, this one
+ /// Second variant of isProfitableToIfCvt. This one
/// checks for the case where two basic blocks from true and false path
/// of a if-then-else (diamond) are predicated on mutally exclusive
/// predicates, where the probability of the true path being taken is given
@@ -489,9 +484,9 @@ public:
return false;
}
- /// isProfitableToDupForIfCvt - Return true if it's profitable for
- /// if-converter to duplicate instructions of specified accumulated
- /// instruction latencies in the specified MBB to enable if-conversion.
+ /// Return true if it's profitable for if-converter to duplicate instructions
+ /// of specified accumulated instruction latencies in the specified MBB to
+ /// enable if-conversion.
/// The probability of the instructions being executed is given by
/// Probability, and Confidence is a measure of our confidence that it
/// will be properly predicted.
@@ -501,7 +496,7 @@ public:
return false;
}
- /// isProfitableToUnpredicate - Return true if it's profitable to unpredicate
+ /// Return true if it's profitable to unpredicate
/// one side of a 'diamond', i.e. two sides of if-else predicated on mutually
/// exclusive predicates.
/// e.g.
@@ -517,7 +512,7 @@ public:
return false;
}
- /// canInsertSelect - Return true if it is possible to insert a select
+ /// Return true if it is possible to insert a select
/// instruction that chooses between TrueReg and FalseReg based on the
/// condition code in Cond.
///
@@ -542,9 +537,8 @@ public:
return false;
}
- /// insertSelect - Insert a select instruction into MBB before I that will
- /// copy TrueReg to DstReg when Cond is true, and FalseReg to DstReg when
- /// Cond is false.
+ /// Insert a select instruction into MBB before I that will copy TrueReg to
+ /// DstReg when Cond is true, and FalseReg to DstReg when Cond is false.
///
/// This function can only be called after canInsertSelect() returned true.
/// The condition in Cond comes from AnalyzeBranch, and it can be assumed
@@ -566,7 +560,7 @@ public:
llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!");
}
- /// analyzeSelect - Analyze the given select instruction, returning true if
+ /// Analyze the given select instruction, returning true if
/// it cannot be understood. It is assumed that MI->isSelect() is true.
///
/// When successful, return the controlling condition and the operands that
@@ -592,7 +586,7 @@ public:
return true;
}
- /// optimizeSelect - Given a select instruction that was understood by
+ /// Given a select instruction that was understood by
/// analyzeSelect and returned Optimizable = true, attempt to optimize MI by
/// merging it with one of its operands. Returns NULL on failure.
///
@@ -614,7 +608,7 @@ public:
llvm_unreachable("Target must implement TargetInstrInfo::optimizeSelect!");
}
- /// copyPhysReg - Emit instructions to copy a pair of physical registers.
+ /// Emit instructions to copy a pair of physical registers.
///
/// This function should support copies within any legal register class as
/// well as any cross-class copies created during instruction selection.
@@ -629,11 +623,10 @@ public:
llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!");
}
- /// storeRegToStackSlot - Store the specified register of the given register
- /// class to the specified stack frame index. The store instruction is to be
- /// added to the given machine basic block before the specified machine
- /// instruction. If isKill is true, the register operand is the last use and
- /// must be marked kill.
+ /// Store the specified register of the given register class to the specified
+ /// stack frame index. The store instruction is to be added to the given
+ /// machine basic block before the specified machine instruction. If isKill
+ /// is true, the register operand is the last use and must be marked kill.
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned SrcReg, bool isKill, int FrameIndex,
@@ -643,10 +636,9 @@ public:
"TargetInstrInfo::storeRegToStackSlot!");
}
- /// loadRegFromStackSlot - Load the specified register of the given register
- /// class from the specified stack frame index. The load instruction is to be
- /// added to the given machine basic block before the specified machine
- /// instruction.
+ /// Load the specified register of the given register class from the specified
+ /// stack frame index. The load instruction is to be added to the given
+ /// machine basic block before the specified machine instruction.
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, int FrameIndex,
@@ -656,7 +648,7 @@ public:
"TargetInstrInfo::loadRegFromStackSlot!");
}
- /// expandPostRAPseudo - This function is called for all pseudo instructions
+ /// This function is called for all pseudo instructions
/// that remain after register allocation. Many pseudo instructions are
/// created to help register allocation. This is the place to convert them
/// into real instructions. The target can edit MI in place, or it can insert
@@ -666,46 +658,42 @@ public:
return false;
}
- /// foldMemoryOperand - Attempt to fold a load or store of the specified stack
+ /// Attempt to fold a load or store of the specified stack
/// slot into the specified machine instruction for the specified operand(s).
/// If this is possible, a new instruction is returned with the specified
/// operand folded, otherwise NULL is returned.
/// The new instruction is inserted before MI, and the client is responsible
/// for removing the old instruction.
- MachineInstr* foldMemoryOperand(MachineBasicBlock::iterator MI,
- const SmallVectorImpl<unsigned> &Ops,
- int FrameIndex) const;
-
- /// foldMemoryOperand - Same as the previous version except it allows folding
- /// of any load and store from / to any address, not just from a specific
- /// stack slot.
- MachineInstr* foldMemoryOperand(MachineBasicBlock::iterator MI,
- 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
+ MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI,
+ ArrayRef<unsigned> Ops, int FrameIndex) const;
+
+ /// Same as the previous version except it allows folding of any load and
+ /// store from / to any address, not just from a specific stack slot.
+ MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI,
+ ArrayRef<unsigned> Ops,
+ MachineInstr *LoadMI) const;
+
+ /// Return true when there is potentially a faster code sequence
+ /// for an instruction chain ending in \p Root. All potential patterns 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.
+ /// 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 replacement 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 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(
@@ -716,27 +704,27 @@ public:
return;
}
- /// useMachineCombiner - return true when a target supports MachineCombiner
+ /// 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
+ /// Target-dependent implementation for foldMemoryOperand.
+ /// Target-independent code in foldMemoryOperand will
/// take care of adding a MachineMemOperand to the newly created instruction.
- virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
- MachineInstr* MI,
- const SmallVectorImpl<unsigned> &Ops,
- int FrameIndex) const {
+ virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF,
+ MachineInstr *MI,
+ ArrayRef<unsigned> Ops,
+ int FrameIndex) const {
return nullptr;
}
- /// foldMemoryOperandImpl - Target-dependent implementation for
- /// foldMemoryOperand. Target-independent code in foldMemoryOperand will
+ /// Target-dependent implementation for foldMemoryOperand.
+ /// Target-independent code in foldMemoryOperand will
/// take care of adding a MachineMemOperand to the newly created instruction.
- virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
- MachineInstr* MI,
- const SmallVectorImpl<unsigned> &Ops,
- MachineInstr* LoadMI) const {
+ virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF,
+ MachineInstr *MI,
+ ArrayRef<unsigned> Ops,
+ MachineInstr *LoadMI) const {
return nullptr;
}
@@ -784,11 +772,9 @@ protected:
}
public:
- /// canFoldMemoryOperand - Returns true for the specified load / store if
- /// folding is possible.
- virtual
- bool canFoldMemoryOperand(const MachineInstr *MI,
- const SmallVectorImpl<unsigned> &Ops) const;
+ /// Returns true for the specified load / store if folding is possible.
+ virtual bool canFoldMemoryOperand(const MachineInstr *MI,
+ ArrayRef<unsigned> Ops) const;
/// unfoldMemoryOperand - Separate a single instruction which folded a load or
/// a store or a load and a store into two or more instruction. If this is
@@ -804,7 +790,7 @@ public:
return false;
}
- /// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new
+ /// Returns the opcode of the would be new
/// instruction after load / store are unfolded from an instruction of the
/// specified opcode. It returns zero if the specified unfolding is not
/// possible. If LoadRegIndex is non-null, it is filled in with the operand
@@ -816,19 +802,18 @@ public:
return 0;
}
- /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler
- /// to determine if two loads are loading from the same base address. It
- /// should only return true if the base pointers are the same and the
- /// only differences between the two addresses are the offset. It also returns
- /// the offsets by reference.
+ /// This is used by the pre-regalloc scheduler to determine if two loads are
+ /// loading from the same base address. It should only return true if the base
+ /// pointers are the same and the only differences between the two addresses
+ /// are the offset. It also returns the offsets by reference.
virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
int64_t &Offset1, int64_t &Offset2) const {
return false;
}
- /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to
- /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should
- /// be scheduled togther. On some targets if two loads are loading from
+ /// This is a used by the pre-regalloc scheduler to determine (in conjunction
+ /// with areLoadsFromSameBasePtr) if two loads should be scheduled together.
+ /// On some targets if two loads are loading from
/// addresses in the same cache line, it's better if they are scheduled
/// together. This function takes two integers that represent the load offsets
/// from the common base address. It returns true if it decides it's desirable
@@ -840,7 +825,7 @@ public:
return false;
}
- /// \brief Get the base register and byte offset of a load/store instr.
+ /// Get the base register and byte offset of a load/store instr.
virtual bool getLdStBaseRegImmOfs(MachineInstr *LdSt,
unsigned &BaseReg, unsigned &Offset,
const TargetRegisterInfo *TRI) const {
@@ -855,23 +840,21 @@ public:
return false;
}
- /// \brief Can this target fuse the given instructions if they are scheduled
+ /// Can this target fuse the given instructions if they are scheduled
/// adjacent.
virtual bool shouldScheduleAdjacent(MachineInstr* First,
MachineInstr *Second) const {
return false;
}
- /// ReverseBranchCondition - Reverses the branch condition of the specified
- /// condition list, returning false on success and true if it cannot be
- /// reversed.
+ /// Reverses the branch condition of the specified condition list,
+ /// returning false on success and true if it cannot be reversed.
virtual
bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
return true;
}
- /// insertNoop - Insert a noop into the instruction stream at the specified
- /// point.
+ /// Insert a noop into the instruction stream at the specified point.
virtual void insertNoop(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const;
@@ -880,23 +863,22 @@ public:
virtual void getNoopForMachoTarget(MCInst &NopInst) const;
- /// isPredicated - Returns true if the instruction is already predicated.
- ///
+ /// Returns true if the instruction is already predicated.
virtual bool isPredicated(const MachineInstr *MI) const {
return false;
}
- /// isUnpredicatedTerminator - Returns true if the instruction is a
+ /// Returns true if the instruction is a
/// terminator instruction that has not been predicated.
virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const;
- /// PredicateInstruction - Convert the instruction into a predicated
- /// instruction. It returns true if the operation was successful.
+ /// Convert the instruction into a predicated instruction.
+ /// It returns true if the operation was successful.
virtual
bool PredicateInstruction(MachineInstr *MI,
const SmallVectorImpl<MachineOperand> &Pred) const;
- /// SubsumesPredicate - Returns true if the first specified predicate
+ /// Returns true if the first specified predicate
/// subsumes the second, e.g. GE subsumes GT.
virtual
bool SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
@@ -904,7 +886,7 @@ public:
return false;
}
- /// DefinesPredicate - If the specified instruction defines any predicate
+ /// If the specified instruction defines any predicate
/// or condition code register(s) used for predication, returns true as well
/// as the definition predicate(s) by reference.
virtual bool DefinesPredicate(MachineInstr *MI,
@@ -912,22 +894,21 @@ public:
return false;
}
- /// isPredicable - Return true if the specified instruction can be predicated.
+ /// Return true if the specified instruction can be predicated.
/// By default, this returns true for every instruction with a
/// PredicateOperand.
virtual bool isPredicable(MachineInstr *MI) const {
return MI->getDesc().isPredicable();
}
- /// isSafeToMoveRegClassDefs - Return true if it's safe to move a machine
+ /// Return true if it's safe to move a machine
/// instruction that defines the specified register class.
virtual bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const {
return true;
}
- /// isSchedulingBoundary - Test if the given instruction should be
- /// considered a scheduling boundary. This primarily includes labels and
- /// terminators.
+ /// Test if the given instruction should be considered a scheduling boundary.
+ /// This primarily includes labels and terminators.
virtual bool isSchedulingBoundary(const MachineInstr *MI,
const MachineBasicBlock *MBB,
const MachineFunction &MF) const;
@@ -937,23 +918,20 @@ public:
virtual unsigned getInlineAsmLength(const char *Str,
const MCAsmInfo &MAI) const;
- /// CreateTargetHazardRecognizer - Allocate and return a hazard recognizer to
- /// use for this target when scheduling the machine instructions before
- /// register allocation.
+ /// Allocate and return a hazard recognizer to use for this target when
+ /// scheduling the machine instructions before register allocation.
virtual ScheduleHazardRecognizer*
CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI,
const ScheduleDAG *DAG) const;
- /// CreateTargetMIHazardRecognizer - Allocate and return a hazard recognizer
- /// to use for this target when scheduling the machine instructions before
- /// register allocation.
+ /// Allocate and return a hazard recognizer to use for this target when
+ /// scheduling the machine instructions before register allocation.
virtual ScheduleHazardRecognizer*
CreateTargetMIHazardRecognizer(const InstrItineraryData*,
const ScheduleDAG *DAG) const;
- /// CreateTargetPostRAHazardRecognizer - Allocate and return a hazard
- /// recognizer to use for this target when scheduling the machine instructions
- /// after register allocation.
+ /// Allocate and return a hazard recognizer to use for this target when
+ /// scheduling the machine instructions after register allocation.
virtual ScheduleHazardRecognizer*
CreateTargetPostRAHazardRecognizer(const InstrItineraryData*,
const ScheduleDAG *DAG) const;
@@ -962,7 +940,7 @@ public:
/// targets may choose to honor.
bool usePreRAHazardRecognizer() const;
- /// analyzeCompare - For a comparison instruction, return the source registers
+ /// For a comparison instruction, return the source registers
/// in SrcReg and SrcReg2 if having two register operands, and the value it
/// compares against in CmpValue. Return true if the comparison instruction
/// can be analyzed.
@@ -972,7 +950,7 @@ public:
return false;
}
- /// optimizeCompareInstr - See if the comparison instruction can be converted
+ /// See if the comparison instruction can be converted
/// into something more efficient. E.g., on ARM most instructions can set the
/// flags register, obviating the need for a separate CMP.
virtual bool optimizeCompareInstr(MachineInstr *CmpInstr,
@@ -983,8 +961,8 @@ public:
}
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
+ /// 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
/// def and use are in the same BB. We only look at one load and see
/// whether it can be folded into MI. FoldAsLoadDefReg is the virtual register
/// defined by the load we are trying to fold. DefMI returns the machine
@@ -997,8 +975,8 @@ public:
return nullptr;
}
- /// FoldImmediate - 'Reg' is known to be defined by a move immediate
- /// instruction, try to fold the immediate into the use instruction.
+ /// 'Reg' is known to be defined by a move immediate instruction,
+ /// try to fold the immediate into the use instruction.
/// If MRI->hasOneNonDBGUse(Reg) is true, and this function returns true,
/// then the caller may assume that DefMI has been erased from its parent
/// block. The caller may assume that it will not be erased by this
@@ -1008,14 +986,14 @@ public:
return false;
}
- /// getNumMicroOps - Return the number of u-operations the given machine
+ /// Return the number of u-operations the given machine
/// instruction will be decoded to on the target cpu. The itinerary's
/// IssueWidth is the number of microops that can be dispatched each
/// cycle. An instruction with zero microops takes no dispatch resources.
virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData,
const MachineInstr *MI) const;
- /// isZeroCost - Return true for pseudo instructions that don't consume any
+ /// Return true for pseudo instructions that don't consume any
/// machine resources in their current form. These are common cases that the
/// scheduler should consider free, rather than conservatively handling them
/// as instructions with no itinerary.
@@ -1027,27 +1005,27 @@ public:
SDNode *DefNode, unsigned DefIdx,
SDNode *UseNode, unsigned UseIdx) const;
- /// getOperandLatency - Compute and return the use operand latency of a given
- /// pair of def and use.
+ /// Compute and return the use operand latency of a given pair of def and use.
/// In most cases, the static scheduling itinerary was enough to determine the
/// operand latency. But it may not be possible for instructions with variable
/// number of defs / uses.
///
- /// This is a raw interface to the itinerary that may be directly overriden by
- /// a target. Use computeOperandLatency to get the best estimate of latency.
+ /// This is a raw interface to the itinerary that may be directly overridden
+ /// by a target. Use computeOperandLatency to get the best estimate of
+ /// latency.
virtual int getOperandLatency(const InstrItineraryData *ItinData,
const MachineInstr *DefMI, unsigned DefIdx,
const MachineInstr *UseMI,
unsigned UseIdx) const;
- /// computeOperandLatency - Compute and return the latency of the given data
+ /// Compute and return the latency of the given data
/// dependent def and use when the operand indices are already known.
unsigned computeOperandLatency(const InstrItineraryData *ItinData,
const MachineInstr *DefMI, unsigned DefIdx,
const MachineInstr *UseMI, unsigned UseIdx)
const;
- /// getInstrLatency - Compute the instruction latency of a given instruction.
+ /// Compute the instruction latency of a given instruction.
/// If the instruction has higher cost when predicated, it's returned via
/// PredCost.
virtual unsigned getInstrLatency(const InstrItineraryData *ItinData,
@@ -1066,14 +1044,13 @@ public:
int computeDefOperandLatency(const InstrItineraryData *ItinData,
const MachineInstr *DefMI) const;
- /// isHighLatencyDef - Return true if this opcode has high latency to its
- /// result.
+ /// Return true if this opcode has high latency to its result.
virtual bool isHighLatencyDef(int opc) const { return false; }
- /// hasHighOperandLatency - Compute operand latency between a def of 'Reg'
- /// and an use in the current loop, return true if the target considered
+ /// Compute operand latency between a def of 'Reg'
+ /// and a use in the current loop. Return true if the target considered
/// it 'high'. This is used by optimization passes such as machine LICM to
- /// determine whether it makes sense to hoist an instruction out even in
+ /// determine whether it makes sense to hoist an instruction out even in a
/// high register pressure situation.
virtual
bool hasHighOperandLatency(const InstrItineraryData *ItinData,
@@ -1083,19 +1060,19 @@ public:
return false;
}
- /// hasLowDefLatency - Compute operand latency of a def of 'Reg', return true
+ /// Compute operand latency of a def of 'Reg'. Return true
/// if the target considered it 'low'.
virtual
bool hasLowDefLatency(const InstrItineraryData *ItinData,
const MachineInstr *DefMI, unsigned DefIdx) const;
- /// verifyInstruction - Perform target specific instruction verification.
+ /// Perform target-specific instruction verification.
virtual
bool verifyInstruction(const MachineInstr *MI, StringRef &ErrInfo) const {
return true;
}
- /// getExecutionDomain - Return the current execution domain and bit mask of
+ /// Return the current execution domain and bit mask of
/// possible domains for instruction.
///
/// Some micro-architectures have multiple execution domains, and multiple
@@ -1119,15 +1096,14 @@ public:
return std::make_pair(0, 0);
}
- /// setExecutionDomain - Change the opcode of MI to execute in Domain.
+ /// Change the opcode of MI to execute in Domain.
///
/// The bit (1 << Domain) must be set in the mask returned from
/// getExecutionDomain(MI).
- ///
virtual void setExecutionDomain(MachineInstr *MI, unsigned Domain) const {}
- /// getPartialRegUpdateClearance - Returns the preferred minimum clearance
+ /// Returns the preferred minimum clearance
/// before an instruction with an unwanted partial register update.
///
/// Some instructions only write part of a register, and implicitly need to
@@ -1176,7 +1152,7 @@ public:
/// \brief Return the minimum clearance before an instruction that reads an
/// unused register.
///
- /// For example, AVX instructions may copy part of an register operand into
+ /// For example, AVX instructions may copy part of a register operand into
/// the unused high bits of the destination register.
///
/// vcvtsi2sdq %rax, %xmm0<undef>, %xmm14
@@ -1193,7 +1169,7 @@ public:
return 0;
}
- /// breakPartialRegDependency - Insert a dependency-breaking instruction
+ /// Insert a dependency-breaking instruction
/// before MI to eliminate an unwanted dependency on OpNum.
///
/// If it wasn't possible to avoid a def in the last N instructions before MI
@@ -1220,10 +1196,10 @@ public:
return nullptr;
}
- // areMemAccessesTriviallyDisjoint - Sometimes, it is possible for the target
+ // 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.
+ // memory addresses and false otherwise.
virtual bool
areMemAccessesTriviallyDisjoint(MachineInstr *MIa, MachineInstr *MIb,
AliasAnalysis *AA = nullptr) const {
@@ -1234,8 +1210,16 @@ public:
return false;
}
+ /// \brief Return the value to use for the MachineCSE's LookAheadLimit,
+ /// which is a heuristic used for CSE'ing phys reg defs.
+ virtual unsigned getMachineCSELookAheadLimit () const {
+ // The default lookahead is small to prevent unprofitable quadratic
+ // behavior.
+ return 5;
+ }
+
private:
- int CallFrameSetupOpcode, CallFrameDestroyOpcode;
+ unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;
};
} // End llvm namespace
diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h
index 71c0166d49b0..c630f5b12a15 100644
--- a/include/llvm/Target/TargetIntrinsicInfo.h
+++ b/include/llvm/Target/TargetIntrinsicInfo.h
@@ -28,8 +28,8 @@ class Type;
/// TargetIntrinsicInfo - Interface to description of machine instruction set
///
class TargetIntrinsicInfo {
- TargetIntrinsicInfo(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION;
- void operator=(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION;
+ TargetIntrinsicInfo(const TargetIntrinsicInfo &) = delete;
+ void operator=(const TargetIntrinsicInfo &) = delete;
public:
TargetIntrinsicInfo();
virtual ~TargetIntrinsicInfo();
diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h
deleted file mode 100644
index 46f87b93b001..000000000000
--- a/include/llvm/Target/TargetLibraryInfo.h
+++ /dev/null
@@ -1,802 +0,0 @@
-//===-- llvm/Target/TargetLibraryInfo.h - Library information ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_TARGETLIBRARYINFO_H
-#define LLVM_TARGET_TARGETLIBRARYINFO_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Pass.h"
-
-namespace llvm {
- class Triple;
-
- namespace LibFunc {
- enum Func {
- /// int _IO_getc(_IO_FILE * __fp);
- under_IO_getc,
- /// int _IO_putc(int __c, _IO_FILE * __fp);
- under_IO_putc,
- /// void operator delete[](void*);
- ZdaPv,
- /// void operator delete[](void*, nothrow);
- ZdaPvRKSt9nothrow_t,
- /// void operator delete[](void*, unsigned int);
- ZdaPvj,
- /// void operator delete[](void*, unsigned long);
- ZdaPvm,
- /// void operator delete(void*);
- ZdlPv,
- /// void operator delete(void*, nothrow);
- ZdlPvRKSt9nothrow_t,
- /// void operator delete(void*, unsigned int);
- ZdlPvj,
- /// void operator delete(void*, unsigned long);
- ZdlPvm,
- /// void *new[](unsigned int);
- Znaj,
- /// void *new[](unsigned int, nothrow);
- ZnajRKSt9nothrow_t,
- /// void *new[](unsigned long);
- Znam,
- /// void *new[](unsigned long, nothrow);
- ZnamRKSt9nothrow_t,
- /// void *new(unsigned int);
- Znwj,
- /// void *new(unsigned int, nothrow);
- ZnwjRKSt9nothrow_t,
- /// void *new(unsigned long);
- Znwm,
- /// void *new(unsigned long, nothrow);
- ZnwmRKSt9nothrow_t,
- /// double __cospi(double x);
- cospi,
- /// float __cospif(float x);
- cospif,
- /// int __cxa_atexit(void (*f)(void *), void *p, void *d);
- cxa_atexit,
- /// void __cxa_guard_abort(guard_t *guard);
- /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi.
- cxa_guard_abort,
- /// int __cxa_guard_acquire(guard_t *guard);
- cxa_guard_acquire,
- /// void __cxa_guard_release(guard_t *guard);
- cxa_guard_release,
- /// int __isoc99_scanf (const char *format, ...)
- dunder_isoc99_scanf,
- /// int __isoc99_sscanf(const char *s, const char *format, ...)
- dunder_isoc99_sscanf,
- /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size);
- memcpy_chk,
- /// void *__memmove_chk(void *s1, const void *s2, size_t n,
- /// size_t s1size);
- memmove_chk,
- /// void *__memset_chk(void *s, char v, size_t n, size_t s1size);
- memset_chk,
- /// double __sincospi_stret(double x);
- sincospi_stret,
- /// float __sincospif_stret(float x);
- sincospif_stret,
- /// double __sinpi(double x);
- sinpi,
- /// float __sinpif(float x);
- sinpif,
- /// double __sqrt_finite(double x);
- sqrt_finite,
- /// float __sqrt_finite(float x);
- sqrtf_finite,
- /// long double __sqrt_finite(long double x);
- sqrtl_finite,
- /// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size);
- stpcpy_chk,
- /// char *__stpncpy_chk(char *s1, const char *s2, size_t n,
- /// size_t s1size);
- stpncpy_chk,
- /// char *__strcpy_chk(char *s1, const char *s2, size_t s1size);
- strcpy_chk,
- /// char * __strdup(const char *s);
- dunder_strdup,
- /// char *__strncpy_chk(char *s1, const char *s2, size_t n,
- /// size_t s1size);
- strncpy_chk,
- /// char *__strndup(const char *s, size_t n);
- dunder_strndup,
- /// char * __strtok_r(char *s, const char *delim, char **save_ptr);
- dunder_strtok_r,
- /// int abs(int j);
- abs,
- /// int access(const char *path, int amode);
- access,
- /// double acos(double x);
- acos,
- /// float acosf(float x);
- acosf,
- /// double acosh(double x);
- acosh,
- /// float acoshf(float x);
- acoshf,
- /// long double acoshl(long double x);
- acoshl,
- /// long double acosl(long double x);
- acosl,
- /// double asin(double x);
- asin,
- /// float asinf(float x);
- asinf,
- /// double asinh(double x);
- asinh,
- /// float asinhf(float x);
- asinhf,
- /// long double asinhl(long double x);
- asinhl,
- /// long double asinl(long double x);
- asinl,
- /// double atan(double x);
- atan,
- /// double atan2(double y, double x);
- atan2,
- /// float atan2f(float y, float x);
- atan2f,
- /// long double atan2l(long double y, long double x);
- atan2l,
- /// float atanf(float x);
- atanf,
- /// double atanh(double x);
- atanh,
- /// float atanhf(float x);
- atanhf,
- /// long double atanhl(long double x);
- atanhl,
- /// long double atanl(long double x);
- atanl,
- /// double atof(const char *str);
- atof,
- /// int atoi(const char *str);
- atoi,
- /// long atol(const char *str);
- atol,
- /// long long atoll(const char *nptr);
- atoll,
- /// int bcmp(const void *s1, const void *s2, size_t n);
- bcmp,
- /// void bcopy(const void *s1, void *s2, size_t n);
- bcopy,
- /// void bzero(void *s, size_t n);
- bzero,
- /// void *calloc(size_t count, size_t size);
- calloc,
- /// double cbrt(double x);
- cbrt,
- /// float cbrtf(float x);
- cbrtf,
- /// long double cbrtl(long double x);
- cbrtl,
- /// double ceil(double x);
- ceil,
- /// float ceilf(float x);
- ceilf,
- /// long double ceill(long double x);
- ceill,
- /// int chmod(const char *path, mode_t mode);
- chmod,
- /// int chown(const char *path, uid_t owner, gid_t group);
- chown,
- /// void clearerr(FILE *stream);
- clearerr,
- /// int closedir(DIR *dirp);
- closedir,
- /// double copysign(double x, double y);
- copysign,
- /// float copysignf(float x, float y);
- copysignf,
- /// long double copysignl(long double x, long double y);
- copysignl,
- /// double cos(double x);
- cos,
- /// float cosf(float x);
- cosf,
- /// double cosh(double x);
- cosh,
- /// float coshf(float x);
- coshf,
- /// long double coshl(long double x);
- coshl,
- /// long double cosl(long double x);
- cosl,
- /// char *ctermid(char *s);
- ctermid,
- /// double exp(double x);
- exp,
- /// double exp10(double x);
- exp10,
- /// float exp10f(float x);
- exp10f,
- /// long double exp10l(long double x);
- exp10l,
- /// double exp2(double x);
- exp2,
- /// float exp2f(float x);
- exp2f,
- /// long double exp2l(long double x);
- exp2l,
- /// float expf(float x);
- expf,
- /// long double expl(long double x);
- expl,
- /// double expm1(double x);
- expm1,
- /// float expm1f(float x);
- expm1f,
- /// long double expm1l(long double x);
- expm1l,
- /// double fabs(double x);
- fabs,
- /// float fabsf(float x);
- fabsf,
- /// long double fabsl(long double x);
- fabsl,
- /// int fclose(FILE *stream);
- fclose,
- /// FILE *fdopen(int fildes, const char *mode);
- fdopen,
- /// int feof(FILE *stream);
- feof,
- /// int ferror(FILE *stream);
- ferror,
- /// int fflush(FILE *stream);
- fflush,
- /// int ffs(int i);
- ffs,
- /// int ffsl(long int i);
- ffsl,
- /// int ffsll(long long int i);
- ffsll,
- /// int fgetc(FILE *stream);
- fgetc,
- /// int fgetpos(FILE *stream, fpos_t *pos);
- fgetpos,
- /// char *fgets(char *s, int n, FILE *stream);
- fgets,
- /// int fileno(FILE *stream);
- fileno,
- /// int fiprintf(FILE *stream, const char *format, ...);
- fiprintf,
- /// void flockfile(FILE *file);
- flockfile,
- /// double floor(double x);
- floor,
- /// float floorf(float x);
- floorf,
- /// long double floorl(long double x);
- floorl,
- /// double fmax(double x, double y);
- fmax,
- /// float fmaxf(float x, float y);
- fmaxf,
- /// long double fmaxl(long double x, long double y);
- fmaxl,
- /// double fmin(double x, double y);
- fmin,
- /// float fminf(float x, float y);
- fminf,
- /// long double fminl(long double x, long double y);
- fminl,
- /// double fmod(double x, double y);
- fmod,
- /// float fmodf(float x, float y);
- fmodf,
- /// long double fmodl(long double x, long double y);
- fmodl,
- /// FILE *fopen(const char *filename, const char *mode);
- fopen,
- /// FILE *fopen64(const char *filename, const char *opentype)
- fopen64,
- /// int fprintf(FILE *stream, const char *format, ...);
- fprintf,
- /// int fputc(int c, FILE *stream);
- fputc,
- /// int fputs(const char *s, FILE *stream);
- fputs,
- /// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
- fread,
- /// void free(void *ptr);
- free,
- /// double frexp(double num, int *exp);
- frexp,
- /// float frexpf(float num, int *exp);
- frexpf,
- /// long double frexpl(long double num, int *exp);
- frexpl,
- /// int fscanf(FILE *stream, const char *format, ... );
- fscanf,
- /// int fseek(FILE *stream, long offset, int whence);
- fseek,
- /// int fseeko(FILE *stream, off_t offset, int whence);
- fseeko,
- /// int fseeko64(FILE *stream, off64_t offset, int whence)
- fseeko64,
- /// int fsetpos(FILE *stream, const fpos_t *pos);
- fsetpos,
- /// int fstat(int fildes, struct stat *buf);
- fstat,
- /// int fstat64(int filedes, struct stat64 *buf)
- fstat64,
- /// int fstatvfs(int fildes, struct statvfs *buf);
- fstatvfs,
- /// int fstatvfs64(int fildes, struct statvfs64 *buf);
- fstatvfs64,
- /// long ftell(FILE *stream);
- ftell,
- /// off_t ftello(FILE *stream);
- ftello,
- /// off64_t ftello64(FILE *stream)
- ftello64,
- /// int ftrylockfile(FILE *file);
- ftrylockfile,
- /// void funlockfile(FILE *file);
- funlockfile,
- /// size_t fwrite(const void *ptr, size_t size, size_t nitems,
- /// FILE *stream);
- fwrite,
- /// int getc(FILE *stream);
- getc,
- /// int getc_unlocked(FILE *stream);
- getc_unlocked,
- /// int getchar(void);
- getchar,
- /// char *getenv(const char *name);
- getenv,
- /// int getitimer(int which, struct itimerval *value);
- getitimer,
- /// int getlogin_r(char *name, size_t namesize);
- getlogin_r,
- /// struct passwd *getpwnam(const char *name);
- getpwnam,
- /// char *gets(char *s);
- gets,
- /// int gettimeofday(struct timeval *tp, void *tzp);
- gettimeofday,
- /// uint32_t htonl(uint32_t hostlong);
- htonl,
- /// uint16_t htons(uint16_t hostshort);
- htons,
- /// int iprintf(const char *format, ...);
- iprintf,
- /// int isascii(int c);
- isascii,
- /// int isdigit(int c);
- isdigit,
- /// long int labs(long int j);
- labs,
- /// int lchown(const char *path, uid_t owner, gid_t group);
- lchown,
- /// double ldexp(double x, int n);
- ldexp,
- /// float ldexpf(float x, int n);
- ldexpf,
- /// long double ldexpl(long double x, int n);
- ldexpl,
- /// long long int llabs(long long int j);
- llabs,
- /// double log(double x);
- log,
- /// double log10(double x);
- log10,
- /// float log10f(float x);
- log10f,
- /// long double log10l(long double x);
- log10l,
- /// double log1p(double x);
- log1p,
- /// float log1pf(float x);
- log1pf,
- /// long double log1pl(long double x);
- log1pl,
- /// double log2(double x);
- log2,
- /// float log2f(float x);
- log2f,
- /// double long double log2l(long double x);
- log2l,
- /// double logb(double x);
- logb,
- /// float logbf(float x);
- logbf,
- /// long double logbl(long double x);
- logbl,
- /// float logf(float x);
- logf,
- /// long double logl(long double x);
- logl,
- /// int lstat(const char *path, struct stat *buf);
- lstat,
- /// int lstat64(const char *path, struct stat64 *buf);
- lstat64,
- /// void *malloc(size_t size);
- malloc,
- /// void *memalign(size_t boundary, size_t size);
- memalign,
- /// void *memccpy(void *s1, const void *s2, int c, size_t n);
- memccpy,
- /// void *memchr(const void *s, int c, size_t n);
- memchr,
- /// int memcmp(const void *s1, const void *s2, size_t n);
- memcmp,
- /// void *memcpy(void *s1, const void *s2, size_t n);
- memcpy,
- /// void *memmove(void *s1, const void *s2, size_t n);
- memmove,
- // void *memrchr(const void *s, int c, size_t n);
- memrchr,
- /// void *memset(void *b, int c, size_t len);
- memset,
- /// void memset_pattern16(void *b, const void *pattern16, size_t len);
- memset_pattern16,
- /// int mkdir(const char *path, mode_t mode);
- mkdir,
- /// time_t mktime(struct tm *timeptr);
- mktime,
- /// double modf(double x, double *iptr);
- modf,
- /// float modff(float, float *iptr);
- modff,
- /// long double modfl(long double value, long double *iptr);
- modfl,
- /// double nearbyint(double x);
- nearbyint,
- /// float nearbyintf(float x);
- nearbyintf,
- /// long double nearbyintl(long double x);
- nearbyintl,
- /// uint32_t ntohl(uint32_t netlong);
- ntohl,
- /// uint16_t ntohs(uint16_t netshort);
- ntohs,
- /// int open(const char *path, int oflag, ... );
- open,
- /// int open64(const char *filename, int flags[, mode_t mode])
- open64,
- /// DIR *opendir(const char *dirname);
- opendir,
- /// int pclose(FILE *stream);
- pclose,
- /// void perror(const char *s);
- perror,
- /// FILE *popen(const char *command, const char *mode);
- popen,
- /// int posix_memalign(void **memptr, size_t alignment, size_t size);
- posix_memalign,
- /// double pow(double x, double y);
- pow,
- /// float powf(float x, float y);
- powf,
- /// long double powl(long double x, long double y);
- powl,
- /// ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
- pread,
- /// int printf(const char *format, ...);
- printf,
- /// int putc(int c, FILE *stream);
- putc,
- /// int putchar(int c);
- putchar,
- /// int puts(const char *s);
- puts,
- /// ssize_t pwrite(int fildes, const void *buf, size_t nbyte,
- /// off_t offset);
- pwrite,
- /// void qsort(void *base, size_t nel, size_t width,
- /// int (*compar)(const void *, const void *));
- qsort,
- /// ssize_t read(int fildes, void *buf, size_t nbyte);
- read,
- /// ssize_t readlink(const char *path, char *buf, size_t bufsize);
- readlink,
- /// void *realloc(void *ptr, size_t size);
- realloc,
- /// void *reallocf(void *ptr, size_t size);
- reallocf,
- /// char *realpath(const char *file_name, char *resolved_name);
- realpath,
- /// int remove(const char *path);
- remove,
- /// int rename(const char *old, const char *new);
- rename,
- /// void rewind(FILE *stream);
- rewind,
- /// double rint(double x);
- rint,
- /// float rintf(float x);
- rintf,
- /// long double rintl(long double x);
- rintl,
- /// int rmdir(const char *path);
- rmdir,
- /// double round(double x);
- round,
- /// float roundf(float x);
- roundf,
- /// long double roundl(long double x);
- roundl,
- /// int scanf(const char *restrict format, ... );
- scanf,
- /// void setbuf(FILE *stream, char *buf);
- setbuf,
- /// int setitimer(int which, const struct itimerval *value,
- /// struct itimerval *ovalue);
- setitimer,
- /// int setvbuf(FILE *stream, char *buf, int type, size_t size);
- setvbuf,
- /// double sin(double x);
- sin,
- /// float sinf(float x);
- sinf,
- /// double sinh(double x);
- sinh,
- /// float sinhf(float x);
- sinhf,
- /// long double sinhl(long double x);
- sinhl,
- /// long double sinl(long double x);
- sinl,
- /// int siprintf(char *str, const char *format, ...);
- siprintf,
- /// int snprintf(char *s, size_t n, const char *format, ...);
- snprintf,
- /// int sprintf(char *str, const char *format, ...);
- sprintf,
- /// double sqrt(double x);
- sqrt,
- /// float sqrtf(float x);
- sqrtf,
- /// long double sqrtl(long double x);
- sqrtl,
- /// int sscanf(const char *s, const char *format, ... );
- sscanf,
- /// int stat(const char *path, struct stat *buf);
- stat,
- /// int stat64(const char *path, struct stat64 *buf);
- stat64,
- /// int statvfs(const char *path, struct statvfs *buf);
- statvfs,
- /// int statvfs64(const char *path, struct statvfs64 *buf)
- statvfs64,
- /// char *stpcpy(char *s1, const char *s2);
- stpcpy,
- /// char *stpncpy(char *s1, const char *s2, size_t n);
- stpncpy,
- /// int strcasecmp(const char *s1, const char *s2);
- strcasecmp,
- /// char *strcat(char *s1, const char *s2);
- strcat,
- /// char *strchr(const char *s, int c);
- strchr,
- /// int strcmp(const char *s1, const char *s2);
- strcmp,
- /// int strcoll(const char *s1, const char *s2);
- strcoll,
- /// char *strcpy(char *s1, const char *s2);
- strcpy,
- /// size_t strcspn(const char *s1, const char *s2);
- strcspn,
- /// char *strdup(const char *s1);
- strdup,
- /// size_t strlen(const char *s);
- strlen,
- /// int strncasecmp(const char *s1, const char *s2, size_t n);
- strncasecmp,
- /// char *strncat(char *s1, const char *s2, size_t n);
- strncat,
- /// int strncmp(const char *s1, const char *s2, size_t n);
- strncmp,
- /// char *strncpy(char *s1, const char *s2, size_t n);
- strncpy,
- /// char *strndup(const char *s1, size_t n);
- strndup,
- /// size_t strnlen(const char *s, size_t maxlen);
- strnlen,
- /// char *strpbrk(const char *s1, const char *s2);
- strpbrk,
- /// char *strrchr(const char *s, int c);
- strrchr,
- /// size_t strspn(const char *s1, const char *s2);
- strspn,
- /// char *strstr(const char *s1, const char *s2);
- strstr,
- /// double strtod(const char *nptr, char **endptr);
- strtod,
- /// float strtof(const char *nptr, char **endptr);
- strtof,
- // char *strtok(char *s1, const char *s2);
- strtok,
- // char *strtok_r(char *s, const char *sep, char **lasts);
- strtok_r,
- /// long int strtol(const char *nptr, char **endptr, int base);
- strtol,
- /// long double strtold(const char *nptr, char **endptr);
- strtold,
- /// long long int strtoll(const char *nptr, char **endptr, int base);
- strtoll,
- /// unsigned long int strtoul(const char *nptr, char **endptr, int base);
- strtoul,
- /// unsigned long long int strtoull(const char *nptr, char **endptr,
- /// int base);
- strtoull,
- /// size_t strxfrm(char *s1, const char *s2, size_t n);
- strxfrm,
- /// int system(const char *command);
- system,
- /// double tan(double x);
- tan,
- /// float tanf(float x);
- tanf,
- /// double tanh(double x);
- tanh,
- /// float tanhf(float x);
- tanhf,
- /// long double tanhl(long double x);
- tanhl,
- /// long double tanl(long double x);
- tanl,
- /// clock_t times(struct tms *buffer);
- times,
- /// FILE *tmpfile(void);
- tmpfile,
- /// FILE *tmpfile64(void)
- tmpfile64,
- /// int toascii(int c);
- toascii,
- /// double trunc(double x);
- trunc,
- /// float truncf(float x);
- truncf,
- /// long double truncl(long double x);
- truncl,
- /// int uname(struct utsname *name);
- uname,
- /// int ungetc(int c, FILE *stream);
- ungetc,
- /// int unlink(const char *path);
- unlink,
- /// int unsetenv(const char *name);
- unsetenv,
- /// int utime(const char *path, const struct utimbuf *times);
- utime,
- /// int utimes(const char *path, const struct timeval times[2]);
- utimes,
- /// void *valloc(size_t size);
- valloc,
- /// int vfprintf(FILE *stream, const char *format, va_list ap);
- vfprintf,
- /// int vfscanf(FILE *stream, const char *format, va_list arg);
- vfscanf,
- /// int vprintf(const char *restrict format, va_list ap);
- vprintf,
- /// int vscanf(const char *format, va_list arg);
- vscanf,
- /// int vsnprintf(char *s, size_t n, const char *format, va_list ap);
- vsnprintf,
- /// int vsprintf(char *s, const char *format, va_list ap);
- vsprintf,
- /// int vsscanf(const char *s, const char *format, va_list arg);
- vsscanf,
- /// ssize_t write(int fildes, const void *buf, size_t nbyte);
- write,
-
- NumLibFuncs
- };
- }
-
-/// TargetLibraryInfo - This immutable pass captures information about what
-/// library functions are available for the current target, and allows a
-/// frontend to disable optimizations through -fno-builtin etc.
-class TargetLibraryInfo : public ImmutablePass {
- virtual void anchor();
- unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4];
- llvm::DenseMap<unsigned, std::string> CustomNames;
- static const char* StandardNames[LibFunc::NumLibFuncs];
-
- enum AvailabilityState {
- StandardName = 3, // (memset to all ones)
- CustomName = 1,
- Unavailable = 0 // (memset to all zeros)
- };
- void setState(LibFunc::Func F, AvailabilityState State) {
- AvailableArray[F/4] &= ~(3 << 2*(F&3));
- AvailableArray[F/4] |= State << 2*(F&3);
- }
- AvailabilityState getState(LibFunc::Func F) const {
- return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
- }
-
-public:
- static char ID;
- 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;
-
- /// has - This function is used by optimizations that want to match on or form
- /// a given library function.
- bool has(LibFunc::Func F) const {
- return getState(F) != Unavailable;
- }
-
- /// hasOptimizedCodeGen - Return true if the function is both available as
- /// a builtin and a candidate for optimized code generation.
- bool hasOptimizedCodeGen(LibFunc::Func F) const {
- if (getState(F) == Unavailable)
- return false;
- switch (F) {
- default: break;
- case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl:
- case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl:
- case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl:
- case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl:
- case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl:
- case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite:
- case LibFunc::sqrtl_finite:
- case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl:
- case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl:
- case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl:
- case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl:
- case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill:
- case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl:
- case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl:
- case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl:
- case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l:
- case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l:
- case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy:
- case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen:
- case LibFunc::memchr:
- return true;
- }
- return false;
- }
-
- StringRef getName(LibFunc::Func F) const {
- AvailabilityState State = getState(F);
- if (State == Unavailable)
- return StringRef();
- if (State == StandardName)
- return StandardNames[F];
- assert(State == CustomName);
- return CustomNames.find(F)->second;
- }
-
- /// setUnavailable - this can be used by whatever sets up TargetLibraryInfo to
- /// ban use of specific library functions.
- void setUnavailable(LibFunc::Func F) {
- setState(F, Unavailable);
- }
-
- void setAvailable(LibFunc::Func F) {
- setState(F, StandardName);
- }
-
- void setAvailableWithName(LibFunc::Func F, StringRef Name) {
- if (StandardNames[F] != Name) {
- setState(F, CustomName);
- CustomNames[F] = Name;
- assert(CustomNames.find(F) != CustomNames.end());
- } else {
- setState(F, StandardName);
- }
- }
-
- /// disableAllFunctions - This disables all builtins, which is used for
- /// options like -fno-builtin.
- void disableAllFunctions();
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 43d6f2772c5e..e2fe9e85fc92 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -77,8 +77,8 @@ namespace llvm {
/// This base class for TargetLowering contains the SelectionDAG-independent
/// parts that can be used from the rest of CodeGen.
class TargetLoweringBase {
- TargetLoweringBase(const TargetLoweringBase&) LLVM_DELETED_FUNCTION;
- void operator=(const TargetLoweringBase&) LLVM_DELETED_FUNCTION;
+ TargetLoweringBase(const TargetLoweringBase&) = delete;
+ void operator=(const TargetLoweringBase&) = delete;
public:
/// This enum indicates whether operations are valid for a target, and if not,
@@ -100,7 +100,8 @@ public:
TypeExpandFloat, // Split this float into two of half the size.
TypeScalarizeVector, // Replace this one-element vector with its element.
TypeSplitVector, // Split this vector into two of half the size.
- TypeWidenVector // This vector should be widened into a larger vector.
+ TypeWidenVector, // This vector should be widened into a larger vector.
+ TypePromoteFloat // Replace this float with a larger one.
};
/// LegalizeKind holds the legalization kind that needs to happen to EVT
@@ -123,6 +124,18 @@ public:
// mask (ex: x86 blends).
};
+ /// Enum that specifies what a AtomicRMWInst is expanded to, if at all. Exists
+ /// because different targets have different levels of support for these
+ /// atomic RMW instructions, and also have different options w.r.t. what they
+ /// should expand to.
+ enum class AtomicRMWExpansionKind {
+ None, // Don't expand the instruction.
+ LLSC, // Expand the instruction into loadlinked/storeconditional; used
+ // by ARM/AArch64. Implies `hasLoadLinkedStoreConditional`
+ // returns true.
+ CmpXChg, // Expand the instruction into cmpxchg; used by at least X86.
+ };
+
static ISD::NodeType getExtendForContent(BooleanContent Content) {
switch (Content) {
case UndefinedBooleanContent:
@@ -148,13 +161,11 @@ protected:
public:
const TargetMachine &getTargetMachine() const { return TM; }
- const DataLayout *getDataLayout() const { return DL; }
- const TargetLoweringObjectFile &getObjFileLowering() const {
- return *TM.getObjFileLowering();
- }
+ const DataLayout *getDataLayout() const { return TM.getDataLayout(); }
bool isBigEndian() const { return !IsLittleEndian; }
bool isLittleEndian() const { return IsLittleEndian; }
+ virtual bool useSoftFloat() const { return false; }
/// Return the pointer type for the given address space, defaults to
/// the pointer type from the data layout.
@@ -247,19 +258,29 @@ public:
/// isLoadBitCastBeneficial() - Return true if the following transform
/// is beneficial.
/// fold (conv (load x)) -> (load (conv*)x)
- /// On architectures that don't natively support some vector loads efficiently,
- /// casting the load to a smaller vector of larger types and loading
- /// is more efficient, however, this can be undone by optimizations in
+ /// On architectures that don't natively support some vector loads
+ /// efficiently, casting the load to a smaller vector of larger types and
+ /// loading is more efficient, however, this can be undone by optimizations in
/// dag combiner.
- virtual bool isLoadBitCastBeneficial(EVT /* Load */, EVT /* Bitcast */) const {
+ virtual bool isLoadBitCastBeneficial(EVT /* Load */,
+ EVT /* Bitcast */) const {
return true;
}
+ /// Return true if it is expected to be cheaper to do a store of a non-zero
+ /// vector constant with the given size and type for the address space than to
+ /// store the individual scalar element constants.
+ virtual bool storeOfVectorConstantIsCheap(EVT MemVT,
+ unsigned NumElem,
+ unsigned AddrSpace) const {
+ return false;
+ }
+
/// \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;
@@ -562,7 +583,8 @@ public:
/// Return how this load with extension should be treated: either it is legal,
/// needs to be promoted to a larger size, needs to be expanded to some other
/// code sequence, or the target has a custom expander for it.
- LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, EVT MemVT) const {
+ 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;
@@ -577,6 +599,14 @@ public:
getLoadExtAction(ExtType, ValVT, MemVT) == Legal;
}
+ /// Return true if the specified load with extension is legal or custom
+ /// on this target.
+ bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const {
+ return ValVT.isSimple() && MemVT.isSimple() &&
+ (getLoadExtAction(ExtType, ValVT, MemVT) == Legal ||
+ getLoadExtAction(ExtType, ValVT, MemVT) == Custom);
+ }
+
/// Return how this store with truncation should be treated: either it is
/// 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.
@@ -954,17 +984,20 @@ public:
return false;
}
- /// Returns the maximal possible offset which can be used for loads / stores
- /// from the global.
- virtual unsigned getMaximalGlobalOffset() const {
- return 0;
- }
-
/// Returns true if a cast between SrcAS and DestAS is a noop.
virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const {
return false;
}
+ /// Return true if the pointer arguments to CI should be aligned by aligning
+ /// the object whose address is being passed. If so then MinSize is set to the
+ /// minimum size the object must be to be aligned and PrefAlign is set to the
+ /// preferred alignment.
+ virtual bool shouldAlignPointerArgs(CallInst * /*CI*/, unsigned & /*MinSize*/,
+ unsigned & /*PrefAlign*/) const {
+ return false;
+ }
+
//===--------------------------------------------------------------------===//
/// \name Helpers for TargetTransformInfo implementations
/// @{
@@ -1031,8 +1064,9 @@ public:
/// 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 {
+ virtual Instruction *emitLeadingFence(IRBuilder<> &Builder,
+ AtomicOrdering Ord, bool IsStore,
+ bool IsLoad) const {
if (!getInsertFencesForAtomic())
return nullptr;
@@ -1042,8 +1076,9 @@ public:
return nullptr;
}
- virtual Instruction* emitTrailingFence(IRBuilder<> &Builder, AtomicOrdering Ord,
- bool IsStore, bool IsLoad) const {
+ virtual Instruction *emitTrailingFence(IRBuilder<> &Builder,
+ AtomicOrdering Ord, bool IsStore,
+ bool IsLoad) const {
if (!getInsertFencesForAtomic())
return nullptr;
@@ -1060,15 +1095,21 @@ public:
return false;
}
+ /// Returns true if arguments should be sign-extended in lib calls.
+ virtual bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const {
+ return IsSigned;
+ }
+
/// 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;
+ /// Returns how the IR-level AtomicExpand pass should expand the given
+ /// AtomicRMW, if at all. Default is to never expand.
+ virtual AtomicRMWExpansionKind
+ shouldExpandAtomicRMWInIR(AtomicRMWInst *) const {
+ return AtomicRMWExpansionKind::None;
}
/// On some platforms, an AtomicRMW that never actually modifies the value
@@ -1082,17 +1123,33 @@ public:
/// 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 {
+ virtual LoadInst *
+ lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const {
return nullptr;
}
+
+ /// Returns true if we should normalize
+ /// select(N0&N1, X, Y) => select(N0, select(N1, X, Y), Y) and
+ /// select(N0|N1, X, Y) => select(N0, select(N1, X, Y, Y)) if it is likely
+ /// that it saves us from materializing N0 and N1 in an integer register.
+ /// Targets that are able to perform and/or on flags should return false here.
+ virtual bool shouldNormalizeToSelectSequence(LLVMContext &Context,
+ EVT VT) const {
+ // If a target has multiple condition registers, then it likely has logical
+ // operations on those registers.
+ if (hasMultipleConditionRegisters())
+ return false;
+ // Only do the transform if the value won't be split into multiple
+ // registers.
+ LegalizeTypeAction Action = getTypeAction(Context, VT);
+ return Action != TypeExpandInteger && Action != TypeExpandFloat &&
+ Action != TypeSplitVector;
+ }
+
//===--------------------------------------------------------------------===//
// TargetLowering Configuration Methods - These methods should be invoked by
// the derived class constructor to configure this object for the target.
//
-
- /// \brief Reset the operation actions based on target options.
- virtual void resetOperationActions() {}
-
protected:
/// Specify how the target extends the result of integer and floating point
/// boolean values from i1 to a wider type. See getBooleanContents.
@@ -1230,12 +1287,12 @@ protected:
/// Return the largest legal super-reg register class of the register class
/// for the specified type and its associated "cost".
- virtual std::pair<const TargetRegisterClass*, uint8_t>
- findRepresentativeClass(MVT VT) const;
+ virtual std::pair<const TargetRegisterClass *, uint8_t>
+ findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const;
/// Once all of the register classes are added, this allows us to compute
/// derived properties we expose.
- void computeRegisterProperties();
+ void computeRegisterProperties(const TargetRegisterInfo *TRI);
/// Indicate that the specified operation does not work with the specified
/// type and indicate what to do about it.
@@ -1455,6 +1512,35 @@ public:
return false;
}
+ virtual bool isProfitableToHoist(Instruction *I) const { return true; }
+
+ /// Return true if the extension represented by \p I is free.
+ /// Unlikely the is[Z|FP]ExtFree family which is based on types,
+ /// this method can use the context provided by \p I to decide
+ /// whether or not \p I is free.
+ /// This method extends the behavior of the is[Z|FP]ExtFree family.
+ /// In other words, if is[Z|FP]Free returns true, then this method
+ /// returns true as well. The converse is not true.
+ /// The target can perform the adequate checks by overriding isExtFreeImpl.
+ /// \pre \p I must be a sign, zero, or fp extension.
+ bool isExtFree(const Instruction *I) const {
+ switch (I->getOpcode()) {
+ case Instruction::FPExt:
+ if (isFPExtFree(EVT::getEVT(I->getType())))
+ return true;
+ break;
+ case Instruction::ZExt:
+ if (isZExtFree(I->getOperand(0)->getType(), I->getType()))
+ return true;
+ break;
+ case Instruction::SExt:
+ break;
+ default:
+ llvm_unreachable("Instruction is not an extension");
+ }
+ return isExtFreeImpl(I);
+ }
+
/// Return true if any actual instruction that defines a value of type Ty1
/// implicitly zero-extends the value to Ty2 in the result register.
///
@@ -1517,6 +1603,10 @@ public:
return false;
}
+ /// Return true if folding a vector load into ExtVal (a sign, zero, or any
+ /// extend node) is profitable.
+ virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const { return false; }
+
/// Return true if an fneg operation is free to the point where it is never
/// worthwhile to replace it with a bitwise operation.
virtual bool isFNegFree(EVT VT) const {
@@ -1606,7 +1696,6 @@ public:
private:
const TargetMachine &TM;
- const DataLayout *DL;
/// True if this is a little endian target.
bool IsLittleEndian;
@@ -1783,136 +1872,8 @@ private:
ValueTypeActionImpl ValueTypeActions;
-public:
- LegalizeKind
- getTypeConversion(LLVMContext &Context, EVT VT) const {
- // If this is a simple type, use the ComputeRegisterProp mechanism.
- if (VT.isSimple()) {
- MVT SVT = VT.getSimpleVT();
- assert((unsigned)SVT.SimpleTy < array_lengthof(TransformToType));
- MVT NVT = TransformToType[SVT.SimpleTy];
- LegalizeTypeAction LA = ValueTypeActions.getTypeAction(SVT);
-
- assert(
- (LA == TypeLegal || LA == TypeSoftenFloat ||
- ValueTypeActions.getTypeAction(NVT) != TypePromoteInteger)
- && "Promote may not follow Expand or Promote");
-
- if (LA == TypeSplitVector)
- return LegalizeKind(LA, EVT::getVectorVT(Context,
- SVT.getVectorElementType(),
- SVT.getVectorNumElements()/2));
- if (LA == TypeScalarizeVector)
- return LegalizeKind(LA, SVT.getVectorElementType());
- return LegalizeKind(LA, NVT);
- }
-
- // Handle Extended Scalar Types.
- if (!VT.isVector()) {
- assert(VT.isInteger() && "Float types must be simple");
- unsigned BitSize = VT.getSizeInBits();
- // First promote to a power-of-two size, then expand if necessary.
- if (BitSize < 8 || !isPowerOf2_32(BitSize)) {
- EVT NVT = VT.getRoundIntegerType(Context);
- assert(NVT != VT && "Unable to round integer VT");
- LegalizeKind NextStep = getTypeConversion(Context, NVT);
- // Avoid multi-step promotion.
- if (NextStep.first == TypePromoteInteger) return NextStep;
- // Return rounded integer type.
- return LegalizeKind(TypePromoteInteger, NVT);
- }
-
- return LegalizeKind(TypeExpandInteger,
- EVT::getIntegerVT(Context, VT.getSizeInBits()/2));
- }
-
- // Handle vector types.
- unsigned NumElts = VT.getVectorNumElements();
- EVT EltVT = VT.getVectorElementType();
-
- // Vectors with only one element are always scalarized.
- if (NumElts == 1)
- return LegalizeKind(TypeScalarizeVector, EltVT);
-
- // Try to widen vector elements until the element type is a power of two and
- // promote it to a legal type later on, for example:
- // <3 x i8> -> <4 x i8> -> <4 x i32>
- if (EltVT.isInteger()) {
- // Vectors with a number of elements that is not a power of two are always
- // widened, for example <3 x i8> -> <4 x i8>.
- if (!VT.isPow2VectorType()) {
- NumElts = (unsigned)NextPowerOf2(NumElts);
- EVT NVT = EVT::getVectorVT(Context, EltVT, NumElts);
- return LegalizeKind(TypeWidenVector, NVT);
- }
-
- // Examine the element type.
- LegalizeKind LK = getTypeConversion(Context, EltVT);
-
- // If type is to be expanded, split the vector.
- // <4 x i140> -> <2 x i140>
- if (LK.first == TypeExpandInteger)
- return LegalizeKind(TypeSplitVector,
- EVT::getVectorVT(Context, EltVT, NumElts / 2));
-
- // Promote the integer element types until a legal vector type is found
- // or until the element integer type is too big. If a legal type was not
- // found, fallback to the usual mechanism of widening/splitting the
- // vector.
- EVT OldEltVT = EltVT;
- while (1) {
- // Increase the bitwidth of the element to the next pow-of-two
- // (which is greater than 8 bits).
- EltVT = EVT::getIntegerVT(Context, 1 + EltVT.getSizeInBits()
- ).getRoundIntegerType(Context);
-
- // Stop trying when getting a non-simple element type.
- // Note that vector elements may be greater than legal vector element
- // types. Example: X86 XMM registers hold 64bit element on 32bit
- // systems.
- if (!EltVT.isSimple()) break;
-
- // Build a new vector type and check if it is legal.
- MVT NVT = MVT::getVectorVT(EltVT.getSimpleVT(), NumElts);
- // Found a legal promoted vector type.
- if (NVT != MVT() && ValueTypeActions.getTypeAction(NVT) == TypeLegal)
- return LegalizeKind(TypePromoteInteger,
- EVT::getVectorVT(Context, EltVT, NumElts));
- }
-
- // Reset the type to the unexpanded type if we did not find a legal vector
- // type with a promoted vector element type.
- EltVT = OldEltVT;
- }
-
- // Try to widen the vector until a legal type is found.
- // If there is no wider legal type, split the vector.
- while (1) {
- // Round up to the next power of 2.
- NumElts = (unsigned)NextPowerOf2(NumElts);
-
- // If there is no simple vector type with this many elements then there
- // cannot be a larger legal vector type. Note that this assumes that
- // there are no skipped intermediate vector types in the simple types.
- if (!EltVT.isSimple()) break;
- MVT LargerVector = MVT::getVectorVT(EltVT.getSimpleVT(), NumElts);
- if (LargerVector == MVT()) break;
-
- // If this type is legal then widen the vector.
- if (ValueTypeActions.getTypeAction(LargerVector) == TypeLegal)
- return LegalizeKind(TypeWidenVector, LargerVector);
- }
-
- // Widen odd vectors to next power of two.
- if (!VT.isPow2VectorType()) {
- EVT NVT = VT.getPow2VectorType(Context);
- return LegalizeKind(TypeWidenVector, NVT);
- }
-
- // Vectors with illegal element types are expanded.
- EVT NVT = EVT::getVectorVT(Context, EltVT, VT.getVectorNumElements() / 2);
- return LegalizeKind(TypeSplitVector, NVT);
- }
+private:
+ LegalizeKind getTypeConversion(LLVMContext &Context, EVT VT) const;
private:
std::vector<std::pair<MVT, const TargetRegisterClass*> > AvailableRegClasses;
@@ -1943,6 +1904,11 @@ private:
CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL];
protected:
+ /// Return true if the extension represented by \p I is free.
+ /// \pre \p I is a sign, zero, or fp extension and
+ /// is[Z|FP]ExtFree of the related types is not true.
+ virtual bool isExtFreeImpl(const Instruction *I) const { return false; }
+
/// \brief Specify maximum number of store instructions per memset call.
///
/// When lowering \@llvm.memset this field specifies the maximum number of
@@ -2010,7 +1976,8 @@ protected:
/// Replace/modify any TargetFrameIndex operands with a targte-dependent
/// sequence of memory operands that is recognized by PrologEpilogInserter.
- MachineBasicBlock *emitPatchPoint(MachineInstr *MI, MachineBasicBlock *MBB) const;
+ MachineBasicBlock *emitPatchPoint(MachineInstr *MI,
+ MachineBasicBlock *MBB) const;
};
/// This class defines information used to lower LLVM code to legal SelectionDAG
@@ -2019,8 +1986,8 @@ protected:
/// This class also defines callbacks that targets must implement to lower
/// target-specific constructs to SelectionDAG operators.
class TargetLowering : public TargetLoweringBase {
- TargetLowering(const TargetLowering&) LLVM_DELETED_FUNCTION;
- void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION;
+ TargetLowering(const TargetLowering&) = delete;
+ void operator=(const TargetLowering&) = delete;
public:
/// NOTE: The TargetMachine owns TLOF.
@@ -2080,6 +2047,7 @@ public:
ISD::CondCode &CCCode, SDLoc DL) const;
/// Returns a pair of (return value, chain).
+ /// It is an error to pass RTLIB::UNKNOWN_LIBCALL as \p LC.
std::pair<SDValue, SDValue> makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC,
EVT RetVT, const SDValue *Ops,
unsigned NumOps, bool isSigned,
@@ -2171,8 +2139,7 @@ public:
void AddToWorklist(SDNode *N);
void RemoveFromWorklist(SDNode *N);
- SDValue CombineTo(SDNode *N, const std::vector<SDValue> &To,
- bool AddTo = true);
+ SDValue CombineTo(SDNode *N, ArrayRef<SDValue> To, bool AddTo = true);
SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true);
SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo = true);
@@ -2653,7 +2620,8 @@ public:
/// specific constraints and their prefixes, and also tie in the associated
/// operand values. If this returns an empty vector, and if the constraint
/// string itself isn't empty, there was an error parsing.
- virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const;
+ virtual AsmOperandInfoVector ParseConstraints(const TargetRegisterInfo *TRI,
+ ImmutableCallSite CS) const;
/// Examine constraint type and operand type and determine a weight value.
/// The operand object must already have been set up with the operand type.
@@ -2684,10 +2652,19 @@ public:
/// pointer.
///
/// This should only be used for C_Register constraints. On error, this
- /// returns a register number of 0 and a null register class pointer..
- virtual std::pair<unsigned, const TargetRegisterClass*>
- getRegForInlineAsmConstraint(const std::string &Constraint,
- MVT VT) const;
+ /// returns a register number of 0 and a null register class pointer.
+ virtual std::pair<unsigned, const TargetRegisterClass *>
+ getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+ const std::string &Constraint, MVT VT) const;
+
+ virtual unsigned
+ getInlineAsmMemConstraint(const std::string &ConstraintCode) const {
+ if (ConstraintCode == "i")
+ return InlineAsm::Constraint_i;
+ else if (ConstraintCode == "m")
+ return InlineAsm::Constraint_m;
+ return InlineAsm::Constraint_Unknown;
+ }
/// Try to replace an X constraint, which matches anything, with another that
/// has more specific requirements based on the type of the corresponding
@@ -2725,7 +2702,7 @@ public:
/// 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
@@ -2736,10 +2713,9 @@ public:
/// 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 {
+ virtual SDValue getRsqrtEstimate(SDValue Operand, DAGCombinerInfo &DCI,
+ unsigned &RefinementSteps,
+ bool &UseOneConstNR) const {
return SDValue();
}
@@ -2751,8 +2727,7 @@ public:
/// 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,
+ virtual SDValue getRecipEstimate(SDValue Operand, DAGCombinerInfo &DCI,
unsigned &RefinementSteps) const {
return SDValue();
}
@@ -2791,6 +2766,8 @@ public:
/// is created but not inserted into any basic blocks, and this method is
/// called to expand it into a sequence of instructions, potentially also
/// creating new basic blocks and control flow.
+ /// As long as the returned basic block is different (i.e., we created a new
+ /// one), the custom inserter is free to modify the rest of \p MBB.
virtual MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
@@ -2806,11 +2783,6 @@ public:
virtual bool useLoadStackGuardNode() const {
return false;
}
-
- /// Returns true if arguments should be sign-extended in lib calls.
- virtual bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const {
- return IsSigned;
- }
};
/// 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 73bf56f018e9..2a17bd200f4d 100644
--- a/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/include/llvm/Target/TargetLoweringObjectFile.h
@@ -29,22 +29,29 @@ namespace llvm {
class MCSymbol;
class MCSymbolRefExpr;
class MCStreamer;
+ class MCValue;
class ConstantExpr;
class GlobalValue;
class TargetMachine;
class TargetLoweringObjectFile : public MCObjectFileInfo {
MCContext *Ctx;
- const DataLayout *DL;
TargetLoweringObjectFile(
- const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION;
- void operator=(const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION;
+ const TargetLoweringObjectFile&) = delete;
+ void operator=(const TargetLoweringObjectFile&) = delete;
+
+protected:
+ const DataLayout *DL;
+ bool SupportIndirectSymViaGOTPCRel;
+ bool SupportGOTPCRelWithOffset;
public:
MCContext &getContext() const { return *Ctx; }
- TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr) {}
+ TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr),
+ SupportIndirectSymViaGOTPCRel(false),
+ SupportGOTPCRelWithOffset(true) {}
virtual ~TargetLoweringObjectFile();
@@ -70,8 +77,8 @@ public:
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
- virtual const MCSection *getSectionForConstant(SectionKind Kind,
- const Constant *C) const;
+ virtual MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const;
/// Classify the specified global variable into a set of target independent
/// categories embodied in SectionKind.
@@ -81,23 +88,32 @@ public:
/// This method computes the appropriate section to emit the specified global
/// variable or function definition. This should not be passed external (or
/// available externally) globals.
- const MCSection *SectionForGlobal(const GlobalValue *GV,
- SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM) const;
+ MCSection *SectionForGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler &Mang, const TargetMachine &TM) const;
/// This method computes the appropriate section to emit the specified global
/// variable or function definition. This should not be passed external (or
/// available externally) globals.
- const MCSection *SectionForGlobal(const GlobalValue *GV,
- Mangler &Mang,
- const TargetMachine &TM) const {
+ MCSection *SectionForGlobal(const GlobalValue *GV, Mangler &Mang,
+ const TargetMachine &TM) const {
return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM);
}
+ virtual void getNameWithPrefix(SmallVectorImpl<char> &OutName,
+ const GlobalValue *GV,
+ bool CannotUsePrivateLabel, Mangler &Mang,
+ const TargetMachine &TM) const;
+
+ virtual MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang,
+ const TargetMachine &TM) const;
+
+ virtual bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
+ const Function &F) const;
+
/// Targets should implement this method to assign a section to globals with
/// an explicit section specfied. The implementation of this method can
/// assume that GV->hasSection() is true.
- virtual const MCSection *
+ virtual MCSection *
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler &Mang, const TargetMachine &TM) const = 0;
@@ -131,13 +147,13 @@ public:
getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding,
MCStreamer &Streamer) const;
- virtual const MCSection *getStaticCtorSection(unsigned Priority,
- const MCSymbol *KeySym) const {
+ virtual MCSection *getStaticCtorSection(unsigned Priority,
+ const MCSymbol *KeySym) const {
return StaticCtorSection;
}
- virtual const MCSection *getStaticDtorSection(unsigned Priority,
- const MCSymbol *KeySym) const {
+ virtual MCSection *getStaticDtorSection(unsigned Priority,
+ const MCSymbol *KeySym) const {
return StaticDtorSection;
}
@@ -151,10 +167,31 @@ public:
return nullptr;
}
+ /// \brief Target supports replacing a data "PC"-relative access to a symbol
+ /// through another symbol, by accessing the later via a GOT entry instead?
+ bool supportIndirectSymViaGOTPCRel() const {
+ return SupportIndirectSymViaGOTPCRel;
+ }
+
+ /// \brief Target GOT "PC"-relative relocation supports encoding an additional
+ /// binary expression with an offset?
+ bool supportGOTPCRelWithOffset() const {
+ return SupportGOTPCRelWithOffset;
+ }
+
+ /// \brief Get the target specific PC relative GOT entry relocation
+ virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
+ const MCValue &MV,
+ int64_t Offset,
+ MachineModuleInfo *MMI,
+ MCStreamer &Streamer) const {
+ return nullptr;
+ }
+
protected:
- virtual const MCSection *
- SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
- Mangler &Mang, const TargetMachine &TM) const = 0;
+ virtual MCSection *SelectSectionForGlobal(const GlobalValue *GV,
+ SectionKind Kind, 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 a4f95c061283..2a1ce0483e10 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -15,6 +15,7 @@
#define LLVM_TARGET_TARGETMACHINE_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/DataLayout.h"
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetOptions.h"
@@ -29,21 +30,25 @@ class Mangler;
class MCAsmInfo;
class MCCodeGenInfo;
class MCContext;
+class MCInstrInfo;
+class MCRegisterInfo;
+class MCSubtargetInfo;
class MCSymbol;
class Target;
class DataLayout;
class TargetLibraryInfo;
class TargetFrameLowering;
+class TargetIRAnalysis;
class TargetIntrinsicInfo;
class TargetLowering;
class TargetPassConfig;
class TargetRegisterInfo;
class TargetSelectionDAGInfo;
class TargetSubtargetInfo;
-class ScalarTargetTransformInfo;
-class VectorTargetTransformInfo;
+class TargetTransformInfo;
class formatted_raw_ostream;
class raw_ostream;
+class raw_pwrite_stream;
class TargetLoweringObjectFile;
// The old pass manager infrastructure is hidden in a legacy namespace now.
@@ -54,34 +59,41 @@ using legacy::PassManagerBase;
//===----------------------------------------------------------------------===//
///
-/// TargetMachine - Primary interface to the complete machine description for
-/// the target machine. All target-specific information should be accessible
-/// through this interface.
+/// Primary interface to the complete machine description for the target
+/// machine. All target-specific information should be accessible through this
+/// interface.
///
class TargetMachine {
- TargetMachine(const TargetMachine &) LLVM_DELETED_FUNCTION;
- void operator=(const TargetMachine &) LLVM_DELETED_FUNCTION;
+ TargetMachine(const TargetMachine &) = delete;
+ void operator=(const TargetMachine &) = delete;
protected: // Can only create subclasses.
- TargetMachine(const Target &T, StringRef TargetTriple,
- StringRef CPU, StringRef FS, const TargetOptions &Options);
+ TargetMachine(const Target &T, StringRef DataLayoutString,
+ StringRef TargetTriple, StringRef CPU, StringRef FS,
+ const TargetOptions &Options);
- /// TheTarget - The Target that this machine was created for.
+ /// The Target that this machine was created for.
const Target &TheTarget;
- /// TargetTriple, TargetCPU, TargetFS - Triple string, CPU name, and target
- /// feature strings the TargetMachine instance is created with.
+ /// For ABI type size and alignment.
+ const DataLayout DL;
+
+ /// Triple string, CPU name, and target feature strings the TargetMachine
+ /// instance is created with.
std::string TargetTriple;
std::string TargetCPU;
std::string TargetFS;
- /// CodeGenInfo - Low level target information such as relocation model.
- /// Non-const to allow resetting optimization level per-function.
+ /// Low level target information such as relocation model. Non-const to
+ /// allow resetting optimization level per-function.
MCCodeGenInfo *CodeGenInfo;
- /// AsmInfo - Contains target specific asm information.
- ///
+ /// Contains target specific asm information.
const MCAsmInfo *AsmInfo;
+ const MCRegisterInfo *MRI;
+ const MCInstrInfo *MII;
+ const MCSubtargetInfo *STI;
+
unsigned RequireStructuredCFG : 1;
public:
@@ -95,40 +107,39 @@ public:
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;
- }
+ /// Virtual method implemented by subclasses that returns a reference to that
+ /// target's TargetSubtargetInfo-derived member variable.
virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const {
- return getSubtargetImpl();
+ return nullptr;
}
virtual TargetLoweringObjectFile *getObjFileLowering() const {
return nullptr;
}
- /// getSubtarget - This method returns a pointer to the specified type of
+ /// This method returns a pointer to the specified type of
/// TargetSubtargetInfo. In debug builds, it verifies that the object being
/// returned is of the correct type.
- template<typename STC> const STC &getSubtarget() const {
- return *static_cast<const STC*>(getSubtargetImpl());
- }
- template <typename STC> const STC &getSubtarget(const Function *) const {
- return *static_cast<const STC*>(getSubtargetImpl());
+ template <typename STC> const STC &getSubtarget(const Function &F) const {
+ return *static_cast<const STC*>(getSubtargetImpl(F));
}
+ /// This method returns a pointer to the DataLayout for the target. It should
+ /// be unchanging for every subtarget.
+ const DataLayout *getDataLayout() const { return &DL; }
+
/// \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;
- /// getMCAsmInfo - Return target specific asm information.
- ///
+ /// Return target specific asm information.
const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; }
- /// getIntrinsicInfo - If intrinsic information is available, return it. If
- /// not, return null.
- ///
+ const MCRegisterInfo *getMCRegisterInfo() const { return MRI; }
+ const MCInstrInfo *getMCInstrInfo() const { return MII; }
+ const MCSubtargetInfo *getMCSubtargetInfo() const { return STI; }
+
+ /// If intrinsic information is available, return it. If not, return null.
virtual const TargetIntrinsicInfo *getIntrinsicInfo() const {
return nullptr;
}
@@ -136,20 +147,18 @@ public:
bool requiresStructuredCFG() const { return RequireStructuredCFG; }
void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; }
- /// getRelocationModel - Returns the code generation relocation model. The
- /// choices are static, PIC, and dynamic-no-pic, and target default.
+ /// Returns the code generation relocation model. The choices are static, PIC,
+ /// and dynamic-no-pic, and target default.
Reloc::Model getRelocationModel() const;
- /// getCodeModel - Returns the code model. The choices are small, kernel,
- /// medium, large, and target default.
+ /// Returns the code model. The choices are small, kernel, medium, large, and
+ /// target default.
CodeModel::Model getCodeModel() const;
- /// getTLSModel - Returns the TLS model which should be used for the given
- /// global variable.
+ /// Returns the TLS model which should be used for the given global variable.
TLSModel::Model getTLSModel(const GlobalValue *GV) const;
- /// getOptLevel - Returns the optimization level: None, Less,
- /// Default, or Aggressive.
+ /// Returns the optimization level: None, Less, Default, or Aggressive.
CodeGenOpt::Level getOptLevel() const;
/// \brief Overrides the optimization level.
@@ -159,47 +168,47 @@ public:
bool shouldPrintMachineCode() const { return Options.PrintMachineCode; }
- /// getAsmVerbosityDefault - Returns the default value of asm verbosity.
+ /// Returns the default value of asm verbosity.
///
- bool getAsmVerbosityDefault() const ;
-
- /// setAsmVerbosityDefault - Set the default value of asm verbosity. Default
- /// is false.
- void setAsmVerbosityDefault(bool);
-
- /// getDataSections - Return true if data objects should be emitted into their
- /// own section, corresponds to -fdata-sections.
- bool getDataSections() const;
-
- /// getFunctionSections - Return true if functions should be emitted into
- /// their own section, corresponding to -ffunction-sections.
- bool getFunctionSections() const;
+ bool getAsmVerbosityDefault() const {
+ return Options.MCOptions.AsmVerbose;
+ }
- /// setDataSections - Set if the data are emit into separate sections.
- void setDataSections(bool);
+ bool getUniqueSectionNames() const { return Options.UniqueSectionNames; }
- /// setFunctionSections - Set if the functions are emit into separate
- /// sections.
- void setFunctionSections(bool);
+ /// Return true if data objects should be emitted into their own section,
+ /// corresponds to -fdata-sections.
+ bool getDataSections() const {
+ return Options.DataSections;
+ }
- /// \brief Register analysis passes for this target with a pass manager.
- virtual void addAnalysisPasses(PassManagerBase &) {}
+ /// Return true if functions should be emitted into their own section,
+ /// corresponding to -ffunction-sections.
+ bool getFunctionSections() const {
+ return Options.FunctionSections;
+ }
- /// CodeGenFileType - These enums are meant to be passed into
- /// addPassesToEmitFile to indicate what type of file to emit, and returned by
- /// it to indicate what type of file could actually be made.
+ /// \brief Get a \c TargetIRAnalysis appropriate for the target.
+ ///
+ /// This is used to construct the new pass manager's target IR analysis pass,
+ /// set up appropriately for this target machine. Even the old pass manager
+ /// uses this to answer queries about the IR.
+ virtual TargetIRAnalysis getTargetIRAnalysis();
+
+ /// These enums are meant to be passed into addPassesToEmitFile to indicate
+ /// what type of file to emit, and returned by it to indicate what type of
+ /// file could actually be made.
enum CodeGenFileType {
CGFT_AssemblyFile,
CGFT_ObjectFile,
CGFT_Null // Do not emit any output.
};
- /// addPassesToEmitFile - Add passes to the specified pass manager to get the
- /// specified file emitted. Typically this will involve several steps of code
- /// generation. This method should return true if emission of this file type
- /// is not supported, or false on success.
- virtual bool addPassesToEmitFile(PassManagerBase &,
- formatted_raw_ostream &,
+ /// Add passes to the specified pass manager to get the specified file
+ /// emitted. Typically this will involve several steps of code generation.
+ /// This method should return true if emission of this file type is not
+ /// supported, or false on success.
+ virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &,
CodeGenFileType,
bool /*DisableVerify*/ = true,
AnalysisID /*StartAfter*/ = nullptr,
@@ -207,14 +216,13 @@ public:
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
- /// used to build custom MCStreamer.
+ /// 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 used to build custom
+ /// MCStreamer.
///
- virtual bool addPassesToEmitMC(PassManagerBase &,
- MCContext *&,
- raw_ostream &,
+ virtual bool addPassesToEmitMC(PassManagerBase &, MCContext *&,
+ raw_pwrite_stream &,
bool /*DisableVerify*/ = true) {
return true;
}
@@ -224,42 +232,42 @@ public:
MCSymbol *getSymbol(const GlobalValue *GV, Mangler &Mang) const;
};
-/// LLVMTargetMachine - This class describes a target machine that is
-/// implemented with the LLVM target-independent code generator.
+/// This class describes a target machine that is implemented with the LLVM
+/// target-independent code generator.
///
class LLVMTargetMachine : public TargetMachine {
protected: // Can only create subclasses.
- LLVMTargetMachine(const Target &T, StringRef TargetTriple,
- StringRef CPU, StringRef FS, TargetOptions Options,
- Reloc::Model RM, CodeModel::Model CM,
+ LLVMTargetMachine(const Target &T, StringRef DataLayoutString,
+ StringRef TargetTriple, StringRef CPU, StringRef FS,
+ TargetOptions Options, Reloc::Model RM, CodeModel::Model CM,
CodeGenOpt::Level OL);
void initAsmInfo();
public:
- /// \brief Register analysis passes for this target with a pass manager.
+ /// \brief Get a TargetIRAnalysis implementation for the target.
///
- /// This registers target independent analysis passes.
- void addAnalysisPasses(PassManagerBase &PM) override;
+ /// This analysis will produce a TTI result which uses the common code
+ /// generator to answer queries about the IR.
+ TargetIRAnalysis getTargetIRAnalysis() override;
- /// createPassConfig - Create a pass configuration object to be used by
- /// addPassToEmitX methods for generating a pipeline of CodeGen passes.
+ /// Create a pass configuration object to be used by addPassToEmitX methods
+ /// for generating a pipeline of CodeGen passes.
virtual TargetPassConfig *createPassConfig(PassManagerBase &PM);
- /// addPassesToEmitFile - Add passes to the specified pass manager to get the
- /// specified file emitted. Typically this will involve several steps of code
- /// generation.
- bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out,
+ /// Add passes to the specified pass manager to get the specified file
+ /// emitted. Typically this will involve several steps of code generation.
+ bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
CodeGenFileType FileType, bool DisableVerify = true,
AnalysisID StartAfter = nullptr,
AnalysisID StopAfter = nullptr) 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
- /// used to build custom MCStreamer.
- ///
+ /// 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 used to build custom
+ /// MCStreamer.
bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
- raw_ostream &OS, bool DisableVerify = true) override;
+ raw_pwrite_stream &OS,
+ bool DisableVerify = true) override;
};
} // End llvm namespace
diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h
index 9ab8242578fd..07a8f6d3d4cd 100644
--- a/include/llvm/Target/TargetOptions.h
+++ b/include/llvm/Target/TargetOptions.h
@@ -20,14 +20,14 @@
namespace llvm {
class MachineFunction;
+ class Module;
class StringRef;
- // Possible float ABI settings. Used with FloatABIType in TargetOptions.h.
namespace FloatABI {
enum ABIType {
- Default, // Target-specific (either soft or hard depending on triple,etc).
- Soft, // Soft float.
- Hard // Hard float.
+ Default, // Target-specific (either soft or hard depending on triple, etc).
+ Soft, // Soft float.
+ Hard // Hard float.
};
}
@@ -57,43 +57,29 @@ namespace llvm {
};
}
- 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()
- : PrintMachineCode(false), NoFramePointerElim(false),
+ : PrintMachineCode(false),
LessPreciseFPMADOption(false), UnsafeFPMath(false),
NoInfsFPMath(false), NoNaNsFPMath(false),
- HonorSignDependentRoundingFPMathOption(false), UseSoftFloat(false),
- NoZerosInBSS(false), JITEmitDebugInfo(false),
- JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false),
+ HonorSignDependentRoundingFPMathOption(false),
+ NoZerosInBSS(false),
+ GuaranteedTailCallOpt(false),
DisableTailCalls(false), StackAlignmentOverride(0),
EnableFastISel(false), PositionIndependentExecutable(false),
UseInitArray(false), DisableIntegratedAS(false),
CompressDebugSections(false), FunctionSections(false),
- DataSections(false), TrapUnreachable(false), TrapFuncName(),
- FloatABIType(FloatABI::Default),
+ DataSections(false), UniqueSectionNames(true), TrapUnreachable(false),
+ TrapFuncName(), FloatABIType(FloatABI::Default),
AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
- FCFI(false), ThreadModel(ThreadModel::POSIX),
- CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}
+ ThreadModel(ThreadModel::POSIX) {}
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs
/// option is specified on the command line, and should enable debugging
/// output from the code generator.
unsigned PrintMachineCode : 1;
- /// NoFramePointerElim - This flag is enabled when the -disable-fp-elim is
- /// specified on the command line. If the target supports the frame pointer
- /// elimination optimization, this option should disable it.
- unsigned NoFramePointerElim : 1;
-
/// DisableFramePointerElim - This returns true if frame pointer elimination
/// optimization should be disabled for the given machine function.
bool DisableFramePointerElim(const MachineFunction &MF) const;
@@ -136,26 +122,11 @@ namespace llvm {
unsigned HonorSignDependentRoundingFPMathOption : 1;
bool HonorSignDependentRoundingFPMath() const;
- /// UseSoftFloat - This flag is enabled when the -soft-float flag is
- /// specified on the command line. When this flag is on, the code generator
- /// will generate libcalls to the software floating point library instead of
- /// target FP instructions.
- unsigned UseSoftFloat : 1;
-
/// NoZerosInBSS - By default some codegens place zero-initialized data to
/// .bss section. This flag disables such behaviour (necessary, e.g. for
/// crt*.o compiling).
unsigned NoZerosInBSS : 1;
- /// JITEmitDebugInfo - This flag indicates that the JIT should try to emit
- /// debug information and notify a debugger about it.
- unsigned JITEmitDebugInfo : 1;
-
- /// JITEmitDebugInfoToDisk - This flag indicates that the JIT should write
- /// the object files generated by the JITEmitDebugInfo flag to disk. This
- /// flag is hidden and is only for debugging the debug info.
- unsigned JITEmitDebugInfoToDisk : 1;
-
/// GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is
/// specified on the commandline. When the flag is on, participating targets
/// will perform tail call optimization on all calls which use the fastcc
@@ -198,6 +169,8 @@ namespace llvm {
/// Emit data into separate sections.
unsigned DataSections : 1;
+ unsigned UniqueSectionNames : 1;
+
/// Emit target-specific trap instruction for 'unreachable' IR instructions.
unsigned TrapUnreachable : 1;
@@ -210,9 +183,9 @@ namespace llvm {
/// FloatABIType - This setting is set by -float-abi=xxx option is specfied
/// on the command line. This setting may either be Default, Soft, or Hard.
/// Default selects the target's default behavior. Soft selects the ABI for
- /// UseSoftFloat, but does not indicate that FP hardware may not be used.
- /// Such a combination is unfortunately popular (e.g. arm-apple-darwin).
- /// Hard presumes that the normal FP ABI is used.
+ /// software floating point, but does not indicate that FP hardware may not
+ /// be used. Such a combination is unfortunately popular (e.g.
+ /// arm-apple-darwin). Hard presumes that the normal FP ABI is used.
FloatABI::ABIType FloatABIType;
/// AllowFPOpFusion - This flag is set by the -fuse-fp-ops=xxx option.
@@ -237,28 +210,10 @@ 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;
};
@@ -274,10 +229,7 @@ inline bool operator==(const TargetOptions &LHS,
ARE_EQUAL(NoInfsFPMath) &&
ARE_EQUAL(NoNaNsFPMath) &&
ARE_EQUAL(HonorSignDependentRoundingFPMathOption) &&
- ARE_EQUAL(UseSoftFloat) &&
ARE_EQUAL(NoZerosInBSS) &&
- ARE_EQUAL(JITEmitDebugInfo) &&
- ARE_EQUAL(JITEmitDebugInfoToDisk) &&
ARE_EQUAL(GuaranteedTailCallOpt) &&
ARE_EQUAL(DisableTailCalls) &&
ARE_EQUAL(StackAlignmentOverride) &&
@@ -289,11 +241,7 @@ inline bool operator==(const TargetOptions &LHS,
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 a7552565c938..121b8a232526 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -46,6 +46,11 @@ public:
const uint32_t *SubClassMask;
const uint16_t *SuperRegIndices;
const unsigned LaneMask;
+ /// Classes with a higher priority value are assigned first by register
+ /// allocators using a greedy heuristic. The value is in the range [0,63].
+ const uint8_t AllocationPriority;
+ /// Whether the class supports two (or more) disjunct subregister indices.
+ const bool HasDisjunctSubRegs;
const sc_iterator SuperClasses;
ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&);
@@ -357,13 +362,13 @@ public:
///
/// then:
///
- /// getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B) != 0
+ /// (getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B)) != 0
///
/// The converse is not necessarily true. If two lane masks have a common
/// bit, the corresponding sub-registers may not overlap, but it can be
/// assumed that they usually will.
+ /// SubIdx == 0 is allowed, it has the lane mask ~0u.
unsigned getSubRegIndexLaneMask(unsigned SubIdx) const {
- // SubIdx == 0 is allowed, it has the lane mask ~0u.
assert(SubIdx < getNumSubRegIndices() && "This is not a subregister index");
return SubRegIndexLaneMasks[SubIdx];
}
@@ -425,10 +430,10 @@ public:
/// closest to the incoming stack pointer if stack grows down, and vice versa.
///
virtual const MCPhysReg*
- getCalleeSavedRegs(const MachineFunction *MF = nullptr) const = 0;
+ getCalleeSavedRegs(const MachineFunction *MF) const = 0;
/// getCallPreservedMask - Return a mask of call-preserved registers for the
- /// given calling convention on the current sub-target. The mask should
+ /// given calling convention on the current function. The mask should
/// include all call-preserved aliases. This is used by the register
/// allocator to determine which registers can be live across a call.
///
@@ -445,7 +450,8 @@ public:
/// instructions should use implicit-def operands to indicate call clobbered
/// registers.
///
- virtual const uint32_t *getCallPreservedMask(CallingConv::ID) const {
+ virtual const uint32_t *getCallPreservedMask(const MachineFunction &MF,
+ CallingConv::ID) const {
// The default mask clobbers everything. All targets should override.
return nullptr;
}
@@ -622,8 +628,9 @@ public:
/// legal to use in the current sub-target and has the same spill size.
/// The returned register class can be used to create virtual registers which
/// means that all its registers can be copied and spilled.
- virtual const TargetRegisterClass*
- getLargestLegalSuperClass(const TargetRegisterClass *RC) const {
+ virtual const TargetRegisterClass *
+ getLargestLegalSuperClass(const TargetRegisterClass *RC,
+ const MachineFunction &) const {
/// The default implementation is very conservative and doesn't allow the
/// register allocator to inflate register classes.
return RC;
@@ -655,7 +662,8 @@ public:
/// Get the register unit pressure limit for this dimension.
/// This limit must be adjusted dynamically for reserved registers.
- virtual unsigned getRegPressureSetLimit(unsigned Idx) const = 0;
+ virtual unsigned getRegPressureSetLimit(const MachineFunction &MF,
+ unsigned Idx) const = 0;
/// Get the dimensions of register pressure impacted by this register class.
/// Returns a -1 terminated array of pressure set IDs.
@@ -686,21 +694,13 @@ public:
const MachineFunction &MF,
const VirtRegMap *VRM = nullptr) const;
- /// avoidWriteAfterWrite - Return true if the register allocator should avoid
- /// writing a register from RC in two consecutive instructions.
- /// This can avoid pipeline stalls on certain architectures.
- /// It does cause increased register pressure, though.
- virtual bool avoidWriteAfterWrite(const TargetRegisterClass *RC) const {
- return false;
- }
-
- /// UpdateRegAllocHint - A callback to allow target a chance to update
+ /// updateRegAllocHint - A callback to allow target a chance to update
/// register allocation hints when a register is "changed" (e.g. coalesced)
/// to another register. e.g. On ARM, some virtual registers should target
/// register pairs, if one of pair is coalesced to another register, the
/// allocation hint of the other half of the pair should be changed to point
/// to the new register.
- virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
+ virtual void updateRegAllocHint(unsigned Reg, unsigned NewReg,
MachineFunction &MF) const {
// Do nothing.
}
@@ -802,9 +802,9 @@ public:
llvm_unreachable("resolveFrameIndex does not exist on this target");
}
- /// isFrameOffsetLegal - Determine whether a given offset immediate is
- /// encodable to resolve a frame index.
- virtual bool isFrameOffsetLegal(const MachineInstr *MI,
+ /// isFrameOffsetLegal - Determine whether a given base register plus offset
+ /// immediate is encodable to resolve a frame index.
+ virtual bool isFrameOffsetLegal(const MachineInstr *MI, unsigned BaseReg,
int64_t Offset) const {
llvm_unreachable("isFrameOffsetLegal does not exist on this target");
}
diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td
index 907baa1b9b1f..7a788cef0237 100644
--- a/include/llvm/Target/TargetSelectionDAG.td
+++ b/include/llvm/Target/TargetSelectionDAG.td
@@ -68,6 +68,18 @@ class SDTCisSubVecOfVec<int ThisOp, int OtherOp>
int OtherOpNum = OtherOp;
}
+// SDTCVecEltisVT - The specified operand is vector type with element type
+// of VT.
+class SDTCVecEltisVT<int OpNum, ValueType vt> : SDTypeConstraint<OpNum> {
+ ValueType VT = vt;
+}
+
+// SDTCisSameNumEltsAs - The two specified operands have identical number
+// of elements.
+class SDTCisSameNumEltsAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> {
+ int OtherOperandNum = OtherOp;
+}
+
//===----------------------------------------------------------------------===//
// Selection DAG Type Profile definitions.
//
@@ -196,6 +208,16 @@ def SDTMaskedLoad: SDTypeProfile<1, 3, [ // masked load
SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameAs<0, 3>
]>;
+def SDTMaskedGather: SDTypeProfile<2, 3, [ // masked gather
+ SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<1, 3>,
+ SDTCisPtrTy<4>, SDTCVecEltisVT<1, i1>, SDTCisSameNumEltsAs<0, 1>
+]>;
+
+def SDTMaskedScatter: SDTypeProfile<1, 3, [ // masked scatter
+ SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameNumEltsAs<0, 1>,
+ SDTCVecEltisVT<0, i1>, SDTCisPtrTy<3>
+]>;
+
def SDTVecShuffle : SDTypeProfile<1, 2, [
SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>
]>;
@@ -358,6 +380,10 @@ def subc : SDNode<"ISD::SUBC" , SDTIntBinOp,
[SDNPOutGlue]>;
def sube : SDNode<"ISD::SUBE" , SDTIntBinOp,
[SDNPOutGlue, SDNPInGlue]>;
+def smin : SDNode<"ISD::SMIN" , SDTIntBinOp>;
+def smax : SDNode<"ISD::SMAX" , SDTIntBinOp>;
+def umin : SDNode<"ISD::UMIN" , SDTIntBinOp>;
+def umax : SDNode<"ISD::UMAX" , SDTIntBinOp>;
def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>;
def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>;
@@ -371,6 +397,7 @@ def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>;
def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>;
def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>;
def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>;
+def addrspacecast : SDNode<"ISD::ADDRSPACECAST", SDTUnaryOp>;
def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>;
def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>;
@@ -380,6 +407,7 @@ def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>;
def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>;
def frem : SDNode<"ISD::FREM" , SDTFPBinOp>;
def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>;
+def fmad : SDNode<"ISD::FMAD" , SDTFPTernaryOp>;
def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>;
def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp>;
def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp>;
@@ -466,6 +494,10 @@ def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore,
[SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
+def masked_scatter : SDNode<"ISD::MSCATTER", SDTMaskedScatter,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def masked_gather : SDNode<"ISD::MGATHER", SDTMaskedGather,
+ [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
// Do not use ld, st directly. Use load, extload, sextload, zextload, store,
// and truncst (see below).
diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h
index d1a3fcf4a50e..bacdd950705b 100644
--- a/include/llvm/Target/TargetSelectionDAGInfo.h
+++ b/include/llvm/Target/TargetSelectionDAGInfo.h
@@ -21,15 +21,14 @@
namespace llvm {
class DataLayout;
-class TargetMachine;
//===----------------------------------------------------------------------===//
/// TargetSelectionDAGInfo - Targets can subclass this to parameterize the
/// SelectionDAG lowering and instruction selection process.
///
class TargetSelectionDAGInfo {
- TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION;
- void operator=(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION;
+ TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) = delete;
+ void operator=(const TargetSelectionDAGInfo &) = delete;
const DataLayout *DL;
diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h
index 4ff88d07bf27..0f427901a8ec 100644
--- a/include/llvm/Target/TargetSubtargetInfo.h
+++ b/include/llvm/Target/TargetSubtargetInfo.h
@@ -42,15 +42,17 @@ template <typename T> class SmallVectorImpl;
/// be exposed through a TargetSubtargetInfo-derived class.
///
class TargetSubtargetInfo : public MCSubtargetInfo {
- TargetSubtargetInfo(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION;
- void operator=(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION;
+ TargetSubtargetInfo(const TargetSubtargetInfo &) = delete;
+ void operator=(const TargetSubtargetInfo &) = delete;
+
protected: // Can only create subclasses...
TargetSubtargetInfo();
+
public:
// AntiDepBreakMode - Type of anti-dependence breaking that should
// be performed before post-RA scheduling.
typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode;
- typedef SmallVectorImpl<const TargetRegisterClass*> RegClassVector;
+ typedef SmallVectorImpl<const TargetRegisterClass *> RegClassVector;
virtual ~TargetSubtargetInfo();
@@ -71,7 +73,6 @@ public:
virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const {
return nullptr;
}
- virtual const DataLayout *getDataLayout() const { return nullptr; }
/// getRegisterInfo - If register information is available, return it. If
/// not, return null. This is kept separate from RegInfo until RegInfo has
@@ -90,21 +91,30 @@ public:
/// MCSchedClassDesc with the isVariant property. This may return the ID of
/// another variant SchedClass, but repeated invocation must quickly terminate
/// in a nonvariant SchedClass.
- virtual unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,
- const TargetSchedModel* SchedModel) const {
+ virtual unsigned resolveSchedClass(unsigned SchedClass,
+ const MachineInstr *MI,
+ const TargetSchedModel *SchedModel) const {
return 0;
}
- /// \brief Temporary API to test migration to MI scheduler.
- bool useMachineScheduler() const;
-
/// \brief True if the subtarget should run MachineScheduler after aggressive
/// coalescing.
///
/// This currently replaces the SelectionDAG scheduler with the "source" order
- /// scheduler. It does not yet disable the postRA scheduler.
+ /// scheduler (though see below for an option to turn this off and use the
+ /// TargetLowering preference). It does not yet disable the postRA scheduler.
virtual bool enableMachineScheduler() const;
+ /// \brief True if the machine scheduler should disable the TLI preference
+ /// for preRA scheduling with the source level scheduler.
+ virtual bool enableMachineSchedDefaultSched() const { return true; }
+
+ /// \brief True if the subtarget should enable joining global copies.
+ ///
+ /// By default this is enabled if the machine scheduler is enabled, but
+ /// can be overridden.
+ virtual bool enableJoinGlobalCopies() const;
+
/// \brief True if the subtarget should run PostMachineScheduler.
///
/// This only takes effect if the target has configured the
@@ -121,20 +131,16 @@ public:
/// scheduling heuristics (no custom MachineSchedStrategy) to make
/// changes to the generic scheduling policy.
virtual void overrideSchedPolicy(MachineSchedPolicy &Policy,
- MachineInstr *begin,
- MachineInstr *end,
+ MachineInstr *begin, MachineInstr *end,
unsigned NumRegionInstrs) const {}
// \brief Perform target specific adjustments to the latency of a schedule
// dependency.
- virtual void adjustSchedDependency(SUnit *def, SUnit *use,
- SDep& dep) const { }
+ 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;
- }
+ 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
@@ -170,9 +176,7 @@ public:
}
/// Enable tracking of subregister liveness in register allocator.
- virtual bool enableSubRegLiveness() const {
- return false;
- }
+ virtual bool enableSubRegLiveness() const { return false; }
};
} // End llvm namespace
diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h
index ce1a7d6a5230..fbd999cbc946 100644
--- a/include/llvm/Transforms/IPO.h
+++ b/include/llvm/Transforms/IPO.h
@@ -199,6 +199,10 @@ ModulePass *createMetaRenamerPass();
/// manager.
ModulePass *createBarrierNoopPass();
+/// \brief This pass lowers bitset metadata and the llvm.bitset.test intrinsic
+/// to bitsets.
+ModulePass *createLowerBitSetsPass();
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/IPO/LowerBitSets.h b/include/llvm/Transforms/IPO/LowerBitSets.h
new file mode 100644
index 000000000000..55d7d84560a0
--- /dev/null
+++ b/include/llvm/Transforms/IPO/LowerBitSets.h
@@ -0,0 +1,198 @@
+//===- LowerBitSets.h - Bitset lowering pass --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines parts of the bitset lowering pass implementation that may
+// be usefully unit tested.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_LOWERBITSETS_H
+#define LLVM_TRANSFORMS_IPO_LOWERBITSETS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include <stdint.h>
+#include <limits>
+#include <set>
+#include <vector>
+
+namespace llvm {
+
+class DataLayout;
+class GlobalVariable;
+class Value;
+
+struct BitSetInfo {
+ // The indices of the set bits in the bitset.
+ std::set<uint64_t> Bits;
+
+ // The byte offset into the combined global represented by the bitset.
+ uint64_t ByteOffset;
+
+ // The size of the bitset in bits.
+ uint64_t BitSize;
+
+ // Log2 alignment of the bit set relative to the combined global.
+ // For example, a log2 alignment of 3 means that bits in the bitset
+ // represent addresses 8 bytes apart.
+ unsigned AlignLog2;
+
+ bool isSingleOffset() const {
+ return Bits.size() == 1;
+ }
+
+ bool isAllOnes() const {
+ return Bits.size() == BitSize;
+ }
+
+ bool containsGlobalOffset(uint64_t Offset) const;
+
+ bool containsValue(const DataLayout &DL,
+ const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout,
+ Value *V, uint64_t COffset = 0) const;
+};
+
+struct BitSetBuilder {
+ SmallVector<uint64_t, 16> Offsets;
+ uint64_t Min, Max;
+
+ BitSetBuilder() : Min(std::numeric_limits<uint64_t>::max()), Max(0) {}
+
+ void addOffset(uint64_t Offset) {
+ if (Min > Offset)
+ Min = Offset;
+ if (Max < Offset)
+ Max = Offset;
+
+ Offsets.push_back(Offset);
+ }
+
+ BitSetInfo build();
+};
+
+/// This class implements a layout algorithm for globals referenced by bit sets
+/// that tries to keep members of small bit sets together. This can
+/// significantly reduce bit set sizes in many cases.
+///
+/// It works by assembling fragments of layout from sets of referenced globals.
+/// Each set of referenced globals causes the algorithm to create a new
+/// fragment, which is assembled by appending each referenced global in the set
+/// into the fragment. If a referenced global has already been referenced by an
+/// fragment created earlier, we instead delete that fragment and append its
+/// contents into the fragment we are assembling.
+///
+/// By starting with the smallest fragments, we minimize the size of the
+/// fragments that are copied into larger fragments. This is most intuitively
+/// thought about when considering the case where the globals are virtual tables
+/// and the bit sets represent their derived classes: in a single inheritance
+/// hierarchy, the optimum layout would involve a depth-first search of the
+/// class hierarchy (and in fact the computed layout ends up looking a lot like
+/// a DFS), but a naive DFS would not work well in the presence of multiple
+/// inheritance. This aspect of the algorithm ends up fitting smaller
+/// hierarchies inside larger ones where that would be beneficial.
+///
+/// For example, consider this class hierarchy:
+///
+/// A B
+/// \ / | \
+/// C D E
+///
+/// We have five bit sets: bsA (A, C), bsB (B, C, D, E), bsC (C), bsD (D) and
+/// bsE (E). If we laid out our objects by DFS traversing B followed by A, our
+/// layout would be {B, C, D, E, A}. This is optimal for bsB as it needs to
+/// cover the only 4 objects in its hierarchy, but not for bsA as it needs to
+/// cover 5 objects, i.e. the entire layout. Our algorithm proceeds as follows:
+///
+/// Add bsC, fragments {{C}}
+/// Add bsD, fragments {{C}, {D}}
+/// Add bsE, fragments {{C}, {D}, {E}}
+/// Add bsA, fragments {{A, C}, {D}, {E}}
+/// Add bsB, fragments {{B, A, C, D, E}}
+///
+/// This layout is optimal for bsA, as it now only needs to cover two (i.e. 3
+/// fewer) objects, at the cost of bsB needing to cover 1 more object.
+///
+/// The bit set lowering pass assigns an object index to each object that needs
+/// to be laid out, and calls addFragment for each bit set passing the object
+/// indices of its referenced globals. It then assembles a layout from the
+/// computed layout in the Fragments field.
+struct GlobalLayoutBuilder {
+ /// The computed layout. Each element of this vector contains a fragment of
+ /// layout (which may be empty) consisting of object indices.
+ std::vector<std::vector<uint64_t>> Fragments;
+
+ /// Mapping from object index to fragment index.
+ std::vector<uint64_t> FragmentMap;
+
+ GlobalLayoutBuilder(uint64_t NumObjects)
+ : Fragments(1), FragmentMap(NumObjects) {}
+
+ /// Add F to the layout while trying to keep its indices contiguous.
+ /// If a previously seen fragment uses any of F's indices, that
+ /// fragment will be laid out inside F.
+ void addFragment(const std::set<uint64_t> &F);
+};
+
+/// This class is used to build a byte array containing overlapping bit sets. By
+/// loading from indexed offsets into the byte array and applying a mask, a
+/// program can test bits from the bit set with a relatively short instruction
+/// sequence. For example, suppose we have 15 bit sets to lay out:
+///
+/// A (16 bits), B (15 bits), C (14 bits), D (13 bits), E (12 bits),
+/// F (11 bits), G (10 bits), H (9 bits), I (7 bits), J (6 bits), K (5 bits),
+/// L (4 bits), M (3 bits), N (2 bits), O (1 bit)
+///
+/// These bits can be laid out in a 16-byte array like this:
+///
+/// Byte Offset
+/// 0123456789ABCDEF
+/// Bit
+/// 7 HHHHHHHHHIIIIIII
+/// 6 GGGGGGGGGGJJJJJJ
+/// 5 FFFFFFFFFFFKKKKK
+/// 4 EEEEEEEEEEEELLLL
+/// 3 DDDDDDDDDDDDDMMM
+/// 2 CCCCCCCCCCCCCCNN
+/// 1 BBBBBBBBBBBBBBBO
+/// 0 AAAAAAAAAAAAAAAA
+///
+/// For example, to test bit X of A, we evaluate ((bits[X] & 1) != 0), or to
+/// test bit X of I, we evaluate ((bits[9 + X] & 0x80) != 0). This can be done
+/// in 1-2 machine instructions on x86, or 4-6 instructions on ARM.
+///
+/// This is a byte array, rather than (say) a 2-byte array or a 4-byte array,
+/// because for one thing it gives us better packing (the more bins there are,
+/// the less evenly they will be filled), and for another, the instruction
+/// sequences can be slightly shorter, both on x86 and ARM.
+struct ByteArrayBuilder {
+ /// The byte array built so far.
+ std::vector<uint8_t> Bytes;
+
+ enum { BitsPerByte = 8 };
+
+ /// The number of bytes allocated so far for each of the bits.
+ uint64_t BitAllocs[BitsPerByte];
+
+ ByteArrayBuilder() {
+ memset(BitAllocs, 0, sizeof(BitAllocs));
+ }
+
+ /// Allocate BitSize bits in the byte array where Bits contains the bits to
+ /// set. AllocByteOffset is set to the offset within the byte array and
+ /// AllocMask is set to the bitmask for those bits. This uses the LPT (Longest
+ /// Processing Time) multiprocessor scheduling algorithm to lay out the bits
+ /// efficiently; the pass allocates bit sets in decreasing size order.
+ void allocate(const std::set<uint64_t> &Bits, uint64_t BitSize,
+ uint64_t &AllocByteOffset, uint8_t &AllocMask);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h
index b1426b4f45ca..5d574ae0bf0f 100644
--- a/include/llvm/Transforms/IPO/PassManagerBuilder.h
+++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h
@@ -19,7 +19,7 @@
namespace llvm {
class Pass;
-class TargetLibraryInfo;
+class TargetLibraryInfoImpl;
class TargetMachine;
// The old pass manager infrastructure is hidden in a legacy namespace now.
@@ -27,8 +27,6 @@ namespace legacy {
class FunctionPassManager;
class PassManagerBase;
}
-using legacy::FunctionPassManager;
-using legacy::PassManagerBase;
/// PassManagerBuilder - This class is used to set up a standard optimization
/// sequence for languages like C and C++, allowing some APIs to customize the
@@ -59,7 +57,7 @@ public:
/// Extensions are passed the builder itself (so they can see how it is
/// configured) as well as the pass manager to add stuff to.
typedef void (*ExtensionFn)(const PassManagerBuilder &Builder,
- PassManagerBase &PM);
+ legacy::PassManagerBase &PM);
enum ExtensionPointTy {
/// EP_EarlyAsPossible - This extension point allows adding passes before
/// any other transformations, allowing them to see the code as it is coming
@@ -105,7 +103,7 @@ public:
/// LibraryInfo - Specifies information about the runtime library for the
/// optimizer. If this is non-null, it is added to both the function and
/// per-module pass pipeline.
- TargetLibraryInfo *LibraryInfo;
+ TargetLibraryInfoImpl *LibraryInfo;
/// Inliner - Specifies the inliner to use. If this is non-null, it is
/// added to the per-module passes.
@@ -122,7 +120,6 @@ public:
bool DisableGVNLoadPRE;
bool VerifyInput;
bool VerifyOutput;
- bool StripDebug;
bool MergeFunctions;
private:
@@ -139,19 +136,21 @@ public:
void addExtension(ExtensionPointTy Ty, ExtensionFn Fn);
private:
- void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const;
- void addInitialAliasAnalysisPasses(PassManagerBase &PM) const;
- void addLTOOptimizationPasses(PassManagerBase &PM);
+ void addExtensionsToPM(ExtensionPointTy ETy,
+ legacy::PassManagerBase &PM) const;
+ void addInitialAliasAnalysisPasses(legacy::PassManagerBase &PM) const;
+ void addLTOOptimizationPasses(legacy::PassManagerBase &PM);
+ void addLateLTOOptimizationPasses(legacy::PassManagerBase &PM);
public:
/// populateFunctionPassManager - This fills in the function pass manager,
/// which is expected to be run on each function immediately as it is
/// generated. The idea is to reduce the size of the IR in memory.
- void populateFunctionPassManager(FunctionPassManager &FPM);
+ void populateFunctionPassManager(legacy::FunctionPassManager &FPM);
/// populateModulePassManager - This sets up the primary pass manager.
- void populateModulePassManager(PassManagerBase &MPM);
- void populateLTOPassManager(PassManagerBase &PM, TargetMachine *TM = nullptr);
+ void populateModulePassManager(legacy::PassManagerBase &MPM);
+ void populateLTOPassManager(legacy::PassManagerBase &PM);
};
/// Registers a function for adding a standard set of passes. This should be
diff --git a/include/llvm/Transforms/InstCombine/InstCombine.h b/include/llvm/Transforms/InstCombine/InstCombine.h
new file mode 100644
index 000000000000..f48ec13107bc
--- /dev/null
+++ b/include/llvm/Transforms/InstCombine/InstCombine.h
@@ -0,0 +1,46 @@
+//===- InstCombine.h - InstCombine pass -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file provides the primary interface to the instcombine pass. This pass
+/// is suitable for use in the new pass manager. For a pass that works with the
+/// legacy pass manager, please look for \c createInstructionCombiningPass() in
+/// Scalar.h.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H
+#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/InstCombine/InstCombineWorklist.h"
+
+namespace llvm {
+
+class InstCombinePass {
+ InstCombineWorklist Worklist;
+
+public:
+ static StringRef name() { return "InstCombinePass"; }
+
+ // Explicitly define constructors for MSVC.
+ InstCombinePass() {}
+ InstCombinePass(InstCombinePass &&Arg) : Worklist(std::move(Arg.Worklist)) {}
+ InstCombinePass &operator=(InstCombinePass &&RHS) {
+ Worklist = std::move(RHS.Worklist);
+ return *this;
+ }
+
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/InstCombine/InstCombineWorklist.h b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
new file mode 100644
index 000000000000..a6bad343db43
--- /dev/null
+++ b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
@@ -0,0 +1,116 @@
+//===- InstCombineWorklist.h - Worklist for InstCombine pass ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H
+#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "instcombine"
+
+namespace llvm {
+
+/// InstCombineWorklist - This is the worklist management logic for
+/// InstCombine.
+class InstCombineWorklist {
+ SmallVector<Instruction*, 256> Worklist;
+ DenseMap<Instruction*, unsigned> WorklistMap;
+
+ void operator=(const InstCombineWorklist&RHS) = delete;
+ InstCombineWorklist(const InstCombineWorklist&) = delete;
+public:
+ InstCombineWorklist() {}
+
+ InstCombineWorklist(InstCombineWorklist &&Arg)
+ : Worklist(std::move(Arg.Worklist)),
+ WorklistMap(std::move(Arg.WorklistMap)) {}
+ InstCombineWorklist &operator=(InstCombineWorklist &&RHS) {
+ Worklist = std::move(RHS.Worklist);
+ WorklistMap = std::move(RHS.WorklistMap);
+ return *this;
+ }
+
+ bool isEmpty() const { return Worklist.empty(); }
+
+ /// Add - Add the specified instruction to the worklist if it isn't already
+ /// in it.
+ void Add(Instruction *I) {
+ if (WorklistMap.insert(std::make_pair(I, Worklist.size())).second) {
+ DEBUG(dbgs() << "IC: ADD: " << *I << '\n');
+ Worklist.push_back(I);
+ }
+ }
+
+ void AddValue(Value *V) {
+ if (Instruction *I = dyn_cast<Instruction>(V))
+ Add(I);
+ }
+
+ /// AddInitialGroup - Add the specified batch of stuff in reverse order.
+ /// which should only be done when the worklist is empty and when the group
+ /// has no duplicates.
+ void AddInitialGroup(Instruction *const *List, unsigned NumEntries) {
+ assert(Worklist.empty() && "Worklist must be empty to add initial group");
+ Worklist.reserve(NumEntries+16);
+ WorklistMap.resize(NumEntries);
+ DEBUG(dbgs() << "IC: ADDING: " << NumEntries << " instrs to worklist\n");
+ for (unsigned Idx = 0; NumEntries; --NumEntries) {
+ Instruction *I = List[NumEntries-1];
+ WorklistMap.insert(std::make_pair(I, Idx++));
+ Worklist.push_back(I);
+ }
+ }
+
+ // Remove - remove I from the worklist if it exists.
+ void Remove(Instruction *I) {
+ DenseMap<Instruction*, unsigned>::iterator It = WorklistMap.find(I);
+ if (It == WorklistMap.end()) return; // Not in worklist.
+
+ // Don't bother moving everything down, just null out the slot.
+ Worklist[It->second] = nullptr;
+
+ WorklistMap.erase(It);
+ }
+
+ Instruction *RemoveOne() {
+ Instruction *I = Worklist.pop_back_val();
+ WorklistMap.erase(I);
+ return I;
+ }
+
+ /// AddUsersToWorkList - When an instruction is simplified, add all users of
+ /// the instruction to the work lists because they might get more simplified
+ /// now.
+ ///
+ void AddUsersToWorkList(Instruction &I) {
+ for (User *U : I.users())
+ Add(cast<Instruction>(U));
+ }
+
+
+ /// Zap - check that the worklist is empty and nuke the backing store for
+ /// the map if it is large.
+ void Zap() {
+ assert(WorklistMap.empty() && "Worklist empty, but map not?");
+
+ // Do an explicit clear, this shrinks the map if needed.
+ WorklistMap.clear();
+ }
+};
+
+} // end namespace llvm.
+
+#undef DEBUG_TYPE
+
+#endif
diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h
index 24e3ef783ee6..884f54fd3737 100644
--- a/include/llvm/Transforms/Instrumentation.h
+++ b/include/llvm/Transforms/Instrumentation.h
@@ -15,6 +15,7 @@
#define LLVM_TRANSFORMS_INSTRUMENTATION_H
#include "llvm/ADT/StringRef.h"
+#include <vector>
#if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID)
inline void *getDFSanArgTLSPtrForJIT() {
@@ -59,6 +60,10 @@ struct GCOVOptions {
// Emit the name of the function in the .gcda files. This is redundant, as
// the function identifier can be used to find the name from the .gcno file.
bool FunctionNamesInData;
+
+ // Emit the exit block immediately after the start block, rather than after
+ // all of the function body's blocks.
+ bool ExitBlockBeforeBody;
};
ModulePass *createGCOVProfilerPass(const GCOVOptions &Options =
GCOVOptions::getDefault());
@@ -69,6 +74,9 @@ struct InstrProfOptions {
// Add the 'noredzone' attribute to added runtime library calls.
bool NoRedZone;
+
+ // Name of the profile file to use as output
+ std::string InstrProfileOutput;
};
/// Insert frontend instrumentation based profiling.
@@ -86,17 +94,36 @@ FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0);
FunctionPass *createThreadSanitizerPass();
// Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation
-ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(),
- void *(*getArgTLS)() = nullptr,
- void *(*getRetValTLS)() = nullptr);
+ModulePass *createDataFlowSanitizerPass(
+ const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
+ void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr);
+
+// Options for sanitizer coverage instrumentation.
+struct SanitizerCoverageOptions {
+ SanitizerCoverageOptions()
+ : CoverageType(SCK_None), IndirectCalls(false), TraceBB(false),
+ TraceCmp(false), Use8bitCounters(false) {}
+
+ enum Type {
+ SCK_None = 0,
+ SCK_Function,
+ SCK_BB,
+ SCK_Edge
+ } CoverageType;
+ bool IndirectCalls;
+ bool TraceBB;
+ bool TraceCmp;
+ bool Use8bitCounters;
+};
// Insert SanitizerCoverage instrumentation.
-ModulePass *createSanitizerCoverageModulePass(int CoverageLevel);
+ModulePass *createSanitizerCoverageModulePass(
+ const SanitizerCoverageOptions &Options = SanitizerCoverageOptions());
#if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID)
-inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile =
- StringRef()) {
- return createDataFlowSanitizerPass(ABIListFile, getDFSanArgTLSPtrForJIT,
+inline ModulePass *createDataFlowSanitizerPassForJIT(
+ const std::vector<std::string> &ABIListFiles = std::vector<std::string>()) {
+ return createDataFlowSanitizerPass(ABIListFiles, getDFSanArgTLSPtrForJIT,
getDFSanRetValTLSPtrForJIT);
}
#endif
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index 5dcd89948759..c4669f121e6a 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -21,6 +21,7 @@ namespace llvm {
class BasicBlockPass;
class FunctionPass;
+class ModulePass;
class Pass;
class GetElementPtrInst;
class PassInfo;
@@ -81,6 +82,13 @@ FunctionPass *createAggressiveDCEPass();
//===----------------------------------------------------------------------===//
//
+// BitTrackingDCE - This pass uses a bit-tracking DCE algorithm in order to
+// remove computations of dead bits.
+//
+FunctionPass *createBitTrackingDCEPass();
+
+//===----------------------------------------------------------------------===//
+//
// SROA - Replace aggregates or pieces of aggregates with scalar SSA values.
//
FunctionPass *createSROAPass(bool RequiresDomTree = true);
@@ -98,6 +106,13 @@ FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1,
//===----------------------------------------------------------------------===//
//
+// InductiveRangeCheckElimination - Transform loops to elide range checks on
+// linear functions of the induction variable.
+//
+Pass *createInductiveRangeCheckEliminationPass();
+
+//===----------------------------------------------------------------------===//
+//
// InductionVariableSimplify - Transform induction variables in a program to all
// use a single canonical induction variable per loop.
//
@@ -125,12 +140,19 @@ Pass *createLICMPass();
//===----------------------------------------------------------------------===//
//
+// LoopInterchange - This pass interchanges loops to provide a more
+// cache-friendly memory access patterns.
+//
+Pass *createLoopInterchangePass();
+
+//===----------------------------------------------------------------------===//
+//
// LoopStrengthReduce - This pass is strength reduces GEP instructions that use
// a loop's canonical induction variable as one of their indices.
//
Pass *createLoopStrengthReducePass();
-Pass *createGlobalMergePass(const TargetMachine *TM = nullptr);
+Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset);
//===----------------------------------------------------------------------===//
//
@@ -401,10 +423,59 @@ createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr,
//===----------------------------------------------------------------------===//
//
+// SpeculativeExecution - Aggressively hoist instructions to enable
+// speculative execution on targets where branches are expensive.
+//
+FunctionPass *createSpeculativeExecutionPass();
+
+//===----------------------------------------------------------------------===//
+//
// LoadCombine - Combine loads into bigger loads.
//
BasicBlockPass *createLoadCombinePass();
+//===----------------------------------------------------------------------===//
+//
+// StraightLineStrengthReduce - This pass strength-reduces some certain
+// instruction patterns in straight-line code.
+//
+FunctionPass *createStraightLineStrengthReducePass();
+
+//===----------------------------------------------------------------------===//
+//
+// PlaceSafepoints - Rewrite any IR calls to gc.statepoints and insert any
+// safepoint polls (method entry, backedge) that might be required. This pass
+// does not generate explicit relocation sequences - that's handled by
+// RewriteStatepointsForGC which can be run at an arbitrary point in the pass
+// order following this pass.
+//
+FunctionPass *createPlaceSafepointsPass();
+
+//===----------------------------------------------------------------------===//
+//
+// RewriteStatepointsForGC - Rewrite any gc.statepoints which do not yet have
+// explicit relocations to include explicit relocations.
+//
+FunctionPass *createRewriteStatepointsForGCPass();
+
+//===----------------------------------------------------------------------===//
+//
+// Float2Int - Demote floats to ints where possible.
+//
+FunctionPass *createFloat2IntPass();
+
+//===----------------------------------------------------------------------===//
+//
+// NaryReassociate - Simplify n-ary operations by reassociation.
+//
+FunctionPass *createNaryReassociatePass();
+
+//===----------------------------------------------------------------------===//
+//
+// LoopDistribute - Distribute loops.
+//
+FunctionPass *createLoopDistributePass();
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Scalar/EarlyCSE.h b/include/llvm/Transforms/Scalar/EarlyCSE.h
new file mode 100644
index 000000000000..e3dd3c050df6
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/EarlyCSE.h
@@ -0,0 +1,39 @@
+//===- EarlyCSE.h - Simple and fast CSE pass --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides the interface for a simple, fast CSE pass.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_EARLYCSE_H
+#define LLVM_TRANSFORMS_SCALAR_EARLYCSE_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// \brief A simple and fast domtree-based CSE pass.
+///
+/// This pass does a simple depth-first walk over the dominator tree,
+/// eliminating trivially redundant instructions and using instsimplify to
+/// canonicalize things as it goes. It is intended to be fast and catch obvious
+/// cases so that instcombine and other passes are more effective. It is
+/// expected that a later pass of GVN will catch the interesting/hard cases.
+class EarlyCSEPass {
+public:
+ static StringRef name() { return "EarlyCSEPass"; }
+
+ /// \brief Run the pass over the function.
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
new file mode 100644
index 000000000000..40283203f3a3
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
@@ -0,0 +1,40 @@
+//===- LowerExpectIntrinsic.h - LowerExpectIntrinsic pass -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// The header file for the LowerExpectIntrinsic pass as used by the new pass
+/// manager.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOWEREXPECTINTRINSIC_H
+#define LLVM_TRANSFORMS_SCALAR_LOWEREXPECTINTRINSIC_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class LowerExpectIntrinsicPass {
+public:
+ static StringRef name() { return "LowerExpectIntrinsicPass"; }
+
+ /// \brief Run the pass over the function.
+ ///
+ /// This will lower all of th expect intrinsic calls in this function into
+ /// branch weight metadata. That metadata will subsequently feed the analysis
+ /// of the probabilities and frequencies of the CFG. After running this pass,
+ /// no more expect intrinsics remain, allowing the rest of the optimizer to
+ /// ignore them.
+ PreservedAnalyses run(Function &F);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Scalar/SimplifyCFG.h b/include/llvm/Transforms/Scalar/SimplifyCFG.h
new file mode 100644
index 000000000000..ef28e0f78a4c
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/SimplifyCFG.h
@@ -0,0 +1,46 @@
+//===- SimplifyCFG.h - Simplify and canonicalize the CFG --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides the interface for the pass responsible for both
+/// simplifying and canonicalizing the CFG.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H
+#define LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// \brief A pass to simplify and canonicalize the CFG of a function.
+///
+/// This pass iteratively simplifies the entire CFG of a function, removing
+/// unnecessary control flows and bringing it into the canonical form expected
+/// by the rest of the mid-level optimizer.
+class SimplifyCFGPass {
+ int BonusInstThreshold;
+
+public:
+ static StringRef name() { return "SimplifyCFGPass"; }
+
+ /// \brief Construct a pass with the default thresholds.
+ SimplifyCFGPass();
+
+ /// \brief Construct a pass with a specific bonus threshold.
+ SimplifyCFGPass(int BonusInstThreshold);
+
+ /// \brief Run the pass over the function.
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 19acf5b2db83..710db03c45d6 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -23,10 +23,11 @@
namespace llvm {
class AliasAnalysis;
+class MemoryDependenceAnalysis;
class DominatorTree;
+class LoopInfo;
class Instruction;
class MDNode;
-class Pass;
class ReturnInst;
class TargetLibraryInfo;
class TerminatorInst;
@@ -39,7 +40,8 @@ void DeleteDeadBlock(BasicBlock *BB);
/// any single-entry PHI nodes in it, fold them away. This handles the case
/// when all entries to the PHI nodes in a block are guaranteed equal, such as
/// when the block has exactly one predecessor.
-void FoldSingleEntryPHINodes(BasicBlock *BB, Pass *P = nullptr);
+void FoldSingleEntryPHINodes(BasicBlock *BB, AliasAnalysis *AA = nullptr,
+ MemoryDependenceAnalysis *MemDep = nullptr);
/// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it
/// is dead. Also recursively delete any operands that become dead as
@@ -50,7 +52,10 @@ bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr);
/// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor,
/// if possible. The return value indicates success or failure.
-bool MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P = nullptr);
+bool MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr,
+ AliasAnalysis *AA = nullptr,
+ MemoryDependenceAnalysis *MemDep = nullptr);
// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI)
// with a value, then remove and delete the original instruction.
@@ -70,18 +75,62 @@ void ReplaceInstWithInst(BasicBlock::InstListType &BIL,
//
void ReplaceInstWithInst(Instruction *From, Instruction *To);
+/// \brief Option class for critical edge splitting.
+///
+/// This provides a builder interface for overriding the default options used
+/// during critical edge splitting.
+struct CriticalEdgeSplittingOptions {
+ AliasAnalysis *AA;
+ DominatorTree *DT;
+ LoopInfo *LI;
+ bool MergeIdenticalEdges;
+ bool DontDeleteUselessPHIs;
+ bool PreserveLCSSA;
+
+ CriticalEdgeSplittingOptions()
+ : AA(nullptr), DT(nullptr), LI(nullptr), MergeIdenticalEdges(false),
+ DontDeleteUselessPHIs(false), PreserveLCSSA(false) {}
+
+ /// \brief Basic case of setting up all the analysis.
+ CriticalEdgeSplittingOptions(AliasAnalysis *AA, DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr)
+ : AA(AA), DT(DT), LI(LI), MergeIdenticalEdges(false),
+ DontDeleteUselessPHIs(false), PreserveLCSSA(false) {}
+
+ /// \brief A common pattern is to preserve the dominator tree and loop
+ /// info but not care about AA.
+ CriticalEdgeSplittingOptions(DominatorTree *DT, LoopInfo *LI)
+ : AA(nullptr), DT(DT), LI(LI), MergeIdenticalEdges(false),
+ DontDeleteUselessPHIs(false), PreserveLCSSA(false) {}
+
+ CriticalEdgeSplittingOptions &setMergeIdenticalEdges() {
+ MergeIdenticalEdges = true;
+ return *this;
+ }
+
+ CriticalEdgeSplittingOptions &setDontDeleteUselessPHIs() {
+ DontDeleteUselessPHIs = true;
+ return *this;
+ }
+
+ CriticalEdgeSplittingOptions &setPreserveLCSSA() {
+ PreserveLCSSA = true;
+ return *this;
+ }
+};
+
/// SplitCriticalEdge - If this edge is a critical edge, insert a new node to
-/// split the critical edge. This will update DominatorTree and
-/// DominatorFrontier information if it is available, thus calling this pass
-/// will not invalidate either of them. This returns the new block if the edge
-/// was split, null otherwise.
+/// split the critical edge. This will update the analyses passed in through
+/// the option struct. This returns the new block if the edge was split, null
+/// otherwise.
///
-/// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the
-/// specified successor will be merged into the same critical edge block.
-/// This is most commonly interesting with switch instructions, which may
-/// have many edges to any one destination. This ensures that all edges to that
-/// dest go to one block instead of each going to a different block, but isn't
-/// the standard definition of a "critical edge".
+/// If MergeIdenticalEdges in the options struct is true (not the default),
+/// *all* edges from TI to the specified successor will be merged into the same
+/// critical edge block. This is most commonly interesting with switch
+/// instructions, which may have many edges to any one destination. This
+/// ensures that all edges to that dest go to one block instead of each going
+/// to a different block, but isn't the standard definition of a "critical
+/// edge".
///
/// It is invalid to call this function on a critical edge that starts at an
/// IndirectBrInst. Splitting these edges will almost always create an invalid
@@ -89,14 +138,15 @@ void ReplaceInstWithInst(Instruction *From, Instruction *To);
/// to.
///
BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
- Pass *P = nullptr,
- bool MergeIdenticalEdges = false,
- bool DontDeleteUselessPHIs = false,
- bool SplitLandingPads = false);
-
-inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
- Pass *P = nullptr) {
- return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P);
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions());
+
+inline BasicBlock *
+SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions()) {
+ return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(),
+ Options);
}
/// SplitCriticalEdge - If the edge from *PI to BB is not critical, return
@@ -105,55 +155,62 @@ inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
/// function. If P is specified, it updates the analyses
/// described above.
inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI,
- Pass *P = nullptr) {
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions()) {
bool MadeChange = false;
TerminatorInst *TI = (*PI)->getTerminator();
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
if (TI->getSuccessor(i) == Succ)
- MadeChange |= !!SplitCriticalEdge(TI, i, P);
+ MadeChange |= !!SplitCriticalEdge(TI, i, Options);
return MadeChange;
}
/// SplitCriticalEdge - If an edge from Src to Dst is critical, split the edge
/// and return true, otherwise return false. This method requires that there be
-/// an edge between the two blocks. If P is specified, it updates the analyses
-/// described above.
-inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst,
- Pass *P = nullptr,
- bool MergeIdenticalEdges = false,
- bool DontDeleteUselessPHIs = false) {
+/// an edge between the two blocks. It updates the analyses
+/// passed in the options struct
+inline BasicBlock *
+SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst,
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions()) {
TerminatorInst *TI = Src->getTerminator();
unsigned i = 0;
while (1) {
assert(i != TI->getNumSuccessors() && "Edge doesn't exist!");
if (TI->getSuccessor(i) == Dst)
- return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges,
- DontDeleteUselessPHIs);
+ return SplitCriticalEdge(TI, i, Options);
++i;
}
}
// SplitAllCriticalEdges - Loop over all of the edges in the CFG,
-// breaking critical edges as they are found. Pass P must not be NULL.
+// breaking critical edges as they are found.
// Returns the number of broken edges.
-unsigned SplitAllCriticalEdges(Function &F, Pass *P);
+unsigned SplitAllCriticalEdges(Function &F,
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions());
-/// SplitEdge - Split the edge connecting specified block. Pass P must
-/// not be NULL.
-BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P);
+/// SplitEdge - Split the edge connecting specified block.
+BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,
+ DominatorTree *DT = nullptr, LoopInfo *LI = nullptr);
/// SplitBlock - Split the specified block at the specified instruction - every
/// thing before SplitPt stays in Old and everything starting with SplitPt moves
/// to a new block. The two blocks are joined by an unconditional branch and
/// the loop info is updated.
///
-BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P);
+BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt,
+ DominatorTree *DT = nullptr, LoopInfo *LI = nullptr);
-/// SplitBlockPredecessors - This method transforms BB by introducing a new
-/// basic block into the function, and moving some of the predecessors of BB to
-/// be predecessors of the new block. The new predecessors are indicated by the
-/// Preds array, which has NumPreds elements in it. The new block is given a
-/// suffix of 'Suffix'. This function returns the new block.
+/// SplitBlockPredecessors - This method introduces at least one new basic block
+/// into the function and moves some of the predecessors of BB to be
+/// predecessors of the new block. The new predecessors are indicated by the
+/// Preds array. The new block is given a suffix of 'Suffix'. Returns new basic
+/// block to which predecessors from Preds are now pointing.
+///
+/// If BB is a landingpad block then additional basicblock might be introduced.
+/// It will have Suffix+".split_lp". See SplitLandingPadPredecessors for more
+/// details on this case.
///
/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree,
/// DominanceFrontier, LoopInfo, and LCCSA but no other analyses.
@@ -161,8 +218,12 @@ BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P);
/// complicated to handle the case where one of the edges being split
/// is an exit of a loop with other exits).
///
-BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock*> Preds,
- const char *Suffix, Pass *P = nullptr);
+BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
+ const char *Suffix,
+ AliasAnalysis *AA = nullptr,
+ DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr,
+ bool PreserveLCSSA = false);
/// SplitLandingPadPredecessors - This method transforms the landing pad,
/// OrigBB, by introducing two new basic blocks into the function. One of those
@@ -177,9 +238,14 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock*> Preds,
/// case where one of the edges being split is an exit of a loop with other
/// exits).
///
-void SplitLandingPadPredecessors(BasicBlock *OrigBB,ArrayRef<BasicBlock*> Preds,
+void SplitLandingPadPredecessors(BasicBlock *OrigBB,
+ ArrayRef<BasicBlock *> Preds,
const char *Suffix, const char *Suffix2,
- Pass *P, SmallVectorImpl<BasicBlock*> &NewBBs);
+ SmallVectorImpl<BasicBlock *> &NewBBs,
+ AliasAnalysis *AA = nullptr,
+ DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr,
+ bool PreserveLCSSA = false);
/// FoldReturnIntoUncondBranch - This method duplicates the specified return
/// instruction into a predecessor which ends in an unconditional branch. If
diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h
index 6387c166ec71..879f295caf0c 100644
--- a/include/llvm/Transforms/Utils/BuildLibCalls.h
+++ b/include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -28,52 +28,50 @@ namespace llvm {
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
/// specified pointer. Ptr is required to be some pointer type, and the
/// return value has 'intptr_t' type.
- Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout *TD,
+ Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL,
const TargetLibraryInfo *TLI);
/// EmitStrNLen - Emit a call to the strnlen function to the builder, for the
/// specified pointer. Ptr is required to be some pointer type, MaxLen must
/// be of size_t type, and the return value has 'intptr_t' type.
Value *EmitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B,
- const DataLayout *TD, const TargetLibraryInfo *TLI);
+ const DataLayout &DL, const TargetLibraryInfo *TLI);
/// EmitStrChr - Emit a call to the strchr function to the builder, for the
/// specified pointer and character. Ptr is required to be some pointer type,
/// and the return value has 'i8*' type.
- Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const DataLayout *TD,
+ Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
const TargetLibraryInfo *TLI);
/// EmitStrNCmp - Emit a call to the strncmp function to the builder.
Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
- const DataLayout *TD, const TargetLibraryInfo *TLI);
+ const DataLayout &DL, const TargetLibraryInfo *TLI);
/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
/// specified pointer arguments.
Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
- const DataLayout *TD, const TargetLibraryInfo *TLI,
- StringRef Name = "strcpy");
+ const TargetLibraryInfo *TLI, StringRef Name = "strcpy");
/// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the
/// specified pointer arguments and length.
Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B,
- const DataLayout *TD, const TargetLibraryInfo *TLI,
- StringRef Name = "strncpy");
+ const TargetLibraryInfo *TLI, StringRef Name = "strncpy");
/// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder.
/// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src
/// are pointers.
Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
- IRBuilder<> &B, const DataLayout *TD,
+ IRBuilder<> &B, const DataLayout &DL,
const TargetLibraryInfo *TLI);
/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.
Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B,
- const DataLayout *TD, const TargetLibraryInfo *TLI);
+ const DataLayout &DL, const TargetLibraryInfo *TLI);
/// EmitMemCmp - Emit a call to the memcmp function.
Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
- const DataLayout *TD, const TargetLibraryInfo *TLI);
+ const DataLayout &DL, const TargetLibraryInfo *TLI);
/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name'
/// (e.g. 'floor'). This function is known to take a single of type matching
@@ -93,28 +91,26 @@ namespace llvm {
/// EmitPutChar - Emit a call to the putchar function. This assumes that Char
/// is an integer.
- Value *EmitPutChar(Value *Char, IRBuilder<> &B, const DataLayout *TD,
- const TargetLibraryInfo *TLI);
+ Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetLibraryInfo *TLI);
/// EmitPutS - Emit a call to the puts function. This assumes that Str is
/// some pointer.
- Value *EmitPutS(Value *Str, IRBuilder<> &B, const DataLayout *TD,
- const TargetLibraryInfo *TLI);
+ Value *EmitPutS(Value *Str, IRBuilder<> &B, const TargetLibraryInfo *TLI);
/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is
/// an i32, and File is a pointer to FILE.
Value *EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
- const DataLayout *TD, const TargetLibraryInfo *TLI);
+ const TargetLibraryInfo *TLI);
/// EmitFPutS - Emit a call to the puts function. Str is required to be a
/// pointer and File is a pointer to FILE.
- Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const DataLayout *TD,
+ Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);
/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
- const DataLayout *TD, const TargetLibraryInfo *TLI);
+ const DataLayout &DL, const TargetLibraryInfo *TLI);
}
#endif
diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h
index 6584abe822d8..cb187ec103d0 100644
--- a/include/llvm/Transforms/Utils/Cloning.h
+++ b/include/llvm/Transforms/Utils/Cloning.h
@@ -95,8 +95,7 @@ struct ClonedCodeInfo {
/// function, you can specify a ClonedCodeInfo object with the optional fifth
/// parameter.
///
-BasicBlock *CloneBasicBlock(const BasicBlock *BB,
- ValueToValueMapTy &VMap,
+BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap,
const Twine &NameSuffix = "", Function *F = nullptr,
ClonedCodeInfo *CodeInfo = nullptr);
@@ -112,8 +111,7 @@ BasicBlock *CloneBasicBlock(const BasicBlock *BB,
/// If ModuleLevelChanges is false, VMap contains no non-identity GlobalValue
/// mappings, and debug info metadata will not be cloned.
///
-Function *CloneFunction(const Function *F,
- ValueToValueMapTy &VMap,
+Function *CloneFunction(const Function *F, ValueToValueMapTy &VMap,
bool ModuleLevelChanges,
ClonedCodeInfo *CodeInfo = nullptr);
@@ -127,14 +125,50 @@ Function *CloneFunction(const Function *F,
/// mappings.
///
void CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
- ValueToValueMapTy &VMap,
- bool ModuleLevelChanges,
+ ValueToValueMapTy &VMap, bool ModuleLevelChanges,
SmallVectorImpl<ReturnInst*> &Returns,
const char *NameSuffix = "",
ClonedCodeInfo *CodeInfo = nullptr,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
+/// A helper class used with CloneAndPruneIntoFromInst to change the default
+/// behavior while instructions are being cloned.
+class CloningDirector {
+public:
+ /// This enumeration describes the way CloneAndPruneIntoFromInst should
+ /// proceed after the CloningDirector has examined an instruction.
+ enum CloningAction {
+ ///< Continue cloning the instruction (default behavior).
+ CloneInstruction,
+ ///< Skip this instruction but continue cloning the current basic block.
+ SkipInstruction,
+ ///< Skip this instruction and stop cloning the current basic block.
+ StopCloningBB,
+ ///< Don't clone the terminator but clone the current block's successors.
+ CloneSuccessors
+ };
+
+ virtual ~CloningDirector() {}
+
+ /// Subclasses must override this function to customize cloning behavior.
+ virtual CloningAction handleInstruction(ValueToValueMapTy &VMap,
+ const Instruction *Inst,
+ BasicBlock *NewBB) = 0;
+
+ virtual ValueMapTypeRemapper *getTypeRemapper() { return nullptr; }
+ virtual ValueMaterializer *getValueMaterializer() { return nullptr; }
+};
+
+void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
+ const Instruction *StartingInst,
+ ValueToValueMapTy &VMap, bool ModuleLevelChanges,
+ SmallVectorImpl<ReturnInst*> &Returns,
+ const char *NameSuffix = "",
+ ClonedCodeInfo *CodeInfo = nullptr,
+ CloningDirector *Director = nullptr);
+
+
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
/// except that it does some simple constant prop and DCE on the fly. The
/// effect of this is to copy significantly less code in cases where (for
@@ -147,12 +181,10 @@ void CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
/// mappings.
///
void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
- ValueToValueMapTy &VMap,
- bool ModuleLevelChanges,
+ ValueToValueMapTy &VMap, bool ModuleLevelChanges,
SmallVectorImpl<ReturnInst*> &Returns,
const char *NameSuffix = "",
ClonedCodeInfo *CodeInfo = nullptr,
- const DataLayout *DL = nullptr,
Instruction *TheCall = nullptr);
/// InlineFunctionInfo - This class captures the data input to the
@@ -160,21 +192,19 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
class InlineFunctionInfo {
public:
explicit InlineFunctionInfo(CallGraph *cg = nullptr,
- const DataLayout *DL = nullptr,
AliasAnalysis *AA = nullptr,
AssumptionCacheTracker *ACT = nullptr)
- : CG(cg), DL(DL), AA(AA), ACT(ACT) {}
+ : CG(cg), 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.
- SmallVector<AllocaInst*, 4> StaticAllocas;
+ SmallVector<AllocaInst *, 4> StaticAllocas;
/// InlinedCalls - InlineFunction fills this in with callsites that were
/// inlined from the callee. This is only filled in if CG is non-null.
@@ -196,9 +226,12 @@ public:
/// exists in the instruction stream. Similarly this will inline a recursive
/// function by one level.
///
-bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI, bool InsertLifetime = true);
-bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, bool InsertLifetime = true);
-bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI, bool InsertLifetime = true);
+bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI,
+ bool InsertLifetime = true);
+bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
+ bool InsertLifetime = true);
+bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
+ bool InsertLifetime = true);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index 14844117f44f..a1bb367ac7b6 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -16,6 +16,7 @@
#define LLVM_TRANSFORMS_UTILS_LOCAL_H
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Operator.h"
@@ -31,7 +32,6 @@ class DbgDeclareInst;
class StoreInst;
class LoadInst;
class Value;
-class Pass;
class PHINode;
class AllocaInst;
class AssumptionCache;
@@ -89,7 +89,7 @@ bool RecursivelyDeleteDeadPHINode(PHINode *PN,
///
/// This returns true if it changed the code, note that it can delete
/// instructions in other blocks as well in this block.
-bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = nullptr,
+bool SimplifyInstructionsInBlock(BasicBlock *BB,
const TargetLibraryInfo *TLI = nullptr);
//===----------------------------------------------------------------------===//
@@ -107,15 +107,14 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = nullptr,
///
/// .. and delete the predecessor corresponding to the '1', this will attempt to
/// recursively fold the 'and' to 0.
-void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
- DataLayout *TD = nullptr);
+void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred);
/// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its
/// predecessor is known to have one successor (BB!). Eliminate the edge
/// between them, moving the instructions in the predecessor into BB. This
/// deletes the predecessor block.
///
-void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = nullptr);
+void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr);
/// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an
/// unconditional branch, and contains no instructions other than PHI nodes,
@@ -138,8 +137,7 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB);
/// the basic block that was pointed to.
///
bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
- unsigned BonusInstThreshold, const DataLayout *TD = nullptr,
- AssumptionCache *AC = nullptr);
+ unsigned BonusInstThreshold, AssumptionCache *AC = nullptr);
/// FlatternCFG - This function is used to flatten a CFG. For
/// example, it uses parallel-and and parallel-or mode to collapse
@@ -151,8 +149,7 @@ 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,
- unsigned BonusInstThreshold = 1);
+bool FoldBranchToCommonDest(BranchInst *BI, 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
@@ -174,18 +171,17 @@ 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,
- AssumptionCache *AC = nullptr,
+ const DataLayout &DL,
const Instruction *CxtI = nullptr,
+ AssumptionCache *AC = 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,
- AssumptionCache *AC = nullptr,
+static inline unsigned getKnownAlignment(Value *V, const DataLayout &DL,
const Instruction *CxtI = nullptr,
+ AssumptionCache *AC = nullptr,
const DominatorTree *DT = nullptr) {
- return getOrEnforceKnownAlignment(V, 0, TD, AC, CxtI, DT);
+ return getOrEnforceKnownAlignment(V, 0, DL, CxtI, AC, DT);
}
/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the
@@ -193,11 +189,11 @@ static inline unsigned getKnownAlignment(Value *V,
/// in the base pointer). Return the result as a signed integer of intptr size.
/// When NoAssumptions is true, no assumptions about index computation not
/// overflowing is made.
-template<typename IRBuilderTy>
-Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP,
+template <typename IRBuilderTy>
+Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP,
bool NoAssumptions = false) {
GEPOperator *GEPOp = cast<GEPOperator>(GEP);
- Type *IntPtrTy = TD.getIntPtrType(GEP->getType());
+ Type *IntPtrTy = DL.getIntPtrType(GEP->getType());
Value *Result = Constant::getNullValue(IntPtrTy);
// If the GEP is inbounds, we know that none of the addressing operations will
@@ -212,7 +208,7 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP,
for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e;
++i, ++GTI) {
Value *Op = *i;
- uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask;
+ uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask;
if (Constant *OpC = dyn_cast<Constant>(Op)) {
if (OpC->isZeroValue())
continue;
@@ -223,7 +219,7 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP,
OpC = OpC->getSplatValue();
uint64_t OpValue = cast<ConstantInt>(OpC)->getZExtValue();
- Size = TD.getStructLayout(STy)->getElementOffset(OpValue);
+ Size = DL.getStructLayout(STy)->getElementOffset(OpValue);
if (Size)
Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size),
@@ -275,10 +271,11 @@ bool LowerDbgDeclare(Function &F);
/// an alloca, if any.
DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
-/// replaceDbgDeclareForAlloca - Replaces llvm.dbg.declare instruction when
-/// alloca is replaced with a new value.
+/// \brief Replaces llvm.dbg.declare instruction when an alloca is replaced with
+/// a new value. If Deref is true, tan additional DW_OP_deref is prepended to
+/// the expression.
bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
- DIBuilder &Builder);
+ DIBuilder &Builder, bool Deref);
/// \brief Remove all blocks that can not be reached from the function's entry.
///
@@ -290,6 +287,10 @@ bool removeUnreachableBlocks(Function &F);
/// Metadata not listed as known via KnownIDs is removed
void combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsigned> KnownIDs);
+/// \brief Replace each use of 'From' with 'To' if that use is dominated by
+/// the given edge. Returns the number of replacements made.
+unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT,
+ const BasicBlockEdge &Edge);
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h
index f315adc49d15..28791f5f43a8 100644
--- a/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/include/llvm/Transforms/Utils/LoopUtils.h
@@ -14,8 +14,14 @@
#ifndef LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
#define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
+
namespace llvm {
class AliasAnalysis;
+class AliasSet;
+class AliasSetTracker;
class AssumptionCache;
class BasicBlock;
class DataLayout;
@@ -23,7 +29,147 @@ class DominatorTree;
class Loop;
class LoopInfo;
class Pass;
+class PredIteratorCache;
class ScalarEvolution;
+class TargetLibraryInfo;
+
+/// \brief Captures loop safety information.
+/// It keep information for loop & its header may throw exception.
+struct LICMSafetyInfo {
+ bool MayThrow; // The current loop contains an instruction which
+ // may throw.
+ bool HeaderMayThrow; // Same as previous, but specific to loop header
+ LICMSafetyInfo() : MayThrow(false), HeaderMayThrow(false)
+ {}
+};
+
+/// This POD struct holds information about a potential reduction operation.
+class ReductionInstDesc {
+
+public:
+ // This enum represents the kind of minmax reduction.
+ enum MinMaxReductionKind {
+ MRK_Invalid,
+ MRK_UIntMin,
+ MRK_UIntMax,
+ MRK_SIntMin,
+ MRK_SIntMax,
+ MRK_FloatMin,
+ MRK_FloatMax
+ };
+ ReductionInstDesc(bool IsRedux, Instruction *I)
+ : IsReduction(IsRedux), PatternLastInst(I), MinMaxKind(MRK_Invalid) {}
+
+ ReductionInstDesc(Instruction *I, MinMaxReductionKind K)
+ : IsReduction(true), PatternLastInst(I), MinMaxKind(K) {}
+
+ bool isReduction() { return IsReduction; }
+
+ MinMaxReductionKind getMinMaxKind() { return MinMaxKind; }
+
+ Instruction *getPatternInst() { return PatternLastInst; }
+
+private:
+ // Is this instruction a reduction candidate.
+ bool IsReduction;
+ // The last instruction in a min/max pattern (select of the select(icmp())
+ // pattern), or the current reduction instruction otherwise.
+ Instruction *PatternLastInst;
+ // If this is a min/max pattern the comparison predicate.
+ MinMaxReductionKind MinMaxKind;
+};
+
+/// This struct holds information about reduction variables.
+class ReductionDescriptor {
+
+public:
+ /// This enum represents the kinds of reductions that we support.
+ enum ReductionKind {
+ RK_NoReduction, ///< Not a reduction.
+ RK_IntegerAdd, ///< Sum of integers.
+ RK_IntegerMult, ///< Product of integers.
+ RK_IntegerOr, ///< Bitwise or logical OR of numbers.
+ RK_IntegerAnd, ///< Bitwise or logical AND of numbers.
+ RK_IntegerXor, ///< Bitwise or logical XOR of numbers.
+ RK_IntegerMinMax, ///< Min/max implemented in terms of select(cmp()).
+ RK_FloatAdd, ///< Sum of floats.
+ RK_FloatMult, ///< Product of floats.
+ RK_FloatMinMax ///< Min/max implemented in terms of select(cmp()).
+ };
+
+ ReductionDescriptor()
+ : StartValue(nullptr), LoopExitInstr(nullptr), Kind(RK_NoReduction),
+ MinMaxKind(ReductionInstDesc::MRK_Invalid) {}
+
+ ReductionDescriptor(Value *Start, Instruction *Exit, ReductionKind K,
+ ReductionInstDesc::MinMaxReductionKind MK)
+ : StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK) {}
+
+ /// Returns a struct describing if the instruction 'I' can be a reduction
+ /// variable of type 'Kind'. If the reduction is a min/max pattern of
+ /// select(icmp()) this function advances the instruction pointer 'I' from the
+ /// compare instruction to the select instruction and stores this pointer in
+ /// 'PatternLastInst' member of the returned struct.
+ static ReductionInstDesc isReductionInstr(Instruction *I, ReductionKind Kind,
+ ReductionInstDesc &Prev,
+ bool HasFunNoNaNAttr);
+
+ /// Returns true if instuction I has multiple uses in Insts
+ static bool hasMultipleUsesOf(Instruction *I,
+ SmallPtrSetImpl<Instruction *> &Insts);
+
+ /// Returns true if all uses of the instruction I is within the Set.
+ static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set);
+
+ /// Returns a struct describing if the instruction if the instruction is a
+ /// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y)
+ /// or max(X, Y).
+ static ReductionInstDesc isMinMaxSelectCmpPattern(Instruction *I,
+ ReductionInstDesc &Prev);
+
+ /// Returns identity corresponding to the ReductionKind.
+ static Constant *getReductionIdentity(ReductionKind K, Type *Tp);
+
+ /// Returns the opcode of binary operation corresponding to the ReductionKind.
+ static unsigned getReductionBinOp(ReductionKind Kind);
+
+ /// Returns a Min/Max operation corresponding to MinMaxReductionKind.
+ static Value *createMinMaxOp(IRBuilder<> &Builder,
+ ReductionInstDesc::MinMaxReductionKind RK,
+ Value *Left, Value *Right);
+
+ /// Returns true if Phi is a reduction of type Kind and adds it to the
+ /// ReductionDescriptor.
+ static bool AddReductionVar(PHINode *Phi, ReductionKind Kind, Loop *TheLoop,
+ bool HasFunNoNaNAttr,
+ ReductionDescriptor &RedDes);
+
+ /// Returns true if Phi is a reduction in TheLoop. The ReductionDescriptor is
+ /// returned in RedDes.
+ static bool isReductionPHI(PHINode *Phi, Loop *TheLoop,
+ ReductionDescriptor &RedDes);
+
+ ReductionKind getReductionKind() { return Kind; }
+
+ ReductionInstDesc::MinMaxReductionKind getMinMaxReductionKind() {
+ return MinMaxKind;
+ }
+
+ TrackingVH<Value> getReductionStartValue() { return StartValue; }
+
+ Instruction *getLoopExitInstr() { return LoopExitInstr; }
+
+private:
+ // The starting value of the reduction.
+ // It does not have to be zero!
+ TrackingVH<Value> StartValue;
+ // The instruction who's value is used outside the loop.
+ Instruction *LoopExitInstr;
+ // The kind of the reduction.
+ ReductionKind Kind;
+ // If this a min/max reduction the kind of reduction.
+ ReductionInstDesc::MinMaxReductionKind MinMaxKind;
+};
BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P);
@@ -35,7 +181,6 @@ 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,
AssumptionCache *AC = nullptr);
/// \brief Put loop into LCSSA form.
@@ -63,6 +208,53 @@ bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI,
/// Returns true if any modifications are made to the loop.
bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI,
ScalarEvolution *SE = nullptr);
+
+/// \brief Walk the specified region of the CFG (defined by all blocks
+/// dominated by the specified block, and that are in the current loop) in
+/// reverse depth first order w.r.t the DominatorTree. This allows us to visit
+/// uses before definitions, allowing us to sink a loop body in one pass without
+/// iteration. Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree,
+/// DataLayout, TargetLibraryInfo, Loop, AliasSet information for all
+/// instructions of the loop and loop safety information as arguments.
+/// It returns changed status.
+bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
+ TargetLibraryInfo *, Loop *, AliasSetTracker *,
+ LICMSafetyInfo *);
+
+/// \brief Walk the specified region of the CFG (defined by all blocks
+/// dominated by the specified block, and that are in the current loop) in depth
+/// first order w.r.t the DominatorTree. This allows us to visit definitions
+/// before uses, allowing us to hoist a loop body in one pass without iteration.
+/// Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree, DataLayout,
+/// TargetLibraryInfo, Loop, AliasSet information for all instructions of the
+/// loop and loop safety information as arguments. It returns changed status.
+bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
+ TargetLibraryInfo *, Loop *, AliasSetTracker *,
+ LICMSafetyInfo *);
+
+/// \brief Try to promote memory values to scalars by sinking stores out of
+/// the loop and moving loads to before the loop. We do this by looping over
+/// the stores in the loop, looking for stores to Must pointers which are
+/// loop invariant. It takes AliasSet, Loop exit blocks vector, loop exit blocks
+/// insertion point vector, PredIteratorCache, LoopInfo, DominatorTree, Loop,
+/// AliasSet information for all instructions of the loop and loop safety
+/// information as arguments. It returns changed status.
+bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock*> &,
+ SmallVectorImpl<Instruction*> &,
+ PredIteratorCache &, LoopInfo *,
+ DominatorTree *, Loop *, AliasSetTracker *,
+ LICMSafetyInfo *);
+
+/// \brief Computes safety information for a loop
+/// checks loop body & header for the possiblity of may throw
+/// exception, it takes LICMSafetyInfo and loop as argument.
+/// Updates safety information in LICMSafetyInfo argument.
+void computeLICMSafetyInfo(LICMSafetyInfo *, Loop *);
+
+/// \brief Checks if the given PHINode in a loop header is an induction
+/// variable. Returns true if this is an induction PHI along with the step
+/// value.
+bool isInductionPHI(PHINode *, ScalarEvolution *, ConstantInt *&);
}
#endif
diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h
index 16904f16e369..622265bae143 100644
--- a/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -14,12 +14,19 @@
#ifndef LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
#define LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
+#include "llvm/ADT/ArrayRef.h"
+#include <utility> // for std::pair
+
namespace llvm {
class Module;
class Function;
class GlobalValue;
class GlobalVariable;
+class Constant;
+class StringRef;
+class Value;
+class Type;
template <class PtrType> class SmallPtrSetImpl;
/// Append F to the list of global ctors of module M with the given Priority.
@@ -36,6 +43,20 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority);
GlobalVariable *collectUsedGlobalVariables(Module &M,
SmallPtrSetImpl<GlobalValue *> &Set,
bool CompilerUsed);
+
+// Validate the result of Module::getOrInsertFunction called for an interface
+// function of given sanitizer. If the instrumented module defines a function
+// with the same name, their prototypes must match, otherwise
+// getOrInsertFunction returns a bitcast.
+Function *checkSanitizerInterfaceFunction(Constant *FuncOrBitcast);
+
+/// \brief Creates sanitizer constructor function, and calls sanitizer's init
+/// function from it.
+/// \return Returns pair of pointers to constructor, and init functions
+/// respectively.
+std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions(
+ Module &M, StringRef CtorName, StringRef InitName,
+ ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs);
} // End llvm namespace
#endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h
index 7874a5fd8119..1c7b2c587a36 100644
--- a/include/llvm/Transforms/Utils/SSAUpdater.h
+++ b/include/llvm/Transforms/Utils/SSAUpdater.h
@@ -14,6 +14,7 @@
#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATER_H
#define LLVM_TRANSFORMS_UTILS_SSAUPDATER_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
@@ -118,8 +119,8 @@ public:
private:
Value *GetValueAtEndOfBlockInternal(BasicBlock *BB);
- void operator=(const SSAUpdater&) LLVM_DELETED_FUNCTION;
- SSAUpdater(const SSAUpdater&) LLVM_DELETED_FUNCTION;
+ void operator=(const SSAUpdater&) = delete;
+ SSAUpdater(const SSAUpdater&) = delete;
};
/// \brief Helper class for promoting a collection of loads and stores into SSA
@@ -135,7 +136,7 @@ protected:
SSAUpdater &SSA;
public:
- LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts,
+ LoadAndStorePromoter(ArrayRef<const Instruction*> Insts,
SSAUpdater &S, StringRef Name = StringRef());
virtual ~LoadAndStorePromoter() {}
diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 70ef0eb765dd..41159603aae5 100644
--- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -15,9 +15,10 @@
#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
#define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"
-#include "llvm/Target/TargetLibraryInfo.h"
namespace llvm {
class Value;
@@ -36,12 +37,11 @@ class Function;
/// 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,
+ FortifiedLibCallSimplifier(const TargetLibraryInfo *TLI,
bool OnlyLowerUnknownSize = false);
/// \brief Take the given call instruction and return a more
@@ -71,15 +71,24 @@ private:
class LibCallSimplifier {
private:
FortifiedLibCallSimplifier FortifiedSimplifier;
- const DataLayout *DL;
+ const DataLayout &DL;
const TargetLibraryInfo *TLI;
bool UnsafeFPShrink;
+ function_ref<void(Instruction *, Value *)> Replacer;
-protected:
- ~LibCallSimplifier() {}
+ /// \brief Internal wrapper for RAUW that is the default implementation.
+ ///
+ /// Other users may provide an alternate function with this signature instead
+ /// of this one.
+ static void replaceAllUsesWithDefault(Instruction *I, Value *With);
+
+ /// \brief Replace an instruction's uses with a value using our replacer.
+ void replaceAllUsesWith(Instruction *I, Value *With);
public:
- LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI);
+ LibCallSimplifier(const DataLayout &DL, const TargetLibraryInfo *TLI,
+ function_ref<void(Instruction *, Value *)> Replacer =
+ &replaceAllUsesWithDefault);
/// optimizeCall - Take the given call instruction and return a more
/// optimal value to replace the instruction with or 0 if a more
@@ -90,11 +99,6 @@ public:
/// 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);
@@ -112,6 +116,7 @@ private:
Value *optimizeStrSpn(CallInst *CI, IRBuilder<> &B);
Value *optimizeStrCSpn(CallInst *CI, IRBuilder<> &B);
Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemChr(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B);
diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h
index af7937265795..5ccee98f97e7 100644
--- a/include/llvm/Transforms/Utils/SymbolRewriter.h
+++ b/include/llvm/Transforms/Utils/SymbolRewriter.h
@@ -60,10 +60,10 @@ namespace SymbolRewriter {
/// select the symbols to rewrite. This descriptor list is passed to the
/// SymbolRewriter pass.
class RewriteDescriptor : public ilist_node<RewriteDescriptor> {
- RewriteDescriptor(const RewriteDescriptor &) LLVM_DELETED_FUNCTION;
+ RewriteDescriptor(const RewriteDescriptor &) = delete;
const RewriteDescriptor &
- operator=(const RewriteDescriptor &) LLVM_DELETED_FUNCTION;
+ operator=(const RewriteDescriptor &) = delete;
public:
enum class Type {
@@ -90,9 +90,6 @@ typedef iplist<RewriteDescriptor> RewriteDescriptorList;
class RewriteMapParser {
public:
- RewriteMapParser() {}
- ~RewriteMapParser() {}
-
bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors);
private:
diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h
index 807367cd4b12..7f2cf8d7f59e 100644
--- a/include/llvm/Transforms/Utils/UnrollLoop.h
+++ b/include/llvm/Transforms/Utils/UnrollLoop.h
@@ -16,20 +16,27 @@
#ifndef LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H
#define LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H
+#include "llvm/ADT/StringRef.h"
+
namespace llvm {
class AssumptionCache;
class Loop;
class LoopInfo;
class LPPassManager;
+class MDNode;
class Pass;
bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime,
- unsigned TripMultiple, LoopInfo *LI, Pass *PP,
- LPPassManager *LPM, AssumptionCache *AC);
+ bool AllowExpensiveTripCount, unsigned TripMultiple,
+ LoopInfo *LI, Pass *PP, LPPassManager *LPM,
+ AssumptionCache *AC);
+
+bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count,
+ bool AllowExpensiveTripCount, LoopInfo *LI,
+ LPPassManager *LPM);
-bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,
- LPPassManager* LPM);
+MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name);
}
#endif
diff --git a/include/llvm/Transforms/Utils/VectorUtils.h b/include/llvm/Transforms/Utils/VectorUtils.h
index b47acf517b37..9f0fb19d667a 100644
--- a/include/llvm/Transforms/Utils/VectorUtils.h
+++ b/include/llvm/Transforms/Utils/VectorUtils.h
@@ -14,9 +14,9 @@
#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
-#include "llvm/Target/TargetLibraryInfo.h"
namespace llvm {
@@ -59,7 +59,7 @@ static inline bool isTriviallyVectorizable(Intrinsic::ID ID) {
}
}
-static bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID,
+static inline bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID,
unsigned ScalarOpdIdx) {
switch (ID) {
case Intrinsic::ctlz:
diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap
index 61f65510c4ea..163cbc3df865 100644
--- a/include/llvm/module.modulemap
+++ b/include/llvm/module.modulemap
@@ -2,7 +2,12 @@ module LLVM_Analysis {
requires cplusplus
umbrella "Analysis"
module * { export * }
+
+ // FIXME: Why is this excluded?
exclude header "Analysis/BlockFrequencyInfoImpl.h"
+
+ // This is intended for (repeated) textual inclusion.
+ textual header "Analysis/TargetLibraryInfo.def"
}
module LLVM_AsmParser { requires cplusplus umbrella "AsmParser" module * { export * } }
@@ -40,7 +45,48 @@ module LLVM_Backend {
module LLVM_Bitcode { requires cplusplus umbrella "Bitcode" module * { export * } }
module LLVM_Config { requires cplusplus umbrella "Config" module * { export * } }
-module LLVM_DebugInfo { requires cplusplus umbrella "DebugInfo" module * { export * } }
+
+module LLVM_DebugInfo {
+ requires cplusplus
+ module DIContext { header "DebugInfo/DIContext.h" export * }
+}
+
+module LLVM_DebugInfo_DWARF {
+ requires cplusplus
+
+ umbrella "DebugInfo/DWARF"
+ module * { export * }
+}
+
+module LLVM_DebugInfo_PDB {
+ requires cplusplus
+
+ umbrella "DebugInfo/PDB"
+ module * { export * }
+
+ // Separate out this subdirectory; it's an optional component that depends on
+ // a separate library which might not be available.
+ //
+ // FIXME: There should be a better way to specify this.
+ exclude header "DebugInfo/PDB/DIA/DIADataStream.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+ exclude header "DebugInfo/PDB/DIA/DIALineNumber.h"
+ exclude header "DebugInfo/PDB/DIA/DIARawSymbol.h"
+ exclude header "DebugInfo/PDB/DIA/DIASession.h"
+ exclude header "DebugInfo/PDB/DIA/DIASourceFile.h"
+ exclude header "DebugInfo/PDB/DIA/DIASupport.h"
+}
+
+module LLVM_DebugInfo_PDB_DIA {
+ requires cplusplus
+
+ umbrella "DebugInfo/PDB/DIA"
+ module * { export * }
+}
+
module LLVM_ExecutionEngine {
requires cplusplus
@@ -55,6 +101,7 @@ module LLVM_ExecutionEngine {
exclude header "ExecutionEngine/JIT.h"
exclude header "ExecutionEngine/MCJIT.h"
exclude header "ExecutionEngine/Interpreter.h"
+ exclude header "ExecutionEngine/OrcMCJITReplacement.h"
}
module LLVM_IR {
@@ -70,29 +117,12 @@ module LLVM_IR {
umbrella "IR"
module * { export * }
- // We cannot have llvm/PassManager.h and llvm/IR/PassManager.h in the same TU,
- // so we can't include llvm/IR/PassManager.h in the IR module.
- exclude header "IR/PassManager.h"
- exclude header "IR/LegacyPassManager.h"
-
// These are intended for (repeated) textual inclusion.
+ textual header "IR/DebugInfoFlags.def"
textual header "IR/Instruction.def"
textual header "IR/Metadata.def"
}
-module LLVM_LegacyPassManager {
- requires cplusplus
- module CompatInterface { header "PassManager.h" export * }
- module Implementation { header "IR/LegacyPassManager.h" export * }
-}
-
-module LLVM_IR_PassManager {
- requires cplusplus
- // FIXME PR19358: This doesn't work! conflict LLVM_LegacyPassManager, "cannot use legacy pass manager and new pass manager in same file"
- header "IR/PassManager.h"
- export *
-}
-
module LLVM_IRReader { requires cplusplus umbrella "IRReader" module * { export * } }
module LLVM_LineEditor { requires cplusplus umbrella "LineEditor" module * { export * } }
module LLVM_LTO { requires cplusplus umbrella "LTO" module * { export * } }
@@ -164,6 +194,7 @@ module LLVM_Utils {
exclude header "Support/TargetRegistry.h"
// These are intended for textual inclusion.
+ textual header "Support/Dwarf.def"
textual header "Support/ELFRelocs/AArch64.def"
textual header "Support/ELFRelocs/ARM.def"
textual header "Support/ELFRelocs/Hexagon.def"